编译器
0.8.18+commit.87f61d96
文件 1 的 57:AccountUtils.sol
pragma solidity ^0.8.0;
import "../error/Errors.sol";
library AccountUtils {
function validateAccount(address account) internal pure {
if (account == address(0)) {
revert Errors.EmptyAccount();
}
}
function validateReceiver(address receiver) internal pure {
if (receiver == address(0)) {
revert Errors.EmptyReceiver();
}
}
}
文件 2 的 57:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 3 的 57:AggregatorInterface.sol
pragma solidity ^0.8.0;
interface AggregatorInterface {
function latestAnswer() external view returns (int256);
function latestTimestamp() external view returns (uint256);
function latestRound() external view returns (uint256);
function getAnswer(uint256 roundId) external view returns (int256);
function getTimestamp(uint256 roundId) external view returns (uint256);
event AnswerUpdated(int256 indexed current, uint256 indexed roundId, uint256 updatedAt);
event NewRound(uint256 indexed roundId, address indexed startedBy, uint256 startedAt);
}
文件 4 的 57:AggregatorV2V3Interface.sol
pragma solidity ^0.8.0;
import {AggregatorInterface} from "./AggregatorInterface.sol";
import {AggregatorV3Interface} from "./AggregatorV3Interface.sol";
interface AggregatorV2V3Interface is AggregatorInterface, AggregatorV3Interface {}
文件 5 的 57:AggregatorV3Interface.sol
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
function getRoundData(
uint80 _roundId
) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
文件 6 的 57:ArbSys.sol
pragma solidity ^0.8.0;
interface ArbSys {
function arbBlockNumber() external view returns (uint256);
function arbBlockHash(uint256 blockNumber) external view returns (bytes32);
}
文件 7 的 57:Array.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../error/Errors.sol";
library Array {
using SafeCast for int256;
function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {
if (index < arr.length) {
return arr[index];
}
return bytes32(0);
}
function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] != value) {
return false;
}
}
return true;
}
function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] <= value) {
return false;
}
}
return true;
}
function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] < value) {
return false;
}
}
return true;
}
function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] >= value) {
return false;
}
}
return true;
}
function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] > value) {
return false;
}
}
return true;
}
function getMedian(uint256[] memory arr) internal pure returns (uint256) {
if (arr.length % 2 == 1) {
return arr[arr.length / 2];
}
return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;
}
function getUncompactedValue(
uint256[] memory compactedValues,
uint256 index,
uint256 compactedValueBitLength,
uint256 bitmask,
string memory label
) internal pure returns (uint256) {
uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;
uint256 slotIndex = index / compactedValuesPerSlot;
if (slotIndex >= compactedValues.length) {
revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);
}
uint256 slotBits = compactedValues[slotIndex];
uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;
uint256 value = (slotBits >> offset) & bitmask;
return value;
}
}
文件 8 的 57:Bank.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../token/TokenUtils.sol";
import "../role/RoleModule.sol";
contract Bank is RoleModule {
using SafeERC20 for IERC20;
DataStore public immutable dataStore;
constructor(RoleStore _roleStore, DataStore _dataStore) RoleModule(_roleStore) {
dataStore = _dataStore;
}
receive() external payable {
address wnt = TokenUtils.wnt(dataStore);
if (msg.sender != wnt) {
revert Errors.InvalidNativeTokenSender(msg.sender);
}
}
function transferOut(
address token,
address receiver,
uint256 amount
) external onlyController {
_transferOut(token, receiver, amount);
}
function transferOut(
address token,
address receiver,
uint256 amount,
bool shouldUnwrapNativeToken
) external onlyController {
address wnt = TokenUtils.wnt(dataStore);
if (token == wnt && shouldUnwrapNativeToken) {
_transferOutNativeToken(token, receiver, amount);
} else {
_transferOut(token, receiver, amount);
}
}
function transferOutNativeToken(
address receiver,
uint256 amount
) external onlyController {
address wnt = TokenUtils.wnt(dataStore);
_transferOutNativeToken(wnt, receiver, amount);
}
function _transferOut(
address token,
address receiver,
uint256 amount
) internal {
if (receiver == address(this)) {
revert Errors.SelfTransferNotSupported(receiver);
}
TokenUtils.transfer(dataStore, token, receiver, amount);
_afterTransferOut(token);
}
function _transferOutNativeToken(
address token,
address receiver,
uint256 amount
) internal {
if (receiver == address(this)) {
revert Errors.SelfTransferNotSupported(receiver);
}
TokenUtils.withdrawAndSendNativeToken(
dataStore,
token,
receiver,
amount
);
_afterTransferOut(token);
}
function _afterTransferOut(address ) internal virtual {}
}
文件 9 的 57:BasicMulticall.sol
pragma solidity ^0.8.0;
import "../error/ErrorUtils.sol";
abstract contract BasicMulticall {
function multicall(bytes[] calldata data) external virtual returns (bytes[] memory results) {
results = new bytes[](data.length);
for (uint256 i; i < data.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
if (!success) {
ErrorUtils.revertWithParsedMessage(result);
}
results[i] = result;
}
return results;
}
}
文件 10 的 57:Calc.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SignedMath.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
library Calc {
using SignedMath for int256;
using SafeCast for uint256;
function boundMagnitude(int256 value, uint256 min, uint256 max) internal pure returns (int256) {
uint256 magnitude = value.abs();
if (magnitude < min) {
magnitude = min;
}
if (magnitude > max) {
magnitude = max;
}
int256 sign = value == 0 ? int256(1) : value / value.abs().toInt256();
return magnitude.toInt256() * sign;
}
function roundUpDivision(uint256 a, uint256 b) internal pure returns (uint256) {
return (a + b - 1) / b;
}
function roundUpMagnitudeDivision(int256 a, uint256 b) internal pure returns (int256) {
if (a < 0) {
return (a - b.toInt256() + 1) / b.toInt256();
}
return (a + b.toInt256() - 1) / b.toInt256();
}
function sumReturnUint256(uint256 a, int256 b) internal pure returns (uint256) {
if (b > 0) {
return a + b.abs();
}
return a - b.abs();
}
function sumReturnInt256(uint256 a, int256 b) internal pure returns (int256) {
return a.toInt256() + b;
}
function diff(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a - b : b - a;
}
function boundedAdd(int256 a, int256 b) internal pure returns (int256) {
if (a == 0 || b == 0 || (a < 0 && b > 0) || (a > 0 && b < 0)) {
return a + b;
}
if (a < 0 && b <= type(int256).min - a) {
return type(int256).min;
}
if (a > 0 && b >= type(int256).max - a) {
return type(int256).max;
}
return a + b;
}
function boundedSub(int256 a, int256 b) internal pure returns (int256) {
if (a == 0 || b == 0 || (a > 0 && b > 0) || (a < 0 && b < 0)) {
return a - b;
}
if (a > 0 && -b >= type(int256).max - a) {
return type(int256).max;
}
if (a < 0 && -b <= type(int256).min - a) {
return type(int256).min;
}
return a - b;
}
function toSigned(uint256 a, bool isPositive) internal pure returns (int256) {
if (isPositive) {
return a.toInt256();
} else {
return -a.toInt256();
}
}
}
文件 11 的 57:Cast.sol
pragma solidity ^0.8.0;
import "../error/Errors.sol";
library Cast {
function toBytes32(address value) internal pure returns (bytes32) {
return bytes32(uint256(uint160(value)));
}
function bytesToUint256(bytes memory uint256AsBytes) internal pure returns (uint256) {
uint256 length = uint256AsBytes.length;
if(length > 32) {
revert Errors.Uint256AsBytesLengthExceeds32Bytes(length);
}
if (length == 0) {
return 0;
}
uint256 value;
assembly {
value := mload(add(uint256AsBytes, 32))
}
return value = value >> (8 * (32 - length));
}
}
文件 12 的 57:Chain.sol
pragma solidity ^0.8.0;
import "./ArbSys.sol";
library Chain {
uint256 public constant ARBITRUM_CHAIN_ID = 42161;
uint256 public constant ARBITRUM_SEPOLIA_CHAIN_ID = 421614;
ArbSys public constant arbSys = ArbSys(address(100));
function currentTimestamp() internal view returns (uint256) {
return block.timestamp;
}
function currentBlockNumber() internal view returns (uint256) {
if (shouldUseArbSysValues()) {
return arbSys.arbBlockNumber();
}
return block.number;
}
function getBlockHash(uint256 blockNumber) internal view returns (bytes32) {
if (shouldUseArbSysValues()) {
return arbSys.arbBlockHash(blockNumber);
}
return blockhash(blockNumber);
}
function shouldUseArbSysValues() internal view returns (bool) {
return block.chainid == ARBITRUM_CHAIN_ID || block.chainid == ARBITRUM_SEPOLIA_CHAIN_ID;
}
}
文件 13 的 57:ChainlinkPriceFeedUtils.sol
pragma solidity ^0.8.0;
import "../chain/Chain.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../utils/Precision.sol";
import "./IPriceFeed.sol";
library ChainlinkPriceFeedUtils {
function getPriceFeedPrice(DataStore dataStore, address token) internal view returns (bool, uint256) {
address priceFeedAddress = dataStore.getAddress(Keys.priceFeedKey(token));
if (priceFeedAddress == address(0)) {
return (false, 0);
}
IPriceFeed priceFeed = IPriceFeed(priceFeedAddress);
(
,
int256 _price,
,
uint256 timestamp,
) = priceFeed.latestRoundData();
if (_price <= 0) {
revert Errors.InvalidFeedPrice(token, _price);
}
uint256 heartbeatDuration = dataStore.getUint(Keys.priceFeedHeartbeatDurationKey(token));
if (Chain.currentTimestamp() > timestamp && Chain.currentTimestamp() - timestamp > heartbeatDuration) {
revert Errors.ChainlinkPriceFeedNotUpdated(token, timestamp, heartbeatDuration);
}
uint256 price = SafeCast.toUint256(_price);
uint256 precision = getPriceFeedMultiplier(dataStore, token);
uint256 adjustedPrice = Precision.mulDiv(price, precision, Precision.FLOAT_PRECISION);
return (true, adjustedPrice);
}
function getPriceFeedMultiplier(DataStore dataStore, address token) internal view returns (uint256) {
uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));
if (multiplier == 0) {
revert Errors.EmptyChainlinkPriceFeedMultiplier(token);
}
return multiplier;
}
}
文件 14 的 57:Config.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../role/RoleModule.sol";
import "../event/EventEmitter.sol";
import "../utils/BasicMulticall.sol";
import "../utils/Precision.sol";
import "../utils/Cast.sol";
import "../market/MarketUtils.sol";
contract Config is ReentrancyGuard, RoleModule, BasicMulticall {
using EventUtils for EventUtils.AddressItems;
using EventUtils for EventUtils.UintItems;
using EventUtils for EventUtils.IntItems;
using EventUtils for EventUtils.BoolItems;
using EventUtils for EventUtils.Bytes32Items;
using EventUtils for EventUtils.BytesItems;
using EventUtils for EventUtils.StringItems;
uint256 public constant MAX_FEE_FACTOR = 5 * Precision.FLOAT_PRECISION / 100;
uint256 public constant MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND = 100000000000000000000000;
uint256 public constant MAX_ALLOWED_FUNDING_INCREASE_FACTOR_PER_SECOND = MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND / 1 hours;
uint256 public constant MAX_ALLOWED_FUNDING_DECREASE_FACTOR_PER_SECOND = MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND / 24 hours;
DataStore public immutable dataStore;
EventEmitter public immutable eventEmitter;
mapping (bytes32 => bool) public allowedBaseKeys;
mapping (bytes32 => bool) public allowedLimitedBaseKeys;
constructor(
RoleStore _roleStore,
DataStore _dataStore,
EventEmitter _eventEmitter
) RoleModule(_roleStore) {
dataStore = _dataStore;
eventEmitter = _eventEmitter;
_initAllowedBaseKeys();
_initAllowedLimitedBaseKeys();
}
modifier onlyKeeper() {
if (
!roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER) &&
!roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)
) {
revert Errors.Unauthorized(msg.sender, "LIMITED / CONFIG KEEPER");
}
_;
}
function initOracleProviderForToken(address token, address provider) external onlyConfigKeeper nonReentrant {
if (dataStore.getAddress(Keys.oracleProviderForTokenKey(token)) != address(0)) {
revert Errors.OracleProviderAlreadyExistsForToken(token);
}
dataStore.setAddress(Keys.oracleProviderForTokenKey(token), provider);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "token", token);
eventData.addressItems.setItem(1, "provider", provider);
eventEmitter.emitEventLog(
"InitOracleProviderForToken",
eventData
);
}
function setPriceFeed(
address token,
address priceFeed,
uint256 priceFeedMultiplier,
uint256 priceFeedHeartbeatDuration,
uint256 stablePrice
) external onlyConfigKeeper nonReentrant {
if (dataStore.getAddress(Keys.priceFeedKey(token)) != address(0)) {
revert Errors.PriceFeedAlreadyExistsForToken(token);
}
dataStore.setAddress(Keys.priceFeedKey(token), priceFeed);
dataStore.setUint(Keys.priceFeedMultiplierKey(token), priceFeedMultiplier);
dataStore.setUint(Keys.priceFeedHeartbeatDurationKey(token), priceFeedHeartbeatDuration);
dataStore.setUint(Keys.stablePriceKey(token), stablePrice);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "token", token);
eventData.addressItems.setItem(1, "priceFeed", priceFeed);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "priceFeedMultiplier", priceFeedMultiplier);
eventData.uintItems.setItem(1, "priceFeedHeartbeatDuration", priceFeedHeartbeatDuration);
eventData.uintItems.setItem(2, "stablePrice", stablePrice);
eventEmitter.emitEventLog1(
"ConfigSetPriceFeed",
Cast.toBytes32(token),
eventData
);
}
function setDataStream(
address token,
bytes32 feedId,
uint256 dataStreamMultiplier,
uint256 dataStreamSpreadReductionFactor
) external onlyConfigKeeper nonReentrant {
if (dataStore.getBytes32(Keys.dataStreamIdKey(token)) != bytes32(0)) {
revert Errors.DataStreamIdAlreadyExistsForToken(token);
}
_validateRange(Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR, abi.encode(token), dataStreamSpreadReductionFactor);
dataStore.setBytes32(Keys.dataStreamIdKey(token), feedId);
dataStore.setUint(Keys.dataStreamMultiplierKey(token), dataStreamMultiplier);
dataStore.setUint(Keys.dataStreamSpreadReductionFactorKey(token), dataStreamSpreadReductionFactor);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "token", token);
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "feedId", feedId);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "dataStreamMultiplier", dataStreamMultiplier);
eventData.uintItems.setItem(1, "dataStreamSpreadReductionFactor", dataStreamSpreadReductionFactor);
eventEmitter.emitEventLog1(
"ConfigSetDataStream",
Cast.toBytes32(token),
eventData
);
}
function setClaimableCollateralFactorForTime(
address market,
address token,
uint256 timeKey,
uint256 factor
) external onlyConfigKeeper nonReentrant {
if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }
bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey);
dataStore.setUint(key, factor);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "timeKey", timeKey);
eventData.uintItems.setItem(1, "factor", factor);
eventEmitter.emitEventLog2(
"SetClaimableCollateralFactorForTime",
Cast.toBytes32(market),
Cast.toBytes32(token),
eventData
);
}
function setClaimableCollateralFactorForAccount(
address market,
address token,
uint256 timeKey,
address account,
uint256 factor
) external onlyConfigKeeper nonReentrant {
if (factor > Precision.FLOAT_PRECISION) { revert Errors.InvalidClaimableFactor(factor); }
bytes32 key = Keys.claimableCollateralFactorKey(market, token, timeKey, account);
dataStore.setUint(key, factor);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "timeKey", timeKey);
eventData.uintItems.setItem(1, "factor", factor);
eventEmitter.emitEventLog2(
"SetClaimableCollateralFactorForAccount",
Cast.toBytes32(market),
Cast.toBytes32(token),
eventData
);
}
function setPositionImpactDistributionRate(
address market,
uint256 minPositionImpactPoolAmount,
uint256 positionImpactPoolDistributionRate
) external onlyConfigKeeper nonReentrant {
MarketUtils.distributePositionImpactPool(dataStore, eventEmitter, market);
dataStore.setUint(Keys.minPositionImpactPoolAmountKey(market), minPositionImpactPoolAmount);
dataStore.setUint(Keys.positionImpactPoolDistributionRateKey(market), positionImpactPoolDistributionRate);
dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "minPositionImpactPoolAmount", minPositionImpactPoolAmount);
eventData.uintItems.setItem(1, "positionImpactPoolDistributionRate", positionImpactPoolDistributionRate);
eventEmitter.emitEventLog1(
"SetPositionImpactPoolDistributionRate",
Cast.toBytes32(market),
eventData
);
}
function setBool(bytes32 baseKey, bytes memory data, bool value) external onlyKeeper nonReentrant {
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
dataStore.setBool(fullKey, value);
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "baseKey", baseKey);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "data", data);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "value", value);
eventEmitter.emitEventLog1(
"SetBool",
baseKey,
eventData
);
}
function setAddress(bytes32 baseKey, bytes memory data, address value) external onlyKeeper nonReentrant {
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
dataStore.setAddress(fullKey, value);
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "baseKey", baseKey);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "data", data);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "value", value);
eventEmitter.emitEventLog1(
"SetAddress",
baseKey,
eventData
);
}
function setBytes32(bytes32 baseKey, bytes memory data, bytes32 value) external onlyKeeper nonReentrant {
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
dataStore.setBytes32(fullKey, value);
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(2);
eventData.bytes32Items.setItem(0, "baseKey", baseKey);
eventData.bytes32Items.setItem(1, "value", value);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "data", data);
eventEmitter.emitEventLog1(
"SetBytes32",
baseKey,
eventData
);
}
function setUint(bytes32 baseKey, bytes memory data, uint256 value) external onlyKeeper nonReentrant {
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
_validateRange(baseKey, data, value);
dataStore.setUint(fullKey, value);
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "baseKey", baseKey);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "data", data);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "value", value);
eventEmitter.emitEventLog1(
"SetUint",
baseKey,
eventData
);
}
function setInt(bytes32 baseKey, bytes memory data, int256 value) external onlyKeeper nonReentrant {
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
dataStore.setInt(fullKey, value);
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "baseKey", baseKey);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "data", data);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "value", value);
eventEmitter.emitEventLog1(
"SetInt",
baseKey,
eventData
);
}
function _initAllowedBaseKeys() internal {
allowedBaseKeys[Keys.HOLDING_ADDRESS] = true;
allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS] = true;
allowedBaseKeys[Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD] = true;
allowedBaseKeys[Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION] = true;
allowedBaseKeys[Keys.IS_MARKET_DISABLED] = true;
allowedBaseKeys[Keys.MAX_SWAP_PATH_LENGTH] = true;
allowedBaseKeys[Keys.MAX_CALLBACK_GAS_LIMIT] = true;
allowedBaseKeys[Keys.REFUND_EXECUTION_FEE_GAS_LIMIT] = true;
allowedBaseKeys[Keys.MIN_POSITION_SIZE_USD] = true;
allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS] = true;
allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;
allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
allowedBaseKeys[Keys.MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT] = true;
allowedBaseKeys[Keys.CREATE_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_SHIFT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_SHIFT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_SHIFT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_ORDER_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_ORDER_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_ADL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.UPDATE_ORDER_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_ORDER_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_GLV_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_GLV_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CREATE_GLV_SHIFT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.EXECUTE_GLV_SHIFT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CLAIM_FUNDING_FEES_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CLAIM_COLLATERAL_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.CLAIM_UI_FEES_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.MIN_AFFILIATE_REWARD_FACTOR] = true;
allowedBaseKeys[Keys.SUBACCOUNT_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS] = true;
allowedBaseKeys[Keys.MAX_ORACLE_PRICE_AGE] = true;
allowedBaseKeys[Keys.MAX_ORACLE_TIMESTAMP_RANGE] = true;
allowedBaseKeys[Keys.ORACLE_TIMESTAMP_ADJUSTMENT] = true;
allowedBaseKeys[Keys.CHAINLINK_PAYMENT_TOKEN] = true;
allowedBaseKeys[Keys.SEQUENCER_GRACE_DURATION] = true;
allowedBaseKeys[Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR] = true;
allowedBaseKeys[Keys.POSITION_FEE_RECEIVER_FACTOR] = true;
allowedBaseKeys[Keys.LIQUIDATION_FEE_RECEIVER_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_FEE_RECEIVER_FACTOR] = true;
allowedBaseKeys[Keys.BORROWING_FEE_RECEIVER_FACTOR] = true;
allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;
allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;
allowedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;
allowedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;
allowedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;
allowedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;
allowedBaseKeys[Keys.DEPOSIT_GAS_LIMIT] = true;
allowedBaseKeys[Keys.WITHDRAWAL_GAS_LIMIT] = true;
allowedBaseKeys[Keys.GLV_DEPOSIT_GAS_LIMIT] = true;
allowedBaseKeys[Keys.GLV_WITHDRAWAL_GAS_LIMIT] = true;
allowedBaseKeys[Keys.GLV_SHIFT_GAS_LIMIT] = true;
allowedBaseKeys[Keys.GLV_PER_MARKET_GAS_LIMIT] = true;
allowedBaseKeys[Keys.SHIFT_GAS_LIMIT] = true;
allowedBaseKeys[Keys.SINGLE_SWAP_GAS_LIMIT] = true;
allowedBaseKeys[Keys.INCREASE_ORDER_GAS_LIMIT] = true;
allowedBaseKeys[Keys.DECREASE_ORDER_GAS_LIMIT] = true;
allowedBaseKeys[Keys.SWAP_ORDER_GAS_LIMIT] = true;
allowedBaseKeys[Keys.TOKEN_TRANSFER_GAS_LIMIT] = true;
allowedBaseKeys[Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT] = true;
allowedBaseKeys[Keys.REQUEST_EXPIRATION_TIME] = true;
allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR] = true;
allowedBaseKeys[Keys.MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER] = true;
allowedBaseKeys[Keys.MIN_COLLATERAL_USD] = true;
allowedBaseKeys[Keys.VIRTUAL_TOKEN_ID] = true;
allowedBaseKeys[Keys.VIRTUAL_MARKET_ID] = true;
allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_SWAPS] = true;
allowedBaseKeys[Keys.VIRTUAL_INVENTORY_FOR_POSITIONS] = true;
allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.MAX_POSITION_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.POSITION_FEE_FACTOR] = true;
allowedBaseKeys[Keys.PRO_DISCOUNT_FACTOR] = true;
allowedBaseKeys[Keys.PRO_TRADER_TIER] = true;
allowedBaseKeys[Keys.LIQUIDATION_FEE_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_FEE_FACTOR] = true;
allowedBaseKeys[Keys.DEPOSIT_FEE_FACTOR] = true;
allowedBaseKeys[Keys.WITHDRAWAL_FEE_FACTOR] = true;
allowedBaseKeys[Keys.ATOMIC_SWAP_FEE_FACTOR] = true;
allowedBaseKeys[Keys.MAX_UI_FEE_FACTOR] = true;
allowedBaseKeys[Keys.MAX_AUTO_CANCEL_ORDERS] = true;
allowedBaseKeys[Keys.MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS] = true;
allowedBaseKeys[Keys.ORACLE_TYPE] = true;
allowedBaseKeys[Keys.RESERVE_FACTOR] = true;
allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true;
allowedBaseKeys[Keys.MAX_PNL_FACTOR] = true;
allowedBaseKeys[Keys.MIN_PNL_FACTOR_AFTER_ADL] = true;
allowedBaseKeys[Keys.FUNDING_FACTOR] = true;
allowedBaseKeys[Keys.FUNDING_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.THRESHOLD_FOR_STABLE_FUNDING] = true;
allowedBaseKeys[Keys.THRESHOLD_FOR_DECREASE_FUNDING] = true;
allowedBaseKeys[Keys.IGNORE_OPEN_INTEREST_FOR_USAGE_FACTOR] = true;
allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true;
allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE] = true;
allowedBaseKeys[Keys.PRICE_FEED_HEARTBEAT_DURATION] = true;
allowedBaseKeys[Keys.IS_GLV_MARKET_DISABLED] = true;
allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_USD] = true;
allowedBaseKeys[Keys.GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT] = true;
allowedBaseKeys[Keys.GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.GLV_SHIFT_MIN_INTERVAL] = true;
allowedBaseKeys[Keys.MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT] = true;
allowedBaseKeys[Keys.GLV_MAX_MARKET_COUNT] = true;
allowedBaseKeys[Keys.SYNC_CONFIG_FEATURE_DISABLED] = true;
allowedBaseKeys[Keys.SYNC_CONFIG_MARKET_DISABLED] = true;
allowedBaseKeys[Keys.SYNC_CONFIG_PARAMETER_DISABLED] = true;
allowedBaseKeys[Keys.SYNC_CONFIG_MARKET_PARAMETER_DISABLED] = true;
allowedBaseKeys[Keys.BUYBACK_BATCH_AMOUNT] = true;
allowedBaseKeys[Keys.BUYBACK_GMX_FACTOR] = true;
allowedBaseKeys[Keys.BUYBACK_MAX_PRICE_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.BUYBACK_MAX_PRICE_AGE] = true;
allowedBaseKeys[Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR] = true;
}
function _initAllowedLimitedBaseKeys() internal {
allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1] = true;
allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_PER_ORACLE_PRICE] = true;
allowedLimitedBaseKeys[Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR] = true;
allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1] = true;
allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_PER_ORACLE_PRICE] = true;
allowedLimitedBaseKeys[Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR] = true;
allowedLimitedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;
allowedLimitedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;
allowedLimitedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;
allowedLimitedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;
allowedLimitedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;
allowedLimitedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
allowedLimitedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
allowedLimitedBaseKeys[Keys.PRO_TRADER_TIER] = true;
}
function _validateKey(bytes32 baseKey) internal view {
if (roleStore.hasRole(msg.sender, Role.CONFIG_KEEPER)) {
if (!allowedBaseKeys[baseKey]) {
revert Errors.InvalidBaseKey(baseKey);
}
return;
}
if (roleStore.hasRole(msg.sender, Role.LIMITED_CONFIG_KEEPER)) {
if (!allowedLimitedBaseKeys[baseKey]) {
revert Errors.InvalidBaseKey(baseKey);
}
return;
}
revert Errors.InvalidBaseKey(baseKey);
}
function _validateRange(bytes32 baseKey, bytes memory data, uint256 value) internal view {
if (
baseKey == Keys.SEQUENCER_GRACE_DURATION
) {
if (value > 7200) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.MAX_FUNDING_FACTOR_PER_SECOND
) {
if (value > MAX_ALLOWED_MAX_FUNDING_FACTOR_PER_SECOND) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
bytes32 minFundingFactorPerSecondKey = Keys.getFullKey(Keys.MIN_FUNDING_FACTOR_PER_SECOND, data);
uint256 minFundingFactorPerSecond = dataStore.getUint(minFundingFactorPerSecondKey);
if (value < minFundingFactorPerSecond) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.MIN_FUNDING_FACTOR_PER_SECOND
) {
bytes32 maxFundingFactorPerSecondKey = Keys.getFullKey(Keys.MAX_FUNDING_FACTOR_PER_SECOND, data);
uint256 maxFundingFactorPerSecond = dataStore.getUint(maxFundingFactorPerSecondKey);
if (value > maxFundingFactorPerSecond) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND
) {
if (value > MAX_ALLOWED_FUNDING_INCREASE_FACTOR_PER_SECOND) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND
) {
if (value > MAX_ALLOWED_FUNDING_DECREASE_FACTOR_PER_SECOND) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.BORROWING_FACTOR ||
baseKey == Keys.BASE_BORROWING_FACTOR
) {
if (value > 50000000000000000000000) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (baseKey == Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR) {
if (value > 100000000000000000000000) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.FUNDING_EXPONENT_FACTOR ||
baseKey == Keys.BORROWING_EXPONENT_FACTOR
) {
if (value > 2 * Precision.FLOAT_PRECISION) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.POSITION_IMPACT_EXPONENT_FACTOR ||
baseKey == Keys.SWAP_IMPACT_EXPONENT_FACTOR
) {
if (value > 3 * Precision.FLOAT_PRECISION) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.FUNDING_FACTOR ||
baseKey == Keys.BORROWING_FACTOR ||
baseKey == Keys.FUNDING_INCREASE_FACTOR_PER_SECOND ||
baseKey == Keys.FUNDING_DECREASE_FACTOR_PER_SECOND ||
baseKey == Keys.MIN_COLLATERAL_FACTOR
) {
if (value > 1 * Precision.FLOAT_PRECISION / 100) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.SWAP_FEE_FACTOR ||
baseKey == Keys.DEPOSIT_FEE_FACTOR ||
baseKey == Keys.WITHDRAWAL_FEE_FACTOR ||
baseKey == Keys.POSITION_FEE_FACTOR ||
baseKey == Keys.MAX_UI_FEE_FACTOR ||
baseKey == Keys.ATOMIC_SWAP_FEE_FACTOR ||
baseKey == Keys.BUYBACK_MAX_PRICE_IMPACT_FACTOR
) {
if (value > 5 * Precision.FLOAT_PRECISION / 100) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (baseKey == Keys.LIQUIDATION_FEE_FACTOR) {
if (value > Precision.FLOAT_PRECISION / 100) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (baseKey == Keys.MIN_COLLATERAL_USD) {
if (value > 10 * Precision.FLOAT_PRECISION) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
if (
baseKey == Keys.POSITION_FEE_RECEIVER_FACTOR ||
baseKey == Keys.SWAP_FEE_RECEIVER_FACTOR ||
baseKey == Keys.BORROWING_FEE_RECEIVER_FACTOR ||
baseKey == Keys.LIQUIDATION_FEE_RECEIVER_FACTOR ||
baseKey == Keys.MAX_PNL_FACTOR ||
baseKey == Keys.MIN_PNL_FACTOR_AFTER_ADL ||
baseKey == Keys.OPTIMAL_USAGE_FACTOR ||
baseKey == Keys.PRO_DISCOUNT_FACTOR ||
baseKey == Keys.BUYBACK_GMX_FACTOR ||
baseKey == Keys.DATA_STREAM_SPREAD_REDUCTION_FACTOR
) {
if (value > Precision.FLOAT_PRECISION) {
revert Errors.ConfigValueExceedsAllowedRange(baseKey, value);
}
}
}
}
文件 15 的 57:ConfigSyncer.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "./Config.sol";
import "./IRiskOracle.sol";
import "../feature/FeatureUtils.sol";
contract ConfigSyncer is ReentrancyGuard, RoleModule {
using EventUtils for EventUtils.UintItems;
using EventUtils for EventUtils.BoolItems;
Config public immutable config;
DataStore public immutable dataStore;
EventEmitter public immutable eventEmitter;
address public immutable riskOracle;
mapping(bytes32 => bool) public allowedBaseKeys;
constructor(
RoleStore _roleStore,
Config _config,
DataStore _dataStore,
EventEmitter _eventEmitter,
address _riskOracle
) RoleModule(_roleStore) {
config = _config;
dataStore = _dataStore;
eventEmitter = _eventEmitter;
riskOracle = _riskOracle;
_initAllowedBaseKeys();
}
function sync(
address[] calldata markets,
string[] calldata parameters
) external onlyLimitedConfigKeeper nonReentrant {
FeatureUtils.validateFeature(dataStore, Keys.syncConfigFeatureDisabledKey(address(this)));
if (markets.length != parameters.length) {
revert Errors.SyncConfigInvalidInputLengths(markets.length, parameters.length);
}
uint256 latestUpdateId = dataStore.getUint(Keys.syncConfigLatestUpdateIdKey());
for (uint256 i; i < markets.length; i++) {
address market = markets[i];
string memory parameter = parameters[i];
bool updateApplied;
bool syncConfigMarketDisabled = dataStore.getBool(Keys.syncConfigMarketDisabledKey(market));
if (syncConfigMarketDisabled) {
revert Errors.SyncConfigUpdatesDisabledForMarket(market);
}
bool syncConfigparameterDisabled = dataStore.getBool(Keys.syncConfigParameterDisabledKey(parameter));
if (syncConfigparameterDisabled) {
revert Errors.SyncConfigUpdatesDisabledForParameter(parameter);
}
bool syncConfigMarketParameterDisabled = dataStore.getBool(
Keys.syncConfigMarketParameterDisabledKey(market, parameter)
);
if (syncConfigMarketParameterDisabled) {
revert Errors.SyncConfigUpdatesDisabledForMarketParameter(market, parameter);
}
IRiskOracle.RiskParameterUpdate memory riskParameterUpdate = IRiskOracle(riskOracle)
.getLatestUpdateByParameterAndMarket(parameter, market);
uint256 updateId = riskParameterUpdate.updateId;
(bytes32 baseKey, bytes memory data) = abi.decode(riskParameterUpdate.additionalData, (bytes32, bytes));
_validateMarketInData(baseKey, market, data);
_validateKey(baseKey);
bytes32 fullKey = Keys.getFullKey(baseKey, data);
uint256 prevValue = dataStore.getUint(fullKey);
uint256 updatedValue = Cast.bytesToUint256(riskParameterUpdate.newValue);
bool syncConfigUpdateCompleted = dataStore.getBool(Keys.syncConfigUpdateCompletedKey(updateId));
if (!syncConfigUpdateCompleted) {
config.setUint(baseKey, data, updatedValue);
dataStore.setBool(Keys.syncConfigUpdateCompletedKey(updateId), true);
updateApplied = true;
if (updateId > latestUpdateId) {
latestUpdateId = updateId;
}
}
EventUtils.EventLogData memory eventData;
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "updateId", updateId);
eventData.uintItems.setItem(1, "prevValue", prevValue);
eventData.uintItems.setItem(2, "nextValue", updatedValue);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "updateApplied", updateApplied);
eventEmitter.emitEventLog("SyncConfig", eventData);
}
if (latestUpdateId > dataStore.getUint(Keys.syncConfigLatestUpdateIdKey())) {
dataStore.setUint(Keys.syncConfigLatestUpdateIdKey(), latestUpdateId);
}
}
function _initAllowedBaseKeys() internal {
allowedBaseKeys[Keys.MAX_POOL_AMOUNT] = true;
allowedBaseKeys[Keys.MAX_POOL_USD_FOR_DEPOSIT] = true;
allowedBaseKeys[Keys.MAX_OPEN_INTEREST] = true;
allowedBaseKeys[Keys.POSITION_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.POSITION_IMPACT_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_IMPACT_FACTOR] = true;
allowedBaseKeys[Keys.SWAP_IMPACT_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.FUNDING_INCREASE_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.FUNDING_DECREASE_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.MIN_FUNDING_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.MAX_FUNDING_FACTOR_PER_SECOND] = true;
allowedBaseKeys[Keys.OPTIMAL_USAGE_FACTOR] = true;
allowedBaseKeys[Keys.BASE_BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.BORROWING_FACTOR] = true;
allowedBaseKeys[Keys.BORROWING_EXPONENT_FACTOR] = true;
allowedBaseKeys[Keys.RESERVE_FACTOR] = true;
allowedBaseKeys[Keys.OPEN_INTEREST_RESERVE_FACTOR] = true;
}
function _validateKey(bytes32 baseKey) internal view {
if (!allowedBaseKeys[baseKey]) {
revert Errors.InvalidBaseKey(baseKey);
}
}
function _validateMarketInData(bytes32 baseKey, address market, bytes memory data) internal pure {
address marketFromData;
if (baseKey == Keys.MAX_PNL_FACTOR) {
(, marketFromData , ) = abi.decode(data, (bytes32, address, bool));
} else {
marketFromData = abi.decode(data, (address));
}
if (market != marketFromData) {
revert Errors.SyncConfigInvalidMarketFromData(market, marketFromData);
}
}
}
文件 16 的 57:Context.sol
pragma solidity ^0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
文件 17 的 57:DataStore.sol
pragma solidity ^0.8.0;
import "../role/RoleModule.sol";
import "../utils/Calc.sol";
contract DataStore is RoleModule {
using SafeCast for int256;
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.UintSet;
using EnumerableValues for EnumerableSet.Bytes32Set;
using EnumerableValues for EnumerableSet.AddressSet;
using EnumerableValues for EnumerableSet.UintSet;
mapping(bytes32 => uint256) public uintValues;
mapping(bytes32 => int256) public intValues;
mapping(bytes32 => address) public addressValues;
mapping(bytes32 => bool) public boolValues;
mapping(bytes32 => string) public stringValues;
mapping(bytes32 => bytes32) public bytes32Values;
mapping(bytes32 => uint256[]) public uintArrayValues;
mapping(bytes32 => int256[]) public intArrayValues;
mapping(bytes32 => address[]) public addressArrayValues;
mapping(bytes32 => bool[]) public boolArrayValues;
mapping(bytes32 => string[]) public stringArrayValues;
mapping(bytes32 => bytes32[]) public bytes32ArrayValues;
mapping(bytes32 => EnumerableSet.Bytes32Set) internal bytes32Sets;
mapping(bytes32 => EnumerableSet.AddressSet) internal addressSets;
mapping(bytes32 => EnumerableSet.UintSet) internal uintSets;
constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
function getUint(bytes32 key) external view returns (uint256) {
return uintValues[key];
}
function setUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
uintValues[key] = value;
return value;
}
function removeUint(bytes32 key) external onlyController {
delete uintValues[key];
}
function applyDeltaToUint(bytes32 key, int256 value, string memory errorMessage) external onlyController returns (uint256) {
uint256 currValue = uintValues[key];
if (value < 0 && (-value).toUint256() > currValue) {
revert(errorMessage);
}
uint256 nextUint = Calc.sumReturnUint256(currValue, value);
uintValues[key] = nextUint;
return nextUint;
}
function applyDeltaToUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
uint256 currValue = uintValues[key];
uint256 nextUint = currValue + value;
uintValues[key] = nextUint;
return nextUint;
}
function applyBoundedDeltaToUint(bytes32 key, int256 value) external onlyController returns (uint256) {
uint256 uintValue = uintValues[key];
if (value < 0 && (-value).toUint256() > uintValue) {
uintValues[key] = 0;
return 0;
}
uint256 nextUint = Calc.sumReturnUint256(uintValue, value);
uintValues[key] = nextUint;
return nextUint;
}
function incrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
uint256 nextUint = uintValues[key] + value;
uintValues[key] = nextUint;
return nextUint;
}
function decrementUint(bytes32 key, uint256 value) external onlyController returns (uint256) {
uint256 nextUint = uintValues[key] - value;
uintValues[key] = nextUint;
return nextUint;
}
function getInt(bytes32 key) external view returns (int256) {
return intValues[key];
}
function setInt(bytes32 key, int256 value) external onlyController returns (int256) {
intValues[key] = value;
return value;
}
function removeInt(bytes32 key) external onlyController {
delete intValues[key];
}
function applyDeltaToInt(bytes32 key, int256 value) external onlyController returns (int256) {
int256 nextInt = intValues[key] + value;
intValues[key] = nextInt;
return nextInt;
}
function incrementInt(bytes32 key, int256 value) external onlyController returns (int256) {
int256 nextInt = intValues[key] + value;
intValues[key] = nextInt;
return nextInt;
}
function decrementInt(bytes32 key, int256 value) external onlyController returns (int256) {
int256 nextInt = intValues[key] - value;
intValues[key] = nextInt;
return nextInt;
}
function getAddress(bytes32 key) external view returns (address) {
return addressValues[key];
}
function setAddress(bytes32 key, address value) external onlyController returns (address) {
addressValues[key] = value;
return value;
}
function removeAddress(bytes32 key) external onlyController {
delete addressValues[key];
}
function getBool(bytes32 key) external view returns (bool) {
return boolValues[key];
}
function setBool(bytes32 key, bool value) external onlyController returns (bool) {
boolValues[key] = value;
return value;
}
function removeBool(bytes32 key) external onlyController {
delete boolValues[key];
}
function getString(bytes32 key) external view returns (string memory) {
return stringValues[key];
}
function setString(bytes32 key, string memory value) external onlyController returns (string memory) {
stringValues[key] = value;
return value;
}
function removeString(bytes32 key) external onlyController {
delete stringValues[key];
}
function getBytes32(bytes32 key) external view returns (bytes32) {
return bytes32Values[key];
}
function setBytes32(bytes32 key, bytes32 value) external onlyController returns (bytes32) {
bytes32Values[key] = value;
return value;
}
function removeBytes32(bytes32 key) external onlyController {
delete bytes32Values[key];
}
function getUintArray(bytes32 key) external view returns (uint256[] memory) {
return uintArrayValues[key];
}
function setUintArray(bytes32 key, uint256[] memory value) external onlyController {
uintArrayValues[key] = value;
}
function removeUintArray(bytes32 key) external onlyController {
delete uintArrayValues[key];
}
function getIntArray(bytes32 key) external view returns (int256[] memory) {
return intArrayValues[key];
}
function setIntArray(bytes32 key, int256[] memory value) external onlyController {
intArrayValues[key] = value;
}
function removeIntArray(bytes32 key) external onlyController {
delete intArrayValues[key];
}
function getAddressArray(bytes32 key) external view returns (address[] memory) {
return addressArrayValues[key];
}
function setAddressArray(bytes32 key, address[] memory value) external onlyController {
addressArrayValues[key] = value;
}
function removeAddressArray(bytes32 key) external onlyController {
delete addressArrayValues[key];
}
function getBoolArray(bytes32 key) external view returns (bool[] memory) {
return boolArrayValues[key];
}
function setBoolArray(bytes32 key, bool[] memory value) external onlyController {
boolArrayValues[key] = value;
}
function removeBoolArray(bytes32 key) external onlyController {
delete boolArrayValues[key];
}
function getStringArray(bytes32 key) external view returns (string[] memory) {
return stringArrayValues[key];
}
function setStringArray(bytes32 key, string[] memory value) external onlyController {
stringArrayValues[key] = value;
}
function removeStringArray(bytes32 key) external onlyController {
delete stringArrayValues[key];
}
function getBytes32Array(bytes32 key) external view returns (bytes32[] memory) {
return bytes32ArrayValues[key];
}
function setBytes32Array(bytes32 key, bytes32[] memory value) external onlyController {
bytes32ArrayValues[key] = value;
}
function removeBytes32Array(bytes32 key) external onlyController {
delete bytes32ArrayValues[key];
}
function containsBytes32(bytes32 setKey, bytes32 value) external view returns (bool) {
return bytes32Sets[setKey].contains(value);
}
function getBytes32Count(bytes32 setKey) external view returns (uint256) {
return bytes32Sets[setKey].length();
}
function getBytes32ValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (bytes32[] memory) {
return bytes32Sets[setKey].valuesAt(start, end);
}
function addBytes32(bytes32 setKey, bytes32 value) external onlyController {
bytes32Sets[setKey].add(value);
}
function removeBytes32(bytes32 setKey, bytes32 value) external onlyController {
bytes32Sets[setKey].remove(value);
}
function containsAddress(bytes32 setKey, address value) external view returns (bool) {
return addressSets[setKey].contains(value);
}
function getAddressCount(bytes32 setKey) external view returns (uint256) {
return addressSets[setKey].length();
}
function getAddressValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (address[] memory) {
return addressSets[setKey].valuesAt(start, end);
}
function addAddress(bytes32 setKey, address value) external onlyController {
addressSets[setKey].add(value);
}
function removeAddress(bytes32 setKey, address value) external onlyController {
addressSets[setKey].remove(value);
}
function containsUint(bytes32 setKey, uint256 value) external view returns (bool) {
return uintSets[setKey].contains(value);
}
function getUintCount(bytes32 setKey) external view returns (uint256) {
return uintSets[setKey].length();
}
function getUintValuesAt(bytes32 setKey, uint256 start, uint256 end) external view returns (uint256[] memory) {
return uintSets[setKey].valuesAt(start, end);
}
function addUint(bytes32 setKey, uint256 value) external onlyController {
uintSets[setKey].add(value);
}
function removeUint(bytes32 setKey, uint256 value) external onlyController {
uintSets[setKey].remove(value);
}
}
文件 18 的 57:ERC20.sol
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
function name() public view virtual override returns (string memory) {
return _name;
}
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
function decimals() public view virtual override returns (uint8) {
return 18;
}
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
function _transfer(address from, address to, uint256 amount) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}
function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
文件 19 的 57:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 20 的 57:EnumerableValues.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
library EnumerableValues {
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.UintSet;
function valuesAt(EnumerableSet.Bytes32Set storage set, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
uint256 max = set.length();
if (end > max) { end = max; }
bytes32[] memory items = new bytes32[](end - start);
for (uint256 i = start; i < end; i++) {
items[i - start] = set.at(i);
}
return items;
}
function valuesAt(EnumerableSet.AddressSet storage set, uint256 start, uint256 end) internal view returns (address[] memory) {
uint256 max = set.length();
if (end > max) { end = max; }
address[] memory items = new address[](end - start);
for (uint256 i = start; i < end; i++) {
items[i - start] = set.at(i);
}
return items;
}
function valuesAt(EnumerableSet.UintSet storage set, uint256 start, uint256 end) internal view returns (uint256[] memory) {
if (start >= set.length()) {
return new uint256[](0);
}
uint256 max = set.length();
if (end > max) { end = max; }
uint256[] memory items = new uint256[](end - start);
for (uint256 i = start; i < end; i++) {
items[i - start] = set.at(i);
}
return items;
}
}
文件 21 的 57:ErrorUtils.sol
pragma solidity ^0.8.0;
library ErrorUtils {
function getRevertMessage(bytes memory result) internal pure returns (string memory, bool) {
if (result.length < 68) {
return ("", false);
}
bytes4 errorSelector = getErrorSelectorFromData(result);
if (errorSelector == bytes4(0x08c379a0)) {
assembly {
result := add(result, 0x04)
}
return (abi.decode(result, (string)), true);
}
return ("", false);
}
function getErrorSelectorFromData(bytes memory data) internal pure returns (bytes4) {
bytes4 errorSelector;
assembly {
errorSelector := mload(add(data, 0x20))
}
return errorSelector;
}
function revertWithParsedMessage(bytes memory result) internal pure {
(string memory revertMessage, bool hasRevertMessage) = getRevertMessage(result);
if (hasRevertMessage) {
revert(revertMessage);
} else {
revertWithCustomError(result);
}
}
function revertWithCustomError(bytes memory result) internal pure {
uint256 length = result.length;
assembly {
revert(add(result, 0x20), length)
}
}
}
文件 22 的 57:Errors.sol
pragma solidity ^0.8.0;
library Errors {
error AdlNotRequired(int256 pnlToPoolFactor, uint256 maxPnlFactorForAdl);
error InvalidAdl(int256 nextPnlToPoolFactor, int256 pnlToPoolFactor);
error PnlOvercorrected(int256 nextPnlToPoolFactor, uint256 minPnlFactorForAdl);
error InvalidSizeDeltaForAdl(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);
error AdlNotEnabled();
error MaxAutoCancelOrdersExceeded(uint256 count, uint256 maxAutoCancelOrders);
error SelfTransferNotSupported(address receiver);
error InvalidNativeTokenSender(address msgSender);
error RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);
error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);
error InsufficientGasLeftForCallback(uint256 gasToBeForwarded, uint256 callbackGasLimit);
error InvalidBaseKey(bytes32 baseKey);
error ConfigValueExceedsAllowedRange(bytes32 baseKey, uint256 value);
error InvalidClaimableFactor(uint256 value);
error OracleProviderAlreadyExistsForToken(address token);
error PriceFeedAlreadyExistsForToken(address token);
error DataStreamIdAlreadyExistsForToken(address token);
error MaxFundingFactorPerSecondLimitExceeded(uint256 maxFundingFactorPerSecond, uint256 limit);
error InvalidSetContributorPaymentInput(uint256 tokensLength, uint256 amountsLength);
error InvalidContributorToken(address token);
error MaxTotalContributorTokenAmountExceeded(address token, uint256 totalAmount, uint256 maxTotalAmount);
error MinContributorPaymentIntervalNotYetPassed(uint256 minPaymentInterval);
error MinContributorPaymentIntervalBelowAllowedRange(uint256 interval);
error InvalidSetMaxTotalContributorTokenAmountInput(uint256 tokensLength, uint256 amountsLength);
error ActionAlreadySignalled();
error ActionNotSignalled();
error SignalTimeNotYetPassed(uint256 signalTime);
error InvalidTimelockDelay(uint256 timelockDelay);
error MaxTimelockDelayExceeded(uint256 timelockDelay);
error InvalidFeeReceiver(address receiver);
error InvalidOracleSigner(address receiver);
error GlvDepositNotFound(bytes32 key);
error GlvShiftNotFound(bytes32 key);
error GlvWithdrawalNotFound(bytes32 key);
error EmptyGlvDepositAmounts();
error EmptyGlvMarketAmount();
error EmptyGlvDeposit();
error InvalidMinGlvTokensForFirstGlvDeposit(uint256 minGlvTokens, uint256 expectedMinGlvTokens);
error InvalidReceiverForFirstGlvDeposit(address receiver, address expectedReceiver);
error EmptyGlvWithdrawal();
error EmptyGlvWithdrawalAmount();
error EmptyGlv(address glv);
error EmptyGlvTokenSupply();
error GlvNegativeMarketPoolValue(address glv, address market);
error GlvUnsupportedMarket(address glv, address market);
error GlvDisabledMarket(address glv, address market);
error GlvEnabledMarket(address glv, address market);
error GlvNonZeroMarketBalance(address glv, address market);
error GlvMaxMarketCountExceeded(address glv, uint256 glvMaxMarketCount);
error GlvMaxMarketTokenBalanceUsdExceeded(address glv, address market, uint256 maxMarketTokenBalanceUsd, uint256 marketTokenBalanceUsd);
error GlvMaxMarketTokenBalanceAmountExceeded(address glv, address market, uint256 maxMarketTokenBalanceAmount, uint256 marketTokenBalanceAmount);
error GlvInsufficientMarketTokenBalance(address glv, address market, uint256 marketTokenBalance, uint256 marketTokenAmount);
error GlvMarketAlreadyExists(address glv, address market);
error GlvInvalidLongToken(address glv, address provided, address expected);
error GlvInvalidShortToken(address glv, address provided, address expected);
error GlvShiftMaxPriceImpactExceeded(uint256 effectivePriceImpactFactor, uint256 glvMaxShiftPriceImpactFactor);
error GlvShiftIntervalNotYetPassed(uint256 currentTimestamp, uint256 lastGlvShiftExecutedAt, uint256 glvShiftMinInterval);
error GlvAlreadyExists(bytes32 salt, address glv);
error GlvSymbolTooLong();
error GlvNameTooLong();
error GlvNotFound(address key);
error DepositNotFound(bytes32 key);
error EmptyDeposit();
error EmptyDepositAmounts();
error MinMarketTokens(uint256 received, uint256 expected);
error EmptyDepositAmountsAfterSwap();
error InvalidPoolValueForDeposit(int256 poolValue);
error InvalidSwapOutputToken(address outputToken, address expectedOutputToken);
error InvalidReceiverForFirstDeposit(address receiver, address expectedReceiver);
error InvalidMinMarketTokensForFirstDeposit(uint256 minMarketTokens, uint256 expectedMinMarketTokens);
error ExternalCallFailed(bytes data);
error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);
error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);
error InvalidExternalCallTarget(address target);
error FeeBatchNotFound(bytes32 key);
error InvalidFeeBatchTokenIndex(uint256 tokenIndex, uint256 feeBatchTokensLength);
error InvalidAmountInForFeeBatch(uint256 amountIn, uint256 remainingAmount);
error InvalidSwapPathForV1(address[] path, address bridgingToken);
error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);
error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);
error InvalidGlvDepositInitialLongToken(address initialLongToken);
error InvalidGlvDepositInitialShortToken(address initialShortToken);
error InvalidGlvDepositSwapPath(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);
error MinGlvTokens(uint256 received, uint256 expected);
error OrderNotUpdatable(uint256 orderType);
error InvalidKeeperForFrozenOrder(address keeper);
error DisabledFeature(bytes32 key);
error InvalidBuybackToken(address buybackToken);
error InvalidVersion(uint256 version);
error InsufficientBuybackOutputAmount(address feeToken, address buybackToken, uint256 outputAmount, uint256 minOutputAmount);
error BuybackAndFeeTokenAreEqual(address feeToken, address buybackToken);
error AvailableFeeAmountIsZero(address feeToken, address buybackToken, uint256 availableFeeAmount);
error MaxBuybackPriceAgeExceeded(uint256 priceTimestamp, uint256 buybackMaxPriceAge, uint256 currentTimestamp);
error EmptyClaimFeesMarket();
error InsufficientExecutionFee(uint256 minExecutionFee, uint256 executionFee);
error InsufficientWntAmountForExecutionFee(uint256 wntAmount, uint256 executionFee);
error InsufficientExecutionGasForErrorHandling(uint256 startingGas, uint256 minHandleErrorGas);
error InsufficientExecutionGas(uint256 startingGas, uint256 estimatedGasLimit, uint256 minAdditionalGasForExecution);
error InsufficientHandleExecutionErrorGas(uint256 gas, uint256 minHandleExecutionErrorGas);
error InsufficientGasForCancellation(uint256 gas, uint256 minHandleExecutionErrorGas);
error MarketAlreadyExists(bytes32 salt, address existingMarketAddress);
error MarketNotFound(address key);
error EmptyMarket();
error DisabledMarket(address market);
error MaxSwapPathLengthExceeded(uint256 swapPathLengh, uint256 maxSwapPathLength);
error InsufficientPoolAmount(uint256 poolAmount, uint256 amount);
error InsufficientReserve(uint256 reservedUsd, uint256 maxReservedUsd);
error InsufficientReserveForOpenInterest(uint256 reservedUsd, uint256 maxReservedUsd);
error UnableToGetOppositeToken(address inputToken, address market);
error UnexpectedTokenForVirtualInventory(address token, address market);
error EmptyMarketTokenSupply();
error InvalidSwapMarket(address market);
error UnableToGetCachedTokenPrice(address token, address market);
error CollateralAlreadyClaimed(uint256 adjustedClaimableAmount, uint256 claimedAmount);
error OpenInterestCannotBeUpdatedForSwapOnlyMarket(address market);
error MaxOpenInterestExceeded(uint256 openInterest, uint256 maxOpenInterest);
error MaxPoolAmountExceeded(uint256 poolAmount, uint256 maxPoolAmount);
error MaxPoolUsdForDepositExceeded(uint256 poolUsd, uint256 maxPoolUsdForDeposit);
error UnexpectedBorrowingFactor(uint256 positionBorrowingFactor, uint256 cumulativeBorrowingFactor);
error UnableToGetBorrowingFactorEmptyPoolUsd();
error UnableToGetFundingFactorEmptyOpenInterest();
error InvalidPositionMarket(address market);
error InvalidCollateralTokenForMarket(address market, address token);
error PnlFactorExceededForLongs(int256 pnlToPoolFactor, uint256 maxPnlFactor);
error PnlFactorExceededForShorts(int256 pnlToPoolFactor, uint256 maxPnlFactor);
error InvalidUiFeeFactor(uint256 uiFeeFactor, uint256 maxUiFeeFactor);
error EmptyAddressInMarketTokenBalanceValidation(address market, address token);
error InvalidMarketTokenBalance(address market, address token, uint256 balance, uint256 expectedMinBalance);
error InvalidMarketTokenBalanceForCollateralAmount(address market, address token, uint256 balance, uint256 collateralAmount);
error InvalidMarketTokenBalanceForClaimableFunding(address market, address token, uint256 balance, uint256 claimableFundingFeeAmount);
error UnexpectedPoolValue(int256 poolValue);
error SequencerDown();
error SequencerGraceDurationNotYetPassed(uint256 timeSinceUp, uint256 sequencerGraceDuration);
error EmptyValidatedPrices();
error InvalidOracleProvider(address provider);
error InvalidOracleProviderForToken(address provider, address expectedProvider);
error GmEmptySigner(uint256 signerIndex);
error InvalidOracleSetPricesProvidersParam(uint256 tokensLength, uint256 providersLength);
error InvalidOracleSetPricesDataParam(uint256 tokensLength, uint256 dataLength);
error GmInvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);
error GmInvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);
error EmptyDataStreamFeedId(address token);
error InvalidDataStreamFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);
error InvalidDataStreamBidAsk(address token, int192 bid, int192 ask);
error InvalidDataStreamPrices(address token, int192 bid, int192 ask);
error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);
error MaxOracleTimestampRangeExceeded(uint256 range, uint256 maxRange);
error GmMinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);
error GmMaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);
error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);
error GmMinPricesNotSorted(address token, uint256 price, uint256 prevPrice);
error GmMaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);
error EmptyChainlinkPriceFeedMultiplier(address token);
error EmptyDataStreamMultiplier(address token);
error InvalidDataStreamSpreadReductionFactor(address token, uint256 spreadReductionFactor);
error InvalidFeedPrice(address token, int256 price);
error ChainlinkPriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);
error GmMaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);
error InvalidGmOraclePrice(address token);
error InvalidGmSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);
error InvalidGmMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);
error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);
error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);
error EmptyChainlinkPriceFeed(address token);
error PriceAlreadySet(address token, uint256 minPrice, uint256 maxPrice);
error MaxRefPriceDeviationExceeded(
address token,
uint256 price,
uint256 refPrice,
uint256 maxRefPriceDeviationFactor
);
error InvalidBlockRangeSet(uint256 largestMinBlockNumber, uint256 smallestMaxBlockNumber);
error EmptyChainlinkPaymentToken();
error NonAtomicOracleProvider(address provider);
error InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);
error EndOfOracleSimulation();
error InvalidGmSignature(address recoveredSigner, address expectedSigner);
error EmptyPrimaryPrice(address token);
error OracleTimestampsAreSmallerThanRequired(uint256 minOracleTimestamp, uint256 expectedTimestamp);
error OracleTimestampsAreLargerThanRequestExpirationTime(uint256 maxOracleTimestamp, uint256 requestTimestamp, uint256 requestExpirationTime);
error EmptyOrder();
error UnsupportedOrderType(uint256 orderType);
error InvalidOrderPrices(
uint256 primaryPriceMin,
uint256 primaryPriceMax,
uint256 triggerPrice,
uint256 orderType
);
error EmptySizeDeltaInTokens();
error PriceImpactLargerThanOrderSize(int256 priceImpactUsd, uint256 sizeDeltaUsd);
error NegativeExecutionPrice(int256 executionPrice, uint256 price, uint256 positionSizeInUsd, int256 priceImpactUsd, uint256 sizeDeltaUsd);
error OrderNotFulfillableAtAcceptablePrice(uint256 price, uint256 acceptablePrice);
error OrderValidFromTimeNotReached(uint256 validFromTime, uint256 currentTimestamp);
error UnexpectedPositionState();
error OrderTypeCannotBeCreated(uint256 orderType);
error OrderAlreadyFrozen();
error MaxTotalCallbackGasLimitForAutoCancelOrdersExceeded(uint256 totalCallbackGasLimit, uint256 maxTotalCallbackGasLimit);
error InvalidReceiver(address receiver);
error UnexpectedValidFromTime(uint256 orderType);
error OrderNotFound(bytes32 key);
error UnexpectedMarket();
error InsufficientFundsToPayForCosts(uint256 remainingCostUsd, string step);
error InvalidOutputToken(address tokenOut, address expectedTokenOut);
error InvalidDecreaseOrderSize(uint256 sizeDeltaUsd, uint256 positionSizeInUsd);
error UnableToWithdrawCollateral(int256 estimatedRemainingCollateralUsd);
error InvalidDecreasePositionSwapType(uint256 decreasePositionSwapType);
error PositionShouldNotBeLiquidated(
string reason,
int256 remainingCollateralUsd,
int256 minCollateralUsd,
int256 minCollateralUsdForLeverage
);
error InsufficientCollateralAmount(uint256 collateralAmount, int256 collateralDeltaAmount);
error InsufficientCollateralUsd(int256 remainingCollateralUsd);
error PositionNotFound(bytes32 key);
error LiquidatablePosition(
string reason,
int256 remainingCollateralUsd,
int256 minCollateralUsd,
int256 minCollateralUsdForLeverage
);
error EmptyPosition();
error InvalidPositionSizeValues(uint256 sizeInUsd, uint256 sizeInTokens);
error MinPositionSize(uint256 positionSizeInUsd, uint256 minPositionSizeUsd);
error UsdDeltaExceedsLongOpenInterest(int256 usdDelta, uint256 longOpenInterest);
error UsdDeltaExceedsShortOpenInterest(int256 usdDelta, uint256 shortOpenInterest);
error ShiftNotFound(bytes32 key);
error EmptyShift();
error EmptyShiftAmount();
error ShiftFromAndToMarketAreEqual(address market);
error LongTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);
error ShortTokensAreNotEqual(address fromMarketLongToken, address toMarketLongToken);
error UsdDeltaExceedsPoolValue(int256 usdDelta, uint256 poolUsd);
error Unauthorized(address msgSender, string role);
error ThereMustBeAtLeastOneRoleAdmin();
error ThereMustBeAtLeastOneTimelockMultiSig();
error InvalidClaimFundingFeesInput(uint256 marketsLength, uint256 tokensLength);
error InvalidClaimCollateralInput(uint256 marketsLength, uint256 tokensLength, uint256 timeKeysLength);
error InvalidClaimAffiliateRewardsInput(uint256 marketsLength, uint256 tokensLength);
error InvalidClaimUiFeesInput(uint256 marketsLength, uint256 tokensLength);
error InvalidTokenIn(address tokenIn, address market);
error InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);
error InsufficientSwapOutputAmount(uint256 outputAmount, uint256 minOutputAmount);
error DuplicatedMarketInSwapPath(address market);
error SwapPriceImpactExceedsAmountIn(uint256 amountAfterFees, int256 negativeImpactAmount);
error InvalidReceiverForSubaccountOrder(address receiver, address expectedReceiver);
error SubaccountNotAuthorized(address account, address subaccount);
error MaxSubaccountActionCountExceeded(address account, address subaccount, uint256 count, uint256 maxCount);
error TokenTransferError(address token, address receiver, uint256 amount);
error EmptyHoldingAddress();
error EmptyTokenTranferGasLimit(address token);
error EmptyAccount();
error EmptyReceiver();
error CompactedArrayOutOfBounds(
uint256[] compactedValues,
uint256 index,
uint256 slotIndex,
string label
);
error ArrayOutOfBoundsUint256(
uint256[] values,
uint256 index,
string label
);
error ArrayOutOfBoundsBytes(
bytes[] values,
uint256 index,
string label
);
error SwapsNotAllowedForAtomicWithdrawal(uint256 longTokenSwapPathLength, uint256 shortTokenSwapPathLength);
error WithdrawalNotFound(bytes32 key);
error EmptyWithdrawal();
error EmptyWithdrawalAmount();
error MinLongTokens(uint256 received, uint256 expected);
error MinShortTokens(uint256 received, uint256 expected);
error InsufficientMarketTokens(uint256 balance, uint256 expected);
error InsufficientWntAmount(uint256 wntAmount, uint256 executionFee);
error InvalidPoolValueForWithdrawal(int256 poolValue);
error MaskIndexOutOfBounds(uint256 index, string label);
error DuplicatedIndex(uint256 index, string label);
error Uint256AsBytesLengthExceeds32Bytes(uint256 length);
error SyncConfigInvalidInputLengths(uint256 marketsLength, uint256 parametersLength);
error SyncConfigUpdatesDisabledForMarket(address market);
error SyncConfigUpdatesDisabledForParameter(string parameter);
error SyncConfigUpdatesDisabledForMarketParameter(address market, string parameter);
error SyncConfigInvalidMarketFromData(address market, address marketFromData);
error EmptyMarketPrice(address market);
}
文件 23 的 57:EventEmitter.sol
pragma solidity ^0.8.0;
import "../role/RoleModule.sol";
import "./EventUtils.sol";
contract EventEmitter is RoleModule {
event EventLog(
address msgSender,
string eventName,
string indexed eventNameHash,
EventUtils.EventLogData eventData
);
event EventLog1(
address msgSender,
string eventName,
string indexed eventNameHash,
bytes32 indexed topic1,
EventUtils.EventLogData eventData
);
event EventLog2(
address msgSender,
string eventName,
string indexed eventNameHash,
bytes32 indexed topic1,
bytes32 indexed topic2,
EventUtils.EventLogData eventData
);
constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
function emitEventLog(
string memory eventName,
EventUtils.EventLogData memory eventData
) external onlyController {
emit EventLog(
msg.sender,
eventName,
eventName,
eventData
);
}
function emitEventLog1(
string memory eventName,
bytes32 topic1,
EventUtils.EventLogData memory eventData
) external onlyController {
emit EventLog1(
msg.sender,
eventName,
eventName,
topic1,
eventData
);
}
function emitEventLog2(
string memory eventName,
bytes32 topic1,
bytes32 topic2,
EventUtils.EventLogData memory eventData
) external onlyController {
emit EventLog2(
msg.sender,
eventName,
eventName,
topic1,
topic2,
eventData
);
}
function emitDataLog1(bytes32 topic1, bytes memory data) external onlyController {
uint256 len = data.length;
assembly {
log1(add(data, 32), len, topic1)
}
}
function emitDataLog2(bytes32 topic1, bytes32 topic2, bytes memory data) external onlyController {
uint256 len = data.length;
assembly {
log2(add(data, 32), len, topic1, topic2)
}
}
function emitDataLog3(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes memory data) external onlyController {
uint256 len = data.length;
assembly {
log3(add(data, 32), len, topic1, topic2, topic3)
}
}
function emitDataLog4(bytes32 topic1, bytes32 topic2, bytes32 topic3, bytes32 topic4, bytes memory data) external onlyController {
uint256 len = data.length;
assembly {
log4(add(data, 32), len, topic1, topic2, topic3, topic4)
}
}
}
文件 24 的 57:EventUtils.sol
pragma solidity ^0.8.0;
library EventUtils {
struct EmitPositionDecreaseParams {
bytes32 key;
address account;
address market;
address collateralToken;
bool isLong;
}
struct EventLogData {
AddressItems addressItems;
UintItems uintItems;
IntItems intItems;
BoolItems boolItems;
Bytes32Items bytes32Items;
BytesItems bytesItems;
StringItems stringItems;
}
struct AddressItems {
AddressKeyValue[] items;
AddressArrayKeyValue[] arrayItems;
}
struct UintItems {
UintKeyValue[] items;
UintArrayKeyValue[] arrayItems;
}
struct IntItems {
IntKeyValue[] items;
IntArrayKeyValue[] arrayItems;
}
struct BoolItems {
BoolKeyValue[] items;
BoolArrayKeyValue[] arrayItems;
}
struct Bytes32Items {
Bytes32KeyValue[] items;
Bytes32ArrayKeyValue[] arrayItems;
}
struct BytesItems {
BytesKeyValue[] items;
BytesArrayKeyValue[] arrayItems;
}
struct StringItems {
StringKeyValue[] items;
StringArrayKeyValue[] arrayItems;
}
struct AddressKeyValue {
string key;
address value;
}
struct AddressArrayKeyValue {
string key;
address[] value;
}
struct UintKeyValue {
string key;
uint256 value;
}
struct UintArrayKeyValue {
string key;
uint256[] value;
}
struct IntKeyValue {
string key;
int256 value;
}
struct IntArrayKeyValue {
string key;
int256[] value;
}
struct BoolKeyValue {
string key;
bool value;
}
struct BoolArrayKeyValue {
string key;
bool[] value;
}
struct Bytes32KeyValue {
string key;
bytes32 value;
}
struct Bytes32ArrayKeyValue {
string key;
bytes32[] value;
}
struct BytesKeyValue {
string key;
bytes value;
}
struct BytesArrayKeyValue {
string key;
bytes[] value;
}
struct StringKeyValue {
string key;
string value;
}
struct StringArrayKeyValue {
string key;
string[] value;
}
function initItems(AddressItems memory items, uint256 size) internal pure {
items.items = new EventUtils.AddressKeyValue[](size);
}
function initArrayItems(AddressItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.AddressArrayKeyValue[](size);
}
function setItem(AddressItems memory items, uint256 index, string memory key, address value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(AddressItems memory items, uint256 index, string memory key, address[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(UintItems memory items, uint256 size) internal pure {
items.items = new EventUtils.UintKeyValue[](size);
}
function initArrayItems(UintItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.UintArrayKeyValue[](size);
}
function setItem(UintItems memory items, uint256 index, string memory key, uint256 value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(UintItems memory items, uint256 index, string memory key, uint256[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(IntItems memory items, uint256 size) internal pure {
items.items = new EventUtils.IntKeyValue[](size);
}
function initArrayItems(IntItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.IntArrayKeyValue[](size);
}
function setItem(IntItems memory items, uint256 index, string memory key, int256 value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(IntItems memory items, uint256 index, string memory key, int256[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(BoolItems memory items, uint256 size) internal pure {
items.items = new EventUtils.BoolKeyValue[](size);
}
function initArrayItems(BoolItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.BoolArrayKeyValue[](size);
}
function setItem(BoolItems memory items, uint256 index, string memory key, bool value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(BoolItems memory items, uint256 index, string memory key, bool[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(Bytes32Items memory items, uint256 size) internal pure {
items.items = new EventUtils.Bytes32KeyValue[](size);
}
function initArrayItems(Bytes32Items memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.Bytes32ArrayKeyValue[](size);
}
function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32 value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(Bytes32Items memory items, uint256 index, string memory key, bytes32[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(BytesItems memory items, uint256 size) internal pure {
items.items = new EventUtils.BytesKeyValue[](size);
}
function initArrayItems(BytesItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.BytesArrayKeyValue[](size);
}
function setItem(BytesItems memory items, uint256 index, string memory key, bytes memory value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(BytesItems memory items, uint256 index, string memory key, bytes[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
function initItems(StringItems memory items, uint256 size) internal pure {
items.items = new EventUtils.StringKeyValue[](size);
}
function initArrayItems(StringItems memory items, uint256 size) internal pure {
items.arrayItems = new EventUtils.StringArrayKeyValue[](size);
}
function setItem(StringItems memory items, uint256 index, string memory key, string memory value) internal pure {
items.items[index].key = key;
items.items[index].value = value;
}
function setItem(StringItems memory items, uint256 index, string memory key, string[] memory value) internal pure {
items.arrayItems[index].key = key;
items.arrayItems[index].value = value;
}
}
文件 25 的 57:FeatureUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
library FeatureUtils {
function isFeatureDisabled(DataStore dataStore, bytes32 key) internal view returns (bool) {
return dataStore.getBool(key);
}
function validateFeature(DataStore dataStore, bytes32 key) internal view {
if (isFeatureDisabled(dataStore, key)) {
revert Errors.DisabledFeature(key);
}
}
}
文件 26 的 57:IERC20.sol
pragma solidity ^0.8.0;
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}
文件 27 的 57:IERC20Metadata.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
interface IERC20Metadata is IERC20 {
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
}
文件 28 的 57:IERC20Permit.sol
pragma solidity ^0.8.0;
interface IERC20Permit {
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
function nonces(address owner) external view returns (uint256);
function DOMAIN_SEPARATOR() external view returns (bytes32);
}
文件 29 的 57:IOracleProvider.sol
pragma solidity ^0.8.0;
import "./OracleUtils.sol";
interface IOracleProvider {
function getOraclePrice(
address token,
bytes memory data
) external returns (OracleUtils.ValidatedPrice memory);
}
文件 30 的 57:IPriceFeed.sol
pragma solidity ^0.8.0;
interface IPriceFeed {
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 31 的 57:IRiskOracle.sol
pragma solidity ^0.8.0;
interface IRiskOracle {
struct RiskParameterUpdate {
uint256 timestamp;
bytes newValue;
string referenceId;
bytes previousValue;
string updateType;
uint256 updateId;
address market;
bytes additionalData;
}
function getLatestUpdateByParameterAndMarket(string memory updateType, address market) external view returns (RiskParameterUpdate memory);
}
文件 32 的 57:IWNT.sol
pragma solidity ^0.8.0;
interface IWNT {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 33 的 57:Keys.sol
pragma solidity ^0.8.0;
library Keys {
bytes32 public constant WNT = keccak256(abi.encode("WNT"));
bytes32 public constant NONCE = keccak256(abi.encode("NONCE"));
bytes32 public constant FEE_RECEIVER = keccak256(abi.encode("FEE_RECEIVER"));
bytes32 public constant HOLDING_ADDRESS = keccak256(abi.encode("HOLDING_ADDRESS"));
bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS"));
bytes32 public constant MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD = keccak256(abi.encode("MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD"));
bytes32 public constant MIN_ADDITIONAL_GAS_FOR_EXECUTION = keccak256(abi.encode("MIN_ADDITIONAL_GAS_FOR_EXECUTION"));
bytes32 public constant REENTRANCY_GUARD_STATUS = keccak256(abi.encode("REENTRANCY_GUARD_STATUS"));
bytes32 public constant DEPOSIT_FEE_TYPE = keccak256(abi.encode("DEPOSIT_FEE_TYPE"));
bytes32 public constant WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("WITHDRAWAL_FEE_TYPE"));
bytes32 public constant SWAP_FEE_TYPE = keccak256(abi.encode("SWAP_FEE_TYPE"));
bytes32 public constant POSITION_FEE_TYPE = keccak256(abi.encode("POSITION_FEE_TYPE"));
bytes32 public constant UI_DEPOSIT_FEE_TYPE = keccak256(abi.encode("UI_DEPOSIT_FEE_TYPE"));
bytes32 public constant UI_WITHDRAWAL_FEE_TYPE = keccak256(abi.encode("UI_WITHDRAWAL_FEE_TYPE"));
bytes32 public constant UI_SWAP_FEE_TYPE = keccak256(abi.encode("UI_SWAP_FEE_TYPE"));
bytes32 public constant UI_POSITION_FEE_TYPE = keccak256(abi.encode("UI_POSITION_FEE_TYPE"));
bytes32 public constant UI_FEE_FACTOR = keccak256(abi.encode("UI_FEE_FACTOR"));
bytes32 public constant MAX_UI_FEE_FACTOR = keccak256(abi.encode("MAX_UI_FEE_FACTOR"));
bytes32 public constant CLAIMABLE_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_FEE_AMOUNT"));
bytes32 public constant CLAIMABLE_UI_FEE_AMOUNT = keccak256(abi.encode("CLAIMABLE_UI_FEE_AMOUNT"));
bytes32 public constant MAX_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_AUTO_CANCEL_ORDERS"));
bytes32 public constant MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS = keccak256(abi.encode("MAX_TOTAL_CALLBACK_GAS_LIMIT_FOR_AUTO_CANCEL_ORDERS"));
bytes32 public constant MARKET_LIST = keccak256(abi.encode("MARKET_LIST"));
bytes32 public constant FEE_BATCH_LIST = keccak256(abi.encode("FEE_BATCH_LIST"));
bytes32 public constant DEPOSIT_LIST = keccak256(abi.encode("DEPOSIT_LIST"));
bytes32 public constant ACCOUNT_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_DEPOSIT_LIST"));
bytes32 public constant WITHDRAWAL_LIST = keccak256(abi.encode("WITHDRAWAL_LIST"));
bytes32 public constant ACCOUNT_WITHDRAWAL_LIST = keccak256(abi.encode("ACCOUNT_WITHDRAWAL_LIST"));
bytes32 public constant SHIFT_LIST = keccak256(abi.encode("SHIFT_LIST"));
bytes32 public constant ACCOUNT_SHIFT_LIST = keccak256(abi.encode("ACCOUNT_SHIFT_LIST"));
bytes32 public constant GLV_LIST = keccak256(abi.encode("GLV_LIST"));
bytes32 public constant GLV_DEPOSIT_LIST = keccak256(abi.encode("GLV_DEPOSIT_LIST"));
bytes32 public constant GLV_SHIFT_LIST = keccak256(abi.encode("GLV_SHIFT_LIST"));
bytes32 public constant ACCOUNT_GLV_DEPOSIT_LIST = keccak256(abi.encode("ACCOUNT_GLV_DEPOSIT_LIST"));
bytes32 public constant GLV_WITHDRAWAL_LIST = keccak256(abi.encode("GLV_WITHDRAWAL_LIST"));
bytes32 public constant ACCOUNT_GLV_WITHDRAWAL_LIST = keccak256(abi.encode("ACCOUNT_GLV_WITHDRAWAL_LIST"));
bytes32 public constant GLV_SUPPORTED_MARKET_LIST = keccak256(abi.encode("GLV_SUPPORTED_MARKET_LIST"));
bytes32 public constant POSITION_LIST = keccak256(abi.encode("POSITION_LIST"));
bytes32 public constant ACCOUNT_POSITION_LIST = keccak256(abi.encode("ACCOUNT_POSITION_LIST"));
bytes32 public constant ORDER_LIST = keccak256(abi.encode("ORDER_LIST"));
bytes32 public constant ACCOUNT_ORDER_LIST = keccak256(abi.encode("ACCOUNT_ORDER_LIST"));
bytes32 public constant SUBACCOUNT_LIST = keccak256(abi.encode("SUBACCOUNT_LIST"));
bytes32 public constant AUTO_CANCEL_ORDER_LIST = keccak256(abi.encode("AUTO_CANCEL_ORDER_LIST"));
bytes32 public constant IS_MARKET_DISABLED = keccak256(abi.encode("IS_MARKET_DISABLED"));
bytes32 public constant MAX_SWAP_PATH_LENGTH = keccak256(abi.encode("MAX_SWAP_PATH_LENGTH"));
bytes32 public constant SWAP_PATH_MARKET_FLAG = keccak256(abi.encode("SWAP_PATH_MARKET_FLAG"));
bytes32 public constant MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode("MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT"));
bytes32 public constant CREATE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_GLV_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant CANCEL_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_GLV_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant CREATE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_GLV_SHIFT_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_GLV_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_GLV_SHIFT_FEATURE_DISABLED"));
bytes32 public constant CREATE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant CANCEL_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_DEPOSIT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_DEPOSIT_FEATURE_DISABLED"));
bytes32 public constant CREATE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CREATE_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant CANCEL_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED"));
bytes32 public constant CREATE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CREATE_SHIFT_FEATURE_DISABLED"));
bytes32 public constant CANCEL_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_SHIFT_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_SHIFT_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_SHIFT_FEATURE_DISABLED"));
bytes32 public constant CREATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CREATE_ORDER_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ORDER_FEATURE_DISABLED"));
bytes32 public constant EXECUTE_ADL_FEATURE_DISABLED = keccak256(abi.encode("EXECUTE_ADL_FEATURE_DISABLED"));
bytes32 public constant UPDATE_ORDER_FEATURE_DISABLED = keccak256(abi.encode("UPDATE_ORDER_FEATURE_DISABLED"));
bytes32 public constant CANCEL_ORDER_FEATURE_DISABLED = keccak256(abi.encode("CANCEL_ORDER_FEATURE_DISABLED"));
bytes32 public constant CLAIM_FUNDING_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_FUNDING_FEES_FEATURE_DISABLED"));
bytes32 public constant CLAIM_COLLATERAL_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_COLLATERAL_FEATURE_DISABLED"));
bytes32 public constant CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED"));
bytes32 public constant CLAIM_UI_FEES_FEATURE_DISABLED = keccak256(abi.encode("CLAIM_UI_FEES_FEATURE_DISABLED"));
bytes32 public constant SUBACCOUNT_FEATURE_DISABLED = keccak256(abi.encode("SUBACCOUNT_FEATURE_DISABLED"));
bytes32 public constant MIN_ORACLE_SIGNERS = keccak256(abi.encode("MIN_ORACLE_SIGNERS"));
bytes32 public constant MIN_ORACLE_BLOCK_CONFIRMATIONS = keccak256(abi.encode("MIN_ORACLE_BLOCK_CONFIRMATIONS"));
bytes32 public constant MAX_ORACLE_PRICE_AGE = keccak256(abi.encode("MAX_ORACLE_PRICE_AGE"));
bytes32 public constant MAX_ORACLE_TIMESTAMP_RANGE = keccak256(abi.encode("MAX_ORACLE_TIMESTAMP_RANGE"));
bytes32 public constant MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode("MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR"));
bytes32 public constant IS_ORACLE_PROVIDER_ENABLED = keccak256(abi.encode("IS_ORACLE_PROVIDER_ENABLED"));
bytes32 public constant IS_ATOMIC_ORACLE_PROVIDER = keccak256(abi.encode("IS_ATOMIC_ORACLE_PROVIDER"));
bytes32 public constant ORACLE_TIMESTAMP_ADJUSTMENT = keccak256(abi.encode("ORACLE_TIMESTAMP_ADJUSTMENT"));
bytes32 public constant ORACLE_PROVIDER_FOR_TOKEN = keccak256(abi.encode("ORACLE_PROVIDER_FOR_TOKEN"));
bytes32 public constant CHAINLINK_PAYMENT_TOKEN = keccak256(abi.encode("CHAINLINK_PAYMENT_TOKEN"));
bytes32 public constant SEQUENCER_GRACE_DURATION = keccak256(abi.encode("SEQUENCER_GRACE_DURATION"));
bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode("POSITION_FEE_RECEIVER_FACTOR"));
bytes32 public constant LIQUIDATION_FEE_RECEIVER_FACTOR = keccak256(abi.encode("LIQUIDATION_FEE_RECEIVER_FACTOR"));
bytes32 public constant SWAP_FEE_RECEIVER_FACTOR = keccak256(abi.encode("SWAP_FEE_RECEIVER_FACTOR"));
bytes32 public constant BORROWING_FEE_RECEIVER_FACTOR = keccak256(abi.encode("BORROWING_FEE_RECEIVER_FACTOR"));
bytes32 public constant ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT_V2_1"));
bytes32 public constant ESTIMATED_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("ESTIMATED_GAS_FEE_PER_ORACLE_PRICE"));
bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR"));
bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1 = keccak256(abi.encode("EXECUTION_GAS_FEE_BASE_AMOUNT_V2_1"));
bytes32 public constant EXECUTION_GAS_FEE_PER_ORACLE_PRICE = keccak256(abi.encode("EXECUTION_GAS_FEE_PER_ORACLE_PRICE"));
bytes32 public constant EXECUTION_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("EXECUTION_GAS_FEE_MULTIPLIER_FACTOR"));
bytes32 public constant DEPOSIT_GAS_LIMIT = keccak256(abi.encode("DEPOSIT_GAS_LIMIT"));
bytes32 public constant WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode("WITHDRAWAL_GAS_LIMIT"));
bytes32 public constant GLV_DEPOSIT_GAS_LIMIT = keccak256(abi.encode("GLV_DEPOSIT_GAS_LIMIT"));
bytes32 public constant GLV_WITHDRAWAL_GAS_LIMIT = keccak256(abi.encode("GLV_WITHDRAWAL_GAS_LIMIT"));
bytes32 public constant GLV_SHIFT_GAS_LIMIT = keccak256(abi.encode("GLV_SHIFT_GAS_LIMIT"));
bytes32 public constant GLV_PER_MARKET_GAS_LIMIT = keccak256(abi.encode("GLV_PER_MARKET_GAS_LIMIT"));
bytes32 public constant SHIFT_GAS_LIMIT = keccak256(abi.encode("SHIFT_GAS_LIMIT"));
bytes32 public constant SINGLE_SWAP_GAS_LIMIT = keccak256(abi.encode("SINGLE_SWAP_GAS_LIMIT"));
bytes32 public constant INCREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("INCREASE_ORDER_GAS_LIMIT"));
bytes32 public constant DECREASE_ORDER_GAS_LIMIT = keccak256(abi.encode("DECREASE_ORDER_GAS_LIMIT"));
bytes32 public constant SWAP_ORDER_GAS_LIMIT = keccak256(abi.encode("SWAP_ORDER_GAS_LIMIT"));
bytes32 public constant TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("TOKEN_TRANSFER_GAS_LIMIT"));
bytes32 public constant NATIVE_TOKEN_TRANSFER_GAS_LIMIT = keccak256(abi.encode("NATIVE_TOKEN_TRANSFER_GAS_LIMIT"));
bytes32 public constant REQUEST_EXPIRATION_TIME = keccak256(abi.encode("REQUEST_EXPIRATION_TIME"));
bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode("MAX_CALLBACK_GAS_LIMIT"));
bytes32 public constant REFUND_EXECUTION_FEE_GAS_LIMIT = keccak256(abi.encode("REFUND_EXECUTION_FEE_GAS_LIMIT"));
bytes32 public constant SAVED_CALLBACK_CONTRACT = keccak256(abi.encode("SAVED_CALLBACK_CONTRACT"));
bytes32 public constant MIN_COLLATERAL_FACTOR = keccak256(abi.encode("MIN_COLLATERAL_FACTOR"));
bytes32 public constant MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER = keccak256(abi.encode("MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER"));
bytes32 public constant MIN_COLLATERAL_USD = keccak256(abi.encode("MIN_COLLATERAL_USD"));
bytes32 public constant MIN_POSITION_SIZE_USD = keccak256(abi.encode("MIN_POSITION_SIZE_USD"));
bytes32 public constant VIRTUAL_TOKEN_ID = keccak256(abi.encode("VIRTUAL_TOKEN_ID"));
bytes32 public constant VIRTUAL_MARKET_ID = keccak256(abi.encode("VIRTUAL_MARKET_ID"));
bytes32 public constant VIRTUAL_INVENTORY_FOR_SWAPS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_SWAPS"));
bytes32 public constant VIRTUAL_INVENTORY_FOR_POSITIONS = keccak256(abi.encode("VIRTUAL_INVENTORY_FOR_POSITIONS"));
bytes32 public constant POSITION_IMPACT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_FACTOR"));
bytes32 public constant POSITION_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("POSITION_IMPACT_EXPONENT_FACTOR"));
bytes32 public constant MAX_POSITION_IMPACT_FACTOR = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR"));
bytes32 public constant MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS = keccak256(abi.encode("MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS"));
bytes32 public constant POSITION_FEE_FACTOR = keccak256(abi.encode("POSITION_FEE_FACTOR"));
bytes32 public constant PRO_TRADER_TIER = keccak256(abi.encode("PRO_TRADER_TIER"));
bytes32 public constant PRO_DISCOUNT_FACTOR = keccak256(abi.encode("PRO_DISCOUNT_FACTOR"));
bytes32 public constant LIQUIDATION_FEE_FACTOR = keccak256(abi.encode("LIQUIDATION_FEE_FACTOR"));
bytes32 public constant SWAP_IMPACT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_FACTOR"));
bytes32 public constant SWAP_IMPACT_EXPONENT_FACTOR = keccak256(abi.encode("SWAP_IMPACT_EXPONENT_FACTOR"));
bytes32 public constant SWAP_FEE_FACTOR = keccak256(abi.encode("SWAP_FEE_FACTOR"));
bytes32 public constant ATOMIC_SWAP_FEE_FACTOR = keccak256(abi.encode("ATOMIC_SWAP_FEE_FACTOR"));
bytes32 public constant DEPOSIT_FEE_FACTOR = keccak256(abi.encode("DEPOSIT_FEE_FACTOR"));
bytes32 public constant WITHDRAWAL_FEE_FACTOR = keccak256(abi.encode("WITHDRAWAL_FEE_FACTOR"));
bytes32 public constant ORACLE_TYPE = keccak256(abi.encode("ORACLE_TYPE"));
bytes32 public constant OPEN_INTEREST = keccak256(abi.encode("OPEN_INTEREST"));
bytes32 public constant OPEN_INTEREST_IN_TOKENS = keccak256(abi.encode("OPEN_INTEREST_IN_TOKENS"));
bytes32 public constant COLLATERAL_SUM = keccak256(abi.encode("COLLATERAL_SUM"));
bytes32 public constant POOL_AMOUNT = keccak256(abi.encode("POOL_AMOUNT"));
bytes32 public constant MAX_POOL_AMOUNT = keccak256(abi.encode("MAX_POOL_AMOUNT"));
bytes32 public constant MAX_POOL_USD_FOR_DEPOSIT = keccak256(abi.encode("MAX_POOL_USD_FOR_DEPOSIT"));
bytes32 public constant MAX_OPEN_INTEREST = keccak256(abi.encode("MAX_OPEN_INTEREST"));
bytes32 public constant POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("POSITION_IMPACT_POOL_AMOUNT"));
bytes32 public constant MIN_POSITION_IMPACT_POOL_AMOUNT = keccak256(abi.encode("MIN_POSITION_IMPACT_POOL_AMOUNT"));
bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTION_RATE = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTION_RATE"));
bytes32 public constant POSITION_IMPACT_POOL_DISTRIBUTED_AT = keccak256(abi.encode("POSITION_IMPACT_POOL_DISTRIBUTED_AT"));
bytes32 public constant SWAP_IMPACT_POOL_AMOUNT = keccak256(abi.encode("SWAP_IMPACT_POOL_AMOUNT"));
bytes32 public constant PRICE_FEED = keccak256(abi.encode("PRICE_FEED"));
bytes32 public constant PRICE_FEED_MULTIPLIER = keccak256(abi.encode("PRICE_FEED_MULTIPLIER"));
bytes32 public constant PRICE_FEED_HEARTBEAT_DURATION = keccak256(abi.encode("PRICE_FEED_HEARTBEAT_DURATION"));
bytes32 public constant DATA_STREAM_ID = keccak256(abi.encode("DATA_STREAM_ID"));
bytes32 public constant DATA_STREAM_MULTIPLIER = keccak256(abi.encode("DATA_STREAM_MULTIPLIER"));
bytes32 public constant DATA_STREAM_SPREAD_REDUCTION_FACTOR = keccak256(abi.encode("DATA_STREAM_SPREAD_REDUCTION_FACTOR"));
bytes32 public constant STABLE_PRICE = keccak256(abi.encode("STABLE_PRICE"));
bytes32 public constant RESERVE_FACTOR = keccak256(abi.encode("RESERVE_FACTOR"));
bytes32 public constant OPEN_INTEREST_RESERVE_FACTOR = keccak256(abi.encode("OPEN_INTEREST_RESERVE_FACTOR"));
bytes32 public constant MAX_PNL_FACTOR = keccak256(abi.encode("MAX_PNL_FACTOR"));
bytes32 public constant MAX_PNL_FACTOR_FOR_TRADERS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_TRADERS"));
bytes32 public constant MAX_PNL_FACTOR_FOR_ADL = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_ADL"));
bytes32 public constant MIN_PNL_FACTOR_AFTER_ADL = keccak256(abi.encode("MIN_PNL_FACTOR_AFTER_ADL"));
bytes32 public constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_DEPOSITS"));
bytes32 public constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_WITHDRAWALS"));
bytes32 public constant LATEST_ADL_AT = keccak256(abi.encode("LATEST_ADL_AT"));
bytes32 public constant IS_ADL_ENABLED = keccak256(abi.encode("IS_ADL_ENABLED"));
bytes32 public constant FUNDING_FACTOR = keccak256(abi.encode("FUNDING_FACTOR"));
bytes32 public constant FUNDING_EXPONENT_FACTOR = keccak256(abi.encode("FUNDING_EXPONENT_FACTOR"));
bytes32 public constant SAVED_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("SAVED_FUNDING_FACTOR_PER_SECOND"));
bytes32 public constant FUNDING_INCREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_INCREASE_FACTOR_PER_SECOND"));
bytes32 public constant FUNDING_DECREASE_FACTOR_PER_SECOND = keccak256(abi.encode("FUNDING_DECREASE_FACTOR_PER_SECOND"));
bytes32 public constant MIN_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MIN_FUNDING_FACTOR_PER_SECOND"));
bytes32 public constant MAX_FUNDING_FACTOR_PER_SECOND = keccak256(abi.encode("MAX_FUNDING_FACTOR_PER_SECOND"));
bytes32 public constant THRESHOLD_FOR_STABLE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_STABLE_FUNDING"));
bytes32 public constant THRESHOLD_FOR_DECREASE_FUNDING = keccak256(abi.encode("THRESHOLD_FOR_DECREASE_FUNDING"));
bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE"));
bytes32 public constant CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
bytes32 public constant FUNDING_UPDATED_AT = keccak256(abi.encode("FUNDING_UPDATED_AT"));
bytes32 public constant CLAIMABLE_FUNDING_AMOUNT = keccak256(abi.encode("CLAIMABLE_FUNDING_AMOUNT"));
bytes32 public constant CLAIMABLE_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMABLE_COLLATERAL_AMOUNT"));
bytes32 public constant CLAIMABLE_COLLATERAL_FACTOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_FACTOR"));
bytes32 public constant CLAIMABLE_COLLATERAL_TIME_DIVISOR = keccak256(abi.encode("CLAIMABLE_COLLATERAL_TIME_DIVISOR"));
bytes32 public constant CLAIMED_COLLATERAL_AMOUNT = keccak256(abi.encode("CLAIMED_COLLATERAL_AMOUNT"));
bytes32 public constant IGNORE_OPEN_INTEREST_FOR_USAGE_FACTOR = keccak256(abi.encode("IGNORE_OPEN_INTEREST_FOR_USAGE_FACTOR"));
bytes32 public constant OPTIMAL_USAGE_FACTOR = keccak256(abi.encode("OPTIMAL_USAGE_FACTOR"));
bytes32 public constant BASE_BORROWING_FACTOR = keccak256(abi.encode("BASE_BORROWING_FACTOR"));
bytes32 public constant ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR = keccak256(abi.encode("ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR"));
bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR"));
bytes32 public constant BORROWING_EXPONENT_FACTOR = keccak256(abi.encode("BORROWING_EXPONENT_FACTOR"));
bytes32 public constant SKIP_BORROWING_FEE_FOR_SMALLER_SIDE = keccak256(abi.encode("SKIP_BORROWING_FEE_FOR_SMALLER_SIDE"));
bytes32 public constant CUMULATIVE_BORROWING_FACTOR = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR"));
bytes32 public constant CUMULATIVE_BORROWING_FACTOR_UPDATED_AT = keccak256(abi.encode("CUMULATIVE_BORROWING_FACTOR_UPDATED_AT"));
bytes32 public constant TOTAL_BORROWING = keccak256(abi.encode("TOTAL_BORROWING"));
bytes32 public constant MIN_AFFILIATE_REWARD_FACTOR = keccak256(abi.encode("MIN_AFFILIATE_REWARD_FACTOR"));
bytes32 public constant AFFILIATE_REWARD = keccak256(abi.encode("AFFILIATE_REWARD"));
bytes32 public constant MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT"));
bytes32 public constant SUBACCOUNT_ACTION_COUNT = keccak256(abi.encode("SUBACCOUNT_ACTION_COUNT"));
bytes32 public constant SUBACCOUNT_AUTO_TOP_UP_AMOUNT = keccak256(abi.encode("SUBACCOUNT_AUTO_TOP_UP_AMOUNT"));
bytes32 public constant SUBACCOUNT_ORDER_ACTION = keccak256(abi.encode("SUBACCOUNT_ORDER_ACTION"));
bytes32 public constant FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX"));
bytes32 public constant FEE_DISTRIBUTOR_SWAP_FEE_BATCH = keccak256(abi.encode("FEE_DISTRIBUTOR_SWAP_FEE_BATCH"));
bytes32 public constant GLV_MAX_MARKET_COUNT = keccak256(abi.encode("GLV_MAX_MARKET_COUNT"));
bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_USD = keccak256(abi.encode("GLV_MAX_MARKET_TOKEN_BALANCE_USD"));
bytes32 public constant GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT = keccak256(abi.encode("GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT"));
bytes32 public constant IS_GLV_MARKET_DISABLED = keccak256(abi.encode("IS_GLV_MARKET_DISABLED"));
bytes32 public constant GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode("GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR"));
bytes32 public constant GLV_SHIFT_LAST_EXECUTED_AT = keccak256(abi.encode("GLV_SHIFT_LAST_EXECUTED_AT"));
bytes32 public constant GLV_SHIFT_MIN_INTERVAL = keccak256(abi.encode("GLV_SHIFT_MIN_INTERVAL"));
bytes32 public constant MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT = keccak256(abi.encode("MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT"));
bytes32 public constant SYNC_CONFIG_FEATURE_DISABLED = keccak256(abi.encode("SYNC_CONFIG_FEATURE_DISABLED"));
bytes32 public constant SYNC_CONFIG_MARKET_DISABLED = keccak256(abi.encode("SYNC_CONFIG_MARKET_DISABLED"));
bytes32 public constant SYNC_CONFIG_PARAMETER_DISABLED = keccak256(abi.encode("SYNC_CONFIG_PARAMETER_DISABLED"));
bytes32 public constant SYNC_CONFIG_MARKET_PARAMETER_DISABLED = keccak256(abi.encode("SYNC_CONFIG_MARKET_PARAMETER_DISABLED"));
bytes32 public constant SYNC_CONFIG_UPDATE_COMPLETED = keccak256(abi.encode("SYNC_CONFIG_UPDATE_COMPLETED"));
bytes32 public constant SYNC_CONFIG_LATEST_UPDATE_ID = keccak256(abi.encode("SYNC_CONFIG_LATEST_UPDATE_ID"));
bytes32 public constant CONTRIBUTOR_ACCOUNT_LIST = keccak256(abi.encode("CONTRIBUTOR_ACCOUNT_LIST"));
bytes32 public constant CONTRIBUTOR_TOKEN_LIST = keccak256(abi.encode("CONTRIBUTOR_TOKEN_LIST"));
bytes32 public constant CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode("CONTRIBUTOR_TOKEN_AMOUNT"));
bytes32 public constant MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT = keccak256(abi.encode("MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT"));
bytes32 public constant CONTRIBUTOR_TOKEN_VAULT = keccak256(abi.encode("CONTRIBUTOR_TOKEN_VAULT"));
bytes32 public constant CONTRIBUTOR_LAST_PAYMENT_AT = keccak256(abi.encode("CONTRIBUTOR_LAST_PAYMENT_AT"));
bytes32 public constant MIN_CONTRIBUTOR_PAYMENT_INTERVAL = keccak256(abi.encode("MIN_CONTRIBUTOR_PAYMENT_INTERVAL"));
bytes32 public constant BUYBACK_BATCH_AMOUNT = keccak256(abi.encode("BUYBACK_BATCH_AMOUNT"));
bytes32 public constant BUYBACK_AVAILABLE_FEE_AMOUNT = keccak256(abi.encode("BUYBACK_AVAILABLE_FEE_AMOUNT"));
bytes32 public constant BUYBACK_GMX_FACTOR = keccak256(abi.encode("BUYBACK_GMX_FACTOR"));
bytes32 public constant BUYBACK_MAX_PRICE_IMPACT_FACTOR = keccak256(abi.encode("BUYBACK_MAX_PRICE_IMPACT_FACTOR"));
bytes32 public constant BUYBACK_MAX_PRICE_AGE = keccak256(abi.encode("BUYBACK_MAX_PRICE_AGE"));
bytes32 public constant WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT = keccak256(abi.encode("WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT"));
string public constant USER_INITIATED_CANCEL = "USER_INITIATED_CANCEL";
function getFullKey(bytes32 baseKey, bytes memory data) internal pure returns (bytes32) {
if (data.length == 0) {
return baseKey;
}
return keccak256(bytes.concat(baseKey, data));
}
function accountDepositListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_DEPOSIT_LIST, account));
}
function accountWithdrawalListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_WITHDRAWAL_LIST, account));
}
function accountShiftListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_SHIFT_LIST, account));
}
function accountGlvDepositListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_GLV_DEPOSIT_LIST, account));
}
function accountGlvWithdrawalListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_GLV_WITHDRAWAL_LIST, account));
}
function glvSupportedMarketListKey(address glv) internal pure returns (bytes32) {
return keccak256(abi.encode(GLV_SUPPORTED_MARKET_LIST, glv));
}
function accountPositionListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_POSITION_LIST, account));
}
function accountOrderListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(ACCOUNT_ORDER_LIST, account));
}
function subaccountListKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(SUBACCOUNT_LIST, account));
}
function autoCancelOrderListKey(bytes32 positionKey) internal pure returns (bytes32) {
return keccak256(abi.encode(AUTO_CANCEL_ORDER_LIST, positionKey));
}
function claimableFeeAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(CLAIMABLE_FEE_AMOUNT, market, token));
}
function claimableUiFeeAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token));
}
function claimableUiFeeAmountKey(address market, address token, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(CLAIMABLE_UI_FEE_AMOUNT, market, token, account));
}
function depositGasLimitKey() internal pure returns (bytes32) {
return DEPOSIT_GAS_LIMIT;
}
function withdrawalGasLimitKey() internal pure returns (bytes32) {
return WITHDRAWAL_GAS_LIMIT;
}
function shiftGasLimitKey() internal pure returns (bytes32) {
return SHIFT_GAS_LIMIT;
}
function glvDepositGasLimitKey() internal pure returns (bytes32) {
return GLV_DEPOSIT_GAS_LIMIT;
}
function glvWithdrawalGasLimitKey() internal pure returns (bytes32) {
return GLV_WITHDRAWAL_GAS_LIMIT;
}
function glvShiftGasLimitKey() internal pure returns (bytes32) {
return GLV_SHIFT_GAS_LIMIT;
}
function glvPerMarketGasLimitKey() internal pure returns (bytes32) {
return GLV_PER_MARKET_GAS_LIMIT;
}
function singleSwapGasLimitKey() internal pure returns (bytes32) {
return SINGLE_SWAP_GAS_LIMIT;
}
function increaseOrderGasLimitKey() internal pure returns (bytes32) {
return INCREASE_ORDER_GAS_LIMIT;
}
function decreaseOrderGasLimitKey() internal pure returns (bytes32) {
return DECREASE_ORDER_GAS_LIMIT;
}
function swapOrderGasLimitKey() internal pure returns (bytes32) {
return SWAP_ORDER_GAS_LIMIT;
}
function swapPathMarketFlagKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
SWAP_PATH_MARKET_FLAG,
market
));
}
function createGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_GLV_DEPOSIT_FEATURE_DISABLED,
module
));
}
function cancelGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_GLV_DEPOSIT_FEATURE_DISABLED,
module
));
}
function executeGlvDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_GLV_DEPOSIT_FEATURE_DISABLED,
module
));
}
function createGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_GLV_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function cancelGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_GLV_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function executeGlvWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_GLV_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function createGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_GLV_SHIFT_FEATURE_DISABLED,
module
));
}
function executeGlvShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_GLV_SHIFT_FEATURE_DISABLED,
module
));
}
function createDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_DEPOSIT_FEATURE_DISABLED,
module
));
}
function cancelDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_DEPOSIT_FEATURE_DISABLED,
module
));
}
function executeDepositFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_DEPOSIT_FEATURE_DISABLED,
module
));
}
function createWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function cancelWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function executeWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function executeAtomicWithdrawalFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_ATOMIC_WITHDRAWAL_FEATURE_DISABLED,
module
));
}
function createShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_SHIFT_FEATURE_DISABLED,
module
));
}
function cancelShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_SHIFT_FEATURE_DISABLED,
module
));
}
function executeShiftFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_SHIFT_FEATURE_DISABLED,
module
));
}
function createOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
return keccak256(abi.encode(
CREATE_ORDER_FEATURE_DISABLED,
module,
orderType
));
}
function executeOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_ORDER_FEATURE_DISABLED,
module,
orderType
));
}
function executeAdlFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
return keccak256(abi.encode(
EXECUTE_ADL_FEATURE_DISABLED,
module,
orderType
));
}
function updateOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
return keccak256(abi.encode(
UPDATE_ORDER_FEATURE_DISABLED,
module,
orderType
));
}
function cancelOrderFeatureDisabledKey(address module, uint256 orderType) internal pure returns (bytes32) {
return keccak256(abi.encode(
CANCEL_ORDER_FEATURE_DISABLED,
module,
orderType
));
}
function claimFundingFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIM_FUNDING_FEES_FEATURE_DISABLED,
module
));
}
function claimCollateralFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIM_COLLATERAL_FEATURE_DISABLED,
module
));
}
function claimAffiliateRewardsFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIM_AFFILIATE_REWARDS_FEATURE_DISABLED,
module
));
}
function claimUiFeesFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIM_UI_FEES_FEATURE_DISABLED,
module
));
}
function subaccountFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
SUBACCOUNT_FEATURE_DISABLED,
module
));
}
function uiFeeFactorKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
UI_FEE_FACTOR,
account
));
}
function isOracleProviderEnabledKey(address provider) internal pure returns (bytes32) {
return keccak256(abi.encode(
IS_ORACLE_PROVIDER_ENABLED,
provider
));
}
function isAtomicOracleProviderKey(address provider) internal pure returns (bytes32) {
return keccak256(abi.encode(
IS_ATOMIC_ORACLE_PROVIDER,
provider
));
}
function oracleTimestampAdjustmentKey(address provider, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
ORACLE_TIMESTAMP_ADJUSTMENT,
provider,
token
));
}
function oracleProviderForTokenKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
ORACLE_PROVIDER_FOR_TOKEN,
token
));
}
function tokenTransferGasLimit(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
TOKEN_TRANSFER_GAS_LIMIT,
token
));
}
function savedCallbackContract(address account, address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
SAVED_CALLBACK_CONTRACT,
account,
market
));
}
function minCollateralFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_COLLATERAL_FACTOR,
market
));
}
function minCollateralFactorForOpenInterestMultiplierKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_COLLATERAL_FACTOR_FOR_OPEN_INTEREST_MULTIPLIER,
market,
isLong
));
}
function virtualTokenIdKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
VIRTUAL_TOKEN_ID,
token
));
}
function virtualMarketIdKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
VIRTUAL_MARKET_ID,
market
));
}
function virtualInventoryForPositionsKey(bytes32 virtualTokenId) internal pure returns (bytes32) {
return keccak256(abi.encode(
VIRTUAL_INVENTORY_FOR_POSITIONS,
virtualTokenId
));
}
function virtualInventoryForSwapsKey(bytes32 virtualMarketId, bool isLongToken) internal pure returns (bytes32) {
return keccak256(abi.encode(
VIRTUAL_INVENTORY_FOR_SWAPS,
virtualMarketId,
isLongToken
));
}
function positionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_IMPACT_FACTOR,
market,
isPositive
));
}
function positionImpactExponentFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_IMPACT_EXPONENT_FACTOR,
market
));
}
function maxPositionImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_POSITION_IMPACT_FACTOR,
market,
isPositive
));
}
function maxPositionImpactFactorForLiquidationsKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_POSITION_IMPACT_FACTOR_FOR_LIQUIDATIONS,
market
));
}
function positionFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_FEE_FACTOR,
market,
forPositiveImpact
));
}
function proTraderTierKey(address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
PRO_TRADER_TIER,
account
));
}
function proDiscountFactorKey(uint256 proTier) internal pure returns (bytes32) {
return keccak256(abi.encode(
PRO_DISCOUNT_FACTOR,
proTier
));
}
function liquidationFeeFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
LIQUIDATION_FEE_FACTOR,
market
));
}
function swapImpactFactorKey(address market, bool isPositive) internal pure returns (bytes32) {
return keccak256(abi.encode(
SWAP_IMPACT_FACTOR,
market,
isPositive
));
}
function swapImpactExponentFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
SWAP_IMPACT_EXPONENT_FACTOR,
market
));
}
function swapFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
return keccak256(abi.encode(
SWAP_FEE_FACTOR,
market,
forPositiveImpact
));
}
function atomicSwapFeeFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
ATOMIC_SWAP_FEE_FACTOR,
market
));
}
function depositFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
return keccak256(abi.encode(
DEPOSIT_FEE_FACTOR,
market,
forPositiveImpact
));
}
function withdrawalFeeFactorKey(address market, bool forPositiveImpact) internal pure returns (bytes32) {
return keccak256(abi.encode(
WITHDRAWAL_FEE_FACTOR,
market,
forPositiveImpact
));
}
function oracleTypeKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
ORACLE_TYPE,
token
));
}
function openInterestKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
OPEN_INTEREST,
market,
collateralToken,
isLong
));
}
function openInterestInTokensKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
OPEN_INTEREST_IN_TOKENS,
market,
collateralToken,
isLong
));
}
function collateralSumKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
COLLATERAL_SUM,
market,
collateralToken,
isLong
));
}
function poolAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
POOL_AMOUNT,
market,
token
));
}
function maxPoolAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_POOL_AMOUNT,
market,
token
));
}
function maxPoolUsdForDepositKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_POOL_USD_FOR_DEPOSIT,
market,
token
));
}
function maxOpenInterestKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_OPEN_INTEREST,
market,
isLong
));
}
function positionImpactPoolAmountKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_IMPACT_POOL_AMOUNT,
market
));
}
function minPositionImpactPoolAmountKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_POSITION_IMPACT_POOL_AMOUNT,
market
));
}
function positionImpactPoolDistributionRateKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_IMPACT_POOL_DISTRIBUTION_RATE,
market
));
}
function positionImpactPoolDistributedAtKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
POSITION_IMPACT_POOL_DISTRIBUTED_AT,
market
));
}
function swapImpactPoolAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
SWAP_IMPACT_POOL_AMOUNT,
market,
token
));
}
function reserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
RESERVE_FACTOR,
market,
isLong
));
}
function openInterestReserveFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
OPEN_INTEREST_RESERVE_FACTOR,
market,
isLong
));
}
function maxPnlFactorKey(bytes32 pnlFactorType, address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_PNL_FACTOR,
pnlFactorType,
market,
isLong
));
}
function minPnlFactorAfterAdlKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_PNL_FACTOR_AFTER_ADL,
market,
isLong
));
}
function latestAdlAtKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
LATEST_ADL_AT,
market,
isLong
));
}
function isAdlEnabledKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
IS_ADL_ENABLED,
market,
isLong
));
}
function fundingFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_FACTOR,
market
));
}
function fundingExponentFactorKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_EXPONENT_FACTOR,
market
));
}
function savedFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
SAVED_FUNDING_FACTOR_PER_SECOND,
market
));
}
function fundingIncreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_INCREASE_FACTOR_PER_SECOND,
market
));
}
function fundingDecreaseFactorPerSecondKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_DECREASE_FACTOR_PER_SECOND,
market
));
}
function minFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_FUNDING_FACTOR_PER_SECOND,
market
));
}
function maxFundingFactorPerSecondKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_FUNDING_FACTOR_PER_SECOND,
market
));
}
function thresholdForStableFundingKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
THRESHOLD_FOR_STABLE_FUNDING,
market
));
}
function thresholdForDecreaseFundingKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
THRESHOLD_FOR_DECREASE_FUNDING,
market
));
}
function fundingFeeAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_FEE_AMOUNT_PER_SIZE,
market,
collateralToken,
isLong
));
}
function claimableFundingAmountPerSizeKey(address market, address collateralToken, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_FUNDING_AMOUNT_PER_SIZE,
market,
collateralToken,
isLong
));
}
function fundingUpdatedAtKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
FUNDING_UPDATED_AT,
market
));
}
function claimableFundingAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_FUNDING_AMOUNT,
market,
token
));
}
function claimableFundingAmountKey(address market, address token, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_FUNDING_AMOUNT,
market,
token,
account
));
}
function claimableCollateralAmountKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_COLLATERAL_AMOUNT,
market,
token
));
}
function claimableCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_COLLATERAL_AMOUNT,
market,
token,
timeKey,
account
));
}
function claimableCollateralFactorKey(address market, address token, uint256 timeKey) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_COLLATERAL_FACTOR,
market,
token,
timeKey
));
}
function claimableCollateralFactorKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMABLE_COLLATERAL_FACTOR,
market,
token,
timeKey,
account
));
}
function claimedCollateralAmountKey(address market, address token, uint256 timeKey, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
CLAIMED_COLLATERAL_AMOUNT,
market,
token,
timeKey,
account
));
}
function optimalUsageFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
OPTIMAL_USAGE_FACTOR,
market,
isLong
));
}
function baseBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
BASE_BORROWING_FACTOR,
market,
isLong
));
}
function aboveOptimalUsageBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
ABOVE_OPTIMAL_USAGE_BORROWING_FACTOR,
market,
isLong
));
}
function borrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
BORROWING_FACTOR,
market,
isLong
));
}
function borrowingExponentFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
BORROWING_EXPONENT_FACTOR,
market,
isLong
));
}
function cumulativeBorrowingFactorKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
CUMULATIVE_BORROWING_FACTOR,
market,
isLong
));
}
function cumulativeBorrowingFactorUpdatedAtKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
CUMULATIVE_BORROWING_FACTOR_UPDATED_AT,
market,
isLong
));
}
function totalBorrowingKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
TOTAL_BORROWING,
market,
isLong
));
}
function affiliateRewardKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
AFFILIATE_REWARD,
market,
token
));
}
function minAffiliateRewardFactorKey(uint256 referralTierLevel) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_AFFILIATE_REWARD_FACTOR,
referralTierLevel
));
}
function maxAllowedSubaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_ALLOWED_SUBACCOUNT_ACTION_COUNT,
account,
subaccount,
actionType
));
}
function subaccountActionCountKey(address account, address subaccount, bytes32 actionType) internal pure returns (bytes32) {
return keccak256(abi.encode(
SUBACCOUNT_ACTION_COUNT,
account,
subaccount,
actionType
));
}
function subaccountAutoTopUpAmountKey(address account, address subaccount) internal pure returns (bytes32) {
return keccak256(abi.encode(
SUBACCOUNT_AUTO_TOP_UP_AMOUNT,
account,
subaccount
));
}
function affiliateRewardKey(address market, address token, address account) internal pure returns (bytes32) {
return keccak256(abi.encode(
AFFILIATE_REWARD,
market,
token,
account
));
}
function isMarketDisabledKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
IS_MARKET_DISABLED,
market
));
}
function minMarketTokensForFirstDepositKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_MARKET_TOKENS_FOR_FIRST_DEPOSIT,
market
));
}
function priceFeedKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
PRICE_FEED,
token
));
}
function dataStreamIdKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
DATA_STREAM_ID,
token
));
}
function dataStreamMultiplierKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
DATA_STREAM_MULTIPLIER,
token
));
}
function dataStreamSpreadReductionFactorKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
DATA_STREAM_SPREAD_REDUCTION_FACTOR,
token
));
}
function priceFeedMultiplierKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
PRICE_FEED_MULTIPLIER,
token
));
}
function priceFeedHeartbeatDurationKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
PRICE_FEED_HEARTBEAT_DURATION,
token
));
}
function stablePriceKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
STABLE_PRICE,
token
));
}
function feeDistributorSwapTokenIndexKey(bytes32 orderKey) internal pure returns (bytes32) {
return keccak256(abi.encode(
FEE_DISTRIBUTOR_SWAP_TOKEN_INDEX,
orderKey
));
}
function feeDistributorSwapFeeBatchKey(bytes32 orderKey) internal pure returns (bytes32) {
return keccak256(abi.encode(
FEE_DISTRIBUTOR_SWAP_FEE_BATCH,
orderKey
));
}
function glvMaxMarketTokenBalanceUsdKey(address glv, address market) internal pure returns (bytes32) {
return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_USD, glv, market));
}
function glvMaxMarketTokenBalanceAmountKey(address glv, address market) internal pure returns (bytes32) {
return keccak256(abi.encode(GLV_MAX_MARKET_TOKEN_BALANCE_AMOUNT, glv, market));
}
function isGlvMarketDisabledKey(address glv, address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
IS_GLV_MARKET_DISABLED,
glv,
market
));
}
function glvShiftMaxPriceImpactFactorKey(address glv) internal pure returns (bytes32) {
return keccak256(abi.encode(
GLV_SHIFT_MAX_PRICE_IMPACT_FACTOR,
glv
));
}
function glvShiftLastExecutedAtKey(address glv) internal pure returns (bytes32) {
return keccak256(abi.encode(
GLV_SHIFT_LAST_EXECUTED_AT,
glv
));
}
function glvShiftMinIntervalKey(address glv) internal pure returns (bytes32) {
return keccak256(abi.encode(
GLV_SHIFT_MIN_INTERVAL,
glv
));
}
function minGlvTokensForFirstGlvDepositKey(address glv) internal pure returns (bytes32) {
return keccak256(abi.encode(
MIN_GLV_TOKENS_FOR_FIRST_DEPOSIT,
glv
));
}
function syncConfigFeatureDisabledKey(address module) internal pure returns (bytes32) {
return keccak256(abi.encode(
SYNC_CONFIG_FEATURE_DISABLED,
module
));
}
function syncConfigMarketDisabledKey(address market) internal pure returns (bytes32) {
return keccak256(abi.encode(
SYNC_CONFIG_MARKET_DISABLED,
market
));
}
function syncConfigParameterDisabledKey(string memory parameter) internal pure returns (bytes32) {
return keccak256(abi.encode(
SYNC_CONFIG_PARAMETER_DISABLED,
parameter
));
}
function syncConfigMarketParameterDisabledKey(address market, string memory parameter) internal pure returns (bytes32) {
return keccak256(abi.encode(
SYNC_CONFIG_MARKET_PARAMETER_DISABLED,
market,
parameter
));
}
function syncConfigUpdateCompletedKey(uint256 updateId) internal pure returns (bytes32) {
return keccak256(abi.encode(
SYNC_CONFIG_UPDATE_COMPLETED,
updateId
));
}
function syncConfigLatestUpdateIdKey() internal pure returns (bytes32) {
return SYNC_CONFIG_LATEST_UPDATE_ID;
}
function contributorTokenAmountKey(address account, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
CONTRIBUTOR_TOKEN_AMOUNT,
account,
token
));
}
function maxTotalContributorTokenAmountKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_TOTAL_CONTRIBUTOR_TOKEN_AMOUNT,
token
));
}
function contributorTokenVaultKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
CONTRIBUTOR_TOKEN_VAULT,
token
));
}
function buybackBatchAmountKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
BUYBACK_BATCH_AMOUNT,
token
));
}
function buybackAvailableFeeAmountKey(address feeToken, address swapToken) internal pure returns (bytes32) {
return keccak256(abi.encode(
BUYBACK_AVAILABLE_FEE_AMOUNT,
feeToken,
swapToken
));
}
function withdrawableBuybackTokenAmountKey(address buybackToken) internal pure returns (bytes32) {
return keccak256(abi.encode(
WITHDRAWABLE_BUYBACK_TOKEN_AMOUNT,
buybackToken
));
}
function buybackGmxFactorKey(uint256 version) internal pure returns (bytes32) {
return keccak256(abi.encode(
BUYBACK_GMX_FACTOR,
version
));
}
function buybackMaxPriceImpactFactorKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
BUYBACK_MAX_PRICE_IMPACT_FACTOR,
token
));
}
}
文件 34 的 57:Market.sol
pragma solidity ^0.8.0;
library Market {
struct Props {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
}
文件 35 的 57:MarketEventUtils.sol
pragma solidity ^0.8.0;
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Cast.sol";
import "./MarketPoolValueInfo.sol";
library MarketEventUtils {
using EventUtils for EventUtils.AddressItems;
using EventUtils for EventUtils.UintItems;
using EventUtils for EventUtils.IntItems;
using EventUtils for EventUtils.BoolItems;
using EventUtils for EventUtils.Bytes32Items;
using EventUtils for EventUtils.BytesItems;
using EventUtils for EventUtils.StringItems;
function emitMarketPoolValueInfo(
EventEmitter eventEmitter,
bytes32 tradeKey,
address market,
MarketPoolValueInfo.Props memory props,
uint256 marketTokensSupply
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "tradeKey", tradeKey);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.intItems.initItems(4);
eventData.intItems.setItem(0, "poolValue", props.poolValue);
eventData.intItems.setItem(1, "longPnl", props.longPnl);
eventData.intItems.setItem(2, "shortPnl", props.shortPnl);
eventData.intItems.setItem(3, "netPnl", props.netPnl);
eventData.uintItems.initItems(8);
eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount);
eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount);
eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd);
eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd);
eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees);
eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor);
eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount);
eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply);
eventEmitter.emitEventLog1(
"MarketPoolValueInfo",
Cast.toBytes32(market),
eventData
);
}
function emitMarketPoolValueUpdated(
EventEmitter eventEmitter,
bytes32 actionType,
bytes32 tradeKey,
address market,
MarketPoolValueInfo.Props memory props,
uint256 marketTokensSupply
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(2);
eventData.bytes32Items.setItem(0, "actionType", actionType);
eventData.bytes32Items.setItem(1, "tradeKey", tradeKey);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.intItems.initItems(4);
eventData.intItems.setItem(0, "poolValue", props.poolValue);
eventData.intItems.setItem(1, "longPnl", props.longPnl);
eventData.intItems.setItem(2, "shortPnl", props.shortPnl);
eventData.intItems.setItem(3, "netPnl", props.netPnl);
eventData.uintItems.initItems(8);
eventData.uintItems.setItem(0, "longTokenAmount", props.longTokenAmount);
eventData.uintItems.setItem(1, "shortTokenAmount", props.shortTokenAmount);
eventData.uintItems.setItem(2, "longTokenUsd", props.longTokenUsd);
eventData.uintItems.setItem(3, "shortTokenUsd", props.shortTokenUsd);
eventData.uintItems.setItem(4, "totalBorrowingFees", props.totalBorrowingFees);
eventData.uintItems.setItem(5, "borrowingFeePoolFactor", props.borrowingFeePoolFactor);
eventData.uintItems.setItem(6, "impactPoolAmount", props.impactPoolAmount);
eventData.uintItems.setItem(7, "marketTokensSupply", marketTokensSupply);
eventEmitter.emitEventLog1(
"MarketPoolValueUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitPoolAmountUpdated(
EventEmitter eventEmitter,
address market,
address token,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"PoolAmountUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitSwapImpactPoolAmountUpdated(
EventEmitter eventEmitter,
address market,
address token,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"SwapImpactPoolAmountUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitPositionImpactPoolDistributed(
EventEmitter eventEmitter,
address market,
uint256 distributionAmount,
uint256 nextPositionImpactPoolAmount
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "distributionAmount", distributionAmount);
eventData.uintItems.setItem(1, "nextPositionImpactPoolAmount", nextPositionImpactPoolAmount);
eventEmitter.emitEventLog1(
"PositionImpactPoolDistributed",
Cast.toBytes32(market),
eventData
);
}
function emitPositionImpactPoolAmountUpdated(
EventEmitter eventEmitter,
address market,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"PositionImpactPoolAmountUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitOpenInterestUpdated(
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "collateralToken", collateralToken);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"OpenInterestUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitVirtualSwapInventoryUpdated(
EventEmitter eventEmitter,
address market,
bool isLongToken,
bytes32 virtualMarketId,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLongToken", isLongToken);
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "virtualMarketId", virtualMarketId);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog2(
"VirtualSwapInventoryUpdated",
Cast.toBytes32(market),
virtualMarketId,
eventData
);
}
function emitVirtualPositionInventoryUpdated(
EventEmitter eventEmitter,
address token,
bytes32 virtualTokenId,
int256 delta,
int256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "token", token);
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "virtualTokenId", virtualTokenId);
eventData.intItems.initItems(2);
eventData.intItems.setItem(0, "delta", delta);
eventData.intItems.setItem(1, "nextValue", nextValue);
eventEmitter.emitEventLog2(
"VirtualPositionInventoryUpdated",
Cast.toBytes32(token),
virtualTokenId,
eventData
);
}
function emitOpenInterestInTokensUpdated(
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "collateralToken", collateralToken);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"OpenInterestInTokensUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitCollateralSumUpdated(
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
int256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "collateralToken", collateralToken);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "delta", delta);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"CollateralSumUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitBorrowingFactorUpdated(
EventEmitter eventEmitter,
address market,
bool isLong,
uint256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "market", market);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"CumulativeBorrowingFactorUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitFundingFeeAmountPerSizeUpdated(
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
uint256 delta,
uint256 value
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "collateralToken", collateralToken);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "value", value);
eventEmitter.emitEventLog1(
"FundingFeeAmountPerSizeUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitClaimableFundingAmountPerSizeUpdated(
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
uint256 delta,
uint256 value
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "collateralToken", collateralToken);
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "value", value);
eventEmitter.emitEventLog1(
"ClaimableFundingAmountPerSizeUpdated",
Cast.toBytes32(market),
eventData
);
}
function emitClaimableFundingUpdated(
EventEmitter eventEmitter,
address market,
address token,
address account,
uint256 delta,
uint256 nextValue,
uint256 nextPoolValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "nextValue", nextValue);
eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"ClaimableFundingUpdated",
Cast.toBytes32(account),
eventData
);
}
function emitFundingFeesClaimed(
EventEmitter eventEmitter,
address market,
address token,
address account,
address receiver,
uint256 amount,
uint256 nextPoolValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(4);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.addressItems.setItem(3, "receiver", receiver);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "amount", amount);
eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"FundingFeesClaimed",
Cast.toBytes32(account),
eventData
);
}
function emitClaimableFundingUpdated(
EventEmitter eventEmitter,
address market,
address token,
uint256 timeKey,
address account,
uint256 delta,
uint256 nextValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "timeKey", timeKey);
eventData.uintItems.setItem(1, "delta", delta);
eventData.uintItems.setItem(2, "nextValue", nextValue);
eventEmitter.emitEventLog1(
"ClaimableFundingUpdated",
Cast.toBytes32(account),
eventData
);
}
function emitClaimableCollateralUpdated(
EventEmitter eventEmitter,
address market,
address token,
uint256 timeKey,
address account,
uint256 delta,
uint256 nextValue,
uint256 nextPoolValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.uintItems.initItems(4);
eventData.uintItems.setItem(0, "timeKey", timeKey);
eventData.uintItems.setItem(1, "delta", delta);
eventData.uintItems.setItem(2, "nextValue", nextValue);
eventData.uintItems.setItem(3, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"ClaimableCollateralUpdated",
Cast.toBytes32(account),
eventData
);
}
function emitCollateralClaimed(
EventEmitter eventEmitter,
address market,
address token,
uint256 timeKey,
address account,
address receiver,
uint256 amount,
uint256 nextPoolValue
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(4);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "token", token);
eventData.addressItems.setItem(2, "account", account);
eventData.addressItems.setItem(3, "receiver", receiver);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "timeKey", timeKey);
eventData.uintItems.setItem(1, "amount", amount);
eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"CollateralClaimed",
Cast.toBytes32(account),
eventData
);
}
function emitUiFeeFactorUpdated(
EventEmitter eventEmitter,
address account,
uint256 uiFeeFactor
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "uiFeeFactor", uiFeeFactor);
eventEmitter.emitEventLog1(
"UiFeeFactorUpdated",
Cast.toBytes32(account),
eventData
);
}
}
文件 36 的 57:MarketPoolValueInfo.sol
pragma solidity ^0.8.0;
library MarketPoolValueInfo {
struct Props {
int256 poolValue;
int256 longPnl;
int256 shortPnl;
int256 netPnl;
uint256 longTokenAmount;
uint256 shortTokenAmount;
uint256 longTokenUsd;
uint256 shortTokenUsd;
uint256 totalBorrowingFees;
uint256 borrowingFeePoolFactor;
uint256 impactPoolAmount;
}
}
文件 37 的 57:MarketStoreUtils.sol
pragma solidity ^0.8.0;
import "../data/Keys.sol";
import "../data/DataStore.sol";
import "./Market.sol";
library MarketStoreUtils {
using Market for Market.Props;
bytes32 public constant MARKET_SALT = keccak256(abi.encode("MARKET_SALT"));
bytes32 public constant MARKET_KEY = keccak256(abi.encode("MARKET_KEY"));
bytes32 public constant MARKET_TOKEN = keccak256(abi.encode("MARKET_TOKEN"));
bytes32 public constant INDEX_TOKEN = keccak256(abi.encode("INDEX_TOKEN"));
bytes32 public constant LONG_TOKEN = keccak256(abi.encode("LONG_TOKEN"));
bytes32 public constant SHORT_TOKEN = keccak256(abi.encode("SHORT_TOKEN"));
function get(DataStore dataStore, address key) public view returns (Market.Props memory) {
Market.Props memory market;
if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {
return market;
}
market.marketToken = dataStore.getAddress(
keccak256(abi.encode(key, MARKET_TOKEN))
);
market.indexToken = dataStore.getAddress(
keccak256(abi.encode(key, INDEX_TOKEN))
);
market.longToken = dataStore.getAddress(
keccak256(abi.encode(key, LONG_TOKEN))
);
market.shortToken = dataStore.getAddress(
keccak256(abi.encode(key, SHORT_TOKEN))
);
return market;
}
function getBySalt(DataStore dataStore, bytes32 salt) external view returns (Market.Props memory) {
address key = dataStore.getAddress(getMarketSaltHash(salt));
return get(dataStore, key);
}
function set(DataStore dataStore, address key, bytes32 salt, Market.Props memory market) external {
dataStore.addAddress(
Keys.MARKET_LIST,
key
);
dataStore.setAddress(
getMarketSaltHash(salt),
key
);
dataStore.setAddress(
keccak256(abi.encode(key, MARKET_TOKEN)),
market.marketToken
);
dataStore.setAddress(
keccak256(abi.encode(key, INDEX_TOKEN)),
market.indexToken
);
dataStore.setAddress(
keccak256(abi.encode(key, LONG_TOKEN)),
market.longToken
);
dataStore.setAddress(
keccak256(abi.encode(key, SHORT_TOKEN)),
market.shortToken
);
}
function remove(DataStore dataStore, address key) external {
if (!dataStore.containsAddress(Keys.MARKET_LIST, key)) {
revert Errors.MarketNotFound(key);
}
dataStore.removeAddress(
Keys.MARKET_LIST,
key
);
dataStore.removeAddress(
keccak256(abi.encode(key, MARKET_TOKEN))
);
dataStore.removeAddress(
keccak256(abi.encode(key, INDEX_TOKEN))
);
dataStore.removeAddress(
keccak256(abi.encode(key, LONG_TOKEN))
);
dataStore.removeAddress(
keccak256(abi.encode(key, SHORT_TOKEN))
);
}
function getMarketSaltHash(bytes32 salt) internal pure returns (bytes32) {
return keccak256(abi.encode(MARKET_SALT, salt));
}
function getMarketCount(DataStore dataStore) internal view returns (uint256) {
return dataStore.getAddressCount(Keys.MARKET_LIST);
}
function getMarketKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (address[] memory) {
return dataStore.getAddressValuesAt(Keys.MARKET_LIST, start, end);
}
}
文件 38 的 57:MarketToken.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../bank/Bank.sol";
contract MarketToken is ERC20, Bank {
constructor(RoleStore _roleStore, DataStore _dataStore) ERC20("GMX Market", "GM") Bank(_roleStore, _dataStore) {
}
function mint(address account, uint256 amount) external onlyController {
_mint(account, amount);
}
function burn(address account, uint256 amount) external onlyController {
_burn(account, amount);
}
}
文件 39 的 57:MarketUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../data/DataStore.sol";
import "../event/EventEmitter.sol";
import "./Market.sol";
import "./MarketPoolValueInfo.sol";
import "./MarketToken.sol";
import "./MarketEventUtils.sol";
import "./MarketStoreUtils.sol";
import "../position/Position.sol";
import "../order/Order.sol";
import "../oracle/Oracle.sol";
import "../price/Price.sol";
import "../utils/Calc.sol";
import "../utils/Precision.sol";
library MarketUtils {
using SignedMath for int256;
using SafeCast for int256;
using SafeCast for uint256;
using Market for Market.Props;
using Position for Position.Props;
using Order for Order.Props;
using Price for Price.Props;
enum FundingRateChangeType {
NoChange,
Increase,
Decrease
}
struct MarketPrices {
Price.Props indexTokenPrice;
Price.Props longTokenPrice;
Price.Props shortTokenPrice;
}
struct CollateralType {
uint256 longToken;
uint256 shortToken;
}
struct PositionType {
CollateralType long;
CollateralType short;
}
struct GetNextFundingAmountPerSizeResult {
bool longsPayShorts;
uint256 fundingFactorPerSecond;
int256 nextSavedFundingFactorPerSecond;
PositionType fundingFeeAmountPerSizeDelta;
PositionType claimableFundingAmountPerSizeDelta;
}
struct GetNextFundingAmountPerSizeCache {
PositionType openInterest;
uint256 longOpenInterest;
uint256 shortOpenInterest;
uint256 durationInSeconds;
uint256 sizeOfLargerSide;
uint256 fundingUsd;
uint256 fundingUsdForLongCollateral;
uint256 fundingUsdForShortCollateral;
}
struct GetNextFundingFactorPerSecondCache {
uint256 diffUsd;
uint256 totalOpenInterest;
uint256 fundingFactor;
uint256 fundingExponentFactor;
uint256 diffUsdAfterExponent;
uint256 diffUsdToOpenInterestFactor;
int256 savedFundingFactorPerSecond;
uint256 savedFundingFactorPerSecondMagnitude;
int256 nextSavedFundingFactorPerSecond;
int256 nextSavedFundingFactorPerSecondWithMinBound;
}
struct FundingConfigCache {
uint256 thresholdForStableFunding;
uint256 thresholdForDecreaseFunding;
uint256 fundingIncreaseFactorPerSecond;
uint256 fundingDecreaseFactorPerSecond;
uint256 minFundingFactorPerSecond;
uint256 maxFundingFactorPerSecond;
}
struct GetExpectedMinTokenBalanceCache {
uint256 poolAmount;
uint256 swapImpactPoolAmount;
uint256 claimableCollateralAmount;
uint256 claimableFeeAmount;
uint256 claimableUiFeeAmount;
uint256 affiliateRewardAmount;
}
function getMarketTokenPrice(
DataStore dataStore,
Market.Props memory market,
Price.Props memory indexTokenPrice,
Price.Props memory longTokenPrice,
Price.Props memory shortTokenPrice,
bytes32 pnlFactorType,
bool maximize
) external view returns (int256, MarketPoolValueInfo.Props memory) {
uint256 supply = getMarketTokenSupply(MarketToken(payable(market.marketToken)));
MarketPoolValueInfo.Props memory poolValueInfo = getPoolValueInfo(
dataStore,
market,
indexTokenPrice,
longTokenPrice,
shortTokenPrice,
pnlFactorType,
maximize
);
if (supply == 0) {
return (Precision.FLOAT_PRECISION.toInt256(), poolValueInfo);
}
if (poolValueInfo.poolValue == 0) { return (0, poolValueInfo); }
int256 marketTokenPrice = Precision.mulDiv(Precision.WEI_PRECISION, poolValueInfo.poolValue, supply);
return (marketTokenPrice, poolValueInfo);
}
function getMarketTokenSupply(MarketToken marketToken) internal view returns (uint256) {
return marketToken.totalSupply();
}
function getOppositeToken(address inputToken, Market.Props memory market) internal pure returns (address) {
if (inputToken == market.longToken) {
return market.shortToken;
}
if (inputToken == market.shortToken) {
return market.longToken;
}
revert Errors.UnableToGetOppositeToken(inputToken, market.marketToken);
}
function validateSwapMarket(DataStore dataStore, address marketAddress) internal view {
Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
validateSwapMarket(dataStore, market);
}
function validateSwapMarket(DataStore dataStore, Market.Props memory market) internal view {
validateEnabledMarket(dataStore, market);
if (market.longToken == market.shortToken) {
revert Errors.InvalidSwapMarket(market.marketToken);
}
}
function getCachedTokenPrice(address token, Market.Props memory market, MarketPrices memory prices) internal pure returns (Price.Props memory) {
if (token == market.longToken) {
return prices.longTokenPrice;
}
if (token == market.shortToken) {
return prices.shortTokenPrice;
}
if (token == market.indexToken) {
return prices.indexTokenPrice;
}
revert Errors.UnableToGetCachedTokenPrice(token, market.marketToken);
}
function getMarketPrices(Oracle oracle, Market.Props memory market) internal view returns (MarketPrices memory) {
return MarketPrices(
oracle.getPrimaryPrice(market.indexToken),
oracle.getPrimaryPrice(market.longToken),
oracle.getPrimaryPrice(market.shortToken)
);
}
function getPoolUsdWithoutPnl(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong,
bool maximize
) internal view returns (uint256) {
address token = isLong ? market.longToken : market.shortToken;
uint256 poolAmount = getPoolAmount(dataStore, market, token);
uint256 tokenPrice;
if (maximize) {
tokenPrice = isLong ? prices.longTokenPrice.max : prices.shortTokenPrice.max;
} else {
tokenPrice = isLong ? prices.longTokenPrice.min : prices.shortTokenPrice.min;
}
return poolAmount * tokenPrice;
}
function getPoolValueInfo(
DataStore dataStore,
Market.Props memory market,
Price.Props memory indexTokenPrice,
Price.Props memory longTokenPrice,
Price.Props memory shortTokenPrice,
bytes32 pnlFactorType,
bool maximize
) public view returns (MarketPoolValueInfo.Props memory) {
MarketPoolValueInfo.Props memory result;
result.longTokenAmount = getPoolAmount(dataStore, market, market.longToken);
result.shortTokenAmount = getPoolAmount(dataStore, market, market.shortToken);
result.longTokenUsd = result.longTokenAmount * longTokenPrice.pickPrice(maximize);
result.shortTokenUsd = result.shortTokenAmount * shortTokenPrice.pickPrice(maximize);
result.poolValue = (result.longTokenUsd + result.shortTokenUsd).toInt256();
MarketPrices memory prices = MarketPrices(
indexTokenPrice,
longTokenPrice,
shortTokenPrice
);
result.totalBorrowingFees = getTotalPendingBorrowingFees(
dataStore,
market,
prices,
true
);
result.totalBorrowingFees += getTotalPendingBorrowingFees(
dataStore,
market,
prices,
false
);
result.borrowingFeePoolFactor = Precision.FLOAT_PRECISION - dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);
result.poolValue += Precision.applyFactor(result.totalBorrowingFees, result.borrowingFeePoolFactor).toInt256();
result.longPnl = getPnl(
dataStore,
market,
indexTokenPrice,
true,
!maximize
);
result.longPnl = getCappedPnl(
dataStore,
market.marketToken,
true,
result.longPnl,
result.longTokenUsd,
pnlFactorType
);
result.shortPnl = getPnl(
dataStore,
market,
indexTokenPrice,
false,
!maximize
);
result.shortPnl = getCappedPnl(
dataStore,
market.marketToken,
false,
result.shortPnl,
result.shortTokenUsd,
pnlFactorType
);
result.netPnl = result.longPnl + result.shortPnl;
result.poolValue = result.poolValue - result.netPnl;
result.impactPoolAmount = getNextPositionImpactPoolAmount(dataStore, market.marketToken);
uint256 impactPoolUsd = result.impactPoolAmount * indexTokenPrice.pickPrice(!maximize);
result.poolValue -= impactPoolUsd.toInt256();
return result;
}
function getNetPnl(
DataStore dataStore,
Market.Props memory market,
Price.Props memory indexTokenPrice,
bool maximize
) internal view returns (int256) {
int256 longPnl = getPnl(dataStore, market, indexTokenPrice, true, maximize);
int256 shortPnl = getPnl(dataStore, market, indexTokenPrice, false, maximize);
return longPnl + shortPnl;
}
function getCappedPnl(
DataStore dataStore,
address market,
bool isLong,
int256 pnl,
uint256 poolUsd,
bytes32 pnlFactorType
) internal view returns (int256) {
if (pnl < 0) { return pnl; }
uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market, isLong);
int256 maxPnl = Precision.applyFactor(poolUsd, maxPnlFactor).toInt256();
return pnl > maxPnl ? maxPnl : pnl;
}
function getPnl(
DataStore dataStore,
Market.Props memory market,
uint256 indexTokenPrice,
bool isLong,
bool maximize
) internal view returns (int256) {
Price.Props memory _indexTokenPrice = Price.Props(indexTokenPrice, indexTokenPrice);
return getPnl(
dataStore,
market,
_indexTokenPrice,
isLong,
maximize
);
}
function getPnl(
DataStore dataStore,
Market.Props memory market,
Price.Props memory indexTokenPrice,
bool isLong,
bool maximize
) internal view returns (int256) {
int256 openInterest = getOpenInterest(dataStore, market, isLong).toInt256();
uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);
if (openInterest == 0 || openInterestInTokens == 0) {
return 0;
}
uint256 price = indexTokenPrice.pickPriceForPnl(isLong, maximize);
int256 openInterestValue = (openInterestInTokens * price).toInt256();
int256 pnl = isLong ? openInterestValue - openInterest : openInterest - openInterestValue;
return pnl;
}
function getPoolAmount(DataStore dataStore, Market.Props memory market, address token) internal view returns (uint256) {
uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
return dataStore.getUint(Keys.poolAmountKey(market.marketToken, token)) / divisor;
}
function getMaxPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {
return dataStore.getUint(Keys.maxPoolAmountKey(market, token));
}
function getMaxPoolUsdForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {
return dataStore.getUint(Keys.maxPoolUsdForDepositKey(market, token));
}
function getUsageFactor(
DataStore dataStore,
Market.Props memory market,
bool isLong,
uint256 reservedUsd,
uint256 poolUsd
) internal view returns (uint256) {
uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);
uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
uint256 reserveUsageFactor = Precision.toFactor(reservedUsd, maxReservedUsd);
if (dataStore.getBool(Keys.IGNORE_OPEN_INTEREST_FOR_USAGE_FACTOR)) {
return reserveUsageFactor;
}
uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);
uint256 openInterest = getOpenInterest(dataStore, market, isLong);
uint256 openInterestUsageFactor = Precision.toFactor(openInterest, maxOpenInterest);
return reserveUsageFactor > openInterestUsageFactor ? reserveUsageFactor : openInterestUsageFactor;
}
function getMaxOpenInterest(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.maxOpenInterestKey(market, isLong));
}
function incrementClaimableCollateralAmount(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address account,
uint256 delta
) internal {
uint256 divisor = dataStore.getUint(Keys.CLAIMABLE_COLLATERAL_TIME_DIVISOR);
uint256 timeKey = Chain.currentTimestamp() / divisor;
uint256 nextValue = dataStore.incrementUint(
Keys.claimableCollateralAmountKey(market, token, timeKey, account),
delta
);
uint256 nextPoolValue = dataStore.incrementUint(
Keys.claimableCollateralAmountKey(market, token),
delta
);
MarketEventUtils.emitClaimableCollateralUpdated(
eventEmitter,
market,
token,
timeKey,
account,
delta,
nextValue,
nextPoolValue
);
}
function incrementClaimableFundingAmount(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address account,
uint256 delta
) internal {
uint256 nextValue = dataStore.incrementUint(
Keys.claimableFundingAmountKey(market, token, account),
delta
);
uint256 nextPoolValue = dataStore.incrementUint(
Keys.claimableFundingAmountKey(market, token),
delta
);
MarketEventUtils.emitClaimableFundingUpdated(
eventEmitter,
market,
token,
account,
delta,
nextValue,
nextPoolValue
);
}
function claimFundingFees(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address account,
address receiver
) internal returns (uint256) {
bytes32 key = Keys.claimableFundingAmountKey(market, token, account);
uint256 claimableAmount = dataStore.getUint(key);
dataStore.setUint(key, 0);
uint256 nextPoolValue = dataStore.decrementUint(
Keys.claimableFundingAmountKey(market, token),
claimableAmount
);
MarketToken(payable(market)).transferOut(
token,
receiver,
claimableAmount
);
validateMarketTokenBalance(dataStore, market);
MarketEventUtils.emitFundingFeesClaimed(
eventEmitter,
market,
token,
account,
receiver,
claimableAmount,
nextPoolValue
);
return claimableAmount;
}
function claimCollateral(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
uint256 timeKey,
address account,
address receiver
) internal returns (uint256) {
uint256 claimableAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market, token, timeKey, account));
uint256 claimableFactor;
{
uint256 claimableFactorForTime = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey));
uint256 claimableFactorForAccount = dataStore.getUint(Keys.claimableCollateralFactorKey(market, token, timeKey, account));
claimableFactor = claimableFactorForTime > claimableFactorForAccount ? claimableFactorForTime : claimableFactorForAccount;
}
if (claimableFactor > Precision.FLOAT_PRECISION) {
revert Errors.InvalidClaimableFactor(claimableFactor);
}
uint256 claimedAmount = dataStore.getUint(Keys.claimedCollateralAmountKey(market, token, timeKey, account));
uint256 adjustedClaimableAmount = Precision.applyFactor(claimableAmount, claimableFactor);
if (adjustedClaimableAmount <= claimedAmount) {
revert Errors.CollateralAlreadyClaimed(adjustedClaimableAmount, claimedAmount);
}
uint256 amountToBeClaimed = adjustedClaimableAmount - claimedAmount;
dataStore.setUint(
Keys.claimedCollateralAmountKey(market, token, timeKey, account),
adjustedClaimableAmount
);
uint256 nextPoolValue = dataStore.decrementUint(
Keys.claimableCollateralAmountKey(market, token),
amountToBeClaimed
);
MarketToken(payable(market)).transferOut(
token,
receiver,
amountToBeClaimed
);
validateMarketTokenBalance(dataStore, market);
MarketEventUtils.emitCollateralClaimed(
eventEmitter,
market,
token,
timeKey,
account,
receiver,
amountToBeClaimed,
nextPoolValue
);
return amountToBeClaimed;
}
function applyDeltaToPoolAmount(
DataStore dataStore,
EventEmitter eventEmitter,
Market.Props memory market,
address token,
int256 delta
) internal returns (uint256) {
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.poolAmountKey(market.marketToken, token),
delta,
"Invalid state, negative poolAmount"
);
applyDeltaToVirtualInventoryForSwaps(
dataStore,
eventEmitter,
market,
token,
delta
);
MarketEventUtils.emitPoolAmountUpdated(eventEmitter, market.marketToken, token, delta, nextValue);
return nextValue;
}
function getAdjustedSwapImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {
(uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedSwapImpactFactors(dataStore, market);
return isPositive ? positiveImpactFactor : negativeImpactFactor;
}
function getAdjustedSwapImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {
uint256 positiveImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, true));
uint256 negativeImpactFactor = dataStore.getUint(Keys.swapImpactFactorKey(market, false));
if (positiveImpactFactor > negativeImpactFactor) {
positiveImpactFactor = negativeImpactFactor;
}
return (positiveImpactFactor, negativeImpactFactor);
}
function getAdjustedPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {
(uint256 positiveImpactFactor, uint256 negativeImpactFactor) = getAdjustedPositionImpactFactors(dataStore, market);
return isPositive ? positiveImpactFactor : negativeImpactFactor;
}
function getAdjustedPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {
uint256 positiveImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, true));
uint256 negativeImpactFactor = dataStore.getUint(Keys.positionImpactFactorKey(market, false));
if (positiveImpactFactor > negativeImpactFactor) {
positiveImpactFactor = negativeImpactFactor;
}
return (positiveImpactFactor, negativeImpactFactor);
}
function getCappedPositionImpactUsd(
DataStore dataStore,
address market,
Price.Props memory indexTokenPrice,
int256 priceImpactUsd,
uint256 sizeDeltaUsd
) internal view returns (int256) {
if (priceImpactUsd < 0) {
return priceImpactUsd;
}
uint256 impactPoolAmount = getPositionImpactPoolAmount(dataStore, market);
int256 maxPriceImpactUsdBasedOnImpactPool = (impactPoolAmount * indexTokenPrice.min).toInt256();
if (priceImpactUsd > maxPriceImpactUsdBasedOnImpactPool) {
priceImpactUsd = maxPriceImpactUsdBasedOnImpactPool;
}
uint256 maxPriceImpactFactor = getMaxPositionImpactFactor(dataStore, market, true);
int256 maxPriceImpactUsdBasedOnMaxPriceImpactFactor = Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();
if (priceImpactUsd > maxPriceImpactUsdBasedOnMaxPriceImpactFactor) {
priceImpactUsd = maxPriceImpactUsdBasedOnMaxPriceImpactFactor;
}
return priceImpactUsd;
}
function getPositionImpactPoolAmount(DataStore dataStore, address market) internal view returns (uint256) {
return dataStore.getUint(Keys.positionImpactPoolAmountKey(market));
}
function getSwapImpactPoolAmount(DataStore dataStore, address market, address token) internal view returns (uint256) {
return dataStore.getUint(Keys.swapImpactPoolAmountKey(market, token));
}
function applyDeltaToSwapImpactPool(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
int256 delta
) internal returns (uint256) {
uint256 nextValue = dataStore.applyBoundedDeltaToUint(
Keys.swapImpactPoolAmountKey(market, token),
delta
);
MarketEventUtils.emitSwapImpactPoolAmountUpdated(eventEmitter, market, token, delta, nextValue);
return nextValue;
}
function applyDeltaToPositionImpactPool(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
int256 delta
) internal returns (uint256) {
uint256 nextValue = dataStore.applyBoundedDeltaToUint(
Keys.positionImpactPoolAmountKey(market),
delta
);
MarketEventUtils.emitPositionImpactPoolAmountUpdated(eventEmitter, market, delta, nextValue);
return nextValue;
}
function applyDeltaToOpenInterest(
DataStore dataStore,
EventEmitter eventEmitter,
Market.Props memory market,
address collateralToken,
bool isLong,
int256 delta
) internal returns (uint256) {
if (market.indexToken == address(0)) {
revert Errors.OpenInterestCannotBeUpdatedForSwapOnlyMarket(market.marketToken);
}
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.openInterestKey(market.marketToken, collateralToken, isLong),
delta,
"Invalid state: negative open interest"
);
applyDeltaToVirtualInventoryForPositions(
dataStore,
eventEmitter,
market.indexToken,
isLong ? -delta : delta
);
if (delta > 0) {
validateOpenInterest(
dataStore,
market,
isLong
);
}
MarketEventUtils.emitOpenInterestUpdated(eventEmitter, market.marketToken, collateralToken, isLong, delta, nextValue);
return nextValue;
}
function applyDeltaToOpenInterestInTokens(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
int256 delta
) internal returns (uint256) {
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.openInterestInTokensKey(market, collateralToken, isLong),
delta,
"Invalid state: negative open interest in tokens"
);
MarketEventUtils.emitOpenInterestInTokensUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);
return nextValue;
}
function applyDeltaToCollateralSum(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
int256 delta
) internal returns (uint256) {
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.collateralSumKey(market, collateralToken, isLong),
delta,
"Invalid state: negative collateralSum"
);
MarketEventUtils.emitCollateralSumUpdated(eventEmitter, market, collateralToken, isLong, delta, nextValue);
return nextValue;
}
function updateFundingState(
DataStore dataStore,
EventEmitter eventEmitter,
Market.Props memory market,
MarketPrices memory prices
) external {
GetNextFundingAmountPerSizeResult memory result = getNextFundingAmountPerSize(dataStore, market, prices);
applyDeltaToFundingFeeAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.longToken,
true,
result.fundingFeeAmountPerSizeDelta.long.longToken
);
applyDeltaToFundingFeeAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.longToken,
false,
result.fundingFeeAmountPerSizeDelta.short.longToken
);
applyDeltaToFundingFeeAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.shortToken,
true,
result.fundingFeeAmountPerSizeDelta.long.shortToken
);
applyDeltaToFundingFeeAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.shortToken,
false,
result.fundingFeeAmountPerSizeDelta.short.shortToken
);
applyDeltaToClaimableFundingAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.longToken,
true,
result.claimableFundingAmountPerSizeDelta.long.longToken
);
applyDeltaToClaimableFundingAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.longToken,
false,
result.claimableFundingAmountPerSizeDelta.short.longToken
);
applyDeltaToClaimableFundingAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.shortToken,
true,
result.claimableFundingAmountPerSizeDelta.long.shortToken
);
applyDeltaToClaimableFundingAmountPerSize(
dataStore,
eventEmitter,
market.marketToken,
market.shortToken,
false,
result.claimableFundingAmountPerSizeDelta.short.shortToken
);
setSavedFundingFactorPerSecond(dataStore, market.marketToken, result.nextSavedFundingFactorPerSecond);
dataStore.setUint(Keys.fundingUpdatedAtKey(market.marketToken), Chain.currentTimestamp());
}
function getNextFundingAmountPerSize(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices
) internal view returns (GetNextFundingAmountPerSizeResult memory) {
GetNextFundingAmountPerSizeResult memory result;
GetNextFundingAmountPerSizeCache memory cache;
uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
cache.openInterest.long.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, true, divisor);
cache.openInterest.long.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, true, divisor);
cache.openInterest.short.longToken = getOpenInterest(dataStore, market.marketToken, market.longToken, false, divisor);
cache.openInterest.short.shortToken = getOpenInterest(dataStore, market.marketToken, market.shortToken, false, divisor);
cache.longOpenInterest = cache.openInterest.long.longToken + cache.openInterest.long.shortToken;
cache.shortOpenInterest = cache.openInterest.short.longToken + cache.openInterest.short.shortToken;
if (cache.longOpenInterest == 0 || cache.shortOpenInterest == 0) {
return result;
}
cache.durationInSeconds = getSecondsSinceFundingUpdated(dataStore, market.marketToken);
cache.sizeOfLargerSide = cache.longOpenInterest > cache.shortOpenInterest ? cache.longOpenInterest : cache.shortOpenInterest;
(result.fundingFactorPerSecond, result.longsPayShorts, result.nextSavedFundingFactorPerSecond) = getNextFundingFactorPerSecond(
dataStore,
market.marketToken,
cache.longOpenInterest,
cache.shortOpenInterest,
cache.durationInSeconds
);
cache.fundingUsd = Precision.applyFactor(cache.sizeOfLargerSide, cache.durationInSeconds * result.fundingFactorPerSecond);
cache.fundingUsd = cache.fundingUsd / divisor;
if (result.longsPayShorts) {
cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.longToken, cache.longOpenInterest);
cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.long.shortToken, cache.longOpenInterest);
} else {
cache.fundingUsdForLongCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.longToken, cache.shortOpenInterest);
cache.fundingUsdForShortCollateral = Precision.mulDiv(cache.fundingUsd, cache.openInterest.short.shortToken, cache.shortOpenInterest);
}
if (result.longsPayShorts) {
result.fundingFeeAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForLongCollateral,
cache.openInterest.long.longToken,
prices.longTokenPrice.max,
true
);
result.fundingFeeAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForShortCollateral,
cache.openInterest.long.shortToken,
prices.shortTokenPrice.max,
true
);
result.claimableFundingAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForLongCollateral,
cache.shortOpenInterest,
prices.longTokenPrice.max,
false
);
result.claimableFundingAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForShortCollateral,
cache.shortOpenInterest,
prices.shortTokenPrice.max,
false
);
} else {
result.fundingFeeAmountPerSizeDelta.short.longToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForLongCollateral,
cache.openInterest.short.longToken,
prices.longTokenPrice.max,
true
);
result.fundingFeeAmountPerSizeDelta.short.shortToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForShortCollateral,
cache.openInterest.short.shortToken,
prices.shortTokenPrice.max,
true
);
result.claimableFundingAmountPerSizeDelta.long.longToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForLongCollateral,
cache.longOpenInterest,
prices.longTokenPrice.max,
false
);
result.claimableFundingAmountPerSizeDelta.long.shortToken = getFundingAmountPerSizeDelta(
cache.fundingUsdForShortCollateral,
cache.longOpenInterest,
prices.shortTokenPrice.max,
false
);
}
return result;
}
function getNextFundingFactorPerSecond(
DataStore dataStore,
address market,
uint256 longOpenInterest,
uint256 shortOpenInterest,
uint256 durationInSeconds
) internal view returns (uint256, bool, int256) {
GetNextFundingFactorPerSecondCache memory cache;
cache.diffUsd = Calc.diff(longOpenInterest, shortOpenInterest);
cache.totalOpenInterest = longOpenInterest + shortOpenInterest;
FundingConfigCache memory configCache;
configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));
if (cache.diffUsd == 0 && configCache.fundingIncreaseFactorPerSecond == 0) {
return (0, true, 0);
}
if (cache.totalOpenInterest == 0) {
revert Errors.UnableToGetFundingFactorEmptyOpenInterest();
}
cache.fundingExponentFactor = getFundingExponentFactor(dataStore, market);
cache.diffUsdAfterExponent = Precision.applyExponentFactor(cache.diffUsd, cache.fundingExponentFactor);
cache.diffUsdToOpenInterestFactor = Precision.toFactor(cache.diffUsdAfterExponent, cache.totalOpenInterest);
if (configCache.fundingIncreaseFactorPerSecond == 0) {
cache.fundingFactor = getFundingFactor(dataStore, market);
uint256 maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));
uint256 fundingFactorPerSecond = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor);
if (fundingFactorPerSecond > maxFundingFactorPerSecond) {
fundingFactorPerSecond = maxFundingFactorPerSecond;
}
return (
fundingFactorPerSecond,
longOpenInterest > shortOpenInterest,
0
);
}
cache.savedFundingFactorPerSecond = getSavedFundingFactorPerSecond(dataStore, market);
cache.savedFundingFactorPerSecondMagnitude = cache.savedFundingFactorPerSecond.abs();
configCache.thresholdForStableFunding = dataStore.getUint(Keys.thresholdForStableFundingKey(market));
configCache.thresholdForDecreaseFunding = dataStore.getUint(Keys.thresholdForDecreaseFundingKey(market));
cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond;
FundingRateChangeType fundingRateChangeType;
bool isSkewTheSameDirectionAsFunding = (cache.savedFundingFactorPerSecond > 0 && longOpenInterest > shortOpenInterest) || (cache.savedFundingFactorPerSecond < 0 && shortOpenInterest > longOpenInterest);
if (isSkewTheSameDirectionAsFunding) {
if (cache.diffUsdToOpenInterestFactor > configCache.thresholdForStableFunding) {
fundingRateChangeType = FundingRateChangeType.Increase;
} else if (cache.diffUsdToOpenInterestFactor < configCache.thresholdForDecreaseFunding) {
fundingRateChangeType = FundingRateChangeType.Decrease;
}
} else {
fundingRateChangeType = FundingRateChangeType.Increase;
}
if (fundingRateChangeType == FundingRateChangeType.Increase) {
int256 increaseValue = Precision.applyFactor(cache.diffUsdToOpenInterestFactor, configCache.fundingIncreaseFactorPerSecond).toInt256() * durationInSeconds.toInt256();
if (longOpenInterest < shortOpenInterest) {
increaseValue = -increaseValue;
}
cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond + increaseValue;
}
if (fundingRateChangeType == FundingRateChangeType.Decrease && cache.savedFundingFactorPerSecondMagnitude != 0) {
configCache.fundingDecreaseFactorPerSecond = dataStore.getUint(Keys.fundingDecreaseFactorPerSecondKey(market));
uint256 decreaseValue = configCache.fundingDecreaseFactorPerSecond * durationInSeconds;
if (cache.savedFundingFactorPerSecondMagnitude <= decreaseValue) {
cache.nextSavedFundingFactorPerSecond = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();
} else {
int256 sign = cache.savedFundingFactorPerSecond / cache.savedFundingFactorPerSecondMagnitude.toInt256();
cache.nextSavedFundingFactorPerSecond = (cache.savedFundingFactorPerSecondMagnitude - decreaseValue).toInt256() * sign;
}
}
configCache.minFundingFactorPerSecond = dataStore.getUint(Keys.minFundingFactorPerSecondKey(market));
configCache.maxFundingFactorPerSecond = dataStore.getUint(Keys.maxFundingFactorPerSecondKey(market));
cache.nextSavedFundingFactorPerSecond = Calc.boundMagnitude(
cache.nextSavedFundingFactorPerSecond,
0,
configCache.maxFundingFactorPerSecond
);
cache.nextSavedFundingFactorPerSecondWithMinBound = Calc.boundMagnitude(
cache.nextSavedFundingFactorPerSecond,
configCache.minFundingFactorPerSecond,
configCache.maxFundingFactorPerSecond
);
return (
cache.nextSavedFundingFactorPerSecondWithMinBound.abs(),
cache.nextSavedFundingFactorPerSecondWithMinBound > 0,
cache.nextSavedFundingFactorPerSecond
);
}
function getFundingAmountPerSizeDelta(
uint256 fundingUsd,
uint256 openInterest,
uint256 tokenPrice,
bool roundUpMagnitude
) internal pure returns (uint256) {
if (fundingUsd == 0 || openInterest == 0) { return 0; }
uint256 fundingUsdPerSize = Precision.mulDiv(
fundingUsd,
Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,
openInterest,
roundUpMagnitude
);
if (roundUpMagnitude) {
return Calc.roundUpDivision(fundingUsdPerSize, tokenPrice);
} else {
return fundingUsdPerSize / tokenPrice;
}
}
function updateCumulativeBorrowingFactor(
DataStore dataStore,
EventEmitter eventEmitter,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) external {
(, uint256 delta) = getNextCumulativeBorrowingFactor(
dataStore,
market,
prices,
isLong
);
incrementCumulativeBorrowingFactor(
dataStore,
eventEmitter,
market.marketToken,
isLong,
delta
);
dataStore.setUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market.marketToken, isLong), Chain.currentTimestamp());
}
function getPnlToPoolFactor(
DataStore dataStore,
Oracle oracle,
address market,
bool isLong,
bool maximize
) internal view returns (int256) {
Market.Props memory _market = getEnabledMarket(dataStore, market);
MarketPrices memory prices = MarketPrices(
oracle.getPrimaryPrice(_market.indexToken),
oracle.getPrimaryPrice(_market.longToken),
oracle.getPrimaryPrice(_market.shortToken)
);
return getPnlToPoolFactor(dataStore, _market, prices, isLong, maximize);
}
function getPnlToPoolFactor(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong,
bool maximize
) internal view returns (int256) {
uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, !maximize);
if (poolUsd == 0) {
return 0;
}
int256 pnl = getPnl(
dataStore,
market,
prices.indexTokenPrice,
isLong,
maximize
);
return Precision.toFactor(pnl, poolUsd);
}
function validateOpenInterest(
DataStore dataStore,
Market.Props memory market,
bool isLong
) internal view {
uint256 openInterest = getOpenInterest(dataStore, market, isLong);
uint256 maxOpenInterest = getMaxOpenInterest(dataStore, market.marketToken, isLong);
if (openInterest > maxOpenInterest) {
revert Errors.MaxOpenInterestExceeded(openInterest, maxOpenInterest);
}
}
function validatePoolAmount(
DataStore dataStore,
Market.Props memory market,
address token
) internal view {
uint256 poolAmount = getPoolAmount(dataStore, market, token);
uint256 maxPoolAmount = getMaxPoolAmount(dataStore, market.marketToken, token);
if (poolAmount > maxPoolAmount) {
revert Errors.MaxPoolAmountExceeded(poolAmount, maxPoolAmount);
}
}
function validatePoolUsdForDeposit(
DataStore dataStore,
Market.Props memory market,
address token,
uint256 tokenPrice
) internal view {
uint256 poolAmount = getPoolAmount(dataStore, market, token);
uint256 poolUsd = poolAmount * tokenPrice;
uint256 maxPoolUsd = getMaxPoolUsdForDeposit(dataStore, market.marketToken, token);
if (poolUsd > maxPoolUsd) {
revert Errors.MaxPoolUsdForDepositExceeded(poolUsd, maxPoolUsd);
}
}
function validateReserve(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view {
uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);
uint256 reserveFactor = getReserveFactor(dataStore, market.marketToken, isLong);
uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
uint256 reservedUsd = getReservedUsd(
dataStore,
market,
prices,
isLong
);
if (reservedUsd > maxReservedUsd) {
revert Errors.InsufficientReserve(reservedUsd, maxReservedUsd);
}
}
function validateOpenInterestReserve(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view {
uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);
uint256 reserveFactor = getOpenInterestReserveFactor(dataStore, market.marketToken, isLong);
uint256 maxReservedUsd = Precision.applyFactor(poolUsd, reserveFactor);
uint256 reservedUsd = getReservedUsd(
dataStore,
market,
prices,
isLong
);
if (reservedUsd > maxReservedUsd) {
revert Errors.InsufficientReserveForOpenInterest(reservedUsd, maxReservedUsd);
}
}
function applySwapImpactWithCap(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
Price.Props memory tokenPrice,
int256 priceImpactUsd
) internal returns (int256, uint256) {
(int256 impactAmount, uint256 cappedDiffUsd) = getSwapImpactAmountWithCap(
dataStore,
market,
token,
tokenPrice,
priceImpactUsd
);
applyDeltaToSwapImpactPool(
dataStore,
eventEmitter,
market,
token,
-impactAmount
);
return (impactAmount, cappedDiffUsd);
}
function getSwapImpactAmountWithCap(
DataStore dataStore,
address market,
address token,
Price.Props memory tokenPrice,
int256 priceImpactUsd
) internal view returns (int256, uint256) {
int256 impactAmount;
uint256 cappedDiffUsd;
if (priceImpactUsd > 0) {
impactAmount = priceImpactUsd / tokenPrice.max.toInt256();
int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();
if (impactAmount > maxImpactAmount) {
cappedDiffUsd = (impactAmount - maxImpactAmount).toUint256() * tokenPrice.max;
impactAmount = maxImpactAmount;
}
} else {
impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);
}
return (impactAmount, cappedDiffUsd);
}
function getFundingAmount(
uint256 latestFundingAmountPerSize,
uint256 positionFundingAmountPerSize,
uint256 positionSizeInUsd,
bool roundUpMagnitude
) internal pure returns (uint256) {
uint256 fundingDiffFactor = (latestFundingAmountPerSize - positionFundingAmountPerSize);
return Precision.mulDiv(
positionSizeInUsd,
fundingDiffFactor,
Precision.FLOAT_PRECISION * Precision.FLOAT_PRECISION_SQRT,
roundUpMagnitude
);
}
function getBorrowingFees(DataStore dataStore, Position.Props memory position) internal view returns (uint256) {
uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, position.market(), position.isLong());
if (position.borrowingFactor() > cumulativeBorrowingFactor) {
revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), cumulativeBorrowingFactor);
}
uint256 diffFactor = cumulativeBorrowingFactor - position.borrowingFactor();
return Precision.applyFactor(position.sizeInUsd(), diffFactor);
}
function getNextBorrowingFees(DataStore dataStore, Position.Props memory position, Market.Props memory market, MarketPrices memory prices) internal view returns (uint256) {
(uint256 nextCumulativeBorrowingFactor, ) = getNextCumulativeBorrowingFactor(
dataStore,
market,
prices,
position.isLong()
);
if (position.borrowingFactor() > nextCumulativeBorrowingFactor) {
revert Errors.UnexpectedBorrowingFactor(position.borrowingFactor(), nextCumulativeBorrowingFactor);
}
uint256 diffFactor = nextCumulativeBorrowingFactor - position.borrowingFactor();
return Precision.applyFactor(position.sizeInUsd(), diffFactor);
}
function getReservedUsd(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view returns (uint256) {
uint256 reservedUsd;
if (isLong) {
uint256 openInterestInTokens = getOpenInterestInTokens(dataStore, market, isLong);
reservedUsd = openInterestInTokens * prices.indexTokenPrice.max;
} else {
reservedUsd = getOpenInterest(dataStore, market, isLong);
}
return reservedUsd;
}
function getVirtualInventoryForSwaps(DataStore dataStore, address market) internal view returns (bool, uint256, uint256) {
bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market));
if (virtualMarketId == bytes32(0)) {
return (false, 0, 0);
}
return (
true,
dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, true)),
dataStore.getUint(Keys.virtualInventoryForSwapsKey(virtualMarketId, false))
);
}
function getIsLongToken(Market.Props memory market, address token) internal pure returns (bool) {
if (token != market.longToken && token != market.shortToken) {
revert Errors.UnexpectedTokenForVirtualInventory(token, market.marketToken);
}
return token == market.longToken;
}
function getVirtualInventoryForPositions(DataStore dataStore, address token) internal view returns (bool, int256) {
bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));
if (virtualTokenId == bytes32(0)) {
return (false, 0);
}
return (true, dataStore.getInt(Keys.virtualInventoryForPositionsKey(virtualTokenId)));
}
function applyDeltaToVirtualInventoryForSwaps(
DataStore dataStore,
EventEmitter eventEmitter,
Market.Props memory market,
address token,
int256 delta
) internal returns (bool, uint256) {
bytes32 virtualMarketId = dataStore.getBytes32(Keys.virtualMarketIdKey(market.marketToken));
if (virtualMarketId == bytes32(0)) {
return (false, 0);
}
bool isLongToken = getIsLongToken(market, token);
uint256 nextValue = dataStore.applyBoundedDeltaToUint(
Keys.virtualInventoryForSwapsKey(virtualMarketId, isLongToken),
delta
);
MarketEventUtils.emitVirtualSwapInventoryUpdated(eventEmitter, market.marketToken, isLongToken, virtualMarketId, delta, nextValue);
return (true, nextValue);
}
function applyDeltaToVirtualInventoryForPositions(
DataStore dataStore,
EventEmitter eventEmitter,
address token,
int256 delta
) internal returns (bool, int256) {
bytes32 virtualTokenId = dataStore.getBytes32(Keys.virtualTokenIdKey(token));
if (virtualTokenId == bytes32(0)) {
return (false, 0);
}
int256 nextValue = dataStore.applyDeltaToInt(
Keys.virtualInventoryForPositionsKey(virtualTokenId),
delta
);
MarketEventUtils.emitVirtualPositionInventoryUpdated(eventEmitter, token, virtualTokenId, delta, nextValue);
return (true, nextValue);
}
function getOpenInterest(
DataStore dataStore,
Market.Props memory market
) internal view returns (uint256) {
uint256 longOpenInterest = getOpenInterest(dataStore, market, true);
uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);
return longOpenInterest + shortOpenInterest;
}
function getOpenInterest(
DataStore dataStore,
Market.Props memory market,
bool isLong
) internal view returns (uint256) {
uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
uint256 openInterestUsingLongTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.longToken, isLong, divisor);
uint256 openInterestUsingShortTokenAsCollateral = getOpenInterest(dataStore, market.marketToken, market.shortToken, isLong, divisor);
return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;
}
function getOpenInterest(
DataStore dataStore,
address market,
address collateralToken,
bool isLong,
uint256 divisor
) internal view returns (uint256) {
return dataStore.getUint(Keys.openInterestKey(market, collateralToken, isLong)) / divisor;
}
function getPoolDivisor(address longToken, address shortToken) internal pure returns (uint256) {
return longToken == shortToken ? 2 : 1;
}
function getOpenInterestInTokens(
DataStore dataStore,
Market.Props memory market,
bool isLong
) internal view returns (uint256) {
uint256 divisor = getPoolDivisor(market.longToken, market.shortToken);
uint256 openInterestUsingLongTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.longToken, isLong, divisor);
uint256 openInterestUsingShortTokenAsCollateral = getOpenInterestInTokens(dataStore, market.marketToken, market.shortToken, isLong, divisor);
return openInterestUsingLongTokenAsCollateral + openInterestUsingShortTokenAsCollateral;
}
function getOpenInterestInTokens(
DataStore dataStore,
address market,
address collateralToken,
bool isLong,
uint256 divisor
) internal view returns (uint256) {
return dataStore.getUint(Keys.openInterestInTokensKey(market, collateralToken, isLong)) / divisor;
}
function getOpenInterestWithPnl(
DataStore dataStore,
Market.Props memory market,
Price.Props memory indexTokenPrice,
bool isLong,
bool maximize
) internal view returns (int256) {
uint256 openInterest = getOpenInterest(dataStore, market, isLong);
int256 pnl = getPnl(dataStore, market, indexTokenPrice, isLong, maximize);
return Calc.sumReturnInt256(openInterest, pnl);
}
function getMaxPositionImpactFactor(DataStore dataStore, address market, bool isPositive) internal view returns (uint256) {
(uint256 maxPositiveImpactFactor, uint256 maxNegativeImpactFactor) = getMaxPositionImpactFactors(dataStore, market);
return isPositive ? maxPositiveImpactFactor : maxNegativeImpactFactor;
}
function getMaxPositionImpactFactors(DataStore dataStore, address market) internal view returns (uint256, uint256) {
uint256 maxPositiveImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, true));
uint256 maxNegativeImpactFactor = dataStore.getUint(Keys.maxPositionImpactFactorKey(market, false));
if (maxPositiveImpactFactor > maxNegativeImpactFactor) {
maxPositiveImpactFactor = maxNegativeImpactFactor;
}
return (maxPositiveImpactFactor, maxNegativeImpactFactor);
}
function getMaxPositionImpactFactorForLiquidations(DataStore dataStore, address market) internal view returns (uint256) {
return dataStore.getUint(Keys.maxPositionImpactFactorForLiquidationsKey(market));
}
function getMinCollateralFactor(DataStore dataStore, address market) internal view returns (uint256) {
return dataStore.getUint(Keys.minCollateralFactorKey(market));
}
function getMinCollateralFactorForOpenInterestMultiplier(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.minCollateralFactorForOpenInterestMultiplierKey(market, isLong));
}
function getMinCollateralFactorForOpenInterest(
DataStore dataStore,
Market.Props memory market,
int256 openInterestDelta,
bool isLong
) internal view returns (uint256) {
uint256 openInterest = getOpenInterest(dataStore, market, isLong);
openInterest = Calc.sumReturnUint256(openInterest, openInterestDelta);
uint256 multiplierFactor = getMinCollateralFactorForOpenInterestMultiplier(dataStore, market.marketToken, isLong);
return Precision.applyFactor(openInterest, multiplierFactor);
}
function getCollateralSum(DataStore dataStore, address market, address collateralToken, bool isLong, uint256 divisor) internal view returns (uint256) {
return dataStore.getUint(Keys.collateralSumKey(market, collateralToken, isLong)) / divisor;
}
function getReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.reserveFactorKey(market, isLong));
}
function getOpenInterestReserveFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.openInterestReserveFactorKey(market, isLong));
}
function getMaxPnlFactor(DataStore dataStore, bytes32 pnlFactorType, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.maxPnlFactorKey(pnlFactorType, market, isLong));
}
function getMinPnlFactorAfterAdl(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.minPnlFactorAfterAdlKey(market, isLong));
}
function getFundingFactor(DataStore dataStore, address market) internal view returns (uint256) {
return dataStore.getUint(Keys.fundingFactorKey(market));
}
function getSavedFundingFactorPerSecond(DataStore dataStore, address market) internal view returns (int256) {
return dataStore.getInt(Keys.savedFundingFactorPerSecondKey(market));
}
function setSavedFundingFactorPerSecond(DataStore dataStore, address market, int256 value) internal returns (int256) {
return dataStore.setInt(Keys.savedFundingFactorPerSecondKey(market), value);
}
function getFundingExponentFactor(DataStore dataStore, address market) internal view returns (uint256) {
return dataStore.getUint(Keys.fundingExponentFactorKey(market));
}
function getFundingFeeAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong));
}
function getClaimableFundingAmountPerSize(DataStore dataStore, address market, address collateralToken, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong));
}
function applyDeltaToFundingFeeAmountPerSize(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
uint256 delta
) internal {
if (delta == 0) { return; }
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.fundingFeeAmountPerSizeKey(market, collateralToken, isLong),
delta
);
MarketEventUtils.emitFundingFeeAmountPerSizeUpdated(
eventEmitter,
market,
collateralToken,
isLong,
delta,
nextValue
);
}
function applyDeltaToClaimableFundingAmountPerSize(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address collateralToken,
bool isLong,
uint256 delta
) internal {
if (delta == 0) { return; }
uint256 nextValue = dataStore.applyDeltaToUint(
Keys.claimableFundingAmountPerSizeKey(market, collateralToken, isLong),
delta
);
MarketEventUtils.emitClaimableFundingAmountPerSizeUpdated(
eventEmitter,
market,
collateralToken,
isLong,
delta,
nextValue
);
}
function getSecondsSinceFundingUpdated(DataStore dataStore, address market) internal view returns (uint256) {
uint256 updatedAt = dataStore.getUint(Keys.fundingUpdatedAtKey(market));
if (updatedAt == 0) { return 0; }
return Chain.currentTimestamp() - updatedAt;
}
function getBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.borrowingFactorKey(market, isLong));
}
function getOptimalUsageFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.optimalUsageFactorKey(market, isLong));
}
function getBorrowingExponentFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.borrowingExponentFactorKey(market, isLong));
}
function getCumulativeBorrowingFactor(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.cumulativeBorrowingFactorKey(market, isLong));
}
function incrementCumulativeBorrowingFactor(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
bool isLong,
uint256 delta
) internal {
uint256 nextCumulativeBorrowingFactor = dataStore.incrementUint(
Keys.cumulativeBorrowingFactorKey(market, isLong),
delta
);
MarketEventUtils.emitBorrowingFactorUpdated(
eventEmitter,
market,
isLong,
delta,
nextCumulativeBorrowingFactor
);
}
function getCumulativeBorrowingFactorUpdatedAt(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.cumulativeBorrowingFactorUpdatedAtKey(market, isLong));
}
function getSecondsSinceCumulativeBorrowingFactorUpdated(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
uint256 updatedAt = getCumulativeBorrowingFactorUpdatedAt(dataStore, market, isLong);
if (updatedAt == 0) { return 0; }
return Chain.currentTimestamp() - updatedAt;
}
function updateTotalBorrowing(
DataStore dataStore,
address market,
bool isLong,
uint256 prevPositionSizeInUsd,
uint256 prevPositionBorrowingFactor,
uint256 nextPositionSizeInUsd,
uint256 nextPositionBorrowingFactor
) external {
uint256 totalBorrowing = getNextTotalBorrowing(
dataStore,
market,
isLong,
prevPositionSizeInUsd,
prevPositionBorrowingFactor,
nextPositionSizeInUsd,
nextPositionBorrowingFactor
);
setTotalBorrowing(dataStore, market, isLong, totalBorrowing);
}
function getNextTotalBorrowing(
DataStore dataStore,
address market,
bool isLong,
uint256 prevPositionSizeInUsd,
uint256 prevPositionBorrowingFactor,
uint256 nextPositionSizeInUsd,
uint256 nextPositionBorrowingFactor
) internal view returns (uint256) {
uint256 totalBorrowing = getTotalBorrowing(dataStore, market, isLong);
totalBorrowing -= Precision.applyFactor(prevPositionSizeInUsd, prevPositionBorrowingFactor);
totalBorrowing += Precision.applyFactor(nextPositionSizeInUsd, nextPositionBorrowingFactor);
return totalBorrowing;
}
function getNextCumulativeBorrowingFactor(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view returns (uint256, uint256) {
uint256 durationInSeconds = getSecondsSinceCumulativeBorrowingFactorUpdated(dataStore, market.marketToken, isLong);
uint256 borrowingFactorPerSecond = getBorrowingFactorPerSecond(
dataStore,
market,
prices,
isLong
);
uint256 cumulativeBorrowingFactor = getCumulativeBorrowingFactor(dataStore, market.marketToken, isLong);
uint256 delta = durationInSeconds * borrowingFactorPerSecond;
uint256 nextCumulativeBorrowingFactor = cumulativeBorrowingFactor + delta;
return (nextCumulativeBorrowingFactor, delta);
}
function getBorrowingFactorPerSecond(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view returns (uint256) {
uint256 reservedUsd = getReservedUsd(
dataStore,
market,
prices,
isLong
);
if (reservedUsd == 0) { return 0; }
bool skipBorrowingFeeForSmallerSide = dataStore.getBool(Keys.SKIP_BORROWING_FEE_FOR_SMALLER_SIDE);
if (skipBorrowingFeeForSmallerSide) {
uint256 longOpenInterest = getOpenInterest(dataStore, market, true);
uint256 shortOpenInterest = getOpenInterest(dataStore, market, false);
if (isLong && longOpenInterest < shortOpenInterest) {
return 0;
}
if (!isLong && shortOpenInterest < longOpenInterest) {
return 0;
}
}
uint256 poolUsd = getPoolUsdWithoutPnl(dataStore, market, prices, isLong, false);
if (poolUsd == 0) {
revert Errors.UnableToGetBorrowingFactorEmptyPoolUsd();
}
uint256 optimalUsageFactor = getOptimalUsageFactor(dataStore, market.marketToken, isLong);
if (optimalUsageFactor != 0) {
return getKinkBorrowingFactor(
dataStore,
market,
isLong,
reservedUsd,
poolUsd,
optimalUsageFactor
);
}
uint256 borrowingExponentFactor = getBorrowingExponentFactor(dataStore, market.marketToken, isLong);
uint256 reservedUsdAfterExponent = Precision.applyExponentFactor(reservedUsd, borrowingExponentFactor);
uint256 reservedUsdToPoolFactor = Precision.toFactor(reservedUsdAfterExponent, poolUsd);
uint256 borrowingFactor = getBorrowingFactor(dataStore, market.marketToken, isLong);
return Precision.applyFactor(reservedUsdToPoolFactor, borrowingFactor);
}
function getKinkBorrowingFactor(
DataStore dataStore,
Market.Props memory market,
bool isLong,
uint256 reservedUsd,
uint256 poolUsd,
uint256 optimalUsageFactor
) internal view returns (uint256) {
uint256 usageFactor = getUsageFactor(
dataStore,
market,
isLong,
reservedUsd,
poolUsd
);
uint256 baseBorrowingFactor = dataStore.getUint(Keys.baseBorrowingFactorKey(market.marketToken, isLong));
uint256 borrowingFactorPerSecond = Precision.applyFactor(
usageFactor,
baseBorrowingFactor
);
if (usageFactor > optimalUsageFactor && Precision.FLOAT_PRECISION > optimalUsageFactor) {
uint256 diff = usageFactor - optimalUsageFactor;
uint256 aboveOptimalUsageBorrowingFactor = dataStore.getUint(Keys.aboveOptimalUsageBorrowingFactorKey(market.marketToken, isLong));
uint256 additionalBorrowingFactorPerSecond;
if (aboveOptimalUsageBorrowingFactor > baseBorrowingFactor) {
additionalBorrowingFactorPerSecond = aboveOptimalUsageBorrowingFactor - baseBorrowingFactor;
}
uint256 divisor = Precision.FLOAT_PRECISION - optimalUsageFactor;
borrowingFactorPerSecond += additionalBorrowingFactorPerSecond * diff / divisor;
}
return borrowingFactorPerSecond;
}
function distributePositionImpactPool(
DataStore dataStore,
EventEmitter eventEmitter,
address market
) external {
(uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);
if (distributionAmount != 0) {
applyDeltaToPositionImpactPool(
dataStore,
eventEmitter,
market,
-distributionAmount.toInt256()
);
MarketEventUtils.emitPositionImpactPoolDistributed(
eventEmitter,
market,
distributionAmount,
nextPositionImpactPoolAmount
);
}
dataStore.setUint(Keys.positionImpactPoolDistributedAtKey(market), Chain.currentTimestamp());
}
function getNextPositionImpactPoolAmount(
DataStore dataStore,
address market
) internal view returns (uint256) {
(, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);
return nextPositionImpactPoolAmount;
}
function getPendingPositionImpactPoolDistributionAmount(
DataStore dataStore,
address market
) internal view returns (uint256, uint256) {
uint256 positionImpactPoolAmount = getPositionImpactPoolAmount(dataStore, market);
if (positionImpactPoolAmount == 0) { return (0, positionImpactPoolAmount); }
uint256 distributionRate = dataStore.getUint(Keys.positionImpactPoolDistributionRateKey(market));
if (distributionRate == 0) { return (0, positionImpactPoolAmount); }
uint256 minPositionImpactPoolAmount = dataStore.getUint(Keys.minPositionImpactPoolAmountKey(market));
if (positionImpactPoolAmount <= minPositionImpactPoolAmount) { return (0, positionImpactPoolAmount); }
uint256 maxDistributionAmount = positionImpactPoolAmount - minPositionImpactPoolAmount;
uint256 durationInSeconds = getSecondsSincePositionImpactPoolDistributed(dataStore, market);
uint256 distributionAmount = Precision.applyFactor(durationInSeconds, distributionRate);
if (distributionAmount > maxDistributionAmount) {
distributionAmount = maxDistributionAmount;
}
return (distributionAmount, positionImpactPoolAmount - distributionAmount);
}
function getSecondsSincePositionImpactPoolDistributed(
DataStore dataStore,
address market
) internal view returns (uint256) {
uint256 distributedAt = dataStore.getUint(Keys.positionImpactPoolDistributedAtKey(market));
if (distributedAt == 0) { return 0; }
return Chain.currentTimestamp() - distributedAt;
}
function getTotalPendingBorrowingFees(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong
) internal view returns (uint256) {
uint256 openInterest = getOpenInterest(
dataStore,
market,
isLong
);
(uint256 nextCumulativeBorrowingFactor, ) = getNextCumulativeBorrowingFactor(
dataStore,
market,
prices,
isLong
);
uint256 totalBorrowing = getTotalBorrowing(dataStore, market.marketToken, isLong);
return Precision.applyFactor(openInterest, nextCumulativeBorrowingFactor) - totalBorrowing;
}
function getTotalBorrowing(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.totalBorrowingKey(market, isLong));
}
function setTotalBorrowing(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {
return dataStore.setUint(Keys.totalBorrowingKey(market, isLong), value);
}
function usdToMarketTokenAmount(
uint256 usdValue,
uint256 poolValue,
uint256 supply
) internal pure returns (uint256) {
if (supply == 0 && poolValue == 0) {
return Precision.floatToWei(usdValue);
}
if (supply == 0 && poolValue > 0) {
return Precision.floatToWei(poolValue + usdValue);
}
return Precision.mulDiv(supply, usdValue, poolValue);
}
function marketTokenAmountToUsd(
uint256 marketTokenAmount,
uint256 poolValue,
uint256 supply
) internal pure returns (uint256) {
if (supply == 0) { revert Errors.EmptyMarketTokenSupply(); }
return Precision.mulDiv(poolValue, marketTokenAmount, supply);
}
function validateEnabledMarket(DataStore dataStore, address marketAddress) internal view {
Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
validateEnabledMarket(dataStore, market);
}
function validateEnabledMarket(DataStore dataStore, Market.Props memory market) internal view {
if (market.marketToken == address(0)) {
revert Errors.EmptyMarket();
}
bool isMarketDisabled = dataStore.getBool(Keys.isMarketDisabledKey(market.marketToken));
if (isMarketDisabled) {
revert Errors.DisabledMarket(market.marketToken);
}
}
function validatePositionMarket(DataStore dataStore, Market.Props memory market) internal view {
validateEnabledMarket(dataStore, market);
if (isSwapOnlyMarket(market)) {
revert Errors.InvalidPositionMarket(market.marketToken);
}
}
function validatePositionMarket(DataStore dataStore, address marketAddress) internal view {
Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
validatePositionMarket(dataStore, market);
}
function isSwapOnlyMarket(Market.Props memory market) internal pure returns (bool) {
return market.indexToken == address(0);
}
function isMarketCollateralToken(Market.Props memory market, address token) internal pure returns (bool) {
return token == market.longToken || token == market.shortToken;
}
function validateMarketCollateralToken(Market.Props memory market, address token) internal pure {
if (!isMarketCollateralToken(market, token)) {
revert Errors.InvalidCollateralTokenForMarket(market.marketToken, token);
}
}
function getEnabledMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {
Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
validateEnabledMarket(dataStore, market);
return market;
}
function getSwapPathMarket(DataStore dataStore, address marketAddress) internal view returns (Market.Props memory) {
Market.Props memory market = MarketStoreUtils.get(dataStore, marketAddress);
validateSwapMarket(dataStore, market);
return market;
}
function getSwapPathMarkets(DataStore dataStore, address[] memory swapPath) internal view returns (Market.Props[] memory) {
Market.Props[] memory markets = new Market.Props[](swapPath.length);
for (uint256 i; i < swapPath.length; i++) {
address marketAddress = swapPath[i];
markets[i] = getSwapPathMarket(dataStore, marketAddress);
}
return markets;
}
function validateSwapPath(DataStore dataStore, address[] memory swapPath) internal view {
uint256 maxSwapPathLength = dataStore.getUint(Keys.MAX_SWAP_PATH_LENGTH);
if (swapPath.length > maxSwapPathLength) {
revert Errors.MaxSwapPathLengthExceeded(swapPath.length, maxSwapPathLength);
}
for (uint256 i; i < swapPath.length; i++) {
address marketAddress = swapPath[i];
validateSwapMarket(dataStore, marketAddress);
}
}
function validateMaxPnl(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bytes32 pnlFactorTypeForLongs,
bytes32 pnlFactorTypeForShorts
) internal view {
(bool isPnlFactorExceededForLongs, int256 pnlToPoolFactorForLongs, uint256 maxPnlFactorForLongs) = isPnlFactorExceeded(
dataStore,
market,
prices,
true,
pnlFactorTypeForLongs
);
if (isPnlFactorExceededForLongs) {
revert Errors.PnlFactorExceededForLongs(pnlToPoolFactorForLongs, maxPnlFactorForLongs);
}
(bool isPnlFactorExceededForShorts, int256 pnlToPoolFactorForShorts, uint256 maxPnlFactorForShorts) = isPnlFactorExceeded(
dataStore,
market,
prices,
false,
pnlFactorTypeForShorts
);
if (isPnlFactorExceededForShorts) {
revert Errors.PnlFactorExceededForShorts(pnlToPoolFactorForShorts, maxPnlFactorForShorts);
}
}
function isPnlFactorExceeded(
DataStore dataStore,
Oracle oracle,
address market,
bool isLong,
bytes32 pnlFactorType
) internal view returns (bool, int256, uint256) {
Market.Props memory _market = getEnabledMarket(dataStore, market);
MarketPrices memory prices = getMarketPrices(oracle, _market);
return isPnlFactorExceeded(
dataStore,
_market,
prices,
isLong,
pnlFactorType
);
}
function isPnlFactorExceeded(
DataStore dataStore,
Market.Props memory market,
MarketPrices memory prices,
bool isLong,
bytes32 pnlFactorType
) internal view returns (bool, int256, uint256) {
int256 pnlToPoolFactor = getPnlToPoolFactor(dataStore, market, prices, isLong, true);
uint256 maxPnlFactor = getMaxPnlFactor(dataStore, pnlFactorType, market.marketToken, isLong);
bool isExceeded = pnlToPoolFactor > 0 && pnlToPoolFactor.toUint256() > maxPnlFactor;
return (isExceeded, pnlToPoolFactor, maxPnlFactor);
}
function getUiFeeFactor(DataStore dataStore, address account) internal view returns (uint256) {
uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);
uint256 uiFeeFactor = dataStore.getUint(Keys.uiFeeFactorKey(account));
return uiFeeFactor < maxUiFeeFactor ? uiFeeFactor : maxUiFeeFactor;
}
function setUiFeeFactor(
DataStore dataStore,
EventEmitter eventEmitter,
address account,
uint256 uiFeeFactor
) internal {
uint256 maxUiFeeFactor = dataStore.getUint(Keys.MAX_UI_FEE_FACTOR);
if (uiFeeFactor > maxUiFeeFactor) {
revert Errors.InvalidUiFeeFactor(uiFeeFactor, maxUiFeeFactor);
}
dataStore.setUint(
Keys.uiFeeFactorKey(account),
uiFeeFactor
);
MarketEventUtils.emitUiFeeFactorUpdated(eventEmitter, account, uiFeeFactor);
}
function validateMarketTokenBalance(
DataStore dataStore,
Market.Props[] memory markets
) public view {
for (uint256 i; i < markets.length; i++) {
validateMarketTokenBalance(dataStore, markets[i]);
}
}
function validateMarketTokenBalance(
DataStore dataStore,
address _market
) public view {
Market.Props memory market = getEnabledMarket(dataStore, _market);
validateMarketTokenBalance(dataStore, market);
}
function validateMarketTokenBalance(
DataStore dataStore,
Market.Props memory market
) public view {
validateMarketTokenBalance(dataStore, market, market.longToken);
if (market.longToken == market.shortToken) {
return;
}
validateMarketTokenBalance(dataStore, market, market.shortToken);
}
function validateMarketTokenBalance(
DataStore dataStore,
Market.Props memory market,
address token
) internal view {
if (market.marketToken == address(0) || token == address(0)) {
revert Errors.EmptyAddressInMarketTokenBalanceValidation(market.marketToken, token);
}
uint256 balance = IERC20(token).balanceOf(market.marketToken);
uint256 expectedMinBalance = getExpectedMinTokenBalance(dataStore, market, token);
if (balance < expectedMinBalance) {
revert Errors.InvalidMarketTokenBalance(market.marketToken, token, balance, expectedMinBalance);
}
uint256 collateralAmount = getCollateralSum(dataStore, market.marketToken, token, true, 1);
collateralAmount += getCollateralSum(dataStore, market.marketToken, token, false, 1);
if (balance < collateralAmount) {
revert Errors.InvalidMarketTokenBalanceForCollateralAmount(market.marketToken, token, balance, collateralAmount);
}
uint256 claimableFundingFeeAmount = dataStore.getUint(Keys.claimableFundingAmountKey(market.marketToken, token));
if (balance < claimableFundingFeeAmount) {
revert Errors.InvalidMarketTokenBalanceForClaimableFunding(market.marketToken, token, balance, claimableFundingFeeAmount);
}
}
function getExpectedMinTokenBalance(
DataStore dataStore,
Market.Props memory market,
address token
) internal view returns (uint256) {
GetExpectedMinTokenBalanceCache memory cache;
cache.poolAmount = dataStore.getUint(Keys.poolAmountKey(market.marketToken, token));
cache.swapImpactPoolAmount = getSwapImpactPoolAmount(dataStore, market.marketToken, token);
cache.claimableCollateralAmount = dataStore.getUint(Keys.claimableCollateralAmountKey(market.marketToken, token));
cache.claimableFeeAmount = dataStore.getUint(Keys.claimableFeeAmountKey(market.marketToken, token));
cache.claimableUiFeeAmount = dataStore.getUint(Keys.claimableUiFeeAmountKey(market.marketToken, token));
cache.affiliateRewardAmount = dataStore.getUint(Keys.affiliateRewardKey(market.marketToken, token));
return
cache.poolAmount
+ cache.swapImpactPoolAmount
+ cache.claimableCollateralAmount
+ cache.claimableFeeAmount
+ cache.claimableUiFeeAmount
+ cache.affiliateRewardAmount;
}
}
文件 40 的 57:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 41 的 57:Oracle.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import { AggregatorV2V3Interface } from "@chainlink/contracts/src/v0.8/shared/interfaces/AggregatorV2V3Interface.sol";
import "../role/RoleModule.sol";
import "./OracleUtils.sol";
import "./IOracleProvider.sol";
import "./ChainlinkPriceFeedUtils.sol";
import "../price/Price.sol";
import "../chain/Chain.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Precision.sol";
import "../utils/Cast.sol";
import "../utils/Uint256Mask.sol";
contract Oracle is RoleModule {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableValues for EnumerableSet.AddressSet;
using Price for Price.Props;
using Uint256Mask for Uint256Mask.Mask;
using EventUtils for EventUtils.AddressItems;
using EventUtils for EventUtils.UintItems;
using EventUtils for EventUtils.IntItems;
using EventUtils for EventUtils.BoolItems;
using EventUtils for EventUtils.Bytes32Items;
using EventUtils for EventUtils.BytesItems;
using EventUtils for EventUtils.StringItems;
DataStore public immutable dataStore;
EventEmitter public immutable eventEmitter;
AggregatorV2V3Interface public immutable sequencerUptimeFeed;
EnumerableSet.AddressSet internal tokensWithPrices;
mapping(address => Price.Props) public primaryPrices;
uint256 public minTimestamp;
uint256 public maxTimestamp;
constructor(
RoleStore _roleStore,
DataStore _dataStore,
EventEmitter _eventEmitter,
AggregatorV2V3Interface _sequencerUptimeFeed
) RoleModule(_roleStore) {
dataStore = _dataStore;
eventEmitter = _eventEmitter;
sequencerUptimeFeed = _sequencerUptimeFeed;
}
function validateSequencerUp() external view {
if (address(sequencerUptimeFeed) == address(0)) {
return;
}
(
,
int256 answer,
uint256 startedAt,
,
) = sequencerUptimeFeed.latestRoundData();
bool isSequencerUp = answer == 0;
if (!isSequencerUp) {
revert Errors.SequencerDown();
}
uint256 sequencerGraceDuration = dataStore.getUint(Keys.SEQUENCER_GRACE_DURATION);
uint256 timeSinceUp = block.timestamp - startedAt;
if (timeSinceUp <= sequencerGraceDuration) {
revert Errors.SequencerGraceDurationNotYetPassed(timeSinceUp, sequencerGraceDuration);
}
}
function setPrices(
OracleUtils.SetPricesParams memory params
) external onlyController {
OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, false);
_setPrices(prices);
}
function setPricesForAtomicAction(
OracleUtils.SetPricesParams memory params
) external onlyController {
OracleUtils.ValidatedPrice[] memory prices = _validatePrices(params, true);
_setPrices(prices);
}
function setPrimaryPrice(address token, Price.Props memory price) external onlyController {
_setPrimaryPrice(token, price);
}
function setTimestamps(uint256 _minTimestamp, uint256 _maxTimestamp) external onlyController {
minTimestamp = _minTimestamp;
maxTimestamp = _maxTimestamp;
}
function clearAllPrices() external onlyController {
uint256 length = tokensWithPrices.length();
for (uint256 i; i < length; i++) {
address token = tokensWithPrices.at(0);
_removePrimaryPrice(token);
}
minTimestamp = 0;
maxTimestamp = 0;
}
function getTokensWithPricesCount() external view returns (uint256) {
return tokensWithPrices.length();
}
function getTokensWithPrices(uint256 start, uint256 end) external view returns (address[] memory) {
return tokensWithPrices.valuesAt(start, end);
}
function getPrimaryPrice(address token) external view returns (Price.Props memory) {
if (token == address(0)) { return Price.Props(0, 0); }
Price.Props memory price = primaryPrices[token];
if (price.isEmpty()) {
revert Errors.EmptyPrimaryPrice(token);
}
return price;
}
function validatePrices(
OracleUtils.SetPricesParams memory params,
bool forAtomicAction
) external onlyController returns (OracleUtils.ValidatedPrice[] memory) {
return _validatePrices(params, forAtomicAction);
}
function _setPrices(
OracleUtils.ValidatedPrice[] memory prices
) internal returns (OracleUtils.ValidatedPrice[] memory) {
if (tokensWithPrices.length() != 0) {
revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());
}
if (prices.length == 0) {
revert Errors.EmptyValidatedPrices();
}
uint256 _minTimestamp = prices[0].timestamp;
uint256 _maxTimestamp = prices[0].timestamp;
for (uint256 i; i < prices.length; i++) {
OracleUtils.ValidatedPrice memory validatedPrice = prices[i];
_setPrimaryPrice(validatedPrice.token, Price.Props(
validatedPrice.min,
validatedPrice.max
));
if (validatedPrice.timestamp < _minTimestamp) {
_minTimestamp = validatedPrice.timestamp;
}
if (validatedPrice.timestamp > _maxTimestamp) {
_maxTimestamp = validatedPrice.timestamp;
}
_emitOraclePriceUpdated(
validatedPrice.token,
validatedPrice.min,
validatedPrice.max,
validatedPrice.timestamp,
validatedPrice.provider
);
}
uint256 maxRange = dataStore.getUint(Keys.MAX_ORACLE_TIMESTAMP_RANGE);
if (_maxTimestamp - _minTimestamp > maxRange) {
revert Errors.MaxOracleTimestampRangeExceeded(_maxTimestamp - _minTimestamp, maxRange);
}
minTimestamp = _minTimestamp;
maxTimestamp = _maxTimestamp;
return prices;
}
function _validatePrices(
OracleUtils.SetPricesParams memory params,
bool forAtomicAction
) internal returns (OracleUtils.ValidatedPrice[] memory) {
if (params.tokens.length != params.providers.length) {
revert Errors.InvalidOracleSetPricesProvidersParam(params.tokens.length, params.providers.length);
}
if (params.tokens.length != params.data.length) {
revert Errors.InvalidOracleSetPricesDataParam(params.tokens.length, params.data.length);
}
OracleUtils.ValidatedPrice[] memory prices = new OracleUtils.ValidatedPrice[](params.tokens.length);
uint256 maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);
uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);
for (uint256 i; i < params.tokens.length; i++) {
address provider = params.providers[i];
if (!dataStore.getBool(Keys.isOracleProviderEnabledKey(provider))) {
revert Errors.InvalidOracleProvider(provider);
}
address token = params.tokens[i];
bool isAtomicProvider = dataStore.getBool(Keys.isAtomicOracleProviderKey(provider));
if (forAtomicAction) {
if (!isAtomicProvider) {
revert Errors.NonAtomicOracleProvider(provider);
}
} else {
address expectedProvider = dataStore.getAddress(Keys.oracleProviderForTokenKey(token));
if (provider != expectedProvider) {
revert Errors.InvalidOracleProviderForToken(provider, expectedProvider);
}
}
bytes memory data = params.data[i];
OracleUtils.ValidatedPrice memory validatedPrice = IOracleProvider(provider).getOraclePrice(
token,
data
);
if (!isAtomicProvider) {
uint256 timestampAdjustment = dataStore.getUint(Keys.oracleTimestampAdjustmentKey(provider, token));
validatedPrice.timestamp -= timestampAdjustment;
}
if (validatedPrice.timestamp + maxPriceAge < Chain.currentTimestamp()) {
revert Errors.MaxPriceAgeExceeded(validatedPrice.timestamp, Chain.currentTimestamp());
}
if (!isAtomicProvider) {
(bool hasRefPrice, uint256 refPrice) = ChainlinkPriceFeedUtils.getPriceFeedPrice(dataStore, token);
if (hasRefPrice) {
_validateRefPrice(
token,
validatedPrice.min,
refPrice,
maxRefPriceDeviationFactor
);
_validateRefPrice(
token,
validatedPrice.max,
refPrice,
maxRefPriceDeviationFactor
);
}
}
prices[i] = validatedPrice;
}
return prices;
}
function _validateRefPrice(
address token,
uint256 price,
uint256 refPrice,
uint256 maxRefPriceDeviationFactor
) internal pure {
uint256 diff = Calc.diff(price, refPrice);
uint256 diffFactor = Precision.toFactor(diff, refPrice);
if (diffFactor > maxRefPriceDeviationFactor) {
revert Errors.MaxRefPriceDeviationExceeded(
token,
price,
refPrice,
maxRefPriceDeviationFactor
);
}
}
function _setPrimaryPrice(address token, Price.Props memory price) internal {
if (price.min > price.max) {
revert Errors.InvalidMinMaxForPrice(token, price.min, price.max);
}
Price.Props memory existingPrice = primaryPrices[token];
if (!existingPrice.isEmpty()) {
revert Errors.PriceAlreadySet(token, existingPrice.min, existingPrice.max);
}
primaryPrices[token] = price;
tokensWithPrices.add(token);
}
function _removePrimaryPrice(address token) internal {
delete primaryPrices[token];
tokensWithPrices.remove(token);
}
function _emitOraclePriceUpdated(
address token,
uint256 minPrice,
uint256 maxPrice,
uint256 timestamp,
address provider
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "token", token);
eventData.addressItems.setItem(1, "provider", provider);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "minPrice", minPrice);
eventData.uintItems.setItem(1, "maxPrice", maxPrice);
eventData.uintItems.setItem(2, "timestamp", timestamp);
eventEmitter.emitEventLog1(
"OraclePriceUpdate",
Cast.toBytes32(token),
eventData
);
}
}
文件 42 的 57:OracleUtils.sol
pragma solidity ^0.8.0;
import "../utils/Array.sol";
import "../price/Price.sol";
library OracleUtils {
using Array for uint256[];
struct SetPricesParams {
address[] tokens;
address[] providers;
bytes[] data;
}
struct ValidatedPrice {
address token;
uint256 min;
uint256 max;
uint256 timestamp;
address provider;
}
struct SimulatePricesParams {
address[] primaryTokens;
Price.Props[] primaryPrices;
uint256 minTimestamp;
uint256 maxTimestamp;
}
function isOracleError(bytes4 errorSelector) internal pure returns (bool) {
if (isOracleTimestampError(errorSelector)) {
return true;
}
if (isEmptyPriceError(errorSelector)) {
return true;
}
return false;
}
function isEmptyPriceError(bytes4 errorSelector) internal pure returns (bool) {
if (errorSelector == Errors.EmptyPrimaryPrice.selector) {
return true;
}
return false;
}
function isOracleTimestampError(bytes4 errorSelector) internal pure returns (bool) {
if (errorSelector == Errors.OracleTimestampsAreLargerThanRequestExpirationTime.selector) {
return true;
}
if (errorSelector == Errors.OracleTimestampsAreSmallerThanRequired.selector) {
return true;
}
return false;
}
}
文件 43 的 57:Order.sol
pragma solidity ^0.8.0;
import "../chain/Chain.sol";
library Order {
using Order for Props;
enum OrderType {
MarketSwap,
LimitSwap,
MarketIncrease,
LimitIncrease,
MarketDecrease,
LimitDecrease,
StopLossDecrease,
Liquidation,
StopIncrease
}
enum SecondaryOrderType {
None,
Adl
}
enum DecreasePositionSwapType {
NoSwap,
SwapPnlTokenToCollateralToken,
SwapCollateralTokenToPnlToken
}
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address receiver;
address cancellationReceiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialCollateralToken;
address[] swapPath;
}
struct Numbers {
OrderType orderType;
DecreasePositionSwapType decreasePositionSwapType;
uint256 sizeDeltaUsd;
uint256 initialCollateralDeltaAmount;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
uint256 minOutputAmount;
uint256 updatedAtTime;
uint256 validFromTime;
}
struct Flags {
bool isLong;
bool shouldUnwrapNativeToken;
bool isFrozen;
bool autoCancel;
}
function account(Props memory props) internal pure returns (address) {
return props.addresses.account;
}
function setAccount(Props memory props, address value) internal pure {
props.addresses.account = value;
}
function receiver(Props memory props) internal pure returns (address) {
return props.addresses.receiver;
}
function setReceiver(Props memory props, address value) internal pure {
props.addresses.receiver = value;
}
function cancellationReceiver(Props memory props) internal pure returns (address) {
return props.addresses.cancellationReceiver;
}
function setCancellationReceiver(Props memory props, address value) internal pure {
props.addresses.cancellationReceiver = value;
}
function callbackContract(Props memory props) internal pure returns (address) {
return props.addresses.callbackContract;
}
function setCallbackContract(Props memory props, address value) internal pure {
props.addresses.callbackContract = value;
}
function market(Props memory props) internal pure returns (address) {
return props.addresses.market;
}
function setMarket(Props memory props, address value) internal pure {
props.addresses.market = value;
}
function initialCollateralToken(Props memory props) internal pure returns (address) {
return props.addresses.initialCollateralToken;
}
function setInitialCollateralToken(Props memory props, address value) internal pure {
props.addresses.initialCollateralToken = value;
}
function uiFeeReceiver(Props memory props) internal pure returns (address) {
return props.addresses.uiFeeReceiver;
}
function setUiFeeReceiver(Props memory props, address value) internal pure {
props.addresses.uiFeeReceiver = value;
}
function swapPath(Props memory props) internal pure returns (address[] memory) {
return props.addresses.swapPath;
}
function setSwapPath(Props memory props, address[] memory value) internal pure {
props.addresses.swapPath = value;
}
function orderType(Props memory props) internal pure returns (OrderType) {
return props.numbers.orderType;
}
function setOrderType(Props memory props, OrderType value) internal pure {
props.numbers.orderType = value;
}
function decreasePositionSwapType(Props memory props) internal pure returns (DecreasePositionSwapType) {
return props.numbers.decreasePositionSwapType;
}
function setDecreasePositionSwapType(Props memory props, DecreasePositionSwapType value) internal pure {
props.numbers.decreasePositionSwapType = value;
}
function sizeDeltaUsd(Props memory props) internal pure returns (uint256) {
return props.numbers.sizeDeltaUsd;
}
function setSizeDeltaUsd(Props memory props, uint256 value) internal pure {
props.numbers.sizeDeltaUsd = value;
}
function initialCollateralDeltaAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.initialCollateralDeltaAmount;
}
function setInitialCollateralDeltaAmount(Props memory props, uint256 value) internal pure {
props.numbers.initialCollateralDeltaAmount = value;
}
function triggerPrice(Props memory props) internal pure returns (uint256) {
return props.numbers.triggerPrice;
}
function setTriggerPrice(Props memory props, uint256 value) internal pure {
props.numbers.triggerPrice = value;
}
function acceptablePrice(Props memory props) internal pure returns (uint256) {
return props.numbers.acceptablePrice;
}
function setAcceptablePrice(Props memory props, uint256 value) internal pure {
props.numbers.acceptablePrice = value;
}
function setExecutionFee(Props memory props, uint256 value) internal pure {
props.numbers.executionFee = value;
}
function executionFee(Props memory props) internal pure returns (uint256) {
return props.numbers.executionFee;
}
function callbackGasLimit(Props memory props) internal pure returns (uint256) {
return props.numbers.callbackGasLimit;
}
function setCallbackGasLimit(Props memory props, uint256 value) internal pure {
props.numbers.callbackGasLimit = value;
}
function minOutputAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.minOutputAmount;
}
function setMinOutputAmount(Props memory props, uint256 value) internal pure {
props.numbers.minOutputAmount = value;
}
function updatedAtTime(Props memory props) internal pure returns (uint256) {
return props.numbers.updatedAtTime;
}
function setUpdatedAtTime(Props memory props, uint256 value) internal pure {
props.numbers.updatedAtTime = value;
}
function validFromTime(Props memory props) internal pure returns (uint256) {
return props.numbers.validFromTime;
}
function setValidFromTime(Props memory props, uint256 value) internal pure {
props.numbers.validFromTime = value;
}
function isLong(Props memory props) internal pure returns (bool) {
return props.flags.isLong;
}
function setIsLong(Props memory props, bool value) internal pure {
props.flags.isLong = value;
}
function shouldUnwrapNativeToken(Props memory props) internal pure returns (bool) {
return props.flags.shouldUnwrapNativeToken;
}
function setShouldUnwrapNativeToken(Props memory props, bool value) internal pure {
props.flags.shouldUnwrapNativeToken = value;
}
function isFrozen(Props memory props) internal pure returns (bool) {
return props.flags.isFrozen;
}
function setIsFrozen(Props memory props, bool value) internal pure {
props.flags.isFrozen = value;
}
function autoCancel(Props memory props) internal pure returns (bool) {
return props.flags.autoCancel;
}
function setAutoCancel(Props memory props, bool value) internal pure {
props.flags.autoCancel = value;
}
function touch(Props memory props) internal view {
props.setUpdatedAtTime(Chain.currentTimestamp());
}
}
文件 44 的 57:PRBMath.sol
pragma solidity >=0.8.4;
error PRBMath__MulDivFixedPointOverflow(uint256 prod1);
error PRBMath__MulDivOverflow(uint256 prod1, uint256 denominator);
error PRBMath__MulDivSignedInputTooSmall();
error PRBMath__MulDivSignedOverflow(uint256 rAbs);
error PRBMathSD59x18__AbsInputTooSmall();
error PRBMathSD59x18__CeilOverflow(int256 x);
error PRBMathSD59x18__DivInputTooSmall();
error PRBMathSD59x18__DivOverflow(uint256 rAbs);
error PRBMathSD59x18__ExpInputTooBig(int256 x);
error PRBMathSD59x18__Exp2InputTooBig(int256 x);
error PRBMathSD59x18__FloorUnderflow(int256 x);
error PRBMathSD59x18__FromIntOverflow(int256 x);
error PRBMathSD59x18__FromIntUnderflow(int256 x);
error PRBMathSD59x18__GmNegativeProduct(int256 x, int256 y);
error PRBMathSD59x18__GmOverflow(int256 x, int256 y);
error PRBMathSD59x18__LogInputTooSmall(int256 x);
error PRBMathSD59x18__MulInputTooSmall();
error PRBMathSD59x18__MulOverflow(uint256 rAbs);
error PRBMathSD59x18__PowuOverflow(uint256 rAbs);
error PRBMathSD59x18__SqrtNegativeInput(int256 x);
error PRBMathSD59x18__SqrtOverflow(int256 x);
error PRBMathUD60x18__AddOverflow(uint256 x, uint256 y);
error PRBMathUD60x18__CeilOverflow(uint256 x);
error PRBMathUD60x18__ExpInputTooBig(uint256 x);
error PRBMathUD60x18__Exp2InputTooBig(uint256 x);
error PRBMathUD60x18__FromUintOverflow(uint256 x);
error PRBMathUD60x18__GmOverflow(uint256 x, uint256 y);
error PRBMathUD60x18__LogInputTooSmall(uint256 x);
error PRBMathUD60x18__SqrtOverflow(uint256 x);
error PRBMathUD60x18__SubUnderflow(uint256 x, uint256 y);
library PRBMath {
struct SD59x18 {
int256 value;
}
struct UD60x18 {
uint256 value;
}
uint256 internal constant SCALE = 1e18;
uint256 internal constant SCALE_LPOTD = 262144;
uint256 internal constant SCALE_INVERSE =
78156646155174841979727994598816262306175212592076161876661_508869554232690281;
function exp2(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = 0x800000000000000000000000000000000000000000000000;
if (x & 0x8000000000000000 > 0) {
result = (result * 0x16A09E667F3BCC909) >> 64;
}
if (x & 0x4000000000000000 > 0) {
result = (result * 0x1306FE0A31B7152DF) >> 64;
}
if (x & 0x2000000000000000 > 0) {
result = (result * 0x1172B83C7D517ADCE) >> 64;
}
if (x & 0x1000000000000000 > 0) {
result = (result * 0x10B5586CF9890F62A) >> 64;
}
if (x & 0x800000000000000 > 0) {
result = (result * 0x1059B0D31585743AE) >> 64;
}
if (x & 0x400000000000000 > 0) {
result = (result * 0x102C9A3E778060EE7) >> 64;
}
if (x & 0x200000000000000 > 0) {
result = (result * 0x10163DA9FB33356D8) >> 64;
}
if (x & 0x100000000000000 > 0) {
result = (result * 0x100B1AFA5ABCBED61) >> 64;
}
if (x & 0x80000000000000 > 0) {
result = (result * 0x10058C86DA1C09EA2) >> 64;
}
if (x & 0x40000000000000 > 0) {
result = (result * 0x1002C605E2E8CEC50) >> 64;
}
if (x & 0x20000000000000 > 0) {
result = (result * 0x100162F3904051FA1) >> 64;
}
if (x & 0x10000000000000 > 0) {
result = (result * 0x1000B175EFFDC76BA) >> 64;
}
if (x & 0x8000000000000 > 0) {
result = (result * 0x100058BA01FB9F96D) >> 64;
}
if (x & 0x4000000000000 > 0) {
result = (result * 0x10002C5CC37DA9492) >> 64;
}
if (x & 0x2000000000000 > 0) {
result = (result * 0x1000162E525EE0547) >> 64;
}
if (x & 0x1000000000000 > 0) {
result = (result * 0x10000B17255775C04) >> 64;
}
if (x & 0x800000000000 > 0) {
result = (result * 0x1000058B91B5BC9AE) >> 64;
}
if (x & 0x400000000000 > 0) {
result = (result * 0x100002C5C89D5EC6D) >> 64;
}
if (x & 0x200000000000 > 0) {
result = (result * 0x10000162E43F4F831) >> 64;
}
if (x & 0x100000000000 > 0) {
result = (result * 0x100000B1721BCFC9A) >> 64;
}
if (x & 0x80000000000 > 0) {
result = (result * 0x10000058B90CF1E6E) >> 64;
}
if (x & 0x40000000000 > 0) {
result = (result * 0x1000002C5C863B73F) >> 64;
}
if (x & 0x20000000000 > 0) {
result = (result * 0x100000162E430E5A2) >> 64;
}
if (x & 0x10000000000 > 0) {
result = (result * 0x1000000B172183551) >> 64;
}
if (x & 0x8000000000 > 0) {
result = (result * 0x100000058B90C0B49) >> 64;
}
if (x & 0x4000000000 > 0) {
result = (result * 0x10000002C5C8601CC) >> 64;
}
if (x & 0x2000000000 > 0) {
result = (result * 0x1000000162E42FFF0) >> 64;
}
if (x & 0x1000000000 > 0) {
result = (result * 0x10000000B17217FBB) >> 64;
}
if (x & 0x800000000 > 0) {
result = (result * 0x1000000058B90BFCE) >> 64;
}
if (x & 0x400000000 > 0) {
result = (result * 0x100000002C5C85FE3) >> 64;
}
if (x & 0x200000000 > 0) {
result = (result * 0x10000000162E42FF1) >> 64;
}
if (x & 0x100000000 > 0) {
result = (result * 0x100000000B17217F8) >> 64;
}
if (x & 0x80000000 > 0) {
result = (result * 0x10000000058B90BFC) >> 64;
}
if (x & 0x40000000 > 0) {
result = (result * 0x1000000002C5C85FE) >> 64;
}
if (x & 0x20000000 > 0) {
result = (result * 0x100000000162E42FF) >> 64;
}
if (x & 0x10000000 > 0) {
result = (result * 0x1000000000B17217F) >> 64;
}
if (x & 0x8000000 > 0) {
result = (result * 0x100000000058B90C0) >> 64;
}
if (x & 0x4000000 > 0) {
result = (result * 0x10000000002C5C860) >> 64;
}
if (x & 0x2000000 > 0) {
result = (result * 0x1000000000162E430) >> 64;
}
if (x & 0x1000000 > 0) {
result = (result * 0x10000000000B17218) >> 64;
}
if (x & 0x800000 > 0) {
result = (result * 0x1000000000058B90C) >> 64;
}
if (x & 0x400000 > 0) {
result = (result * 0x100000000002C5C86) >> 64;
}
if (x & 0x200000 > 0) {
result = (result * 0x10000000000162E43) >> 64;
}
if (x & 0x100000 > 0) {
result = (result * 0x100000000000B1721) >> 64;
}
if (x & 0x80000 > 0) {
result = (result * 0x10000000000058B91) >> 64;
}
if (x & 0x40000 > 0) {
result = (result * 0x1000000000002C5C8) >> 64;
}
if (x & 0x20000 > 0) {
result = (result * 0x100000000000162E4) >> 64;
}
if (x & 0x10000 > 0) {
result = (result * 0x1000000000000B172) >> 64;
}
if (x & 0x8000 > 0) {
result = (result * 0x100000000000058B9) >> 64;
}
if (x & 0x4000 > 0) {
result = (result * 0x10000000000002C5D) >> 64;
}
if (x & 0x2000 > 0) {
result = (result * 0x1000000000000162E) >> 64;
}
if (x & 0x1000 > 0) {
result = (result * 0x10000000000000B17) >> 64;
}
if (x & 0x800 > 0) {
result = (result * 0x1000000000000058C) >> 64;
}
if (x & 0x400 > 0) {
result = (result * 0x100000000000002C6) >> 64;
}
if (x & 0x200 > 0) {
result = (result * 0x10000000000000163) >> 64;
}
if (x & 0x100 > 0) {
result = (result * 0x100000000000000B1) >> 64;
}
if (x & 0x80 > 0) {
result = (result * 0x10000000000000059) >> 64;
}
if (x & 0x40 > 0) {
result = (result * 0x1000000000000002C) >> 64;
}
if (x & 0x20 > 0) {
result = (result * 0x10000000000000016) >> 64;
}
if (x & 0x10 > 0) {
result = (result * 0x1000000000000000B) >> 64;
}
if (x & 0x8 > 0) {
result = (result * 0x10000000000000006) >> 64;
}
if (x & 0x4 > 0) {
result = (result * 0x10000000000000003) >> 64;
}
if (x & 0x2 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
if (x & 0x1 > 0) {
result = (result * 0x10000000000000001) >> 64;
}
result *= SCALE;
result >>= (191 - (x >> 64));
}
}
function mostSignificantBit(uint256 x) internal pure returns (uint256 msb) {
if (x >= 2**128) {
x >>= 128;
msb += 128;
}
if (x >= 2**64) {
x >>= 64;
msb += 64;
}
if (x >= 2**32) {
x >>= 32;
msb += 32;
}
if (x >= 2**16) {
x >>= 16;
msb += 16;
}
if (x >= 2**8) {
x >>= 8;
msb += 8;
}
if (x >= 2**4) {
x >>= 4;
msb += 4;
}
if (x >= 2**2) {
x >>= 2;
msb += 2;
}
if (x >= 2**1) {
msb += 1;
}
}
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
unchecked {
result = prod0 / denominator;
}
return result;
}
if (prod1 >= denominator) {
revert PRBMath__MulDivOverflow(prod1, denominator);
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
unchecked {
uint256 lpotdod = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, lpotdod)
prod0 := div(prod0, lpotdod)
lpotdod := add(div(sub(0, lpotdod), lpotdod), 1)
}
prod0 |= prod1 * lpotdod;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDivFixedPoint(uint256 x, uint256 y) internal pure returns (uint256 result) {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 >= SCALE) {
revert PRBMath__MulDivFixedPointOverflow(prod1);
}
uint256 remainder;
uint256 roundUpUnit;
assembly {
remainder := mulmod(x, y, SCALE)
roundUpUnit := gt(remainder, 499999999999999999)
}
if (prod1 == 0) {
unchecked {
result = (prod0 / SCALE) + roundUpUnit;
return result;
}
}
assembly {
result := add(
mul(
or(
div(sub(prod0, remainder), SCALE_LPOTD),
mul(sub(prod1, gt(remainder, prod0)), add(div(sub(0, SCALE_LPOTD), SCALE_LPOTD), 1))
),
SCALE_INVERSE
),
roundUpUnit
)
}
}
function mulDivSigned(
int256 x,
int256 y,
int256 denominator
) internal pure returns (int256 result) {
if (x == type(int256).min || y == type(int256).min || denominator == type(int256).min) {
revert PRBMath__MulDivSignedInputTooSmall();
}
uint256 ax;
uint256 ay;
uint256 ad;
unchecked {
ax = x < 0 ? uint256(-x) : uint256(x);
ay = y < 0 ? uint256(-y) : uint256(y);
ad = denominator < 0 ? uint256(-denominator) : uint256(denominator);
}
uint256 rAbs = mulDiv(ax, ay, ad);
if (rAbs > uint256(type(int256).max)) {
revert PRBMath__MulDivSignedOverflow(rAbs);
}
uint256 sx;
uint256 sy;
uint256 sd;
assembly {
sx := sgt(x, sub(0, 1))
sy := sgt(y, sub(0, 1))
sd := sgt(denominator, sub(0, 1))
}
result = sx ^ sy ^ sd == 0 ? -int256(rAbs) : int256(rAbs);
}
function sqrt(uint256 x) internal pure returns (uint256 result) {
if (x == 0) {
return 0;
}
uint256 xAux = uint256(x);
result = 1;
if (xAux >= 0x100000000000000000000000000000000) {
xAux >>= 128;
result <<= 64;
}
if (xAux >= 0x10000000000000000) {
xAux >>= 64;
result <<= 32;
}
if (xAux >= 0x100000000) {
xAux >>= 32;
result <<= 16;
}
if (xAux >= 0x10000) {
xAux >>= 16;
result <<= 8;
}
if (xAux >= 0x100) {
xAux >>= 8;
result <<= 4;
}
if (xAux >= 0x10) {
xAux >>= 4;
result <<= 2;
}
if (xAux >= 0x8) {
result <<= 1;
}
unchecked {
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
result = (result + x / result) >> 1;
uint256 roundedDownResult = x / result;
return result >= roundedDownResult ? roundedDownResult : result;
}
}
}
文件 45 的 57:PRBMathUD60x18.sol
pragma solidity >=0.8.4;
import "./PRBMath.sol";
library PRBMathUD60x18 {
uint256 internal constant HALF_SCALE = 5e17;
uint256 internal constant LOG2_E = 1_442695040888963407;
uint256 internal constant MAX_UD60x18 =
115792089237316195423570985008687907853269984665640564039457_584007913129639935;
uint256 internal constant MAX_WHOLE_UD60x18 =
115792089237316195423570985008687907853269984665640564039457_000000000000000000;
uint256 internal constant SCALE = 1e18;
function avg(uint256 x, uint256 y) internal pure returns (uint256 result) {
unchecked {
result = (x >> 1) + (y >> 1) + (x & y & 1);
}
}
function ceil(uint256 x) internal pure returns (uint256 result) {
if (x > MAX_WHOLE_UD60x18) {
revert PRBMathUD60x18__CeilOverflow(x);
}
assembly {
let remainder := mod(x, SCALE)
let delta := sub(SCALE, remainder)
result := add(x, mul(delta, gt(remainder, 0)))
}
}
function div(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = PRBMath.mulDiv(x, SCALE, y);
}
function e() internal pure returns (uint256 result) {
result = 2_718281828459045235;
}
function exp(uint256 x) internal pure returns (uint256 result) {
if (x >= 133_084258667509499441) {
revert PRBMathUD60x18__ExpInputTooBig(x);
}
unchecked {
uint256 doubleScaleProduct = x * LOG2_E;
result = exp2((doubleScaleProduct + HALF_SCALE) / SCALE);
}
}
function exp2(uint256 x) internal pure returns (uint256 result) {
if (x >= 192e18) {
revert PRBMathUD60x18__Exp2InputTooBig(x);
}
unchecked {
uint256 x192x64 = (x << 64) / SCALE;
result = PRBMath.exp2(x192x64);
}
}
function floor(uint256 x) internal pure returns (uint256 result) {
assembly {
let remainder := mod(x, SCALE)
result := sub(x, mul(remainder, gt(remainder, 0)))
}
}
function frac(uint256 x) internal pure returns (uint256 result) {
assembly {
result := mod(x, SCALE)
}
}
function fromUint(uint256 x) internal pure returns (uint256 result) {
unchecked {
if (x > MAX_UD60x18 / SCALE) {
revert PRBMathUD60x18__FromUintOverflow(x);
}
result = x * SCALE;
}
}
function gm(uint256 x, uint256 y) internal pure returns (uint256 result) {
if (x == 0) {
return 0;
}
unchecked {
uint256 xy = x * y;
if (xy / x != y) {
revert PRBMathUD60x18__GmOverflow(x, y);
}
result = PRBMath.sqrt(xy);
}
}
function inv(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = 1e36 / x;
}
}
function ln(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = (log2(x) * SCALE) / LOG2_E;
}
}
function log10(uint256 x) internal pure returns (uint256 result) {
if (x < SCALE) {
revert PRBMathUD60x18__LogInputTooSmall(x);
}
assembly {
switch x
case 1 { result := mul(SCALE, sub(0, 18)) }
case 10 { result := mul(SCALE, sub(1, 18)) }
case 100 { result := mul(SCALE, sub(2, 18)) }
case 1000 { result := mul(SCALE, sub(3, 18)) }
case 10000 { result := mul(SCALE, sub(4, 18)) }
case 100000 { result := mul(SCALE, sub(5, 18)) }
case 1000000 { result := mul(SCALE, sub(6, 18)) }
case 10000000 { result := mul(SCALE, sub(7, 18)) }
case 100000000 { result := mul(SCALE, sub(8, 18)) }
case 1000000000 { result := mul(SCALE, sub(9, 18)) }
case 10000000000 { result := mul(SCALE, sub(10, 18)) }
case 100000000000 { result := mul(SCALE, sub(11, 18)) }
case 1000000000000 { result := mul(SCALE, sub(12, 18)) }
case 10000000000000 { result := mul(SCALE, sub(13, 18)) }
case 100000000000000 { result := mul(SCALE, sub(14, 18)) }
case 1000000000000000 { result := mul(SCALE, sub(15, 18)) }
case 10000000000000000 { result := mul(SCALE, sub(16, 18)) }
case 100000000000000000 { result := mul(SCALE, sub(17, 18)) }
case 1000000000000000000 { result := 0 }
case 10000000000000000000 { result := SCALE }
case 100000000000000000000 { result := mul(SCALE, 2) }
case 1000000000000000000000 { result := mul(SCALE, 3) }
case 10000000000000000000000 { result := mul(SCALE, 4) }
case 100000000000000000000000 { result := mul(SCALE, 5) }
case 1000000000000000000000000 { result := mul(SCALE, 6) }
case 10000000000000000000000000 { result := mul(SCALE, 7) }
case 100000000000000000000000000 { result := mul(SCALE, 8) }
case 1000000000000000000000000000 { result := mul(SCALE, 9) }
case 10000000000000000000000000000 { result := mul(SCALE, 10) }
case 100000000000000000000000000000 { result := mul(SCALE, 11) }
case 1000000000000000000000000000000 { result := mul(SCALE, 12) }
case 10000000000000000000000000000000 { result := mul(SCALE, 13) }
case 100000000000000000000000000000000 { result := mul(SCALE, 14) }
case 1000000000000000000000000000000000 { result := mul(SCALE, 15) }
case 10000000000000000000000000000000000 { result := mul(SCALE, 16) }
case 100000000000000000000000000000000000 { result := mul(SCALE, 17) }
case 1000000000000000000000000000000000000 { result := mul(SCALE, 18) }
case 10000000000000000000000000000000000000 { result := mul(SCALE, 19) }
case 100000000000000000000000000000000000000 { result := mul(SCALE, 20) }
case 1000000000000000000000000000000000000000 { result := mul(SCALE, 21) }
case 10000000000000000000000000000000000000000 { result := mul(SCALE, 22) }
case 100000000000000000000000000000000000000000 { result := mul(SCALE, 23) }
case 1000000000000000000000000000000000000000000 { result := mul(SCALE, 24) }
case 10000000000000000000000000000000000000000000 { result := mul(SCALE, 25) }
case 100000000000000000000000000000000000000000000 { result := mul(SCALE, 26) }
case 1000000000000000000000000000000000000000000000 { result := mul(SCALE, 27) }
case 10000000000000000000000000000000000000000000000 { result := mul(SCALE, 28) }
case 100000000000000000000000000000000000000000000000 { result := mul(SCALE, 29) }
case 1000000000000000000000000000000000000000000000000 { result := mul(SCALE, 30) }
case 10000000000000000000000000000000000000000000000000 { result := mul(SCALE, 31) }
case 100000000000000000000000000000000000000000000000000 { result := mul(SCALE, 32) }
case 1000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 33) }
case 10000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 34) }
case 100000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 35) }
case 1000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 36) }
case 10000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 37) }
case 100000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 38) }
case 1000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 39) }
case 10000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 40) }
case 100000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 41) }
case 1000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 42) }
case 10000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 43) }
case 100000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 44) }
case 1000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 45) }
case 10000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 46) }
case 100000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 47) }
case 1000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 48) }
case 10000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 49) }
case 100000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 50) }
case 1000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 51) }
case 10000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 52) }
case 100000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 53) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 54) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 55) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 56) }
case 1000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 57) }
case 10000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 58) }
case 100000000000000000000000000000000000000000000000000000000000000000000000000000 { result := mul(SCALE, 59) }
default {
result := MAX_UD60x18
}
}
if (result == MAX_UD60x18) {
unchecked {
result = (log2(x) * SCALE) / 3_321928094887362347;
}
}
}
function log2(uint256 x) internal pure returns (uint256 result) {
if (x < SCALE) {
revert PRBMathUD60x18__LogInputTooSmall(x);
}
unchecked {
uint256 n = PRBMath.mostSignificantBit(x / SCALE);
result = n * SCALE;
uint256 y = x >> n;
if (y == SCALE) {
return result;
}
for (uint256 delta = HALF_SCALE; delta > 0; delta >>= 1) {
y = (y * y) / SCALE;
if (y >= 2 * SCALE) {
result += delta;
y >>= 1;
}
}
}
}
function mul(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = PRBMath.mulDivFixedPoint(x, y);
}
function pi() internal pure returns (uint256 result) {
result = 3_141592653589793238;
}
function pow(uint256 x, uint256 y) internal pure returns (uint256 result) {
if (x == 0) {
result = y == 0 ? SCALE : uint256(0);
} else {
result = exp2(mul(log2(x), y));
}
}
function powu(uint256 x, uint256 y) internal pure returns (uint256 result) {
result = y & 1 > 0 ? x : SCALE;
for (y >>= 1; y > 0; y >>= 1) {
x = PRBMath.mulDivFixedPoint(x, x);
if (y & 1 > 0) {
result = PRBMath.mulDivFixedPoint(result, x);
}
}
}
function scale() internal pure returns (uint256 result) {
result = SCALE;
}
function sqrt(uint256 x) internal pure returns (uint256 result) {
unchecked {
if (x > MAX_UD60x18 / SCALE) {
revert PRBMathUD60x18__SqrtOverflow(x);
}
result = PRBMath.sqrt(x * SCALE);
}
}
function toUint(uint256 x) internal pure returns (uint256 result) {
unchecked {
result = x / SCALE;
}
}
}
文件 46 的 57:Position.sol
pragma solidity ^0.8.0;
library Position {
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address market;
address collateralToken;
}
struct Numbers {
uint256 sizeInUsd;
uint256 sizeInTokens;
uint256 collateralAmount;
uint256 borrowingFactor;
uint256 fundingFeeAmountPerSize;
uint256 longTokenClaimableFundingAmountPerSize;
uint256 shortTokenClaimableFundingAmountPerSize;
uint256 increasedAtTime;
uint256 decreasedAtTime;
}
struct Flags {
bool isLong;
}
function account(Props memory props) internal pure returns (address) {
return props.addresses.account;
}
function setAccount(Props memory props, address value) internal pure {
props.addresses.account = value;
}
function market(Props memory props) internal pure returns (address) {
return props.addresses.market;
}
function setMarket(Props memory props, address value) internal pure {
props.addresses.market = value;
}
function collateralToken(Props memory props) internal pure returns (address) {
return props.addresses.collateralToken;
}
function setCollateralToken(Props memory props, address value) internal pure {
props.addresses.collateralToken = value;
}
function sizeInUsd(Props memory props) internal pure returns (uint256) {
return props.numbers.sizeInUsd;
}
function setSizeInUsd(Props memory props, uint256 value) internal pure {
props.numbers.sizeInUsd = value;
}
function sizeInTokens(Props memory props) internal pure returns (uint256) {
return props.numbers.sizeInTokens;
}
function setSizeInTokens(Props memory props, uint256 value) internal pure {
props.numbers.sizeInTokens = value;
}
function collateralAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.collateralAmount;
}
function setCollateralAmount(Props memory props, uint256 value) internal pure {
props.numbers.collateralAmount = value;
}
function borrowingFactor(Props memory props) internal pure returns (uint256) {
return props.numbers.borrowingFactor;
}
function setBorrowingFactor(Props memory props, uint256 value) internal pure {
props.numbers.borrowingFactor = value;
}
function fundingFeeAmountPerSize(Props memory props) internal pure returns (uint256) {
return props.numbers.fundingFeeAmountPerSize;
}
function setFundingFeeAmountPerSize(Props memory props, uint256 value) internal pure {
props.numbers.fundingFeeAmountPerSize = value;
}
function longTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {
return props.numbers.longTokenClaimableFundingAmountPerSize;
}
function setLongTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {
props.numbers.longTokenClaimableFundingAmountPerSize = value;
}
function shortTokenClaimableFundingAmountPerSize(Props memory props) internal pure returns (uint256) {
return props.numbers.shortTokenClaimableFundingAmountPerSize;
}
function setShortTokenClaimableFundingAmountPerSize(Props memory props, uint256 value) internal pure {
props.numbers.shortTokenClaimableFundingAmountPerSize = value;
}
function increasedAtTime(Props memory props) internal pure returns (uint256) {
return props.numbers.increasedAtTime;
}
function setIncreasedAtTime(Props memory props, uint256 value) internal pure {
props.numbers.increasedAtTime = value;
}
function decreasedAtTime(Props memory props) internal pure returns (uint256) {
return props.numbers.decreasedAtTime;
}
function setDecreasedAtTime(Props memory props, uint256 value) internal pure {
props.numbers.decreasedAtTime = value;
}
function isLong(Props memory props) internal pure returns (bool) {
return props.flags.isLong;
}
function setIsLong(Props memory props, bool value) internal pure {
props.flags.isLong = value;
}
function getPositionKey(address _account, address _market, address _collateralToken, bool _isLong) internal pure returns (bytes32) {
bytes32 _key = keccak256(abi.encode(_account, _market, _collateralToken, _isLong));
return _key;
}
}
文件 47 的 57:Precision.sol
pragma solidity ^0.8.0;
import "prb-math/contracts/PRBMathUD60x18.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "@openzeppelin/contracts/utils/math/SignedMath.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
library Precision {
using SafeCast for uint256;
using SignedMath for int256;
uint256 public constant FLOAT_PRECISION = 10 ** 30;
uint256 public constant FLOAT_PRECISION_SQRT = 10 ** 15;
uint256 public constant WEI_PRECISION = 10 ** 18;
uint256 public constant BASIS_POINTS_DIVISOR = 10000;
uint256 public constant FLOAT_TO_WEI_DIVISOR = 10 ** 12;
function applyFactor(uint256 value, uint256 factor) internal pure returns (uint256) {
return mulDiv(value, factor, FLOAT_PRECISION);
}
function applyFactor(uint256 value, int256 factor) internal pure returns (int256) {
return mulDiv(value, factor, FLOAT_PRECISION);
}
function applyFactor(uint256 value, int256 factor, bool roundUpMagnitude) internal pure returns (int256) {
return mulDiv(value, factor, FLOAT_PRECISION, roundUpMagnitude);
}
function mulDiv(uint256 value, uint256 numerator, uint256 denominator) internal pure returns (uint256) {
return Math.mulDiv(value, numerator, denominator);
}
function mulDiv(int256 value, uint256 numerator, uint256 denominator) internal pure returns (int256) {
return mulDiv(numerator, value, denominator);
}
function mulDiv(uint256 value, int256 numerator, uint256 denominator) internal pure returns (int256) {
uint256 result = mulDiv(value, numerator.abs(), denominator);
return numerator > 0 ? result.toInt256() : -result.toInt256();
}
function mulDiv(uint256 value, int256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (int256) {
uint256 result = mulDiv(value, numerator.abs(), denominator, roundUpMagnitude);
return numerator > 0 ? result.toInt256() : -result.toInt256();
}
function mulDiv(uint256 value, uint256 numerator, uint256 denominator, bool roundUpMagnitude) internal pure returns (uint256) {
if (roundUpMagnitude) {
return Math.mulDiv(value, numerator, denominator, Math.Rounding.Up);
}
return Math.mulDiv(value, numerator, denominator);
}
function applyExponentFactor(
uint256 floatValue,
uint256 exponentFactor
) internal pure returns (uint256) {
if (floatValue < FLOAT_PRECISION) {
return 0;
}
if (exponentFactor == FLOAT_PRECISION) {
return floatValue;
}
uint256 weiValue = PRBMathUD60x18.pow(
floatToWei(floatValue),
floatToWei(exponentFactor)
);
return weiToFloat(weiValue);
}
function toFactor(uint256 value, uint256 divisor, bool roundUpMagnitude) internal pure returns (uint256) {
if (value == 0) { return 0; }
if (roundUpMagnitude) {
return Math.mulDiv(value, FLOAT_PRECISION, divisor, Math.Rounding.Up);
}
return Math.mulDiv(value, FLOAT_PRECISION, divisor);
}
function toFactor(uint256 value, uint256 divisor) internal pure returns (uint256) {
return toFactor(value, divisor, false);
}
function toFactor(int256 value, uint256 divisor) internal pure returns (int256) {
uint256 result = toFactor(value.abs(), divisor);
return value > 0 ? result.toInt256() : -result.toInt256();
}
function floatToWei(uint256 value) internal pure returns (uint256) {
return value / FLOAT_TO_WEI_DIVISOR;
}
function weiToFloat(uint256 value) internal pure returns (uint256) {
return value * FLOAT_TO_WEI_DIVISOR;
}
function basisPointsToFloat(uint256 basisPoints) internal pure returns (uint256) {
return basisPoints * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;
}
}
文件 48 的 57:Price.sol
pragma solidity ^0.8.0;
library Price {
struct Props {
uint256 min;
uint256 max;
}
function isEmpty(Props memory props) internal pure returns (bool) {
return props.min == 0 || props.max == 0;
}
function midPrice(Props memory props) internal pure returns (uint256) {
return (props.max + props.min) / 2;
}
function pickPrice(Props memory props, bool maximize) internal pure returns (uint256) {
return maximize ? props.max : props.min;
}
function pickPriceForPnl(Props memory props, bool isLong, bool maximize) internal pure returns (uint256) {
if (isLong) {
return maximize ? props.max : props.min;
}
return maximize ? props.min : props.max;
}
}
文件 49 的 57:ReentrancyGuard.sol
pragma solidity ^0.8.0;
abstract contract ReentrancyGuard {
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
}
function _nonReentrantAfter() private {
_status = _NOT_ENTERED;
}
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}
文件 50 的 57:Role.sol
pragma solidity ^0.8.0;
library Role {
bytes32 public constant ROLE_ADMIN = keccak256(abi.encode("ROLE_ADMIN"));
bytes32 public constant TIMELOCK_ADMIN = keccak256(abi.encode("TIMELOCK_ADMIN"));
bytes32 public constant TIMELOCK_MULTISIG = keccak256(abi.encode("TIMELOCK_MULTISIG"));
bytes32 public constant CONFIG_KEEPER = keccak256(abi.encode("CONFIG_KEEPER"));
bytes32 public constant LIMITED_CONFIG_KEEPER = keccak256(abi.encode("LIMITED_CONFIG_KEEPER"));
bytes32 public constant CONTROLLER = keccak256(abi.encode("CONTROLLER"));
bytes32 public constant GOV_TOKEN_CONTROLLER = keccak256(abi.encode("GOV_TOKEN_CONTROLLER"));
bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode("ROUTER_PLUGIN"));
bytes32 public constant MARKET_KEEPER = keccak256(abi.encode("MARKET_KEEPER"));
bytes32 public constant FEE_KEEPER = keccak256(abi.encode("FEE_KEEPER"));
bytes32 public constant FEE_DISTRIBUTION_KEEPER = keccak256(abi.encode("FEE_DISTRIBUTION_KEEPER"));
bytes32 public constant ORDER_KEEPER = keccak256(abi.encode("ORDER_KEEPER"));
bytes32 public constant FROZEN_ORDER_KEEPER = keccak256(abi.encode("FROZEN_ORDER_KEEPER"));
bytes32 public constant PRICING_KEEPER = keccak256(abi.encode("PRICING_KEEPER"));
bytes32 public constant LIQUIDATION_KEEPER = keccak256(abi.encode("LIQUIDATION_KEEPER"));
bytes32 public constant ADL_KEEPER = keccak256(abi.encode("ADL_KEEPER"));
bytes32 public constant CONTRIBUTOR_KEEPER = keccak256(abi.encode("CONTRIBUTOR_KEEPER"));
bytes32 public constant CONTRIBUTOR_DISTRIBUTOR = keccak256(abi.encode("CONTRIBUTOR_DISTRIBUTOR"));
}
文件 51 的 57:RoleModule.sol
pragma solidity ^0.8.0;
import "./RoleStore.sol";
contract RoleModule {
RoleStore public immutable roleStore;
constructor(RoleStore _roleStore) {
roleStore = _roleStore;
}
modifier onlySelf() {
if (msg.sender != address(this)) {
revert Errors.Unauthorized(msg.sender, "SELF");
}
_;
}
modifier onlyTimelockMultisig() {
_validateRole(Role.TIMELOCK_MULTISIG, "TIMELOCK_MULTISIG");
_;
}
modifier onlyTimelockAdmin() {
_validateRole(Role.TIMELOCK_ADMIN, "TIMELOCK_ADMIN");
_;
}
modifier onlyConfigKeeper() {
_validateRole(Role.CONFIG_KEEPER, "CONFIG_KEEPER");
_;
}
modifier onlyLimitedConfigKeeper() {
_validateRole(Role.LIMITED_CONFIG_KEEPER, "LIMITED_CONFIG_KEEPER");
_;
}
modifier onlyController() {
_validateRole(Role.CONTROLLER, "CONTROLLER");
_;
}
modifier onlyGovTokenController() {
_validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER");
_;
}
modifier onlyRouterPlugin() {
_validateRole(Role.ROUTER_PLUGIN, "ROUTER_PLUGIN");
_;
}
modifier onlyMarketKeeper() {
_validateRole(Role.MARKET_KEEPER, "MARKET_KEEPER");
_;
}
modifier onlyFeeKeeper() {
_validateRole(Role.FEE_KEEPER, "FEE_KEEPER");
_;
}
modifier onlyFeeDistributionKeeper() {
_validateRole(Role.FEE_DISTRIBUTION_KEEPER, "FEE_DISTRIBUTION_KEEPER");
_;
}
modifier onlyOrderKeeper() {
_validateRole(Role.ORDER_KEEPER, "ORDER_KEEPER");
_;
}
modifier onlyPricingKeeper() {
_validateRole(Role.PRICING_KEEPER, "PRICING_KEEPER");
_;
}
modifier onlyLiquidationKeeper() {
_validateRole(Role.LIQUIDATION_KEEPER, "LIQUIDATION_KEEPER");
_;
}
modifier onlyAdlKeeper() {
_validateRole(Role.ADL_KEEPER, "ADL_KEEPER");
_;
}
modifier onlyContributorKeeper() {
_validateRole(Role.CONTRIBUTOR_KEEPER, "CONTRIBUTOR_KEEPER");
_;
}
modifier onlyContributorDistributor() {
_validateRole(Role.CONTRIBUTOR_DISTRIBUTOR, "CONTRIBUTOR_DISTRIBUTOR");
_;
}
function _validateRole(bytes32 role, string memory roleName) internal view {
if (!roleStore.hasRole(msg.sender, role)) {
revert Errors.Unauthorized(msg.sender, roleName);
}
}
}
文件 52 的 57:RoleStore.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "../utils/EnumerableValues.sol";
import "./Role.sol";
import "../error/Errors.sol";
contract RoleStore {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableSet for EnumerableSet.Bytes32Set;
using EnumerableValues for EnumerableSet.AddressSet;
using EnumerableValues for EnumerableSet.Bytes32Set;
EnumerableSet.Bytes32Set internal roles;
mapping(bytes32 => EnumerableSet.AddressSet) internal roleMembers;
mapping(address => mapping (bytes32 => bool)) roleCache;
modifier onlyRoleAdmin() {
if (!hasRole(msg.sender, Role.ROLE_ADMIN)) {
revert Errors.Unauthorized(msg.sender, "ROLE_ADMIN");
}
_;
}
constructor() {
_grantRole(msg.sender, Role.ROLE_ADMIN);
}
function grantRole(address account, bytes32 roleKey) external onlyRoleAdmin {
_grantRole(account, roleKey);
}
function revokeRole(address account, bytes32 roleKey) external onlyRoleAdmin {
_revokeRole(account, roleKey);
}
function hasRole(address account, bytes32 roleKey) public view returns (bool) {
return roleCache[account][roleKey];
}
function getRoleCount() external view returns (uint256) {
return roles.length();
}
function getRoles(uint256 start, uint256 end) external view returns (bytes32[] memory) {
return roles.valuesAt(start, end);
}
function getRoleMemberCount(bytes32 roleKey) external view returns (uint256) {
return roleMembers[roleKey].length();
}
function getRoleMembers(bytes32 roleKey, uint256 start, uint256 end) external view returns (address[] memory) {
return roleMembers[roleKey].valuesAt(start, end);
}
function _grantRole(address account, bytes32 roleKey) internal {
roles.add(roleKey);
roleMembers[roleKey].add(account);
roleCache[account][roleKey] = true;
}
function _revokeRole(address account, bytes32 roleKey) internal {
roleMembers[roleKey].remove(account);
roleCache[account][roleKey] = false;
if (roleMembers[roleKey].length() == 0) {
if (roleKey == Role.ROLE_ADMIN) {
revert Errors.ThereMustBeAtLeastOneRoleAdmin();
}
if (roleKey == Role.TIMELOCK_MULTISIG) {
revert Errors.ThereMustBeAtLeastOneTimelockMultiSig();
}
}
}
}
文件 53 的 57:SafeCast.sol
pragma solidity ^0.8.0;
library SafeCast {
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
文件 54 的 57:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 55 的 57:SignedMath.sol
pragma solidity ^0.8.0;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 56 的 57:TokenUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../error/ErrorUtils.sol";
import "../utils/AccountUtils.sol";
import "./IWNT.sol";
library TokenUtils {
using Address for address;
using SafeERC20 for IERC20;
event TokenTransferReverted(string reason, bytes returndata);
event NativeTokenTransferReverted(string reason);
function wnt(DataStore dataStore) internal view returns (address) {
return dataStore.getAddress(Keys.WNT);
}
function transfer(
DataStore dataStore,
address token,
address receiver,
uint256 amount
) internal {
if (amount == 0) { return; }
AccountUtils.validateReceiver(receiver);
uint256 gasLimit = dataStore.getUint(Keys.tokenTransferGasLimit(token));
if (gasLimit == 0) {
revert Errors.EmptyTokenTranferGasLimit(token);
}
(bool success0, ) = nonRevertingTransferWithGasLimit(
IERC20(token),
receiver,
amount,
gasLimit
);
if (success0) { return; }
address holdingAddress = dataStore.getAddress(Keys.HOLDING_ADDRESS);
if (holdingAddress == address(0)) {
revert Errors.EmptyHoldingAddress();
}
(bool success1, bytes memory returndata) = nonRevertingTransferWithGasLimit(
IERC20(token),
holdingAddress,
amount,
gasLimit
);
if (success1) { return; }
(string memory reason, ) = ErrorUtils.getRevertMessage(returndata);
emit TokenTransferReverted(reason, returndata);
revert Errors.TokenTransferError(token, receiver, amount);
}
function sendNativeToken(
DataStore dataStore,
address receiver,
uint256 amount
) internal {
if (amount == 0) { return; }
AccountUtils.validateReceiver(receiver);
uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);
bool success;
assembly {
success := call(
gasLimit,
receiver,
amount,
0,
0,
0,
0
)
}
if (success) { return; }
depositAndSendWrappedNativeToken(
dataStore,
receiver,
amount
);
}
function depositAndSendWrappedNativeToken(
DataStore dataStore,
address receiver,
uint256 amount
) internal {
if (amount == 0) { return; }
AccountUtils.validateReceiver(receiver);
address _wnt = wnt(dataStore);
IWNT(_wnt).deposit{value: amount}();
transfer(
dataStore,
_wnt,
receiver,
amount
);
}
function withdrawAndSendNativeToken(
DataStore dataStore,
address _wnt,
address receiver,
uint256 amount
) internal {
if (amount == 0) { return; }
AccountUtils.validateReceiver(receiver);
IWNT(_wnt).withdraw(amount);
uint256 gasLimit = dataStore.getUint(Keys.NATIVE_TOKEN_TRANSFER_GAS_LIMIT);
bool success;
assembly {
success := call(
gasLimit,
receiver,
amount,
0,
0,
0,
0
)
}
if (success) { return; }
depositAndSendWrappedNativeToken(
dataStore,
receiver,
amount
);
}
function nonRevertingTransferWithGasLimit(
IERC20 token,
address to,
uint256 amount,
uint256 gasLimit
) internal returns (bool, bytes memory) {
bytes memory data = abi.encodeWithSelector(token.transfer.selector, to, amount);
(bool success, bytes memory returndata) = address(token).call{ gas: gasLimit }(data);
if (success) {
if (returndata.length == 0) {
if (!address(token).isContract()) {
return (false, "Call to non-contract");
}
}
if (returndata.length > 0 && !abi.decode(returndata, (bool))) {
return (false, returndata);
}
return (true, returndata);
}
return (false, returndata);
}
}
文件 57 的 57:Uint256Mask.sol
pragma solidity ^0.8.0;
import "../error/Errors.sol";
library Uint256Mask {
struct Mask {
uint256 bits;
}
function validateUniqueAndSetIndex(
Mask memory mask,
uint256 index,
string memory label
) internal pure {
if (index >= 256) {
revert Errors.MaskIndexOutOfBounds(index, label);
}
uint256 bit = 1 << index;
if (mask.bits & bit != 0) {
revert Errors.DuplicatedIndex(index, label);
}
mask.bits = mask.bits | bit;
}
}
{
"compilationTarget": {
"contracts/config/ConfigSyncer.sol": "ConfigSyncer"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": []
}
[{"inputs":[{"internalType":"contract RoleStore","name":"_roleStore","type":"address"},{"internalType":"contract Config","name":"_config","type":"address"},{"internalType":"contract DataStore","name":"_dataStore","type":"address"},{"internalType":"contract EventEmitter","name":"_eventEmitter","type":"address"},{"internalType":"address","name":"_riskOracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"DisabledFeature","type":"error"},{"inputs":[{"internalType":"bytes32","name":"baseKey","type":"bytes32"}],"name":"InvalidBaseKey","type":"error"},{"inputs":[{"internalType":"uint256","name":"marketsLength","type":"uint256"},{"internalType":"uint256","name":"parametersLength","type":"uint256"}],"name":"SyncConfigInvalidInputLengths","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"address","name":"marketFromData","type":"address"}],"name":"SyncConfigInvalidMarketFromData","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"SyncConfigUpdatesDisabledForMarket","type":"error"},{"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"string","name":"parameter","type":"string"}],"name":"SyncConfigUpdatesDisabledForMarketParameter","type":"error"},{"inputs":[{"internalType":"string","name":"parameter","type":"string"}],"name":"SyncConfigUpdatesDisabledForParameter","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"Uint256AsBytesLengthExceeds32Bytes","type":"error"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"string","name":"role","type":"string"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"allowedBaseKeys","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"config","outputs":[{"internalType":"contract Config","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataStore","outputs":[{"internalType":"contract DataStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"eventEmitter","outputs":[{"internalType":"contract EventEmitter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"riskOracle","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"roleStore","outputs":[{"internalType":"contract RoleStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"markets","type":"address[]"},{"internalType":"string[]","name":"parameters","type":"string[]"}],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"}]