编译器
0.8.18+commit.87f61d96
文件 1 的 92: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 的 92: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 functionCall(target, data, "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");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(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) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(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) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResult(success, returndata, errorMessage);
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 3 的 92:AdlUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../event/EventEmitter.sol";
import "../order/OrderStoreUtils.sol";
import "../order/OrderEventUtils.sol";
import "../position/PositionUtils.sol";
import "../position/PositionStoreUtils.sol";
import "../nonce/NonceUtils.sol";
import "../callback/CallbackUtils.sol";
library AdlUtils {
using SafeCast for int256;
using Array for uint256[];
using Market for Market.Props;
using Position for Position.Props;
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;
struct CreateAdlOrderParams {
DataStore dataStore;
EventEmitter eventEmitter;
address account;
address market;
address collateralToken;
bool isLong;
uint256 sizeDeltaUsd;
uint256 updatedAtBlock;
}
function updateAdlState(
DataStore dataStore,
EventEmitter eventEmitter,
Oracle oracle,
address market,
bool isLong,
uint256[] memory maxOracleBlockNumbers
) external {
uint256 latestAdlBlock = getLatestAdlBlock(dataStore, market, isLong);
if (!maxOracleBlockNumbers.areGreaterThanOrEqualTo(latestAdlBlock)) {
revert Errors.OracleBlockNumbersAreSmallerThanRequired(maxOracleBlockNumbers, latestAdlBlock);
}
Market.Props memory _market = MarketUtils.getEnabledMarket(dataStore, market);
MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(oracle, _market);
(bool shouldEnableAdl, int256 pnlToPoolFactor, uint256 maxPnlFactor) = MarketUtils.isPnlFactorExceeded(
dataStore,
_market,
prices,
isLong,
Keys.MAX_PNL_FACTOR_FOR_ADL
);
setIsAdlEnabled(dataStore, market, isLong, shouldEnableAdl);
setLatestAdlBlock(dataStore, market, isLong, Chain.currentBlockNumber());
emitAdlStateUpdated(eventEmitter, market, isLong, pnlToPoolFactor, maxPnlFactor, shouldEnableAdl);
}
function createAdlOrder(CreateAdlOrderParams memory params) external returns (bytes32) {
bytes32 positionKey = PositionUtils.getPositionKey(params.account, params.market, params.collateralToken, params.isLong);
Position.Props memory position = PositionStoreUtils.get(params.dataStore, positionKey);
if (params.sizeDeltaUsd > position.sizeInUsd()) {
revert Errors.InvalidSizeDeltaForAdl(params.sizeDeltaUsd, position.sizeInUsd());
}
Order.Addresses memory addresses = Order.Addresses(
params.account,
params.account,
CallbackUtils.getSavedCallbackContract(params.dataStore, params.account, params.market),
address(0),
params.market,
position.collateralToken(),
new address[](0)
);
Order.Numbers memory numbers = Order.Numbers(
Order.OrderType.MarketDecrease,
Order.DecreasePositionSwapType.SwapPnlTokenToCollateralToken,
params.sizeDeltaUsd,
0,
0,
position.isLong() ? 0 : type(uint256).max,
0,
params.dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT),
0,
params.updatedAtBlock
);
Order.Flags memory flags = Order.Flags(
position.isLong(),
true,
false
);
Order.Props memory order = Order.Props(
addresses,
numbers,
flags
);
bytes32 key = NonceUtils.getNextKey(params.dataStore);
OrderStoreUtils.set(params.dataStore, key, order);
OrderEventUtils.emitOrderCreated(params.eventEmitter, key, order);
return key;
}
function validateAdl(
DataStore dataStore,
address market,
bool isLong,
uint256[] memory maxOracleBlockNumbers
) external view {
bool isAdlEnabled = AdlUtils.getIsAdlEnabled(dataStore, market, isLong);
if (!isAdlEnabled) {
revert Errors.AdlNotEnabled();
}
uint256 latestAdlBlock = AdlUtils.getLatestAdlBlock(dataStore, market, isLong);
if (!maxOracleBlockNumbers.areGreaterThanOrEqualTo(latestAdlBlock)) {
revert Errors.OracleBlockNumbersAreSmallerThanRequired(maxOracleBlockNumbers, latestAdlBlock);
}
}
function getLatestAdlBlock(DataStore dataStore, address market, bool isLong) internal view returns (uint256) {
return dataStore.getUint(Keys.latestAdlBlockKey(market, isLong));
}
function setLatestAdlBlock(DataStore dataStore, address market, bool isLong, uint256 value) internal returns (uint256) {
return dataStore.setUint(Keys.latestAdlBlockKey(market, isLong), value);
}
function getIsAdlEnabled(DataStore dataStore, address market, bool isLong) internal view returns (bool) {
return dataStore.getBool(Keys.isAdlEnabledKey(market, isLong));
}
function setIsAdlEnabled(DataStore dataStore, address market, bool isLong, bool value) internal returns (bool) {
return dataStore.setBool(Keys.isAdlEnabledKey(market, isLong), value);
}
function emitAdlStateUpdated(
EventEmitter eventEmitter,
address market,
bool isLong,
int256 pnlToPoolFactor,
uint256 maxPnlFactor,
bool shouldEnableAdl
) internal {
EventUtils.EventLogData memory eventData;
eventData.intItems.initItems(1);
eventData.intItems.setItem(0, "pnlToPoolFactor", pnlToPoolFactor);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "maxPnlFactor", maxPnlFactor);
eventData.boolItems.initItems(2);
eventData.boolItems.setItem(0, "isLong", isLong);
eventData.boolItems.setItem(1, "shouldEnableAdl", shouldEnableAdl);
eventEmitter.emitEventLog1(
"AdlStateUpdated",
Cast.toBytes32(market),
eventData
);
}
}
文件 4 的 92:ArbSys.sol
pragma solidity ^0.8.0;
interface ArbSys {
function arbBlockNumber() external view returns (uint256);
function arbBlockHash(uint256 blockNumber) external view returns (bytes32);
}
文件 5 的 92: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;
}
}
文件 6 的 92: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 {}
}
文件 7 的 92:BaseOrderUtils.sol
pragma solidity ^0.8.0;
import "./Order.sol";
import "../market/Market.sol";
import "../data/DataStore.sol";
import "../event/EventEmitter.sol";
import "../referral/IReferralStorage.sol";
import "../order/OrderVault.sol";
import "../oracle/Oracle.sol";
import "../swap/SwapHandler.sol";
library BaseOrderUtils {
using SafeCast for int256;
using SafeCast for uint256;
using Order for Order.Props;
using Price for Price.Props;
struct CreateOrderParams {
CreateOrderParamsAddresses addresses;
CreateOrderParamsNumbers numbers;
Order.OrderType orderType;
Order.DecreasePositionSwapType decreasePositionSwapType;
bool isLong;
bool shouldUnwrapNativeToken;
bytes32 referralCode;
}
struct CreateOrderParamsAddresses {
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialCollateralToken;
address[] swapPath;
}
struct CreateOrderParamsNumbers {
uint256 sizeDeltaUsd;
uint256 initialCollateralDeltaAmount;
uint256 triggerPrice;
uint256 acceptablePrice;
uint256 executionFee;
uint256 callbackGasLimit;
uint256 minOutputAmount;
}
struct ExecuteOrderParams {
ExecuteOrderParamsContracts contracts;
bytes32 key;
Order.Props order;
Market.Props[] swapPathMarkets;
uint256[] minOracleBlockNumbers;
uint256[] maxOracleBlockNumbers;
Market.Props market;
address keeper;
uint256 startingGas;
Order.SecondaryOrderType secondaryOrderType;
}
struct ExecuteOrderParamsContracts {
DataStore dataStore;
EventEmitter eventEmitter;
OrderVault orderVault;
Oracle oracle;
SwapHandler swapHandler;
IReferralStorage referralStorage;
}
struct GetExecutionPriceCache {
uint256 price;
uint256 executionPrice;
int256 adjustedPriceImpactUsd;
}
function isMarketOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.MarketSwap ||
orderType == Order.OrderType.MarketIncrease ||
orderType == Order.OrderType.MarketDecrease;
}
function isLimitOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.LimitSwap ||
orderType == Order.OrderType.LimitIncrease ||
orderType == Order.OrderType.LimitDecrease;
}
function isSwapOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.MarketSwap ||
orderType == Order.OrderType.LimitSwap;
}
function isPositionOrder(Order.OrderType orderType) internal pure returns (bool) {
return isIncreaseOrder(orderType) || isDecreaseOrder(orderType);
}
function isIncreaseOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.MarketIncrease ||
orderType == Order.OrderType.LimitIncrease;
}
function isDecreaseOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.MarketDecrease ||
orderType == Order.OrderType.LimitDecrease ||
orderType == Order.OrderType.StopLossDecrease ||
orderType == Order.OrderType.Liquidation;
}
function isLiquidationOrder(Order.OrderType orderType) internal pure returns (bool) {
return orderType == Order.OrderType.Liquidation;
}
function validateOrderTriggerPrice(
Oracle oracle,
address indexToken,
Order.OrderType orderType,
uint256 triggerPrice,
bool isLong
) internal view {
if (
isSwapOrder(orderType) ||
isMarketOrder(orderType) ||
isLiquidationOrder(orderType)
) {
return;
}
Price.Props memory primaryPrice = oracle.getPrimaryPrice(indexToken);
if (orderType == Order.OrderType.LimitIncrease) {
bool ok = isLong ? primaryPrice.max <= triggerPrice : primaryPrice.min >= triggerPrice;
if (!ok) {
revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
}
return;
}
if (orderType == Order.OrderType.LimitDecrease) {
bool ok = isLong ? primaryPrice.min >= triggerPrice : primaryPrice.max <= triggerPrice;
if (!ok) {
revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
}
return;
}
if (orderType == Order.OrderType.StopLossDecrease) {
bool ok = isLong ? primaryPrice.min <= triggerPrice : primaryPrice.max >= triggerPrice;
if (!ok) {
revert Errors.InvalidOrderPrices(primaryPrice.min, primaryPrice.max, triggerPrice, uint256(orderType));
}
return;
}
revert Errors.UnsupportedOrderType();
}
function getExecutionPriceForIncrease(
uint256 sizeDeltaUsd,
uint256 sizeDeltaInTokens,
uint256 acceptablePrice,
bool isLong
) internal pure returns (uint256) {
if (sizeDeltaInTokens == 0) {
revert Errors.EmptySizeDeltaInTokens();
}
uint256 executionPrice = sizeDeltaUsd / sizeDeltaInTokens;
if (
(isLong && executionPrice <= acceptablePrice) ||
(!isLong && executionPrice >= acceptablePrice)
) {
return executionPrice;
}
revert Errors.OrderNotFulfillableAtAcceptablePrice(executionPrice, acceptablePrice);
}
function getExecutionPriceForDecrease(
Price.Props memory indexTokenPrice,
uint256 positionSizeInUsd,
uint256 positionSizeInTokens,
uint256 sizeDeltaUsd,
int256 priceImpactUsd,
uint256 acceptablePrice,
bool isLong
) internal pure returns (uint256) {
GetExecutionPriceCache memory cache;
cache.price = indexTokenPrice.pickPrice(!isLong);
cache.executionPrice = cache.price;
if (sizeDeltaUsd > 0 && positionSizeInTokens > 0) {
cache.adjustedPriceImpactUsd = isLong ? priceImpactUsd : -priceImpactUsd;
if (cache.adjustedPriceImpactUsd < 0 && (-cache.adjustedPriceImpactUsd).toUint256() > sizeDeltaUsd) {
revert Errors.PriceImpactLargerThanOrderSize(cache.adjustedPriceImpactUsd, sizeDeltaUsd);
}
int256 adjustment = Precision.mulDiv(positionSizeInUsd, cache.adjustedPriceImpactUsd, positionSizeInTokens) / sizeDeltaUsd.toInt256();
int256 _executionPrice = cache.price.toInt256() + adjustment;
if (_executionPrice < 0) {
revert Errors.NegativeExecutionPrice(_executionPrice, cache.price, positionSizeInUsd, cache.adjustedPriceImpactUsd, sizeDeltaUsd);
}
cache.executionPrice = _executionPrice.toUint256();
}
if (
(isLong && cache.executionPrice >= acceptablePrice) ||
(!isLong && cache.executionPrice <= acceptablePrice)
) {
return cache.executionPrice;
}
revert Errors.OrderNotFulfillableAtAcceptablePrice(cache.executionPrice, acceptablePrice);
}
function validateNonEmptyOrder(Order.Props memory order) internal pure {
if (order.account() == address(0)) {
revert Errors.EmptyOrder();
}
if (order.sizeDeltaUsd() == 0 && order.initialCollateralDeltaAmount() == 0) {
revert Errors.EmptyOrder();
}
}
}
文件 8 的 92:Bits.sol
pragma solidity ^0.8.0;
library Bits {
uint256 constant public BITMASK_8 = ~uint256(0) >> (256 - 8);
uint256 constant public BITMASK_16 = ~uint256(0) >> (256 - 16);
uint256 constant public BITMASK_32 = ~uint256(0) >> (256 - 32);
uint256 constant public BITMASK_64 = ~uint256(0) >> (256 - 64);
}
文件 9 的 92: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();
}
}
}
文件 10 的 92:CallbackUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/Address.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../error/ErrorUtils.sol";
import "./IOrderCallbackReceiver.sol";
import "./IDepositCallbackReceiver.sol";
import "./IWithdrawalCallbackReceiver.sol";
library CallbackUtils {
using Address for address;
using Deposit for Deposit.Props;
using Withdrawal for Withdrawal.Props;
using Order for Order.Props;
event AfterDepositExecutionError(bytes32 key, Deposit.Props deposit);
event AfterDepositCancellationError(bytes32 key, Deposit.Props deposit);
event AfterWithdrawalExecutionError(bytes32 key, Withdrawal.Props withdrawal);
event AfterWithdrawalCancellationError(bytes32 key, Withdrawal.Props withdrawal);
event AfterOrderExecutionError(bytes32 key, Order.Props order);
event AfterOrderCancellationError(bytes32 key, Order.Props order);
event AfterOrderFrozenError(bytes32 key, Order.Props order);
function validateCallbackGasLimit(DataStore dataStore, uint256 callbackGasLimit) internal view {
uint256 maxCallbackGasLimit = dataStore.getUint(Keys.MAX_CALLBACK_GAS_LIMIT);
if (callbackGasLimit > maxCallbackGasLimit) {
revert Errors.MaxCallbackGasLimitExceeded(callbackGasLimit, maxCallbackGasLimit);
}
}
function setSavedCallbackContract(DataStore dataStore, address account, address market, address callbackContract) external {
dataStore.setAddress(Keys.savedCallbackContract(account, market), callbackContract);
}
function getSavedCallbackContract(DataStore dataStore, address account, address market) internal view returns (address) {
return dataStore.getAddress(Keys.savedCallbackContract(account, market));
}
function afterDepositExecution(
bytes32 key,
Deposit.Props memory deposit,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(deposit.callbackContract())) { return; }
try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositExecution{ gas: deposit.callbackGasLimit() }(
key,
deposit,
eventData
) {
} catch {
emit AfterDepositExecutionError(key, deposit);
}
}
function afterDepositCancellation(
bytes32 key,
Deposit.Props memory deposit,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(deposit.callbackContract())) { return; }
try IDepositCallbackReceiver(deposit.callbackContract()).afterDepositCancellation{ gas: deposit.callbackGasLimit() }(
key,
deposit,
eventData
) {
} catch {
emit AfterDepositCancellationError(key, deposit);
}
}
function afterWithdrawalExecution(
bytes32 key,
Withdrawal.Props memory withdrawal,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }
try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalExecution{ gas: withdrawal.callbackGasLimit() }(
key,
withdrawal,
eventData
) {
} catch {
emit AfterWithdrawalExecutionError(key, withdrawal);
}
}
function afterWithdrawalCancellation(
bytes32 key,
Withdrawal.Props memory withdrawal,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(withdrawal.callbackContract())) { return; }
try IWithdrawalCallbackReceiver(withdrawal.callbackContract()).afterWithdrawalCancellation{ gas: withdrawal.callbackGasLimit() }(
key,
withdrawal,
eventData
) {
} catch {
emit AfterWithdrawalCancellationError(key, withdrawal);
}
}
function afterOrderExecution(
bytes32 key,
Order.Props memory order,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(order.callbackContract())) { return; }
try IOrderCallbackReceiver(order.callbackContract()).afterOrderExecution{ gas: order.callbackGasLimit() }(
key,
order,
eventData
) {
} catch {
emit AfterOrderExecutionError(key, order);
}
}
function afterOrderCancellation(
bytes32 key,
Order.Props memory order,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(order.callbackContract())) { return; }
try IOrderCallbackReceiver(order.callbackContract()).afterOrderCancellation{ gas: order.callbackGasLimit() }(
key,
order,
eventData
) {
} catch {
emit AfterOrderCancellationError(key, order);
}
}
function afterOrderFrozen(
bytes32 key,
Order.Props memory order,
EventUtils.EventLogData memory eventData
) internal {
if (!isValidCallbackContract(order.callbackContract())) { return; }
try IOrderCallbackReceiver(order.callbackContract()).afterOrderFrozen{ gas: order.callbackGasLimit() }(
key,
order,
eventData
) {
} catch {
emit AfterOrderFrozenError(key, order);
}
}
function isValidCallbackContract(address callbackContract) internal view returns (bool) {
if (callbackContract == address(0)) { return false; }
if (!callbackContract.isContract()) { return false; }
return true;
}
}
文件 11 的 92:Cast.sol
pragma solidity ^0.8.0;
library Cast {
function toBytes32(address value) internal pure returns (bytes32) {
return bytes32(uint256(uint160(value)));
}
}
文件 12 的 92:Chain.sol
pragma solidity ^0.8.0;
import "./ArbSys.sol";
library Chain {
uint256 constant public ARBITRUM_CHAIN_ID = 42161;
uint256 constant public ARBITRUM_GOERLI_CHAIN_ID = 421613;
ArbSys constant public 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_GOERLI_CHAIN_ID;
}
}
文件 13 的 92: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;
}
}
文件 14 的 92:DataStore.sol
pragma solidity ^0.8.0;
import "../role/RoleModule.sol";
import "../utils/Calc.sol";
import "../utils/Printer.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);
}
}
文件 15 的 92:Deposit.sol
pragma solidity ^0.8.0;
library Deposit {
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address initialLongToken;
address initialShortToken;
address[] longTokenSwapPath;
address[] shortTokenSwapPath;
}
struct Numbers {
uint256 initialLongTokenAmount;
uint256 initialShortTokenAmount;
uint256 minMarketTokens;
uint256 updatedAtBlock;
uint256 executionFee;
uint256 callbackGasLimit;
}
struct Flags {
bool shouldUnwrapNativeToken;
}
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 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 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 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 initialLongToken(Props memory props) internal pure returns (address) {
return props.addresses.initialLongToken;
}
function setInitialLongToken(Props memory props, address value) internal pure {
props.addresses.initialLongToken = value;
}
function initialShortToken(Props memory props) internal pure returns (address) {
return props.addresses.initialShortToken;
}
function setInitialShortToken(Props memory props, address value) internal pure {
props.addresses.initialShortToken = value;
}
function longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
return props.addresses.longTokenSwapPath;
}
function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {
props.addresses.longTokenSwapPath = value;
}
function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
return props.addresses.shortTokenSwapPath;
}
function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {
props.addresses.shortTokenSwapPath = value;
}
function initialLongTokenAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.initialLongTokenAmount;
}
function setInitialLongTokenAmount(Props memory props, uint256 value) internal pure {
props.numbers.initialLongTokenAmount = value;
}
function initialShortTokenAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.initialShortTokenAmount;
}
function setInitialShortTokenAmount(Props memory props, uint256 value) internal pure {
props.numbers.initialShortTokenAmount = value;
}
function minMarketTokens(Props memory props) internal pure returns (uint256) {
return props.numbers.minMarketTokens;
}
function setMinMarketTokens(Props memory props, uint256 value) internal pure {
props.numbers.minMarketTokens = value;
}
function updatedAtBlock(Props memory props) internal pure returns (uint256) {
return props.numbers.updatedAtBlock;
}
function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
props.numbers.updatedAtBlock = value;
}
function executionFee(Props memory props) internal pure returns (uint256) {
return props.numbers.executionFee;
}
function setExecutionFee(Props memory props, uint256 value) internal pure {
props.numbers.executionFee = value;
}
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 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;
}
}
文件 16 的 92:ECDSA.sol
pragma solidity ^0.8.0;
import "../Strings.sol";
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS,
InvalidSignatureV
}
function _throwError(RecoverError error) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert("ECDSA: invalid signature");
} else if (error == RecoverError.InvalidSignatureLength) {
revert("ECDSA: invalid signature length");
} else if (error == RecoverError.InvalidSignatureS) {
revert("ECDSA: invalid signature 's' value");
} else if (error == RecoverError.InvalidSignatureV) {
revert("ECDSA: invalid signature 'v' value");
}
}
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength);
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, signature);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address, RecoverError) {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
function recover(
bytes32 hash,
bytes32 r,
bytes32 vs
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, r, vs);
_throwError(error);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS);
}
if (v != 27 && v != 28) {
return (address(0), RecoverError.InvalidSignatureV);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature);
}
return (signer, RecoverError.NoError);
}
function recover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address) {
(address recovered, RecoverError error) = tryRecover(hash, v, r, s);
_throwError(error);
return recovered;
}
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
}
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s));
}
function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
}
}
文件 17 的 92: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;
_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 {}
}
文件 18 的 92: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) {
return _values(set._inner);
}
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;
}
}
文件 19 的 92: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;
}
}
文件 20 的 92: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)
}
}
}
文件 21 的 92: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 SelfTransferNotSupported(address receiver);
error InvalidNativeTokenSender(address msgSender);
error CouldNotSendNativeToken(address receiver, uint256 amount);
error MaxCallbackGasLimitExceeded(uint256 callbackGasLimit, uint256 maxCallbackGasLimit);
error InvalidBaseKey(bytes32 baseKey);
error InvalidFeeFactor(bytes32 baseKey, uint256 value);
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 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 RequestNotYetCancellable(uint256 requestAge, uint256 requestExpirationAge, string requestType);
error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);
error InvalidLongTokenForMigration(address market, address migrationLongToken, address marketLongToken);
error InvalidShortTokenForMigration(address market, address migrationShortToken, address marketShortToken);
error OrderNotUpdatable(uint256 orderType);
error InvalidKeeperForFrozenOrder(address keeper);
error DisabledFeature(bytes32 key);
error InvalidClaimFeesInput(uint256 marketsLength, uint256 tokensLength);
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 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 MaxPoolAmountForDepositExceeded(uint256 poolAmount, uint256 maxPoolAmountForDeposit);
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 EmptySigner(uint256 signerIndex);
error InvalidBlockNumber(uint256 minOracleBlockNumber, uint256 currentBlockNumber);
error InvalidMinMaxBlockNumber(uint256 minOracleBlockNumber, uint256 maxOracleBlockNumber);
error HasRealtimeFeedId(address token, bytes32 feedId);
error InvalidRealtimeFeedLengths(uint256 tokensLength, uint256 dataLength);
error EmptyRealtimeFeedId(address token);
error InvalidRealtimeFeedId(address token, bytes32 feedId, bytes32 expectedFeedId);
error InvalidRealtimeBidAsk(address token, int192 bid, int192 ask);
error InvalidRealtimeBlockHash(address token, bytes32 blockHash, bytes32 expectedBlockHash);
error InvalidRealtimePrices(address token, int192 bid, int192 ask);
error RealtimeMaxPriceAgeExceeded(address token, uint256 oracleTimestamp, uint256 currentTimestamp);
error MaxPriceAgeExceeded(uint256 oracleTimestamp, uint256 currentTimestamp);
error MinOracleSigners(uint256 oracleSigners, uint256 minOracleSigners);
error MaxOracleSigners(uint256 oracleSigners, uint256 maxOracleSigners);
error BlockNumbersNotSorted(uint256 minOracleBlockNumber, uint256 prevMinOracleBlockNumber);
error MinPricesNotSorted(address token, uint256 price, uint256 prevPrice);
error MaxPricesNotSorted(address token, uint256 price, uint256 prevPrice);
error EmptyPriceFeedMultiplier(address token);
error EmptyRealtimeFeedMultiplier(address token);
error InvalidFeedPrice(address token, int256 price);
error PriceFeedNotUpdated(address token, uint256 timestamp, uint256 heartbeatDuration);
error MaxSignerIndex(uint256 signerIndex, uint256 maxSignerIndex);
error InvalidOraclePrice(address token);
error InvalidSignerMinMaxPrice(uint256 minPrice, uint256 maxPrice);
error InvalidMedianMinMaxPrice(uint256 minPrice, uint256 maxPrice);
error NonEmptyTokensWithPrices(uint256 tokensWithPricesLength);
error InvalidMinMaxForPrice(address token, uint256 min, uint256 max);
error EmptyPriceFeed(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 InvalidPrimaryPricesForSimulation(uint256 primaryTokensLength, uint256 primaryPricesLength);
error EndOfOracleSimulation();
error EmptyCompactedPrice(uint256 index);
error EmptyCompactedBlockNumber(uint256 index);
error EmptyCompactedTimestamp(uint256 index);
error UnsupportedOracleBlockNumberType(uint256 oracleBlockNumberType);
error InvalidSignature(address recoveredSigner, address expectedSigner);
error EmptyPrimaryPrice(address token);
error OracleBlockNumbersAreSmallerThanRequired(uint256[] oracleBlockNumbers, uint256 expectedBlockNumber);
error OracleBlockNumberNotWithinRange(
uint256[] minOracleBlockNumbers,
uint256[] maxOracleBlockNumbers,
uint256 blockNumber
);
error EmptyOrder();
error UnsupportedOrderType();
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 UnexpectedPositionState();
error OrderTypeCannotBeCreated(uint256 orderType);
error OrderAlreadyFrozen();
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 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 EmptyTokenTranferGasLimit(address token);
error TokenTransferError(address token, address receiver, uint256 amount);
error EmptyHoldingAddress();
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 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);
}
文件 22 的 92: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)
}
}
}
文件 23 的 92: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;
}
}
文件 24 的 92:ExchangeUtils.sol
pragma solidity ^0.8.0;
import "../bank/StrictBank.sol";
import "../chain/Chain.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
library ExchangeUtils {
function validateRequestCancellation(
DataStore dataStore,
uint256 createdAtBlock,
string memory requestType
) internal view {
uint256 requestExpirationAge = dataStore.getUint(Keys.REQUEST_EXPIRATION_BLOCK_AGE);
uint256 requestAge = Chain.currentBlockNumber() - createdAtBlock;
if (requestAge < requestExpirationAge) {
revert Errors.RequestNotYetCancellable(requestAge, requestExpirationAge, requestType);
}
}
}
文件 25 的 92:ExecuteWithdrawalUtils.sol
pragma solidity ^0.8.0;
import "../adl/AdlUtils.sol";
import "../data/DataStore.sol";
import "./WithdrawalVault.sol";
import "./WithdrawalStoreUtils.sol";
import "./WithdrawalEventUtils.sol";
import "../nonce/NonceUtils.sol";
import "../pricing/SwapPricingUtils.sol";
import "../oracle/Oracle.sol";
import "../oracle/OracleUtils.sol";
import "../gas/GasUtils.sol";
import "../callback/CallbackUtils.sol";
import "../utils/Array.sol";
import "../utils/AccountUtils.sol";
library ExecuteWithdrawalUtils {
using SafeCast for uint256;
using SafeCast for int256;
using Array for uint256[];
using Price for Price.Props;
using Withdrawal for Withdrawal.Props;
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;
struct ExecuteWithdrawalParams {
DataStore dataStore;
EventEmitter eventEmitter;
WithdrawalVault withdrawalVault;
Oracle oracle;
bytes32 key;
uint256[] minOracleBlockNumbers;
uint256[] maxOracleBlockNumbers;
address keeper;
uint256 startingGas;
}
struct ExecuteWithdrawalCache {
uint256 longTokenOutputAmount;
uint256 shortTokenOutputAmount;
SwapPricingUtils.SwapFees longTokenFees;
SwapPricingUtils.SwapFees shortTokenFees;
uint256 longTokenPoolAmountDelta;
uint256 shortTokenPoolAmountDelta;
}
struct ExecuteWithdrawalResult {
address outputToken;
uint256 outputAmount;
address secondaryOutputToken;
uint256 secondaryOutputAmount;
}
struct SwapCache {
Market.Props[] swapPathMarkets;
SwapUtils.SwapParams swapParams;
address outputToken;
uint256 outputAmount;
}
function executeWithdrawal(ExecuteWithdrawalParams memory params, Withdrawal.Props memory withdrawal) external {
params.startingGas -= gasleft() / 63;
WithdrawalStoreUtils.remove(params.dataStore, params.key, withdrawal.account());
if (withdrawal.account() == address(0)) {
revert Errors.EmptyWithdrawal();
}
if (withdrawal.marketTokenAmount() == 0) {
revert Errors.EmptyWithdrawalAmount();
}
OracleUtils.validateBlockNumberWithinRange(
params.minOracleBlockNumbers,
params.maxOracleBlockNumbers,
withdrawal.updatedAtBlock()
);
MarketUtils.distributePositionImpactPool(
params.dataStore,
params.eventEmitter,
withdrawal.market()
);
uint256 marketTokensBalance = MarketToken(payable(withdrawal.market())).balanceOf(address(params.withdrawalVault));
if (marketTokensBalance < withdrawal.marketTokenAmount()) {
revert Errors.InsufficientMarketTokens(marketTokensBalance, withdrawal.marketTokenAmount());
}
ExecuteWithdrawalResult memory result = _executeWithdrawal(params, withdrawal);
WithdrawalEventUtils.emitWithdrawalExecuted(
params.eventEmitter,
params.key,
withdrawal.account()
);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "outputToken", result.outputToken);
eventData.addressItems.setItem(1, "secondaryOutputToken", result.secondaryOutputToken);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "outputAmount", result.outputAmount);
eventData.uintItems.setItem(1, "secondaryOutputAmount", result.secondaryOutputAmount);
CallbackUtils.afterWithdrawalExecution(params.key, withdrawal, eventData);
GasUtils.payExecutionFee(
params.dataStore,
params.eventEmitter,
params.withdrawalVault,
withdrawal.executionFee(),
params.startingGas,
params.keeper,
withdrawal.account()
);
}
function _executeWithdrawal(
ExecuteWithdrawalParams memory params,
Withdrawal.Props memory withdrawal
) internal returns (ExecuteWithdrawalResult memory) {
Market.Props memory market = MarketUtils.getEnabledMarket(params.dataStore, withdrawal.market());
MarketUtils.MarketPrices memory prices = MarketUtils.getMarketPrices(
params.oracle,
market
);
ExecuteWithdrawalCache memory cache;
(cache.longTokenOutputAmount, cache.shortTokenOutputAmount) = _getOutputAmounts(params, market, prices, withdrawal.marketTokenAmount());
cache.longTokenFees = SwapPricingUtils.getSwapFees(
params.dataStore,
market.marketToken,
cache.longTokenOutputAmount,
false,
withdrawal.uiFeeReceiver()
);
FeeUtils.incrementClaimableFeeAmount(
params.dataStore,
params.eventEmitter,
market.marketToken,
market.longToken,
cache.longTokenFees.feeReceiverAmount,
Keys.WITHDRAWAL_FEE_TYPE
);
FeeUtils.incrementClaimableUiFeeAmount(
params.dataStore,
params.eventEmitter,
withdrawal.uiFeeReceiver(),
market.marketToken,
market.longToken,
cache.longTokenFees.uiFeeAmount,
Keys.UI_WITHDRAWAL_FEE_TYPE
);
cache.shortTokenFees = SwapPricingUtils.getSwapFees(
params.dataStore,
market.marketToken,
cache.shortTokenOutputAmount,
false,
withdrawal.uiFeeReceiver()
);
FeeUtils.incrementClaimableFeeAmount(
params.dataStore,
params.eventEmitter,
market.marketToken,
market.shortToken,
cache.shortTokenFees.feeReceiverAmount,
Keys.WITHDRAWAL_FEE_TYPE
);
FeeUtils.incrementClaimableUiFeeAmount(
params.dataStore,
params.eventEmitter,
withdrawal.uiFeeReceiver(),
market.marketToken,
market.shortToken,
cache.shortTokenFees.uiFeeAmount,
Keys.UI_WITHDRAWAL_FEE_TYPE
);
cache.longTokenPoolAmountDelta = cache.longTokenOutputAmount - cache.longTokenFees.feeAmountForPool;
cache.longTokenOutputAmount = cache.longTokenFees.amountAfterFees;
cache.shortTokenPoolAmountDelta = cache.shortTokenOutputAmount - cache.shortTokenFees.feeAmountForPool;
cache.shortTokenOutputAmount = cache.shortTokenFees.amountAfterFees;
MarketUtils.applyDeltaToPoolAmount(
params.dataStore,
params.eventEmitter,
market,
market.longToken,
-cache.longTokenPoolAmountDelta.toInt256()
);
MarketUtils.applyDeltaToPoolAmount(
params.dataStore,
params.eventEmitter,
market,
market.shortToken,
-cache.shortTokenPoolAmountDelta.toInt256()
);
MarketUtils.validateReserve(
params.dataStore,
market,
prices,
true
);
MarketUtils.validateReserve(
params.dataStore,
market,
prices,
false
);
MarketUtils.validateMaxPnl(
params.dataStore,
market,
prices,
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS
);
MarketToken(payable(market.marketToken)).burn(
address(params.withdrawalVault),
withdrawal.marketTokenAmount()
);
params.withdrawalVault.syncTokenBalance(market.marketToken);
ExecuteWithdrawalResult memory result;
(result.outputToken, result.outputAmount) = _swap(
params,
market,
market.longToken,
cache.longTokenOutputAmount,
withdrawal.longTokenSwapPath(),
withdrawal.minLongTokenAmount(),
withdrawal.receiver(),
withdrawal.uiFeeReceiver(),
withdrawal.shouldUnwrapNativeToken()
);
(result.secondaryOutputToken, result.secondaryOutputAmount) = _swap(
params,
market,
market.shortToken,
cache.shortTokenOutputAmount,
withdrawal.shortTokenSwapPath(),
withdrawal.minShortTokenAmount(),
withdrawal.receiver(),
withdrawal.uiFeeReceiver(),
withdrawal.shouldUnwrapNativeToken()
);
SwapPricingUtils.emitSwapFeesCollected(
params.eventEmitter,
params.key,
market.marketToken,
market.longToken,
prices.longTokenPrice.min,
Keys.WITHDRAWAL_FEE_TYPE,
cache.longTokenFees
);
SwapPricingUtils.emitSwapFeesCollected(
params.eventEmitter,
params.key,
market.marketToken,
market.shortToken,
prices.shortTokenPrice.min,
Keys.WITHDRAWAL_FEE_TYPE,
cache.shortTokenFees
);
MarketUtils.validateMarketTokenBalance(params.dataStore, market);
MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
params.dataStore,
market,
prices.indexTokenPrice,
prices.longTokenPrice,
prices.shortTokenPrice,
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
false
);
uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
MarketEventUtils.emitMarketPoolValueUpdated(
params.eventEmitter,
keccak256(abi.encode("WITHDRAWAL")),
params.key,
market.marketToken,
poolValueInfo,
marketTokensSupply
);
return result;
}
function _swap(
ExecuteWithdrawalParams memory params,
Market.Props memory market,
address tokenIn,
uint256 amountIn,
address[] memory swapPath,
uint256 minOutputAmount,
address receiver,
address uiFeeReceiver,
bool shouldUnwrapNativeToken
) internal returns (address, uint256) {
SwapCache memory cache;
cache.swapPathMarkets = MarketUtils.getSwapPathMarkets(params.dataStore, swapPath);
cache.swapParams.dataStore = params.dataStore;
cache.swapParams.eventEmitter = params.eventEmitter;
cache.swapParams.oracle = params.oracle;
cache.swapParams.bank = Bank(payable(market.marketToken));
cache.swapParams.key = params.key;
cache.swapParams.tokenIn = tokenIn;
cache.swapParams.amountIn = amountIn;
cache.swapParams.swapPathMarkets = cache.swapPathMarkets;
cache.swapParams.minOutputAmount = minOutputAmount;
cache.swapParams.receiver = receiver;
cache.swapParams.uiFeeReceiver = uiFeeReceiver;
cache.swapParams.shouldUnwrapNativeToken = shouldUnwrapNativeToken;
(cache.outputToken, cache.outputAmount) = SwapUtils.swap(cache.swapParams);
MarketUtils.validateMarketTokenBalance(params.dataStore, cache.swapPathMarkets);
return (cache.outputToken, cache.outputAmount);
}
function _getOutputAmounts(
ExecuteWithdrawalParams memory params,
Market.Props memory market,
MarketUtils.MarketPrices memory prices,
uint256 marketTokenAmount
) internal returns (uint256, uint256) {
MarketPoolValueInfo.Props memory poolValueInfo = MarketUtils.getPoolValueInfo(
params.dataStore,
market,
params.oracle.getPrimaryPrice(market.indexToken),
prices.longTokenPrice,
prices.shortTokenPrice,
Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
false
);
if (poolValueInfo.poolValue <= 0) {
revert Errors.InvalidPoolValueForWithdrawal(poolValueInfo.poolValue);
}
uint256 poolValue = poolValueInfo.poolValue.toUint256();
uint256 marketTokensSupply = MarketUtils.getMarketTokenSupply(MarketToken(payable(market.marketToken)));
MarketEventUtils.emitMarketPoolValueInfo(
params.eventEmitter,
params.key,
market.marketToken,
poolValueInfo,
marketTokensSupply
);
uint256 longTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.longToken);
uint256 shortTokenPoolAmount = MarketUtils.getPoolAmount(params.dataStore, market, market.shortToken);
uint256 longTokenPoolUsd = longTokenPoolAmount * prices.longTokenPrice.max;
uint256 shortTokenPoolUsd = shortTokenPoolAmount * prices.shortTokenPrice.max;
uint256 totalPoolUsd = longTokenPoolUsd + shortTokenPoolUsd;
uint256 marketTokensUsd = MarketUtils.marketTokenAmountToUsd(marketTokenAmount, poolValue, marketTokensSupply);
uint256 longTokenOutputUsd = Precision.mulDiv(marketTokensUsd, longTokenPoolUsd, totalPoolUsd);
uint256 shortTokenOutputUsd = Precision.mulDiv(marketTokensUsd, shortTokenPoolUsd, totalPoolUsd);
return (
longTokenOutputUsd / prices.longTokenPrice.max,
shortTokenOutputUsd / prices.shortTokenPrice.max
);
}
}
文件 26 的 92:FeatureUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../data/Keys.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);
}
}
}
文件 27 的 92:FeeUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Cast.sol";
import "../utils/AccountUtils.sol";
import "../market/MarketUtils.sol";
import "../market/MarketToken.sol";
library FeeUtils {
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 incrementClaimableFeeAmount(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
uint256 delta,
bytes32 feeType
) external {
if (delta == 0) {
return;
}
bytes32 key = Keys.claimableFeeAmountKey(market, token);
uint256 nextValue = dataStore.incrementUint(
key,
delta
);
emitClaimableFeeAmountUpdated(
eventEmitter,
market,
token,
delta,
nextValue,
feeType
);
}
function incrementClaimableUiFeeAmount(
DataStore dataStore,
EventEmitter eventEmitter,
address uiFeeReceiver,
address market,
address token,
uint256 delta,
bytes32 feeType
) external {
if (delta == 0) {
return;
}
uint256 nextValue = dataStore.incrementUint(
Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver),
delta
);
uint256 nextPoolValue = dataStore.incrementUint(
Keys.claimableUiFeeAmountKey(market, token),
delta
);
emitClaimableUiFeeAmountUpdated(
eventEmitter,
uiFeeReceiver,
market,
token,
delta,
nextValue,
nextPoolValue,
feeType
);
}
function claimFees(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address receiver
) internal {
AccountUtils.validateReceiver(receiver);
bytes32 key = Keys.claimableFeeAmountKey(market, token);
uint256 feeAmount = dataStore.getUint(key);
dataStore.setUint(key, 0);
MarketToken(payable(market)).transferOut(
token,
receiver,
feeAmount
);
MarketUtils.validateMarketTokenBalance(dataStore, market);
emitFeesClaimed(
eventEmitter,
market,
receiver,
feeAmount
);
}
function claimUiFees(
DataStore dataStore,
EventEmitter eventEmitter,
address uiFeeReceiver,
address market,
address token,
address receiver
) external returns (uint256) {
AccountUtils.validateReceiver(receiver);
bytes32 key = Keys.claimableUiFeeAmountKey(market, token, uiFeeReceiver);
uint256 feeAmount = dataStore.getUint(key);
dataStore.setUint(key, 0);
uint256 nextPoolValue = dataStore.decrementUint(
Keys.claimableUiFeeAmountKey(market, token),
feeAmount
);
MarketToken(payable(market)).transferOut(
token,
receiver,
feeAmount
);
MarketUtils.validateMarketTokenBalance(dataStore, market);
emitUiFeesClaimed(
eventEmitter,
uiFeeReceiver,
market,
receiver,
feeAmount,
nextPoolValue
);
return feeAmount;
}
function emitClaimableFeeAmountUpdated(
EventEmitter eventEmitter,
address market,
address token,
uint256 delta,
uint256 nextValue,
bytes32 feeType
) internal {
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, "delta", delta);
eventData.uintItems.setItem(1, "nextValue", nextValue);
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "feeType", feeType);
eventEmitter.emitEventLog2(
"ClaimableFeeAmountUpdated",
Cast.toBytes32(market),
feeType,
eventData
);
}
function emitClaimableUiFeeAmountUpdated(
EventEmitter eventEmitter,
address uiFeeReceiver,
address market,
address token,
uint256 delta,
uint256 nextValue,
uint256 nextPoolValue,
bytes32 feeType
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver);
eventData.addressItems.setItem(1, "market", market);
eventData.addressItems.setItem(2, "token", token);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "nextValue", nextValue);
eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "feeType", feeType);
eventEmitter.emitEventLog2(
"ClaimableUiFeeAmountUpdated",
Cast.toBytes32(market),
feeType,
eventData
);
}
function emitFeesClaimed(
EventEmitter eventEmitter,
address market,
address receiver,
uint256 feeAmount
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(2);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "receiver", receiver);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "feeAmount", feeAmount);
eventEmitter.emitEventLog1(
"FeesClaimed",
Cast.toBytes32(market),
eventData
);
}
function emitUiFeesClaimed(
EventEmitter eventEmitter,
address uiFeeReceiver,
address market,
address receiver,
uint256 feeAmount,
uint256 nextPoolValue
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "uiFeeReceiver", uiFeeReceiver);
eventData.addressItems.setItem(1, "market", market);
eventData.addressItems.setItem(2, "receiver", receiver);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "feeAmount", feeAmount);
eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"UiFeesClaimed",
Cast.toBytes32(market),
eventData
);
}
}
文件 28 的 92:GasUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../utils/Precision.sol";
import "../deposit/Deposit.sol";
import "../withdrawal/Withdrawal.sol";
import "../order/Order.sol";
import "../order/BaseOrderUtils.sol";
import "../bank/StrictBank.sol";
library GasUtils {
using Deposit for Deposit.Props;
using Withdrawal for Withdrawal.Props;
using Order for Order.Props;
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;
event KeeperExecutionFee(address keeper, uint256 amount);
event UserRefundFee(address user, uint256 amount);
function getMinHandleExecutionErrorGas(DataStore dataStore) internal view returns (uint256) {
return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS);
}
function getMinHandleExecutionErrorGasToForward(DataStore dataStore) internal view returns (uint256) {
return dataStore.getUint(Keys.MIN_HANDLE_EXECUTION_ERROR_GAS_TO_FORWARD);
}
function getMinAdditionalGasForExecution(DataStore dataStore) internal view returns (uint256) {
return dataStore.getUint(Keys.MIN_ADDITIONAL_GAS_FOR_EXECUTION);
}
function getExecutionGas(DataStore dataStore, uint256 startingGas) internal view returns (uint256) {
uint256 minHandleExecutionErrorGasToForward = GasUtils.getMinHandleExecutionErrorGasToForward(dataStore);
if (startingGas < minHandleExecutionErrorGasToForward) {
revert Errors.InsufficientExecutionGasForErrorHandling(startingGas, minHandleExecutionErrorGasToForward);
}
return startingGas - minHandleExecutionErrorGasToForward;
}
function validateExecutionGas(DataStore dataStore, uint256 startingGas, uint256 estimatedGasLimit) internal view {
uint256 minAdditionalGasForExecution = getMinAdditionalGasForExecution(dataStore);
if (startingGas < estimatedGasLimit + minAdditionalGasForExecution) {
revert Errors.InsufficientExecutionGas(startingGas, estimatedGasLimit, minAdditionalGasForExecution);
}
}
function validateExecutionErrorGas(DataStore dataStore, bytes memory reasonBytes) internal view {
if (reasonBytes.length != 0 || tx.origin != address(0)) { return; }
uint256 gas = gasleft();
uint256 minHandleExecutionErrorGas = getMinHandleExecutionErrorGas(dataStore);
if (gas < minHandleExecutionErrorGas) {
revert Errors.InsufficientHandleExecutionErrorGas(gas, minHandleExecutionErrorGas);
}
}
function payExecutionFee(
DataStore dataStore,
EventEmitter eventEmitter,
StrictBank bank,
uint256 executionFee,
uint256 startingGas,
address keeper,
address refundReceiver
) external {
startingGas -= gasleft() / 63;
uint256 gasUsed = startingGas - gasleft();
uint256 executionFeeForKeeper = adjustGasUsage(dataStore, gasUsed) * tx.gasprice;
if (executionFeeForKeeper > executionFee) {
executionFeeForKeeper = executionFee;
}
bank.transferOutNativeToken(
keeper,
executionFeeForKeeper
);
emitKeeperExecutionFee(eventEmitter, keeper, executionFeeForKeeper);
uint256 refundFeeAmount = executionFee - executionFeeForKeeper;
if (refundFeeAmount == 0) {
return;
}
bank.transferOutNativeToken(
refundReceiver,
refundFeeAmount
);
emitExecutionFeeRefund(eventEmitter, refundReceiver, refundFeeAmount);
}
function validateExecutionFee(DataStore dataStore, uint256 estimatedGasLimit, uint256 executionFee) internal view {
uint256 gasLimit = adjustGasLimitForEstimate(dataStore, estimatedGasLimit);
uint256 minExecutionFee = gasLimit * tx.gasprice;
if (executionFee < minExecutionFee) {
revert Errors.InsufficientExecutionFee(minExecutionFee, executionFee);
}
}
function adjustGasUsage(DataStore dataStore, uint256 gasUsed) internal view returns (uint256) {
uint256 baseGasLimit = dataStore.getUint(Keys.EXECUTION_GAS_FEE_BASE_AMOUNT);
uint256 multiplierFactor = dataStore.getUint(Keys.EXECUTION_GAS_FEE_MULTIPLIER_FACTOR);
uint256 gasLimit = baseGasLimit + Precision.applyFactor(gasUsed, multiplierFactor);
return gasLimit;
}
function adjustGasLimitForEstimate(DataStore dataStore, uint256 estimatedGasLimit) internal view returns (uint256) {
uint256 baseGasLimit = dataStore.getUint(Keys.ESTIMATED_GAS_FEE_BASE_AMOUNT);
uint256 multiplierFactor = dataStore.getUint(Keys.ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR);
uint256 gasLimit = baseGasLimit + Precision.applyFactor(estimatedGasLimit, multiplierFactor);
return gasLimit;
}
function estimateExecuteDepositGasLimit(DataStore dataStore, Deposit.Props memory deposit) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
uint256 swapCount = deposit.longTokenSwapPath().length + deposit.shortTokenSwapPath().length;
uint256 gasForSwaps = swapCount * gasPerSwap;
if (deposit.initialLongTokenAmount() == 0 || deposit.initialShortTokenAmount() == 0) {
return dataStore.getUint(Keys.depositGasLimitKey(true)) + deposit.callbackGasLimit() + gasForSwaps;
}
return dataStore.getUint(Keys.depositGasLimitKey(false)) + deposit.callbackGasLimit() + gasForSwaps;
}
function estimateExecuteWithdrawalGasLimit(DataStore dataStore, Withdrawal.Props memory withdrawal) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
uint256 swapCount = withdrawal.longTokenSwapPath().length + withdrawal.shortTokenSwapPath().length;
uint256 gasForSwaps = swapCount * gasPerSwap;
return dataStore.getUint(Keys.withdrawalGasLimitKey()) + withdrawal.callbackGasLimit() + gasForSwaps;
}
function estimateExecuteOrderGasLimit(DataStore dataStore, Order.Props memory order) internal view returns (uint256) {
if (BaseOrderUtils.isIncreaseOrder(order.orderType())) {
return estimateExecuteIncreaseOrderGasLimit(dataStore, order);
}
if (BaseOrderUtils.isDecreaseOrder(order.orderType())) {
return estimateExecuteDecreaseOrderGasLimit(dataStore, order);
}
if (BaseOrderUtils.isSwapOrder(order.orderType())) {
return estimateExecuteSwapOrderGasLimit(dataStore, order);
}
revert Errors.UnsupportedOrderType();
}
function estimateExecuteIncreaseOrderGasLimit(DataStore dataStore, Order.Props memory order) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
return dataStore.getUint(Keys.increaseOrderGasLimitKey()) + gasPerSwap * order.swapPath().length + order.callbackGasLimit();
}
function estimateExecuteDecreaseOrderGasLimit(DataStore dataStore, Order.Props memory order) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
uint256 swapCount = order.swapPath().length;
if (order.decreasePositionSwapType() != Order.DecreasePositionSwapType.NoSwap) {
swapCount += 1;
}
return dataStore.getUint(Keys.decreaseOrderGasLimitKey()) + gasPerSwap * swapCount + order.callbackGasLimit();
}
function estimateExecuteSwapOrderGasLimit(DataStore dataStore, Order.Props memory order) internal view returns (uint256) {
uint256 gasPerSwap = dataStore.getUint(Keys.singleSwapGasLimitKey());
return dataStore.getUint(Keys.swapOrderGasLimitKey()) + gasPerSwap * order.swapPath().length + order.callbackGasLimit();
}
function emitKeeperExecutionFee(
EventEmitter eventEmitter,
address keeper,
uint256 executionFeeAmount
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "keeper", keeper);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "executionFeeAmount", executionFeeAmount);
eventEmitter.emitEventLog1(
"KeeperExecutionFee",
Cast.toBytes32(keeper),
eventData
);
}
function emitExecutionFeeRefund(
EventEmitter eventEmitter,
address receiver,
uint256 refundFeeAmount
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "receiver", receiver);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "refundFeeAmount", refundFeeAmount);
eventEmitter.emitEventLog1(
"ExecutionFeeRefund",
Cast.toBytes32(receiver),
eventData
);
}
}
文件 29 的 92:GlobalReentrancyGuard.sol
pragma solidity ^0.8.0;
import "../data/Keys.sol";
import "../data/DataStore.sol";
abstract contract GlobalReentrancyGuard {
uint256 private constant NOT_ENTERED = 0;
uint256 private constant ENTERED = 1;
DataStore public immutable dataStore;
constructor(DataStore _dataStore) {
dataStore = _dataStore;
}
modifier globalNonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
uint256 status = dataStore.getUint(Keys.REENTRANCY_GUARD_STATUS);
require(status == NOT_ENTERED, "ReentrancyGuard: reentrant call");
dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, ENTERED);
}
function _nonReentrantAfter() private {
dataStore.setUint(Keys.REENTRANCY_GUARD_STATUS, NOT_ENTERED);
}
}
文件 30 的 92:IDepositCallbackReceiver.sol
pragma solidity ^0.8.0;
import "../event/EventUtils.sol";
import "../deposit/Deposit.sol";
interface IDepositCallbackReceiver {
function afterDepositExecution(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external;
function afterDepositCancellation(bytes32 key, Deposit.Props memory deposit, EventUtils.EventLogData memory eventData) external;
}
文件 31 的 92: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);
}
文件 32 的 92: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);
}
文件 33 的 92:IOrderCallbackReceiver.sol
pragma solidity ^0.8.0;
import "../event/EventUtils.sol";
import "../order/Order.sol";
interface IOrderCallbackReceiver {
function afterOrderExecution(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
function afterOrderCancellation(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
function afterOrderFrozen(bytes32 key, Order.Props memory order, EventUtils.EventLogData memory eventData) external;
}
文件 34 的 92:IPriceFeed.sol
pragma solidity ^0.8.0;
interface IPriceFeed {
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 35 的 92:IRealtimeFeedVerifier.sol
pragma solidity ^0.8.0;
interface IRealtimeFeedVerifier {
function verify(bytes memory data) external returns (bytes memory);
}
文件 36 的 92:IReferralStorage.sol
pragma solidity ^0.8.0;
import "./ReferralTier.sol";
interface IReferralStorage {
function codeOwners(bytes32 _code) external view returns (address);
function traderReferralCodes(address _account) external view returns (bytes32);
function referrerDiscountShares(address _account) external view returns (uint256);
function referrerTiers(address _account) external view returns (uint256);
function getTraderReferralInfo(address _account) external view returns (bytes32, address);
function setTraderReferralCode(address _account, bytes32 _code) external;
function setTier(uint256 _tierId, uint256 _totalRebate, uint256 _discountShare) external;
function setReferrerTier(address _referrer, uint256 _tierId) external;
function govSetCodeOwner(bytes32 _code, address _newAccount) external;
function tiers(uint256 _tierLevel) external view returns (uint256, uint256);
}
文件 37 的 92:IWNT.sol
pragma solidity ^0.8.0;
interface IWNT {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 38 的 92:IWithdrawalCallbackReceiver.sol
pragma solidity ^0.8.0;
import "../event/EventUtils.sol";
import "../withdrawal/Withdrawal.sol";
interface IWithdrawalCallbackReceiver {
function afterWithdrawalExecution(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external;
function afterWithdrawalCancellation(bytes32 key, Withdrawal.Props memory withdrawal, EventUtils.EventLogData memory eventData) external;
}
文件 39 的 92:IWithdrawalHandler.sol
pragma solidity ^0.8.0;
import "../withdrawal/WithdrawalUtils.sol";
import "../oracle/OracleUtils.sol";
interface IWithdrawalHandler {
function createWithdrawal(address account, WithdrawalUtils.CreateWithdrawalParams calldata params) external returns (bytes32);
function cancelWithdrawal(bytes32 key) external;
function simulateExecuteWithdrawal(bytes32 key, OracleUtils.SimulatePricesParams memory params) external;
}
文件 40 的 92: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 IN_STRICT_PRICE_FEED_MODE = keccak256(abi.encode("IN_STRICT_PRICE_FEED_MODE"));
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 MARKET_LIST = keccak256(abi.encode("MARKET_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 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 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_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 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_REF_PRICE_DEVIATION_FACTOR = keccak256(abi.encode("MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR"));
bytes32 public constant POSITION_FEE_RECEIVER_FACTOR = keccak256(abi.encode("POSITION_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 = keccak256(abi.encode("ESTIMATED_GAS_FEE_BASE_AMOUNT"));
bytes32 public constant ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR = keccak256(abi.encode("ESTIMATED_GAS_FEE_MULTIPLIER_FACTOR"));
bytes32 public constant EXECUTION_GAS_FEE_BASE_AMOUNT = keccak256(abi.encode("EXECUTION_GAS_FEE_BASE_AMOUNT"));
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 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_BLOCK_AGE = keccak256(abi.encode("REQUEST_EXPIRATION_BLOCK_AGE"));
bytes32 public constant MAX_CALLBACK_GAS_LIMIT = keccak256(abi.encode("MAX_CALLBACK_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 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 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_AMOUNT_FOR_DEPOSIT = keccak256(abi.encode("MAX_POOL_AMOUNT_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 REALTIME_FEED_ID = keccak256(abi.encode("REALTIME_FEED_ID"));
bytes32 public constant REALTIME_FEED_MULTIPLIER = keccak256(abi.encode("REALTIME_FEED_MULTIPLIER"));
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_BLOCK = keccak256(abi.encode("LATEST_ADL_BLOCK"));
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 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 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_CREATE_ORDER_ACTION = keccak256(abi.encode("SUBACCOUNT_CREATE_ORDER_ACTION"));
string public constant USER_INITIATED_CANCEL = "USER_INITIATED_CANCEL";
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 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 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(bool singleToken) internal pure returns (bytes32) {
return keccak256(abi.encode(
DEPOSIT_GAS_LIMIT,
singleToken
));
}
function withdrawalGasLimitKey() internal pure returns (bytes32) {
return keccak256(abi.encode(
WITHDRAWAL_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 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 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 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 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 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 maxPoolAmountForDepositKey(address market, address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
MAX_POOL_AMOUNT_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 latestAdlBlockKey(address market, bool isLong) internal pure returns (bytes32) {
return keccak256(abi.encode(
LATEST_ADL_BLOCK,
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 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 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 realtimeFeedIdKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
REALTIME_FEED_ID,
token
));
}
function realtimeFeedMultiplierKey(address token) internal pure returns (bytes32) {
return keccak256(abi.encode(
REALTIME_FEED_MULTIPLIER,
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
));
}
}
文件 41 的 92:Market.sol
pragma solidity ^0.8.0;
library Market {
struct Props {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
}
文件 42 的 92: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
);
}
}
文件 43 的 92: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;
}
}
文件 44 的 92: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);
}
}
文件 45 的 92: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);
}
}
文件 46 的 92:MarketUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../data/DataStore.sol";
import "../event/EventEmitter.sol";
import "../bank/StrictBank.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 getMaxPoolAmountForDeposit(DataStore dataStore, address market, address token) internal view returns (uint256) {
return dataStore.getUint(Keys.maxPoolAmountForDepositKey(market, token));
}
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;
}
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;
if (cache.diffUsd == 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);
FundingConfigCache memory configCache;
configCache.fundingIncreaseFactorPerSecond = dataStore.getUint(Keys.fundingIncreaseFactorPerSecondKey(market));
if (configCache.fundingIncreaseFactorPerSecond == 0) {
cache.fundingFactor = getFundingFactor(dataStore, market);
return (
Precision.applyFactor(cache.diffUsdToOpenInterestFactor, cache.fundingFactor),
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 validatePoolAmountForDeposit(
DataStore dataStore,
Market.Props memory market,
address token
) internal view {
uint256 poolAmount = getPoolAmount(dataStore, market, token);
uint256 maxPoolAmount = getMaxPoolAmountForDeposit(dataStore, market.marketToken, token);
if (poolAmount > maxPoolAmount) {
revert Errors.MaxPoolAmountForDepositExceeded(poolAmount, maxPoolAmount);
}
}
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) {
int256 impactAmount = getSwapImpactAmountWithCap(
dataStore,
market,
token,
tokenPrice,
priceImpactUsd
);
applyDeltaToSwapImpactPool(
dataStore,
eventEmitter,
market,
token,
-impactAmount
);
return impactAmount;
}
function getSwapImpactAmountWithCap(
DataStore dataStore,
address market,
address token,
Price.Props memory tokenPrice,
int256 priceImpactUsd
) internal view returns (int256) {
uint256 price = priceImpactUsd > 0 ? tokenPrice.max : tokenPrice.min;
int256 impactAmount;
if (priceImpactUsd > 0) {
impactAmount = priceImpactUsd / price.toInt256();
int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();
if (impactAmount > maxImpactAmount) {
impactAmount = maxImpactAmount;
}
} else {
impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, price);
}
return impactAmount;
}
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 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 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 distributePositionImpactPool(
DataStore dataStore,
EventEmitter eventEmitter,
address market
) external {
(uint256 distributionAmount, uint256 nextPositionImpactPoolAmount) = getPendingPositionImpactPoolDistributionAmount(dataStore, market);
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;
}
}
文件 47 的 92: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);
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;
uint256 x = a;
if (x >> 128 > 0) {
x >>= 128;
result <<= 64;
}
if (x >> 64 > 0) {
x >>= 64;
result <<= 32;
}
if (x >> 32 > 0) {
x >>= 32;
result <<= 16;
}
if (x >> 16 > 0) {
x >>= 16;
result <<= 8;
}
if (x >> 8 > 0) {
x >>= 8;
result <<= 4;
}
if (x >> 4 > 0) {
x >>= 4;
result <<= 2;
}
if (x >> 2 > 0) {
result <<= 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) {
uint256 result = sqrt(a);
if (rounding == Rounding.Up && result * result < a) {
result += 1;
}
return result;
}
}
文件 48 的 92:NonceUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../data/Keys.sol";
library NonceUtils {
function getCurrentNonce(DataStore dataStore) internal view returns (uint256) {
return dataStore.getUint(Keys.NONCE);
}
function incrementNonce(DataStore dataStore) internal returns (uint256) {
return dataStore.incrementUint(Keys.NONCE, 1);
}
function getNextKey(DataStore dataStore) internal returns (bytes32) {
uint256 nonce = incrementNonce(dataStore);
bytes32 key = keccak256(abi.encode(address(dataStore), nonce));
return key;
}
}
文件 49 的 92:Oracle.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../role/RoleModule.sol";
import "./OracleStore.sol";
import "./OracleUtils.sol";
import "./IPriceFeed.sol";
import "./IRealtimeFeedVerifier.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/Bits.sol";
import "../utils/Array.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;
struct ValidatedPrice {
address token;
uint256 min;
uint256 max;
uint256 timestamp;
uint256 minBlockNumber;
uint256 maxBlockNumber;
}
struct SetPricesCache {
OracleUtils.ReportInfo info;
uint256 minBlockConfirmations;
uint256 maxPriceAge;
uint256 maxRefPriceDeviationFactor;
uint256 prevMinOracleBlockNumber;
ValidatedPrice[] validatedPrices;
}
struct SetPricesInnerCache {
bytes32 feedId;
uint256 priceIndex;
uint256 signatureIndex;
uint256 minPriceIndex;
uint256 maxPriceIndex;
uint256[] minPrices;
uint256[] maxPrices;
Uint256Mask.Mask minPriceIndexMask;
Uint256Mask.Mask maxPriceIndexMask;
}
uint256 public constant SIGNER_INDEX_LENGTH = 16;
uint256 public constant MAX_SIGNERS = 256 / SIGNER_INDEX_LENGTH - 1;
uint256 public constant MAX_SIGNER_INDEX = 256;
OracleStore public immutable oracleStore;
IRealtimeFeedVerifier public immutable realtimeFeedVerifier;
EnumerableSet.AddressSet internal tokensWithPrices;
mapping(address => Price.Props) public primaryPrices;
constructor(
RoleStore _roleStore,
OracleStore _oracleStore,
IRealtimeFeedVerifier _realtimeFeedVerifier
) RoleModule(_roleStore) {
oracleStore = _oracleStore;
realtimeFeedVerifier = _realtimeFeedVerifier;
}
function setPrices(
DataStore dataStore,
EventEmitter eventEmitter,
OracleUtils.SetPricesParams memory params
) external onlyController {
if (tokensWithPrices.length() != 0) {
revert Errors.NonEmptyTokensWithPrices(tokensWithPrices.length());
}
_setPricesFromPriceFeeds(dataStore, eventEmitter, params.priceFeedTokens);
OracleUtils.RealtimeFeedReport[] memory reports = _setPricesFromRealtimeFeeds(dataStore, eventEmitter, params);
ValidatedPrice[] memory validatedPrices = _setPrices(
dataStore,
eventEmitter,
params
);
_validateBlockRanges(reports, validatedPrices);
}
function setPrimaryPrice(address token, Price.Props memory price) external onlyController {
_setPrimaryPrice(token, price);
}
function clearAllPrices() external onlyController {
uint256 length = tokensWithPrices.length();
for (uint256 i; i < length; i++) {
address token = tokensWithPrices.at(0);
_removePrimaryPrice(token);
}
}
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 getStablePrice(DataStore dataStore, address token) public view returns (uint256) {
return dataStore.getUint(Keys.stablePriceKey(token));
}
function getPriceFeedMultiplier(DataStore dataStore, address token) public view returns (uint256) {
uint256 multiplier = dataStore.getUint(Keys.priceFeedMultiplierKey(token));
if (multiplier == 0) {
revert Errors.EmptyPriceFeedMultiplier(token);
}
return multiplier;
}
function getRealtimeFeedMultiplier(DataStore dataStore, address token) public view returns (uint256) {
uint256 multiplier = dataStore.getUint(Keys.realtimeFeedMultiplierKey(token));
if (multiplier == 0) {
revert Errors.EmptyRealtimeFeedMultiplier(token);
}
return multiplier;
}
function validatePrices(
DataStore dataStore,
OracleUtils.SetPricesParams memory params
) external view returns (ValidatedPrice[] memory) {
return _validatePrices(dataStore, params);
}
function validateRealtimeFeeds(
DataStore dataStore,
address[] memory realtimeFeedTokens,
bytes[] memory realtimeFeedData
) external onlyController returns (OracleUtils.RealtimeFeedReport[] memory) {
return _validateRealtimeFeeds(dataStore, realtimeFeedTokens, realtimeFeedData);
}
function _setPrices(
DataStore dataStore,
EventEmitter eventEmitter,
OracleUtils.SetPricesParams memory params
) internal returns (ValidatedPrice[] memory) {
ValidatedPrice[] memory validatedPrices = _validatePrices(dataStore, params);
for (uint256 i; i < validatedPrices.length; i++) {
ValidatedPrice memory validatedPrice = validatedPrices[i];
emitOraclePriceUpdated(
eventEmitter,
validatedPrice.token,
validatedPrice.min,
validatedPrice.max,
validatedPrice.timestamp,
OracleUtils.PriceSourceType.InternalFeed
);
_setPrimaryPrice(validatedPrice.token, Price.Props(
validatedPrice.min,
validatedPrice.max
));
}
return validatedPrices;
}
function _validatePrices(
DataStore dataStore,
OracleUtils.SetPricesParams memory params
) internal view returns (ValidatedPrice[] memory) {
if (params.tokens.length == 0) {
return new ValidatedPrice[](0);
}
address[] memory signers = _getSigners(dataStore, params);
SetPricesCache memory cache;
cache.validatedPrices = new ValidatedPrice[](params.tokens.length);
cache.minBlockConfirmations = dataStore.getUint(Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS);
cache.maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);
cache.maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);
for (uint256 i; i < params.tokens.length; i++) {
OracleUtils.ReportInfo memory reportInfo;
SetPricesInnerCache memory innerCache;
reportInfo.minOracleBlockNumber = OracleUtils.getUncompactedOracleBlockNumber(params.compactedMinOracleBlockNumbers, i);
reportInfo.maxOracleBlockNumber = OracleUtils.getUncompactedOracleBlockNumber(params.compactedMaxOracleBlockNumbers, i);
if (reportInfo.minOracleBlockNumber > reportInfo.maxOracleBlockNumber) {
revert Errors.InvalidMinMaxBlockNumber(reportInfo.minOracleBlockNumber, reportInfo.maxOracleBlockNumber);
}
reportInfo.oracleTimestamp = OracleUtils.getUncompactedOracleTimestamp(params.compactedOracleTimestamps, i);
if (reportInfo.maxOracleBlockNumber >= Chain.currentBlockNumber()) {
revert Errors.InvalidBlockNumber(reportInfo.maxOracleBlockNumber, Chain.currentBlockNumber());
}
if (reportInfo.oracleTimestamp + cache.maxPriceAge < Chain.currentTimestamp()) {
revert Errors.MaxPriceAgeExceeded(reportInfo.oracleTimestamp, Chain.currentTimestamp());
}
if (reportInfo.minOracleBlockNumber < cache.prevMinOracleBlockNumber) {
revert Errors.BlockNumbersNotSorted(reportInfo.minOracleBlockNumber, cache.prevMinOracleBlockNumber);
}
cache.prevMinOracleBlockNumber = reportInfo.minOracleBlockNumber;
if (Chain.currentBlockNumber() - reportInfo.maxOracleBlockNumber <= cache.minBlockConfirmations) {
reportInfo.blockHash = Chain.getBlockHash(reportInfo.maxOracleBlockNumber);
}
reportInfo.token = params.tokens[i];
if (dataStore.getBool(Keys.IN_STRICT_PRICE_FEED_MODE)) {
innerCache.feedId = dataStore.getBytes32(Keys.realtimeFeedIdKey(reportInfo.token));
if (innerCache.feedId != bytes32(0)) {
revert Errors.HasRealtimeFeedId(reportInfo.token, innerCache.feedId);
}
}
reportInfo.precision = 10 ** OracleUtils.getUncompactedDecimal(params.compactedDecimals, i);
reportInfo.tokenOracleType = dataStore.getBytes32(Keys.oracleTypeKey(reportInfo.token));
innerCache.minPrices = new uint256[](signers.length);
innerCache.maxPrices = new uint256[](signers.length);
for (uint256 j = 0; j < signers.length; j++) {
innerCache.priceIndex = i * signers.length + j;
innerCache.minPrices[j] = OracleUtils.getUncompactedPrice(params.compactedMinPrices, innerCache.priceIndex);
innerCache.maxPrices[j] = OracleUtils.getUncompactedPrice(params.compactedMaxPrices, innerCache.priceIndex);
if (j == 0) { continue; }
if (innerCache.minPrices[j - 1] > innerCache.minPrices[j]) {
revert Errors.MinPricesNotSorted(reportInfo.token, innerCache.minPrices[j], innerCache.minPrices[j - 1]);
}
if (innerCache.maxPrices[j - 1] > innerCache.maxPrices[j]) {
revert Errors.MaxPricesNotSorted(reportInfo.token, innerCache.maxPrices[j], innerCache.maxPrices[j - 1]);
}
}
for (uint256 j = 0; j < signers.length; j++) {
innerCache.signatureIndex = i * signers.length + j;
innerCache.minPriceIndex = OracleUtils.getUncompactedPriceIndex(params.compactedMinPricesIndexes, innerCache.signatureIndex);
innerCache.maxPriceIndex = OracleUtils.getUncompactedPriceIndex(params.compactedMaxPricesIndexes, innerCache.signatureIndex);
if (innerCache.signatureIndex >= params.signatures.length) {
revert Errors.ArrayOutOfBoundsBytes(params.signatures, innerCache.signatureIndex, "signatures");
}
if (innerCache.minPriceIndex >= innerCache.minPrices.length) {
revert Errors.ArrayOutOfBoundsUint256(innerCache.minPrices, innerCache.minPriceIndex, "minPrices");
}
if (innerCache.maxPriceIndex >= innerCache.maxPrices.length) {
revert Errors.ArrayOutOfBoundsUint256(innerCache.maxPrices, innerCache.maxPriceIndex, "maxPrices");
}
innerCache.minPriceIndexMask.validateUniqueAndSetIndex(innerCache.minPriceIndex, "minPriceIndex");
innerCache.maxPriceIndexMask.validateUniqueAndSetIndex(innerCache.maxPriceIndex, "maxPriceIndex");
reportInfo.minPrice = innerCache.minPrices[innerCache.minPriceIndex];
reportInfo.maxPrice = innerCache.maxPrices[innerCache.maxPriceIndex];
if (reportInfo.minPrice > reportInfo.maxPrice) {
revert Errors.InvalidSignerMinMaxPrice(reportInfo.minPrice, reportInfo.maxPrice);
}
OracleUtils.validateSigner(
_getSalt(),
reportInfo,
params.signatures[innerCache.signatureIndex],
signers[j]
);
}
uint256 medianMinPrice = Array.getMedian(innerCache.minPrices) * reportInfo.precision;
uint256 medianMaxPrice = Array.getMedian(innerCache.maxPrices) * reportInfo.precision;
(bool hasPriceFeed, uint256 refPrice) = _getPriceFeedPrice(dataStore, reportInfo.token);
if (hasPriceFeed) {
validateRefPrice(
reportInfo.token,
medianMinPrice,
refPrice,
cache.maxRefPriceDeviationFactor
);
validateRefPrice(
reportInfo.token,
medianMaxPrice,
refPrice,
cache.maxRefPriceDeviationFactor
);
}
if (medianMinPrice == 0 || medianMaxPrice == 0) {
revert Errors.InvalidOraclePrice(reportInfo.token);
}
if (medianMinPrice > medianMaxPrice) {
revert Errors.InvalidMedianMinMaxPrice(medianMinPrice, medianMaxPrice);
}
cache.validatedPrices[i] = ValidatedPrice(
reportInfo.token,
medianMinPrice,
medianMaxPrice,
reportInfo.oracleTimestamp,
reportInfo.minOracleBlockNumber,
reportInfo.maxOracleBlockNumber
);
}
return cache.validatedPrices;
}
function _validateRealtimeFeeds(
DataStore dataStore,
address[] memory realtimeFeedTokens,
bytes[] memory realtimeFeedData
) internal returns (OracleUtils.RealtimeFeedReport[] memory) {
if (realtimeFeedTokens.length != realtimeFeedData.length) {
revert Errors.InvalidRealtimeFeedLengths(realtimeFeedTokens.length, realtimeFeedData.length);
}
OracleUtils.RealtimeFeedReport[] memory reports = new OracleUtils.RealtimeFeedReport[](realtimeFeedTokens.length);
uint256 minBlockConfirmations = dataStore.getUint(Keys.MIN_ORACLE_BLOCK_CONFIRMATIONS);
uint256 maxPriceAge = dataStore.getUint(Keys.MAX_ORACLE_PRICE_AGE);
for (uint256 i; i < realtimeFeedTokens.length; i++) {
address token = realtimeFeedTokens[i];
bytes32 feedId = dataStore.getBytes32(Keys.realtimeFeedIdKey(token));
if (feedId == bytes32(0)) {
revert Errors.EmptyRealtimeFeedId(token);
}
bytes memory data = realtimeFeedData[i];
bytes memory verifierResponse = realtimeFeedVerifier.verify(data);
OracleUtils.RealtimeFeedReport memory report = abi.decode(verifierResponse, (OracleUtils.RealtimeFeedReport));
if (feedId != report.feedId) {
revert Errors.InvalidRealtimeFeedId(token, report.feedId, feedId);
}
if (report.bid <= 0 || report.ask <= 0) {
revert Errors.InvalidRealtimePrices(token, report.bid, report.ask);
}
if (report.bid > report.ask) {
revert Errors.InvalidRealtimeBidAsk(token, report.bid, report.ask);
}
if (
!(tx.origin == address(0) && Chain.currentBlockNumber() == report.blocknumberUpperBound) &&
(Chain.currentBlockNumber() - report.blocknumberUpperBound <= minBlockConfirmations)
) {
bytes32 blockHash = Chain.getBlockHash(report.blocknumberUpperBound);
if (report.upperBlockhash != blockHash) {
revert Errors.InvalidRealtimeBlockHash(token, report.upperBlockhash, blockHash);
}
}
if (report.currentBlockTimestamp + maxPriceAge < Chain.currentTimestamp()) {
revert Errors.RealtimeMaxPriceAgeExceeded(token, report.currentBlockTimestamp, Chain.currentTimestamp());
}
reports[i] = report;
}
return reports;
}
function _getSigners(
DataStore dataStore,
OracleUtils.SetPricesParams memory params
) internal view returns (address[] memory) {
address[] memory signers = new address[](params.signerInfo & Bits.BITMASK_16);
if (signers.length < dataStore.getUint(Keys.MIN_ORACLE_SIGNERS)) {
revert Errors.MinOracleSigners(signers.length, dataStore.getUint(Keys.MIN_ORACLE_SIGNERS));
}
if (signers.length > MAX_SIGNERS) {
revert Errors.MaxOracleSigners(signers.length, MAX_SIGNERS);
}
Uint256Mask.Mask memory signerIndexMask;
for (uint256 i; i < signers.length; i++) {
uint256 signerIndex = params.signerInfo >> (16 + 16 * i) & Bits.BITMASK_16;
if (signerIndex >= MAX_SIGNER_INDEX) {
revert Errors.MaxSignerIndex(signerIndex, MAX_SIGNER_INDEX);
}
signerIndexMask.validateUniqueAndSetIndex(signerIndex, "signerIndex");
signers[i] = oracleStore.getSigner(signerIndex);
if (signers[i] == address(0)) {
revert Errors.EmptySigner(signerIndex);
}
}
return signers;
}
function _validateBlockRanges(
OracleUtils.RealtimeFeedReport[] memory reports,
ValidatedPrice[] memory validatedPrices
) internal pure {
uint256 largestMinBlockNumber;
uint256 smallestMaxBlockNumber = type(uint256).max;
for (uint256 i; i < reports.length; i++) {
OracleUtils.RealtimeFeedReport memory report = reports[i];
if (report.blocknumberLowerBound > largestMinBlockNumber) {
largestMinBlockNumber = report.blocknumberLowerBound;
}
if (report.blocknumberUpperBound < smallestMaxBlockNumber) {
smallestMaxBlockNumber = report.blocknumberUpperBound;
}
}
for (uint256 i; i < validatedPrices.length; i++) {
ValidatedPrice memory validatedPrice = validatedPrices[i];
if (validatedPrice.minBlockNumber > largestMinBlockNumber) {
largestMinBlockNumber = validatedPrice.minBlockNumber;
}
if (validatedPrice.maxBlockNumber < smallestMaxBlockNumber) {
smallestMaxBlockNumber = validatedPrice.maxBlockNumber;
}
}
if (largestMinBlockNumber > smallestMaxBlockNumber) {
revert Errors.InvalidBlockRangeSet(largestMinBlockNumber, smallestMaxBlockNumber);
}
}
function _getSalt() internal view returns (bytes32) {
return keccak256(abi.encode(block.chainid, "xget-oracle-v1"));
}
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 _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.PriceFeedNotUpdated(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 _setPricesFromRealtimeFeeds(
DataStore dataStore,
EventEmitter eventEmitter,
OracleUtils.SetPricesParams memory params
) internal returns (OracleUtils.RealtimeFeedReport[] memory) {
OracleUtils.RealtimeFeedReport[] memory reports = _validateRealtimeFeeds(
dataStore,
params.realtimeFeedTokens,
params.realtimeFeedData
);
uint256 maxRefPriceDeviationFactor = dataStore.getUint(Keys.MAX_ORACLE_REF_PRICE_DEVIATION_FACTOR);
for (uint256 i; i < params.realtimeFeedTokens.length; i++) {
address token = params.realtimeFeedTokens[i];
OracleUtils.RealtimeFeedReport memory report = reports[i];
uint256 precision = getRealtimeFeedMultiplier(dataStore, token);
uint256 adjustedBidPrice = Precision.mulDiv(uint256(uint192(report.bid)), precision, Precision.FLOAT_PRECISION);
uint256 adjustedAskPrice = Precision.mulDiv(uint256(uint192(report.ask)), precision, Precision.FLOAT_PRECISION);
(bool hasPriceFeed, uint256 refPrice) = _getPriceFeedPrice(dataStore, token);
if (hasPriceFeed) {
validateRefPrice(
token,
adjustedBidPrice,
refPrice,
maxRefPriceDeviationFactor
);
validateRefPrice(
token,
adjustedAskPrice,
refPrice,
maxRefPriceDeviationFactor
);
}
Price.Props memory priceProps = Price.Props(
adjustedBidPrice,
adjustedAskPrice
);
_setPrimaryPrice(token, priceProps);
emitOraclePriceUpdated(
eventEmitter,
token,
priceProps.min,
priceProps.max,
report.currentBlockTimestamp,
OracleUtils.PriceSourceType.RealtimeFeed
);
}
return reports;
}
function _setPricesFromPriceFeeds(DataStore dataStore, EventEmitter eventEmitter, address[] memory priceFeedTokens) internal {
for (uint256 i; i < priceFeedTokens.length; i++) {
address token = priceFeedTokens[i];
(bool hasPriceFeed, uint256 price) = _getPriceFeedPrice(dataStore, token);
if (!hasPriceFeed) {
revert Errors.EmptyPriceFeed(token);
}
uint256 stablePrice = getStablePrice(dataStore, token);
Price.Props memory priceProps;
if (stablePrice > 0) {
priceProps = Price.Props(
price < stablePrice ? price : stablePrice,
price < stablePrice ? stablePrice : price
);
} else {
priceProps = Price.Props(
price,
price
);
}
_setPrimaryPrice(token, priceProps);
emitOraclePriceUpdated(
eventEmitter,
token,
priceProps.min,
priceProps.max,
Chain.currentTimestamp(),
OracleUtils.PriceSourceType.PriceFeed
);
}
}
function emitOraclePriceUpdated(
EventEmitter eventEmitter,
address token,
uint256 minPrice,
uint256 maxPrice,
uint256 timestamp,
OracleUtils.PriceSourceType priceSourceType
) internal {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "token", token);
eventData.uintItems.initItems(4);
eventData.uintItems.setItem(0, "minPrice", minPrice);
eventData.uintItems.setItem(1, "maxPrice", maxPrice);
eventData.uintItems.setItem(2, "timestamp", timestamp);
eventData.uintItems.setItem(3, "priceSourceType", uint256(priceSourceType));
eventEmitter.emitEventLog1(
"OraclePriceUpdate",
Cast.toBytes32(token),
eventData
);
}
}
文件 50 的 92:OracleModule.sol
pragma solidity ^0.8.0;
import "./Oracle.sol";
import "../event/EventEmitter.sol";
contract OracleModule {
event OracleError(string reason);
modifier withOraclePrices(
Oracle oracle,
DataStore dataStore,
EventEmitter eventEmitter,
OracleUtils.SetPricesParams memory params
) {
oracle.setPrices(dataStore, eventEmitter, params);
_;
oracle.clearAllPrices();
}
modifier withSimulatedOraclePrices(
Oracle oracle,
OracleUtils.SimulatePricesParams memory params
) {
if (params.primaryTokens.length != params.primaryPrices.length) {
revert Errors.InvalidPrimaryPricesForSimulation(params.primaryTokens.length, params.primaryPrices.length);
}
for (uint256 i; i < params.primaryTokens.length; i++) {
address token = params.primaryTokens[i];
Price.Props memory price = params.primaryPrices[i];
oracle.setPrimaryPrice(token, price);
}
_;
revert Errors.EndOfOracleSimulation();
}
}
文件 51 的 92:OracleStore.sol
pragma solidity ^0.8.0;
import "../role/RoleModule.sol";
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Cast.sol";
contract OracleStore is RoleModule {
using EnumerableSet for EnumerableSet.AddressSet;
using EnumerableValues for EnumerableSet.AddressSet;
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;
EventEmitter public immutable eventEmitter;
EnumerableSet.AddressSet internal signers;
constructor(RoleStore _roleStore, EventEmitter _eventEmitter) RoleModule(_roleStore) {
eventEmitter = _eventEmitter;
}
function addSigner(address account) external onlyController {
signers.add(account);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventEmitter.emitEventLog1(
"SignerAdded",
Cast.toBytes32(account),
eventData
);
}
function removeSigner(address account) external onlyController {
signers.remove(account);
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventEmitter.emitEventLog1(
"SignerRemoved",
Cast.toBytes32(account),
eventData
);
}
function getSignerCount() external view returns (uint256) {
return signers.length();
}
function getSigner(uint256 index) external view returns (address) {
return signers.at(index);
}
function getSigners(uint256 start, uint256 end) external view returns (address[] memory) {
return signers.valuesAt(start, end);
}
}
文件 52 的 92:OracleUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../utils/Array.sol";
import "../utils/Bits.sol";
import "../price/Price.sol";
import "../utils/Printer.sol";
library OracleUtils {
using Array for uint256[];
enum PriceSourceType {
InternalFeed,
PriceFeed,
RealtimeFeed
}
enum OracleBlockNumberType {
Min,
Max
}
struct SetPricesParams {
uint256 signerInfo;
address[] tokens;
uint256[] compactedMinOracleBlockNumbers;
uint256[] compactedMaxOracleBlockNumbers;
uint256[] compactedOracleTimestamps;
uint256[] compactedDecimals;
uint256[] compactedMinPrices;
uint256[] compactedMinPricesIndexes;
uint256[] compactedMaxPrices;
uint256[] compactedMaxPricesIndexes;
bytes[] signatures;
address[] priceFeedTokens;
address[] realtimeFeedTokens;
bytes[] realtimeFeedData;
}
struct SimulatePricesParams {
address[] primaryTokens;
Price.Props[] primaryPrices;
}
struct ReportInfo {
uint256 minOracleBlockNumber;
uint256 maxOracleBlockNumber;
uint256 oracleTimestamp;
bytes32 blockHash;
address token;
bytes32 tokenOracleType;
uint256 precision;
uint256 minPrice;
uint256 maxPrice;
}
struct RealtimeFeedReport {
bytes32 feedId;
uint32 observationsTimestamp;
int192 median;
int192 bid;
int192 ask;
uint64 blocknumberUpperBound;
bytes32 upperBlockhash;
uint64 blocknumberLowerBound;
uint64 currentBlockTimestamp;
}
uint256 public constant COMPACTED_PRICE_BIT_LENGTH = 32;
uint256 public constant COMPACTED_PRICE_BITMASK = Bits.BITMASK_32;
uint256 public constant COMPACTED_PRECISION_BIT_LENGTH = 8;
uint256 public constant COMPACTED_PRECISION_BITMASK = Bits.BITMASK_8;
uint256 public constant COMPACTED_BLOCK_NUMBER_BIT_LENGTH = 64;
uint256 public constant COMPACTED_BLOCK_NUMBER_BITMASK = Bits.BITMASK_64;
uint256 public constant COMPACTED_TIMESTAMP_BIT_LENGTH = 64;
uint256 public constant COMPACTED_TIMESTAMP_BITMASK = Bits.BITMASK_64;
uint256 public constant COMPACTED_PRICE_INDEX_BIT_LENGTH = 8;
uint256 public constant COMPACTED_PRICE_INDEX_BITMASK = Bits.BITMASK_8;
function validateBlockNumberWithinRange(
uint256[] memory minOracleBlockNumbers,
uint256[] memory maxOracleBlockNumbers,
uint256 blockNumber
) internal pure {
if (!isBlockNumberWithinRange(
minOracleBlockNumbers,
maxOracleBlockNumbers,
blockNumber
)) {
revert Errors.OracleBlockNumberNotWithinRange(
minOracleBlockNumbers,
maxOracleBlockNumbers,
blockNumber
);
}
}
function isBlockNumberWithinRange(
uint256[] memory minOracleBlockNumbers,
uint256[] memory maxOracleBlockNumbers,
uint256 blockNumber
) internal pure returns (bool) {
if (!minOracleBlockNumbers.areLessThanOrEqualTo(blockNumber)) {
return false;
}
if (!maxOracleBlockNumbers.areGreaterThanOrEqualTo(blockNumber)) {
return false;
}
return true;
}
function getUncompactedPrice(uint256[] memory compactedPrices, uint256 index) internal pure returns (uint256) {
uint256 price = Array.getUncompactedValue(
compactedPrices,
index,
COMPACTED_PRICE_BIT_LENGTH,
COMPACTED_PRICE_BITMASK,
"getUncompactedPrice"
);
if (price == 0) { revert Errors.EmptyCompactedPrice(index); }
return price;
}
function getUncompactedDecimal(uint256[] memory compactedDecimals, uint256 index) internal pure returns (uint256) {
uint256 decimal = Array.getUncompactedValue(
compactedDecimals,
index,
COMPACTED_PRECISION_BIT_LENGTH,
COMPACTED_PRECISION_BITMASK,
"getUncompactedDecimal"
);
return decimal;
}
function getUncompactedPriceIndex(uint256[] memory compactedPriceIndexes, uint256 index) internal pure returns (uint256) {
uint256 priceIndex = Array.getUncompactedValue(
compactedPriceIndexes,
index,
COMPACTED_PRICE_INDEX_BIT_LENGTH,
COMPACTED_PRICE_INDEX_BITMASK,
"getUncompactedPriceIndex"
);
return priceIndex;
}
function getUncompactedOracleBlockNumbers(
uint256[] memory compactedOracleBlockNumbers,
uint256 compactedOracleBlockNumbersLength,
OracleUtils.RealtimeFeedReport[] memory reports,
OracleBlockNumberType oracleBlockNumberType
) internal pure returns (uint256[] memory) {
uint256[] memory blockNumbers = new uint256[](compactedOracleBlockNumbersLength + reports.length);
for (uint256 i; i < compactedOracleBlockNumbersLength; i++) {
blockNumbers[i] = getUncompactedOracleBlockNumber(compactedOracleBlockNumbers, i);
}
if (oracleBlockNumberType == OracleBlockNumberType.Min) {
for (uint256 i; i < reports.length; i++) {
blockNumbers[compactedOracleBlockNumbersLength + i] = reports[i].blocknumberLowerBound;
}
} else if (oracleBlockNumberType == OracleBlockNumberType.Max) {
for (uint256 i; i < reports.length; i++) {
blockNumbers[compactedOracleBlockNumbersLength + i] = reports[i].blocknumberUpperBound;
}
} else {
revert Errors.UnsupportedOracleBlockNumberType(uint256(oracleBlockNumberType));
}
return blockNumbers;
}
function getUncompactedOracleBlockNumber(uint256[] memory compactedOracleBlockNumbers, uint256 index) internal pure returns (uint256) {
uint256 blockNumber = Array.getUncompactedValue(
compactedOracleBlockNumbers,
index,
COMPACTED_BLOCK_NUMBER_BIT_LENGTH,
COMPACTED_BLOCK_NUMBER_BITMASK,
"getUncompactedOracleBlockNumber"
);
if (blockNumber == 0) { revert Errors.EmptyCompactedBlockNumber(index); }
return blockNumber;
}
function getUncompactedOracleTimestamp(uint256[] memory compactedOracleTimestamps, uint256 index) internal pure returns (uint256) {
uint256 timestamp = Array.getUncompactedValue(
compactedOracleTimestamps,
index,
COMPACTED_TIMESTAMP_BIT_LENGTH,
COMPACTED_TIMESTAMP_BITMASK,
"getUncompactedOracleTimestamp"
);
if (timestamp == 0) { revert Errors.EmptyCompactedTimestamp(index); }
return timestamp;
}
function validateSigner(
bytes32 salt,
ReportInfo memory info,
bytes memory signature,
address expectedSigner
) internal pure {
bytes32 digest = ECDSA.toEthSignedMessageHash(
keccak256(abi.encode(
salt,
info.minOracleBlockNumber,
info.maxOracleBlockNumber,
info.oracleTimestamp,
info.blockHash,
info.token,
info.tokenOracleType,
info.precision,
info.minPrice,
info.maxPrice
))
);
address recoveredSigner = ECDSA.recover(digest, signature);
if (recoveredSigner != expectedSigner) {
revert Errors.InvalidSignature(recoveredSigner, expectedSigner);
}
}
function revertOracleBlockNumberNotWithinRange(
uint256[] memory minOracleBlockNumbers,
uint256[] memory maxOracleBlockNumbers,
uint256 blockNumber
) internal pure {
revert Errors.OracleBlockNumberNotWithinRange(minOracleBlockNumbers, maxOracleBlockNumbers, blockNumber);
}
function isOracleError(bytes4 errorSelector) internal pure returns (bool) {
if (isOracleBlockNumberError(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 isOracleBlockNumberError(bytes4 errorSelector) internal pure returns (bool) {
if (errorSelector == Errors.OracleBlockNumbersAreSmallerThanRequired.selector) {
return true;
}
if (errorSelector == Errors.OracleBlockNumberNotWithinRange.selector) {
return true;
}
return false;
}
}
文件 53 的 92: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
}
enum SecondaryOrderType {
None,
Adl
}
enum DecreasePositionSwapType {
NoSwap,
SwapPnlTokenToCollateralToken,
SwapCollateralTokenToPnlToken
}
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address receiver;
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 updatedAtBlock;
}
struct Flags {
bool isLong;
bool shouldUnwrapNativeToken;
bool isFrozen;
}
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 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 updatedAtBlock(Props memory props) internal pure returns (uint256) {
return props.numbers.updatedAtBlock;
}
function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
props.numbers.updatedAtBlock = 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 touch(Props memory props) internal view {
props.setUpdatedAtBlock(Chain.currentBlockNumber());
}
}
文件 54 的 92:OrderEventUtils.sol
pragma solidity ^0.8.0;
import "../event/EventEmitter.sol";
import "../utils/Cast.sol";
import "./Order.sol";
library OrderEventUtils {
using Order for Order.Props;
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 emitOrderCreated(
EventEmitter eventEmitter,
bytes32 key,
Order.Props memory order
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(6);
eventData.addressItems.setItem(0, "account", order.account());
eventData.addressItems.setItem(1, "receiver", order.receiver());
eventData.addressItems.setItem(2, "callbackContract", order.callbackContract());
eventData.addressItems.setItem(3, "uiFeeReceiver", order.uiFeeReceiver());
eventData.addressItems.setItem(4, "market", order.market());
eventData.addressItems.setItem(5, "initialCollateralToken", order.initialCollateralToken());
eventData.addressItems.initArrayItems(1);
eventData.addressItems.setItem(0, "swapPath", order.swapPath());
eventData.uintItems.initItems(10);
eventData.uintItems.setItem(0, "orderType", uint256(order.orderType()));
eventData.uintItems.setItem(1, "decreasePositionSwapType", uint256(order.decreasePositionSwapType()));
eventData.uintItems.setItem(2, "sizeDeltaUsd", order.sizeDeltaUsd());
eventData.uintItems.setItem(3, "initialCollateralDeltaAmount", order.initialCollateralDeltaAmount());
eventData.uintItems.setItem(4, "triggerPrice", order.triggerPrice());
eventData.uintItems.setItem(5, "acceptablePrice", order.acceptablePrice());
eventData.uintItems.setItem(6, "executionFee", order.executionFee());
eventData.uintItems.setItem(7, "callbackGasLimit", order.callbackGasLimit());
eventData.uintItems.setItem(8, "minOutputAmount", order.minOutputAmount());
eventData.uintItems.setItem(9, "updatedAtBlock", order.updatedAtBlock());
eventData.boolItems.initItems(3);
eventData.boolItems.setItem(0, "isLong", order.isLong());
eventData.boolItems.setItem(1, "shouldUnwrapNativeToken", order.shouldUnwrapNativeToken());
eventData.boolItems.setItem(2, "isFrozen", order.isFrozen());
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventEmitter.emitEventLog2(
"OrderCreated",
key,
Cast.toBytes32(order.account()),
eventData
);
}
function emitOrderExecuted(
EventEmitter eventEmitter,
bytes32 key,
address account,
Order.SecondaryOrderType secondaryOrderType
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.uintItems.initItems(1);
eventData.uintItems.setItem(0, "secondaryOrderType", uint256(secondaryOrderType));
eventEmitter.emitEventLog2(
"OrderExecuted",
key,
Cast.toBytes32(account),
eventData
);
}
function emitOrderUpdated(
EventEmitter eventEmitter,
bytes32 key,
address account,
uint256 sizeDeltaUsd,
uint256 acceptablePrice,
uint256 triggerPrice,
uint256 minOutputAmount
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.uintItems.initItems(4);
eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd);
eventData.uintItems.setItem(1, "acceptablePrice", acceptablePrice);
eventData.uintItems.setItem(2, "triggerPrice", triggerPrice);
eventData.uintItems.setItem(3, "minOutputAmount", minOutputAmount);
eventEmitter.emitEventLog2(
"OrderUpdated",
key,
Cast.toBytes32(account),
eventData
);
}
function emitOrderSizeDeltaAutoUpdated(
EventEmitter eventEmitter,
bytes32 key,
uint256 sizeDeltaUsd,
uint256 nextSizeDeltaUsd
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "sizeDeltaUsd", sizeDeltaUsd);
eventData.uintItems.setItem(1, "nextSizeDeltaUsd", nextSizeDeltaUsd);
eventEmitter.emitEventLog1(
"OrderSizeDeltaAutoUpdated",
key,
eventData
);
}
function emitOrderCollateralDeltaAmountAutoUpdated(
EventEmitter eventEmitter,
bytes32 key,
uint256 collateralDeltaAmount,
uint256 nextCollateralDeltaAmount
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "collateralDeltaAmount", collateralDeltaAmount);
eventData.uintItems.setItem(1, "nextCollateralDeltaAmount", nextCollateralDeltaAmount);
eventEmitter.emitEventLog1(
"OrderCollateralDeltaAmountAutoUpdated",
key,
eventData
);
}
function emitOrderCancelled(
EventEmitter eventEmitter,
bytes32 key,
address account,
string memory reason,
bytes memory reasonBytes
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.stringItems.initItems(1);
eventData.stringItems.setItem(0, "reason", reason);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
eventEmitter.emitEventLog2(
"OrderCancelled",
key,
Cast.toBytes32(account),
eventData
);
}
function emitOrderFrozen(
EventEmitter eventEmitter,
bytes32 key,
address account,
string memory reason,
bytes memory reasonBytes
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.stringItems.initItems(1);
eventData.stringItems.setItem(0, "reason", reason);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
eventEmitter.emitEventLog2(
"OrderFrozen",
key,
Cast.toBytes32(account),
eventData
);
}
}
文件 55 的 92:OrderStoreUtils.sol
pragma solidity ^0.8.0;
import "../data/Keys.sol";
import "../data/DataStore.sol";
import "./Order.sol";
library OrderStoreUtils {
using Order for Order.Props;
bytes32 public constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
bytes32 public constant RECEIVER = keccak256(abi.encode("RECEIVER"));
bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
bytes32 public constant MARKET = keccak256(abi.encode("MARKET"));
bytes32 public constant INITIAL_COLLATERAL_TOKEN = keccak256(abi.encode("INITIAL_COLLATERAL_TOKEN"));
bytes32 public constant SWAP_PATH = keccak256(abi.encode("SWAP_PATH"));
bytes32 public constant ORDER_TYPE = keccak256(abi.encode("ORDER_TYPE"));
bytes32 public constant DECREASE_POSITION_SWAP_TYPE = keccak256(abi.encode("DECREASE_POSITION_SWAP_TYPE"));
bytes32 public constant SIZE_DELTA_USD = keccak256(abi.encode("SIZE_DELTA_USD"));
bytes32 public constant INITIAL_COLLATERAL_DELTA_AMOUNT = keccak256(abi.encode("INITIAL_COLLATERAL_DELTA_AMOUNT"));
bytes32 public constant TRIGGER_PRICE = keccak256(abi.encode("TRIGGER_PRICE"));
bytes32 public constant ACCEPTABLE_PRICE = keccak256(abi.encode("ACCEPTABLE_PRICE"));
bytes32 public constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
bytes32 public constant MIN_OUTPUT_AMOUNT = keccak256(abi.encode("MIN_OUTPUT_AMOUNT"));
bytes32 public constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
bytes32 public constant IS_LONG = keccak256(abi.encode("IS_LONG"));
bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
bytes32 public constant IS_FROZEN = keccak256(abi.encode("IS_FROZEN"));
function get(DataStore dataStore, bytes32 key) external view returns (Order.Props memory) {
Order.Props memory order;
if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {
return order;
}
order.setAccount(dataStore.getAddress(
keccak256(abi.encode(key, ACCOUNT))
));
order.setReceiver(dataStore.getAddress(
keccak256(abi.encode(key, RECEIVER))
));
order.setCallbackContract(dataStore.getAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT))
));
order.setUiFeeReceiver(dataStore.getAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER))
));
order.setMarket(dataStore.getAddress(
keccak256(abi.encode(key, MARKET))
));
order.setInitialCollateralToken(dataStore.getAddress(
keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))
));
order.setSwapPath(dataStore.getAddressArray(
keccak256(abi.encode(key, SWAP_PATH))
));
order.setOrderType(Order.OrderType(dataStore.getUint(
keccak256(abi.encode(key, ORDER_TYPE))
)));
order.setDecreasePositionSwapType(Order.DecreasePositionSwapType(dataStore.getUint(
keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))
)));
order.setSizeDeltaUsd(dataStore.getUint(
keccak256(abi.encode(key, SIZE_DELTA_USD))
));
order.setInitialCollateralDeltaAmount(dataStore.getUint(
keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))
));
order.setTriggerPrice(dataStore.getUint(
keccak256(abi.encode(key, TRIGGER_PRICE))
));
order.setAcceptablePrice(dataStore.getUint(
keccak256(abi.encode(key, ACCEPTABLE_PRICE))
));
order.setExecutionFee(dataStore.getUint(
keccak256(abi.encode(key, EXECUTION_FEE))
));
order.setCallbackGasLimit(dataStore.getUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
));
order.setMinOutputAmount(dataStore.getUint(
keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))
));
order.setUpdatedAtBlock(dataStore.getUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK))
));
order.setIsLong(dataStore.getBool(
keccak256(abi.encode(key, IS_LONG))
));
order.setShouldUnwrapNativeToken(dataStore.getBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
));
order.setIsFrozen(dataStore.getBool(
keccak256(abi.encode(key, IS_FROZEN))
));
return order;
}
function set(DataStore dataStore, bytes32 key, Order.Props memory order) external {
dataStore.addBytes32(
Keys.ORDER_LIST,
key
);
dataStore.addBytes32(
Keys.accountOrderListKey(order.account()),
key
);
dataStore.setAddress(
keccak256(abi.encode(key, ACCOUNT)),
order.account()
);
dataStore.setAddress(
keccak256(abi.encode(key, RECEIVER)),
order.receiver()
);
dataStore.setAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT)),
order.callbackContract()
);
dataStore.setAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER)),
order.uiFeeReceiver()
);
dataStore.setAddress(
keccak256(abi.encode(key, MARKET)),
order.market()
);
dataStore.setAddress(
keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN)),
order.initialCollateralToken()
);
dataStore.setAddressArray(
keccak256(abi.encode(key, SWAP_PATH)),
order.swapPath()
);
dataStore.setUint(
keccak256(abi.encode(key, ORDER_TYPE)),
uint256(order.orderType())
);
dataStore.setUint(
keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE)),
uint256(order.decreasePositionSwapType())
);
dataStore.setUint(
keccak256(abi.encode(key, SIZE_DELTA_USD)),
order.sizeDeltaUsd()
);
dataStore.setUint(
keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT)),
order.initialCollateralDeltaAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, TRIGGER_PRICE)),
order.triggerPrice()
);
dataStore.setUint(
keccak256(abi.encode(key, ACCEPTABLE_PRICE)),
order.acceptablePrice()
);
dataStore.setUint(
keccak256(abi.encode(key, EXECUTION_FEE)),
order.executionFee()
);
dataStore.setUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
order.callbackGasLimit()
);
dataStore.setUint(
keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT)),
order.minOutputAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
order.updatedAtBlock()
);
dataStore.setBool(
keccak256(abi.encode(key, IS_LONG)),
order.isLong()
);
dataStore.setBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
order.shouldUnwrapNativeToken()
);
dataStore.setBool(
keccak256(abi.encode(key, IS_FROZEN)),
order.isFrozen()
);
}
function remove(DataStore dataStore, bytes32 key, address account) external {
if (!dataStore.containsBytes32(Keys.ORDER_LIST, key)) {
revert Errors.OrderNotFound(key);
}
dataStore.removeBytes32(
Keys.ORDER_LIST,
key
);
dataStore.removeBytes32(
Keys.accountOrderListKey(account),
key
);
dataStore.removeAddress(
keccak256(abi.encode(key, ACCOUNT))
);
dataStore.removeAddress(
keccak256(abi.encode(key, RECEIVER))
);
dataStore.removeAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT))
);
dataStore.removeAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER))
);
dataStore.removeAddress(
keccak256(abi.encode(key, MARKET))
);
dataStore.removeAddress(
keccak256(abi.encode(key, INITIAL_COLLATERAL_TOKEN))
);
dataStore.removeAddressArray(
keccak256(abi.encode(key, SWAP_PATH))
);
dataStore.removeUint(
keccak256(abi.encode(key, ORDER_TYPE))
);
dataStore.removeUint(
keccak256(abi.encode(key, DECREASE_POSITION_SWAP_TYPE))
);
dataStore.removeUint(
keccak256(abi.encode(key, SIZE_DELTA_USD))
);
dataStore.removeUint(
keccak256(abi.encode(key, INITIAL_COLLATERAL_DELTA_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, TRIGGER_PRICE))
);
dataStore.removeUint(
keccak256(abi.encode(key, ACCEPTABLE_PRICE))
);
dataStore.removeUint(
keccak256(abi.encode(key, EXECUTION_FEE))
);
dataStore.removeUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
);
dataStore.removeUint(
keccak256(abi.encode(key, MIN_OUTPUT_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK))
);
dataStore.removeBool(
keccak256(abi.encode(key, IS_LONG))
);
dataStore.removeBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
);
dataStore.removeBool(
keccak256(abi.encode(key, IS_FROZEN))
);
}
function getOrderCount(DataStore dataStore) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.ORDER_LIST);
}
function getOrderKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.ORDER_LIST, start, end);
}
function getAccountOrderCount(DataStore dataStore, address account) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.accountOrderListKey(account));
}
function getAccountOrderKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.accountOrderListKey(account), start, end);
}
}
文件 56 的 92:OrderVault.sol
pragma solidity ^0.8.0;
import "../bank/StrictBank.sol";
contract OrderVault is StrictBank {
constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
}
文件 57 的 92: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;
}
}
}
文件 58 的 92: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;
}
}
}
文件 59 的 92: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 increasedAtBlock;
uint256 decreasedAtBlock;
}
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 increasedAtBlock(Props memory props) internal pure returns (uint256) {
return props.numbers.increasedAtBlock;
}
function setIncreasedAtBlock(Props memory props, uint256 value) internal pure {
props.numbers.increasedAtBlock = value;
}
function decreasedAtBlock(Props memory props) internal pure returns (uint256) {
return props.numbers.decreasedAtBlock;
}
function setDecreasedAtBlock(Props memory props, uint256 value) internal pure {
props.numbers.decreasedAtBlock = 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;
}
}
文件 60 的 92:PositionPricingUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SignedMath.sol";
import "../market/MarketUtils.sol";
import "../utils/Precision.sol";
import "../utils/Calc.sol";
import "./PricingUtils.sol";
import "../referral/IReferralStorage.sol";
import "../referral/ReferralUtils.sol";
library PositionPricingUtils {
using SignedMath for int256;
using SafeCast for uint256;
using SafeCast for int256;
using Position for Position.Props;
using Price for Price.Props;
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;
struct GetPositionFeesParams {
DataStore dataStore;
IReferralStorage referralStorage;
Position.Props position;
Price.Props collateralTokenPrice;
bool forPositiveImpact;
address longToken;
address shortToken;
uint256 sizeDeltaUsd;
address uiFeeReceiver;
}
struct GetPriceImpactUsdParams {
DataStore dataStore;
Market.Props market;
int256 usdDelta;
bool isLong;
}
struct OpenInterestParams {
uint256 longOpenInterest;
uint256 shortOpenInterest;
uint256 nextLongOpenInterest;
uint256 nextShortOpenInterest;
}
struct PositionFees {
PositionReferralFees referral;
PositionFundingFees funding;
PositionBorrowingFees borrowing;
PositionUiFees ui;
Price.Props collateralTokenPrice;
uint256 positionFeeFactor;
uint256 protocolFeeAmount;
uint256 positionFeeReceiverFactor;
uint256 feeReceiverAmount;
uint256 feeAmountForPool;
uint256 positionFeeAmountForPool;
uint256 positionFeeAmount;
uint256 totalCostAmountExcludingFunding;
uint256 totalCostAmount;
}
struct PositionReferralFees {
bytes32 referralCode;
address affiliate;
address trader;
uint256 totalRebateFactor;
uint256 traderDiscountFactor;
uint256 totalRebateAmount;
uint256 traderDiscountAmount;
uint256 affiliateRewardAmount;
}
struct PositionBorrowingFees {
uint256 borrowingFeeUsd;
uint256 borrowingFeeAmount;
uint256 borrowingFeeReceiverFactor;
uint256 borrowingFeeAmountForFeeReceiver;
}
struct PositionFundingFees {
uint256 fundingFeeAmount;
uint256 claimableLongTokenAmount;
uint256 claimableShortTokenAmount;
uint256 latestFundingFeeAmountPerSize;
uint256 latestLongTokenClaimableFundingAmountPerSize;
uint256 latestShortTokenClaimableFundingAmountPerSize;
}
struct PositionUiFees {
address uiFeeReceiver;
uint256 uiFeeReceiverFactor;
uint256 uiFeeAmount;
}
function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) {
OpenInterestParams memory openInterestParams = getNextOpenInterest(params);
int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParams);
if (priceImpactUsd >= 0) { return priceImpactUsd; }
(bool hasVirtualInventory, int256 virtualInventory) = MarketUtils.getVirtualInventoryForPositions(params.dataStore, params.market.indexToken);
if (!hasVirtualInventory) { return priceImpactUsd; }
OpenInterestParams memory openInterestParamsForVirtualInventory = getNextOpenInterestForVirtualInventory(params, virtualInventory);
int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market.marketToken, openInterestParamsForVirtualInventory);
return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd;
}
function _getPriceImpactUsd(DataStore dataStore, address market, OpenInterestParams memory openInterestParams) internal view returns (int256) {
uint256 initialDiffUsd = Calc.diff(openInterestParams.longOpenInterest, openInterestParams.shortOpenInterest);
uint256 nextDiffUsd = Calc.diff(openInterestParams.nextLongOpenInterest, openInterestParams.nextShortOpenInterest);
bool isSameSideRebalance = openInterestParams.longOpenInterest <= openInterestParams.shortOpenInterest == openInterestParams.nextLongOpenInterest <= openInterestParams.nextShortOpenInterest;
uint256 impactExponentFactor = dataStore.getUint(Keys.positionImpactExponentFactorKey(market));
if (isSameSideRebalance) {
bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
uint256 impactFactor = MarketUtils.getAdjustedPositionImpactFactor(dataStore, market, hasPositiveImpact);
return PricingUtils.getPriceImpactUsdForSameSideRebalance(
initialDiffUsd,
nextDiffUsd,
impactFactor,
impactExponentFactor
);
} else {
(uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedPositionImpactFactors(dataStore, market);
return PricingUtils.getPriceImpactUsdForCrossoverRebalance(
initialDiffUsd,
nextDiffUsd,
positiveImpactFactor,
negativeImpactFactor,
impactExponentFactor
);
}
}
function getNextOpenInterest(
GetPriceImpactUsdParams memory params
) internal view returns (OpenInterestParams memory) {
uint256 longOpenInterest = MarketUtils.getOpenInterest(
params.dataStore,
params.market,
true
);
uint256 shortOpenInterest = MarketUtils.getOpenInterest(
params.dataStore,
params.market,
false
);
return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);
}
function getNextOpenInterestForVirtualInventory(
GetPriceImpactUsdParams memory params,
int256 virtualInventory
) internal pure returns (OpenInterestParams memory) {
uint256 longOpenInterest;
uint256 shortOpenInterest;
if (virtualInventory > 0) {
shortOpenInterest = virtualInventory.toUint256();
} else {
longOpenInterest = (-virtualInventory).toUint256();
}
if (params.usdDelta < 0) {
uint256 offset = (-params.usdDelta).toUint256();
longOpenInterest += offset;
shortOpenInterest += offset;
}
return getNextOpenInterestParams(params, longOpenInterest, shortOpenInterest);
}
function getNextOpenInterestParams(
GetPriceImpactUsdParams memory params,
uint256 longOpenInterest,
uint256 shortOpenInterest
) internal pure returns (OpenInterestParams memory) {
uint256 nextLongOpenInterest = longOpenInterest;
uint256 nextShortOpenInterest = shortOpenInterest;
if (params.isLong) {
if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > longOpenInterest) {
revert Errors.UsdDeltaExceedsLongOpenInterest(params.usdDelta, longOpenInterest);
}
nextLongOpenInterest = Calc.sumReturnUint256(longOpenInterest, params.usdDelta);
} else {
if (params.usdDelta < 0 && (-params.usdDelta).toUint256() > shortOpenInterest) {
revert Errors.UsdDeltaExceedsShortOpenInterest(params.usdDelta, shortOpenInterest);
}
nextShortOpenInterest = Calc.sumReturnUint256(shortOpenInterest, params.usdDelta);
}
OpenInterestParams memory openInterestParams = OpenInterestParams(
longOpenInterest,
shortOpenInterest,
nextLongOpenInterest,
nextShortOpenInterest
);
return openInterestParams;
}
function getPositionFees(
GetPositionFeesParams memory params
) internal view returns (PositionFees memory) {
PositionFees memory fees = getPositionFeesAfterReferral(
params.dataStore,
params.referralStorage,
params.collateralTokenPrice,
params.forPositiveImpact,
params.position.account(),
params.position.market(),
params.sizeDeltaUsd
);
uint256 borrowingFeeUsd = MarketUtils.getBorrowingFees(params.dataStore, params.position);
fees.borrowing = getBorrowingFees(
params.dataStore,
params.collateralTokenPrice,
borrowingFeeUsd
);
fees.feeAmountForPool = fees.positionFeeAmountForPool + fees.borrowing.borrowingFeeAmount - fees.borrowing.borrowingFeeAmountForFeeReceiver;
fees.feeReceiverAmount += fees.borrowing.borrowingFeeAmountForFeeReceiver;
fees.funding.latestFundingFeeAmountPerSize = MarketUtils.getFundingFeeAmountPerSize(
params.dataStore,
params.position.market(),
params.position.collateralToken(),
params.position.isLong()
);
fees.funding.latestLongTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
params.dataStore,
params.position.market(),
params.longToken,
params.position.isLong()
);
fees.funding.latestShortTokenClaimableFundingAmountPerSize = MarketUtils.getClaimableFundingAmountPerSize(
params.dataStore,
params.position.market(),
params.shortToken,
params.position.isLong()
);
fees.funding = getFundingFees(
fees.funding,
params.position
);
fees.ui = getUiFees(
params.dataStore,
params.collateralTokenPrice,
params.sizeDeltaUsd,
params.uiFeeReceiver
);
fees.totalCostAmountExcludingFunding =
fees.positionFeeAmount
+ fees.borrowing.borrowingFeeAmount
+ fees.ui.uiFeeAmount
- fees.referral.traderDiscountAmount;
fees.totalCostAmount =
fees.totalCostAmountExcludingFunding
+ fees.funding.fundingFeeAmount;
return fees;
}
function getBorrowingFees(
DataStore dataStore,
Price.Props memory collateralTokenPrice,
uint256 borrowingFeeUsd
) internal view returns (PositionBorrowingFees memory) {
PositionBorrowingFees memory borrowingFees;
borrowingFees.borrowingFeeUsd = borrowingFeeUsd;
borrowingFees.borrowingFeeAmount = borrowingFeeUsd / collateralTokenPrice.min;
borrowingFees.borrowingFeeReceiverFactor = dataStore.getUint(Keys.BORROWING_FEE_RECEIVER_FACTOR);
borrowingFees.borrowingFeeAmountForFeeReceiver = Precision.applyFactor(borrowingFees.borrowingFeeAmount, borrowingFees.borrowingFeeReceiverFactor);
return borrowingFees;
}
function getFundingFees(
PositionFundingFees memory fundingFees,
Position.Props memory position
) internal pure returns (PositionFundingFees memory) {
fundingFees.fundingFeeAmount = MarketUtils.getFundingAmount(
fundingFees.latestFundingFeeAmountPerSize,
position.fundingFeeAmountPerSize(),
position.sizeInUsd(),
true
);
fundingFees.claimableLongTokenAmount = MarketUtils.getFundingAmount(
fundingFees.latestLongTokenClaimableFundingAmountPerSize,
position.longTokenClaimableFundingAmountPerSize(),
position.sizeInUsd(),
false
);
fundingFees.claimableShortTokenAmount = MarketUtils.getFundingAmount(
fundingFees.latestShortTokenClaimableFundingAmountPerSize,
position.shortTokenClaimableFundingAmountPerSize(),
position.sizeInUsd(),
false
);
return fundingFees;
}
function getUiFees(
DataStore dataStore,
Price.Props memory collateralTokenPrice,
uint256 sizeDeltaUsd,
address uiFeeReceiver
) internal view returns (PositionUiFees memory) {
PositionUiFees memory uiFees;
if (uiFeeReceiver == address(0)) {
return uiFees;
}
uiFees.uiFeeReceiver = uiFeeReceiver;
uiFees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);
uiFees.uiFeeAmount = Precision.applyFactor(sizeDeltaUsd, uiFees.uiFeeReceiverFactor) / collateralTokenPrice.min;
return uiFees;
}
function getPositionFeesAfterReferral(
DataStore dataStore,
IReferralStorage referralStorage,
Price.Props memory collateralTokenPrice,
bool forPositiveImpact,
address account,
address market,
uint256 sizeDeltaUsd
) internal view returns (PositionFees memory) {
PositionFees memory fees;
fees.collateralTokenPrice = collateralTokenPrice;
fees.referral.trader = account;
(
fees.referral.referralCode,
fees.referral.affiliate,
fees.referral.totalRebateFactor,
fees.referral.traderDiscountFactor
) = ReferralUtils.getReferralInfo(referralStorage, account);
fees.positionFeeFactor = dataStore.getUint(Keys.positionFeeFactorKey(market, forPositiveImpact));
fees.positionFeeAmount = Precision.applyFactor(sizeDeltaUsd, fees.positionFeeFactor) / collateralTokenPrice.min;
fees.referral.totalRebateAmount = Precision.applyFactor(fees.positionFeeAmount, fees.referral.totalRebateFactor);
fees.referral.traderDiscountAmount = Precision.applyFactor(fees.referral.totalRebateAmount, fees.referral.traderDiscountFactor);
fees.referral.affiliateRewardAmount = fees.referral.totalRebateAmount - fees.referral.traderDiscountAmount;
fees.protocolFeeAmount = fees.positionFeeAmount - fees.referral.totalRebateAmount;
fees.positionFeeReceiverFactor = dataStore.getUint(Keys.POSITION_FEE_RECEIVER_FACTOR);
fees.feeReceiverAmount = Precision.applyFactor(fees.protocolFeeAmount, fees.positionFeeReceiverFactor);
fees.positionFeeAmountForPool = fees.protocolFeeAmount - fees.feeReceiverAmount;
return fees;
}
}
文件 61 的 92:PositionStoreUtils.sol
pragma solidity ^0.8.0;
import "../data/Keys.sol";
import "../data/DataStore.sol";
import "./Position.sol";
library PositionStoreUtils {
using Position for Position.Props;
bytes32 public constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
bytes32 public constant MARKET = keccak256(abi.encode("MARKET"));
bytes32 public constant COLLATERAL_TOKEN = keccak256(abi.encode("COLLATERAL_TOKEN"));
bytes32 public constant SIZE_IN_USD = keccak256(abi.encode("SIZE_IN_USD"));
bytes32 public constant SIZE_IN_TOKENS = keccak256(abi.encode("SIZE_IN_TOKENS"));
bytes32 public constant COLLATERAL_AMOUNT = keccak256(abi.encode("COLLATERAL_AMOUNT"));
bytes32 public constant BORROWING_FACTOR = keccak256(abi.encode("BORROWING_FACTOR"));
bytes32 public constant FUNDING_FEE_AMOUNT_PER_SIZE = keccak256(abi.encode("FUNDING_FEE_AMOUNT_PER_SIZE"));
bytes32 public constant LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
bytes32 public constant SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE = keccak256(abi.encode("SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE"));
bytes32 public constant INCREASED_AT_BLOCK = keccak256(abi.encode("INCREASED_AT_BLOCK"));
bytes32 public constant DECREASED_AT_BLOCK = keccak256(abi.encode("DECREASED_AT_BLOCK"));
bytes32 public constant IS_LONG = keccak256(abi.encode("IS_LONG"));
function get(DataStore dataStore, bytes32 key) external view returns (Position.Props memory) {
Position.Props memory position;
if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {
return position;
}
position.setAccount(dataStore.getAddress(
keccak256(abi.encode(key, ACCOUNT))
));
position.setMarket(dataStore.getAddress(
keccak256(abi.encode(key, MARKET))
));
position.setCollateralToken(dataStore.getAddress(
keccak256(abi.encode(key, COLLATERAL_TOKEN))
));
position.setSizeInUsd(dataStore.getUint(
keccak256(abi.encode(key, SIZE_IN_USD))
));
position.setSizeInTokens(dataStore.getUint(
keccak256(abi.encode(key, SIZE_IN_TOKENS))
));
position.setCollateralAmount(dataStore.getUint(
keccak256(abi.encode(key, COLLATERAL_AMOUNT))
));
position.setBorrowingFactor(dataStore.getUint(
keccak256(abi.encode(key, BORROWING_FACTOR))
));
position.setFundingFeeAmountPerSize(dataStore.getUint(
keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))
));
position.setLongTokenClaimableFundingAmountPerSize(dataStore.getUint(
keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
));
position.setShortTokenClaimableFundingAmountPerSize(dataStore.getUint(
keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
));
position.setIncreasedAtBlock(dataStore.getUint(
keccak256(abi.encode(key, INCREASED_AT_BLOCK))
));
position.setDecreasedAtBlock(dataStore.getUint(
keccak256(abi.encode(key, DECREASED_AT_BLOCK))
));
position.setIsLong(dataStore.getBool(
keccak256(abi.encode(key, IS_LONG))
));
return position;
}
function set(DataStore dataStore, bytes32 key, Position.Props memory position) external {
dataStore.addBytes32(
Keys.POSITION_LIST,
key
);
dataStore.addBytes32(
Keys.accountPositionListKey(position.account()),
key
);
dataStore.setAddress(
keccak256(abi.encode(key, ACCOUNT)),
position.account()
);
dataStore.setAddress(
keccak256(abi.encode(key, MARKET)),
position.market()
);
dataStore.setAddress(
keccak256(abi.encode(key, COLLATERAL_TOKEN)),
position.collateralToken()
);
dataStore.setUint(
keccak256(abi.encode(key, SIZE_IN_USD)),
position.sizeInUsd()
);
dataStore.setUint(
keccak256(abi.encode(key, SIZE_IN_TOKENS)),
position.sizeInTokens()
);
dataStore.setUint(
keccak256(abi.encode(key, COLLATERAL_AMOUNT)),
position.collateralAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, BORROWING_FACTOR)),
position.borrowingFactor()
);
dataStore.setUint(
keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE)),
position.fundingFeeAmountPerSize()
);
dataStore.setUint(
keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),
position.longTokenClaimableFundingAmountPerSize()
);
dataStore.setUint(
keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE)),
position.shortTokenClaimableFundingAmountPerSize()
);
dataStore.setUint(
keccak256(abi.encode(key, INCREASED_AT_BLOCK)),
position.increasedAtBlock()
);
dataStore.setUint(
keccak256(abi.encode(key, DECREASED_AT_BLOCK)),
position.decreasedAtBlock()
);
dataStore.setBool(
keccak256(abi.encode(key, IS_LONG)),
position.isLong()
);
}
function remove(DataStore dataStore, bytes32 key, address account) external {
if (!dataStore.containsBytes32(Keys.POSITION_LIST, key)) {
revert Errors.PositionNotFound(key);
}
dataStore.removeBytes32(
Keys.POSITION_LIST,
key
);
dataStore.removeBytes32(
Keys.accountPositionListKey(account),
key
);
dataStore.removeAddress(
keccak256(abi.encode(key, ACCOUNT))
);
dataStore.removeAddress(
keccak256(abi.encode(key, MARKET))
);
dataStore.removeAddress(
keccak256(abi.encode(key, COLLATERAL_TOKEN))
);
dataStore.removeUint(
keccak256(abi.encode(key, SIZE_IN_USD))
);
dataStore.removeUint(
keccak256(abi.encode(key, SIZE_IN_TOKENS))
);
dataStore.removeUint(
keccak256(abi.encode(key, COLLATERAL_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, BORROWING_FACTOR))
);
dataStore.removeUint(
keccak256(abi.encode(key, FUNDING_FEE_AMOUNT_PER_SIZE))
);
dataStore.removeUint(
keccak256(abi.encode(key, LONG_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
);
dataStore.removeUint(
keccak256(abi.encode(key, SHORT_TOKEN_CLAIMABLE_FUNDING_AMOUNT_PER_SIZE))
);
dataStore.removeUint(
keccak256(abi.encode(key, INCREASED_AT_BLOCK))
);
dataStore.removeUint(
keccak256(abi.encode(key, DECREASED_AT_BLOCK))
);
dataStore.removeBool(
keccak256(abi.encode(key, IS_LONG))
);
}
function getPositionCount(DataStore dataStore) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.POSITION_LIST);
}
function getPositionKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.POSITION_LIST, start, end);
}
function getAccountPositionCount(DataStore dataStore, address account) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.accountPositionListKey(account));
}
function getAccountPositionKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.accountPositionListKey(account), start, end);
}
}
文件 62 的 92:PositionUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../utils/Precision.sol";
import "./Position.sol";
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../pricing/PositionPricingUtils.sol";
import "../order/BaseOrderUtils.sol";
library PositionUtils {
using SafeCast for uint256;
using SafeCast for int256;
using Price for Price.Props;
using Position for Position.Props;
using Order for Order.Props;
struct UpdatePositionParams {
BaseOrderUtils.ExecuteOrderParamsContracts contracts;
Market.Props market;
Order.Props order;
bytes32 orderKey;
Position.Props position;
bytes32 positionKey;
Order.SecondaryOrderType secondaryOrderType;
}
struct UpdatePositionParamsContracts {
DataStore dataStore;
EventEmitter eventEmitter;
Oracle oracle;
SwapHandler swapHandler;
IReferralStorage referralStorage;
}
struct WillPositionCollateralBeSufficientValues {
uint256 positionSizeInUsd;
uint256 positionCollateralAmount;
int256 realizedPnlUsd;
int256 openInterestDelta;
}
struct DecreasePositionCollateralValuesOutput {
address outputToken;
uint256 outputAmount;
address secondaryOutputToken;
uint256 secondaryOutputAmount;
}
struct DecreasePositionCollateralValues {
uint256 executionPrice;
uint256 remainingCollateralAmount;
int256 basePnlUsd;
int256 uncappedBasePnlUsd;
uint256 sizeDeltaInTokens;
int256 priceImpactUsd;
uint256 priceImpactDiffUsd;
DecreasePositionCollateralValuesOutput output;
}
struct DecreasePositionCache {
MarketUtils.MarketPrices prices;
int256 estimatedPositionPnlUsd;
int256 estimatedRealizedPnlUsd;
int256 estimatedRemainingPnlUsd;
address pnlToken;
Price.Props pnlTokenPrice;
Price.Props collateralTokenPrice;
uint256 initialCollateralAmount;
uint256 nextPositionSizeInUsd;
uint256 nextPositionBorrowingFactor;
}
struct GetPositionPnlUsdCache {
int256 positionValue;
int256 totalPositionPnl;
int256 uncappedTotalPositionPnl;
address pnlToken;
uint256 poolTokenAmount;
uint256 poolTokenPrice;
uint256 poolTokenUsd;
int256 poolPnl;
int256 cappedPoolPnl;
uint256 sizeDeltaInTokens;
int256 positionPnlUsd;
int256 uncappedPositionPnlUsd;
}
struct IsPositionLiquidatableInfo {
int256 remainingCollateralUsd;
int256 minCollateralUsd;
int256 minCollateralUsdForLeverage;
}
struct IsPositionLiquidatableCache {
int256 positionPnlUsd;
uint256 minCollateralFactor;
Price.Props collateralTokenPrice;
uint256 collateralUsd;
int256 usdDeltaForPriceImpact;
int256 priceImpactUsd;
bool hasPositiveImpact;
}
struct GetExecutionPriceForDecreaseCache {
int256 priceImpactUsd;
uint256 priceImpactDiffUsd;
uint256 executionPrice;
}
function getPositionPnlUsd(
DataStore dataStore,
Market.Props memory market,
MarketUtils.MarketPrices memory prices,
Position.Props memory position,
uint256 sizeDeltaUsd
) public view returns (int256, int256, uint256) {
GetPositionPnlUsdCache memory cache;
uint256 executionPrice = prices.indexTokenPrice.pickPriceForPnl(position.isLong(), false);
cache.positionValue = (position.sizeInTokens() * executionPrice).toInt256();
cache.totalPositionPnl = position.isLong() ? cache.positionValue - position.sizeInUsd().toInt256() : position.sizeInUsd().toInt256() - cache.positionValue;
cache.uncappedTotalPositionPnl = cache.totalPositionPnl;
if (cache.totalPositionPnl > 0) {
cache.pnlToken = position.isLong() ? market.longToken : market.shortToken;
cache.poolTokenAmount = MarketUtils.getPoolAmount(dataStore, market, cache.pnlToken);
cache.poolTokenPrice = position.isLong() ? prices.longTokenPrice.min : prices.shortTokenPrice.min;
cache.poolTokenUsd = cache.poolTokenAmount * cache.poolTokenPrice;
cache.poolPnl = MarketUtils.getPnl(
dataStore,
market,
prices.indexTokenPrice,
position.isLong(),
true
);
cache.cappedPoolPnl = MarketUtils.getCappedPnl(
dataStore,
market.marketToken,
position.isLong(),
cache.poolPnl,
cache.poolTokenUsd,
Keys.MAX_PNL_FACTOR_FOR_TRADERS
);
if (cache.cappedPoolPnl != cache.poolPnl && cache.cappedPoolPnl > 0 && cache.poolPnl > 0) {
cache.totalPositionPnl = Precision.mulDiv(cache.totalPositionPnl.toUint256(), cache.cappedPoolPnl, cache.poolPnl.toUint256());
}
}
if (position.sizeInUsd() == sizeDeltaUsd) {
cache.sizeDeltaInTokens = position.sizeInTokens();
} else {
if (position.isLong()) {
cache.sizeDeltaInTokens = Calc.roundUpDivision(position.sizeInTokens() * sizeDeltaUsd, position.sizeInUsd());
} else {
cache.sizeDeltaInTokens = position.sizeInTokens() * sizeDeltaUsd / position.sizeInUsd();
}
}
cache.positionPnlUsd = Precision.mulDiv(cache.totalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());
cache.uncappedPositionPnlUsd = Precision.mulDiv(cache.uncappedTotalPositionPnl, cache.sizeDeltaInTokens, position.sizeInTokens());
return (cache.positionPnlUsd, cache.uncappedPositionPnlUsd, cache.sizeDeltaInTokens);
}
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;
}
function validateNonEmptyPosition(Position.Props memory position) internal pure {
if (position.sizeInUsd() == 0 && position.sizeInTokens() == 0 && position.collateralAmount() == 0) {
revert Errors.EmptyPosition();
}
}
function validatePosition(
DataStore dataStore,
IReferralStorage referralStorage,
Position.Props memory position,
Market.Props memory market,
MarketUtils.MarketPrices memory prices,
bool shouldValidateMinPositionSize,
bool shouldValidateMinCollateralUsd
) public view {
if (position.sizeInUsd() == 0 || position.sizeInTokens() == 0) {
revert Errors.InvalidPositionSizeValues(position.sizeInUsd(), position.sizeInTokens());
}
MarketUtils.validateEnabledMarket(dataStore, market.marketToken);
MarketUtils.validateMarketCollateralToken(market, position.collateralToken());
if (shouldValidateMinPositionSize) {
uint256 minPositionSizeUsd = dataStore.getUint(Keys.MIN_POSITION_SIZE_USD);
if (position.sizeInUsd() < minPositionSizeUsd) {
revert Errors.MinPositionSize(position.sizeInUsd(), minPositionSizeUsd);
}
}
(bool isLiquidatable, string memory reason, IsPositionLiquidatableInfo memory info) = isPositionLiquidatable(
dataStore,
referralStorage,
position,
market,
prices,
shouldValidateMinCollateralUsd
);
if (isLiquidatable) {
revert Errors.LiquidatablePosition(
reason,
info.remainingCollateralUsd,
info.minCollateralUsd,
info.minCollateralUsdForLeverage
);
}
}
function isPositionLiquidatable(
DataStore dataStore,
IReferralStorage referralStorage,
Position.Props memory position,
Market.Props memory market,
MarketUtils.MarketPrices memory prices,
bool shouldValidateMinCollateralUsd
) public view returns (bool, string memory, IsPositionLiquidatableInfo memory) {
IsPositionLiquidatableCache memory cache;
IsPositionLiquidatableInfo memory info;
(cache.positionPnlUsd, , ) = getPositionPnlUsd(
dataStore,
market,
prices,
position,
position.sizeInUsd()
);
cache.collateralTokenPrice = MarketUtils.getCachedTokenPrice(
position.collateralToken(),
market,
prices
);
cache.collateralUsd = position.collateralAmount() * cache.collateralTokenPrice.min;
cache.usdDeltaForPriceImpact = -position.sizeInUsd().toInt256();
cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
PositionPricingUtils.GetPriceImpactUsdParams(
dataStore,
market,
cache.usdDeltaForPriceImpact,
position.isLong()
)
);
cache.hasPositiveImpact = cache.priceImpactUsd > 0;
if (cache.priceImpactUsd >= 0) {
cache.priceImpactUsd = 0;
} else {
uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactorForLiquidations(
dataStore,
market.marketToken
);
int256 maxNegativePriceImpactUsd = -Precision.applyFactor(position.sizeInUsd(), maxPriceImpactFactor).toInt256();
if (cache.priceImpactUsd < maxNegativePriceImpactUsd) {
cache.priceImpactUsd = maxNegativePriceImpactUsd;
}
}
PositionPricingUtils.GetPositionFeesParams memory getPositionFeesParams = PositionPricingUtils.GetPositionFeesParams(
dataStore,
referralStorage,
position,
cache.collateralTokenPrice,
cache.hasPositiveImpact,
market.longToken,
market.shortToken,
position.sizeInUsd(),
address(0)
);
PositionPricingUtils.PositionFees memory fees = PositionPricingUtils.getPositionFees(getPositionFeesParams);
uint256 collateralCostUsd = fees.totalCostAmount * cache.collateralTokenPrice.min;
info.remainingCollateralUsd =
cache.collateralUsd.toInt256()
+ cache.positionPnlUsd
+ cache.priceImpactUsd
- collateralCostUsd.toInt256();
cache.minCollateralFactor = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);
info.minCollateralUsdForLeverage = Precision.applyFactor(position.sizeInUsd(), cache.minCollateralFactor).toInt256();
if (shouldValidateMinCollateralUsd) {
info.minCollateralUsd = dataStore.getUint(Keys.MIN_COLLATERAL_USD).toInt256();
if (info.remainingCollateralUsd < info.minCollateralUsd) {
return (true, "min collateral", info);
}
}
if (info.remainingCollateralUsd <= 0) {
return (true, "< 0", info);
}
if (info.remainingCollateralUsd < info.minCollateralUsdForLeverage) {
return (true, "min collateral for leverage", info);
}
return (false, "", info);
}
function willPositionCollateralBeSufficient(
DataStore dataStore,
Market.Props memory market,
MarketUtils.MarketPrices memory prices,
address collateralToken,
bool isLong,
WillPositionCollateralBeSufficientValues memory values
) public view returns (bool, int256) {
Price.Props memory collateralTokenPrice = MarketUtils.getCachedTokenPrice(
collateralToken,
market,
prices
);
int256 remainingCollateralUsd = values.positionCollateralAmount.toInt256() * collateralTokenPrice.min.toInt256();
if (values.realizedPnlUsd < 0) {
remainingCollateralUsd = remainingCollateralUsd + values.realizedPnlUsd;
}
if (remainingCollateralUsd < 0) {
return (false, remainingCollateralUsd);
}
uint256 minCollateralFactor = MarketUtils.getMinCollateralFactorForOpenInterest(
dataStore,
market,
values.openInterestDelta,
isLong
);
uint256 minCollateralFactorForMarket = MarketUtils.getMinCollateralFactor(dataStore, market.marketToken);
if (minCollateralFactorForMarket > minCollateralFactor) {
minCollateralFactor = minCollateralFactorForMarket;
}
int256 minCollateralUsdForLeverage = Precision.applyFactor(values.positionSizeInUsd, minCollateralFactor).toInt256();
bool willBeSufficient = remainingCollateralUsd >= minCollateralUsdForLeverage;
return (willBeSufficient, remainingCollateralUsd);
}
function updateFundingAndBorrowingState(
PositionUtils.UpdatePositionParams memory params,
MarketUtils.MarketPrices memory prices
) internal {
MarketUtils.updateFundingState(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market,
prices
);
MarketUtils.updateCumulativeBorrowingFactor(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market,
prices,
true
);
MarketUtils.updateCumulativeBorrowingFactor(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market,
prices,
false
);
}
function updateTotalBorrowing(
PositionUtils.UpdatePositionParams memory params,
uint256 nextPositionSizeInUsd,
uint256 nextPositionBorrowingFactor
) internal {
MarketUtils.updateTotalBorrowing(
params.contracts.dataStore,
params.market.marketToken,
params.position.isLong(),
params.position.sizeInUsd(),
params.position.borrowingFactor(),
nextPositionSizeInUsd,
nextPositionBorrowingFactor
);
}
function incrementClaimableFundingAmount(
PositionUtils.UpdatePositionParams memory params,
PositionPricingUtils.PositionFees memory fees
) internal {
if (fees.funding.claimableLongTokenAmount > 0) {
MarketUtils.incrementClaimableFundingAmount(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market.marketToken,
params.market.longToken,
params.order.account(),
fees.funding.claimableLongTokenAmount
);
}
if (fees.funding.claimableShortTokenAmount > 0) {
MarketUtils.incrementClaimableFundingAmount(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market.marketToken,
params.market.shortToken,
params.order.account(),
fees.funding.claimableShortTokenAmount
);
}
}
function updateOpenInterest(
PositionUtils.UpdatePositionParams memory params,
int256 sizeDeltaUsd,
int256 sizeDeltaInTokens
) internal {
if (sizeDeltaUsd != 0) {
MarketUtils.applyDeltaToOpenInterest(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.market,
params.position.collateralToken(),
params.position.isLong(),
sizeDeltaUsd
);
MarketUtils.applyDeltaToOpenInterestInTokens(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.position.market(),
params.position.collateralToken(),
params.position.isLong(),
sizeDeltaInTokens
);
}
}
function handleReferral(
PositionUtils.UpdatePositionParams memory params,
PositionPricingUtils.PositionFees memory fees
) internal {
ReferralUtils.incrementAffiliateReward(
params.contracts.dataStore,
params.contracts.eventEmitter,
params.position.market(),
params.position.collateralToken(),
fees.referral.affiliate,
fees.referral.affiliateRewardAmount
);
}
function getExecutionPriceForIncrease(
UpdatePositionParams memory params,
Price.Props memory indexTokenPrice
) external view returns (int256, int256, uint256, uint256) {
if (params.order.sizeDeltaUsd() == 0) {
return (0, 0, 0, indexTokenPrice.pickPrice(params.position.isLong()));
}
int256 priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
PositionPricingUtils.GetPriceImpactUsdParams(
params.contracts.dataStore,
params.market,
params.order.sizeDeltaUsd().toInt256(),
params.order.isLong()
)
);
priceImpactUsd = MarketUtils.getCappedPositionImpactUsd(
params.contracts.dataStore,
params.market.marketToken,
indexTokenPrice,
priceImpactUsd,
params.order.sizeDeltaUsd()
);
int256 priceImpactAmount;
if (priceImpactUsd > 0) {
priceImpactAmount = priceImpactUsd / indexTokenPrice.max.toInt256();
} else {
priceImpactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, indexTokenPrice.min);
}
uint256 baseSizeDeltaInTokens;
if (params.position.isLong()) {
baseSizeDeltaInTokens = params.order.sizeDeltaUsd() / indexTokenPrice.max;
} else {
baseSizeDeltaInTokens = Calc.roundUpDivision(params.order.sizeDeltaUsd(), indexTokenPrice.min);
}
int256 sizeDeltaInTokens;
if (params.position.isLong()) {
sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() + priceImpactAmount;
} else {
sizeDeltaInTokens = baseSizeDeltaInTokens.toInt256() - priceImpactAmount;
}
if (sizeDeltaInTokens < 0) {
revert Errors.PriceImpactLargerThanOrderSize(priceImpactUsd, params.order.sizeDeltaUsd());
}
uint256 executionPrice = BaseOrderUtils.getExecutionPriceForIncrease(
params.order.sizeDeltaUsd(),
sizeDeltaInTokens.toUint256(),
params.order.acceptablePrice(),
params.position.isLong()
);
return (priceImpactUsd, priceImpactAmount, sizeDeltaInTokens.toUint256(), executionPrice);
}
function getExecutionPriceForDecrease(
UpdatePositionParams memory params,
Price.Props memory indexTokenPrice
) external view returns (int256, uint256, uint256) {
uint256 sizeDeltaUsd = params.order.sizeDeltaUsd();
if (sizeDeltaUsd == 0) {
return (0, 0, indexTokenPrice.pickPrice(!params.position.isLong()));
}
GetExecutionPriceForDecreaseCache memory cache;
cache.priceImpactUsd = PositionPricingUtils.getPriceImpactUsd(
PositionPricingUtils.GetPriceImpactUsdParams(
params.contracts.dataStore,
params.market,
-sizeDeltaUsd.toInt256(),
params.order.isLong()
)
);
cache.priceImpactUsd = MarketUtils.getCappedPositionImpactUsd(
params.contracts.dataStore,
params.market.marketToken,
indexTokenPrice,
cache.priceImpactUsd,
sizeDeltaUsd
);
if (cache.priceImpactUsd < 0) {
uint256 maxPriceImpactFactor = MarketUtils.getMaxPositionImpactFactor(
params.contracts.dataStore,
params.market.marketToken,
false
);
int256 minPriceImpactUsd = -Precision.applyFactor(sizeDeltaUsd, maxPriceImpactFactor).toInt256();
if (cache.priceImpactUsd < minPriceImpactUsd) {
cache.priceImpactDiffUsd = (minPriceImpactUsd - cache.priceImpactUsd).toUint256();
cache.priceImpactUsd = minPriceImpactUsd;
}
}
cache.executionPrice = BaseOrderUtils.getExecutionPriceForDecrease(
indexTokenPrice,
params.position.sizeInUsd(),
params.position.sizeInTokens(),
sizeDeltaUsd,
cache.priceImpactUsd,
params.order.acceptablePrice(),
params.position.isLong()
);
return (cache.priceImpactUsd, cache.priceImpactDiffUsd, cache.executionPrice);
}
}
文件 63 的 92: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/SafeMath.sol";
import "@openzeppelin/contracts/utils/math/SignedMath.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "./Calc.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;
}
}
文件 64 的 92: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;
}
}
文件 65 的 92:PricingUtils.sol
pragma solidity ^0.8.0;
import "prb-math/contracts/PRBMathUD60x18.sol";
import "../utils/Calc.sol";
import "../utils/Precision.sol";
import "../market/MarketUtils.sol";
library PricingUtils {
function getPriceImpactUsdForSameSideRebalance(
uint256 initialDiffUsd,
uint256 nextDiffUsd,
uint256 impactFactor,
uint256 impactExponentFactor
) internal pure returns (int256) {
bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
uint256 deltaDiffUsd = Calc.diff(
applyImpactFactor(initialDiffUsd, impactFactor, impactExponentFactor),
applyImpactFactor(nextDiffUsd, impactFactor, impactExponentFactor)
);
int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, hasPositiveImpact);
return priceImpactUsd;
}
function getPriceImpactUsdForCrossoverRebalance(
uint256 initialDiffUsd,
uint256 nextDiffUsd,
uint256 positiveImpactFactor,
uint256 negativeImpactFactor,
uint256 impactExponentFactor
) internal pure returns (int256) {
uint256 positiveImpactUsd = applyImpactFactor(initialDiffUsd, positiveImpactFactor, impactExponentFactor);
uint256 negativeImpactUsd = applyImpactFactor(nextDiffUsd, negativeImpactFactor, impactExponentFactor);
uint256 deltaDiffUsd = Calc.diff(positiveImpactUsd, negativeImpactUsd);
int256 priceImpactUsd = Calc.toSigned(deltaDiffUsd, positiveImpactUsd > negativeImpactUsd);
return priceImpactUsd;
}
function applyImpactFactor(
uint256 diffUsd,
uint256 impactFactor,
uint256 impactExponentFactor
) internal pure returns (uint256) {
uint256 exponentValue = Precision.applyExponentFactor(diffUsd, impactExponentFactor);
return Precision.applyFactor(exponentValue, impactFactor);
}
}
文件 66 的 92:Printer.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "hardhat/console.sol";
library Printer {
using SafeCast for int256;
function log(string memory label, int256 value) internal view {
if (value < 0) {
console.log(
"%s -%s",
label,
(-value).toUint256()
);
} else {
console.log(
"%s +%s",
label,
value.toUint256()
);
}
}
}
文件 67 的 92: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() {
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
_status = _ENTERED;
_;
_status = _NOT_ENTERED;
}
}
文件 68 的 92:ReferralEventUtils.sol
pragma solidity ^0.8.0;
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Cast.sol";
library ReferralEventUtils {
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 emitAffiliateRewardUpdated(
EventEmitter eventEmitter,
address market,
address token,
address affiliate,
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, "affiliate", affiliate);
eventData.uintItems.initItems(3);
eventData.uintItems.setItem(0, "delta", delta);
eventData.uintItems.setItem(1, "nextValue", nextValue);
eventData.uintItems.setItem(2, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog2(
"AffiliateRewardUpdated",
Cast.toBytes32(market),
Cast.toBytes32(affiliate),
eventData
);
}
function emitAffiliateRewardClaimed(
EventEmitter eventEmitter,
address market,
address token,
address affiliate,
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, "affiliate", affiliate);
eventData.addressItems.setItem(3, "receiver", receiver);
eventData.uintItems.initItems(2);
eventData.uintItems.setItem(0, "amount", amount);
eventData.uintItems.setItem(1, "nextPoolValue", nextPoolValue);
eventEmitter.emitEventLog1(
"AffiliateRewardClaimed",
Cast.toBytes32(affiliate),
eventData
);
}
}
文件 69 的 92:ReferralTier.sol
pragma solidity ^0.8.0;
library ReferralTier {
struct Props {
uint256 totalRebate;
uint256 discountShare;
}
}
文件 70 的 92:ReferralUtils.sol
pragma solidity ^0.8.0;
import "../data/DataStore.sol";
import "../data/Keys.sol";
import "../event/EventEmitter.sol";
import "../market/MarketToken.sol";
import "../market/MarketUtils.sol";
import "./IReferralStorage.sol";
import "./ReferralTier.sol";
import "./ReferralEventUtils.sol";
import "../utils/Precision.sol";
library ReferralUtils {
function setTraderReferralCode(
IReferralStorage referralStorage,
address account,
bytes32 referralCode
) internal {
if (referralCode == bytes32(0)) { return; }
if (referralStorage.traderReferralCodes(account) != bytes32(0)) { return; }
referralStorage.setTraderReferralCode(account, referralCode);
}
function incrementAffiliateReward(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address affiliate,
uint256 delta
) internal {
if (delta == 0) { return; }
uint256 nextValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token, affiliate), delta);
uint256 nextPoolValue = dataStore.incrementUint(Keys.affiliateRewardKey(market, token), delta);
ReferralEventUtils.emitAffiliateRewardUpdated(
eventEmitter,
market,
token,
affiliate,
delta,
nextValue,
nextPoolValue
);
}
function getReferralInfo(
IReferralStorage referralStorage,
address trader
) internal view returns (bytes32, address, uint256, uint256) {
bytes32 code = referralStorage.traderReferralCodes(trader);
address affiliate;
uint256 totalRebate;
uint256 discountShare;
if (code != bytes32(0)) {
affiliate = referralStorage.codeOwners(code);
uint256 referralTierLevel = referralStorage.referrerTiers(affiliate);
(totalRebate, discountShare) = referralStorage.tiers(referralTierLevel);
uint256 customDiscountShare = referralStorage.referrerDiscountShares(affiliate);
if (customDiscountShare != 0) {
discountShare = customDiscountShare;
}
}
return (
code,
affiliate,
Precision.basisPointsToFloat(totalRebate),
Precision.basisPointsToFloat(discountShare)
);
}
function claimAffiliateReward(
DataStore dataStore,
EventEmitter eventEmitter,
address market,
address token,
address account,
address receiver
) external returns (uint256) {
bytes32 key = Keys.affiliateRewardKey(market, token, account);
uint256 rewardAmount = dataStore.getUint(key);
dataStore.setUint(key, 0);
uint256 nextPoolValue = dataStore.decrementUint(Keys.affiliateRewardKey(market, token), rewardAmount);
MarketToken(payable(market)).transferOut(
token,
receiver,
rewardAmount
);
MarketUtils.validateMarketTokenBalance(dataStore, market);
ReferralEventUtils.emitAffiliateRewardClaimed(
eventEmitter,
market,
token,
account,
receiver,
rewardAmount,
nextPoolValue
);
return rewardAmount;
}
}
文件 71 的 92: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 CONTROLLER = keccak256(abi.encode("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 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"));
}
文件 72 的 92: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 onlyController() {
_validateRole(Role.CONTROLLER, "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 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");
_;
}
function _validateRole(bytes32 role, string memory roleName) internal view {
if (!roleStore.hasRole(msg.sender, role)) {
revert Errors.Unauthorized(msg.sender, roleName);
}
}
}
文件 73 的 92: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();
}
}
}
}
文件 74 的 92: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) {
require(value >= type(int248).min && value <= type(int248).max, "SafeCast: value doesn't fit in 248 bits");
return int248(value);
}
function toInt240(int256 value) internal pure returns (int240) {
require(value >= type(int240).min && value <= type(int240).max, "SafeCast: value doesn't fit in 240 bits");
return int240(value);
}
function toInt232(int256 value) internal pure returns (int232) {
require(value >= type(int232).min && value <= type(int232).max, "SafeCast: value doesn't fit in 232 bits");
return int232(value);
}
function toInt224(int256 value) internal pure returns (int224) {
require(value >= type(int224).min && value <= type(int224).max, "SafeCast: value doesn't fit in 224 bits");
return int224(value);
}
function toInt216(int256 value) internal pure returns (int216) {
require(value >= type(int216).min && value <= type(int216).max, "SafeCast: value doesn't fit in 216 bits");
return int216(value);
}
function toInt208(int256 value) internal pure returns (int208) {
require(value >= type(int208).min && value <= type(int208).max, "SafeCast: value doesn't fit in 208 bits");
return int208(value);
}
function toInt200(int256 value) internal pure returns (int200) {
require(value >= type(int200).min && value <= type(int200).max, "SafeCast: value doesn't fit in 200 bits");
return int200(value);
}
function toInt192(int256 value) internal pure returns (int192) {
require(value >= type(int192).min && value <= type(int192).max, "SafeCast: value doesn't fit in 192 bits");
return int192(value);
}
function toInt184(int256 value) internal pure returns (int184) {
require(value >= type(int184).min && value <= type(int184).max, "SafeCast: value doesn't fit in 184 bits");
return int184(value);
}
function toInt176(int256 value) internal pure returns (int176) {
require(value >= type(int176).min && value <= type(int176).max, "SafeCast: value doesn't fit in 176 bits");
return int176(value);
}
function toInt168(int256 value) internal pure returns (int168) {
require(value >= type(int168).min && value <= type(int168).max, "SafeCast: value doesn't fit in 168 bits");
return int168(value);
}
function toInt160(int256 value) internal pure returns (int160) {
require(value >= type(int160).min && value <= type(int160).max, "SafeCast: value doesn't fit in 160 bits");
return int160(value);
}
function toInt152(int256 value) internal pure returns (int152) {
require(value >= type(int152).min && value <= type(int152).max, "SafeCast: value doesn't fit in 152 bits");
return int152(value);
}
function toInt144(int256 value) internal pure returns (int144) {
require(value >= type(int144).min && value <= type(int144).max, "SafeCast: value doesn't fit in 144 bits");
return int144(value);
}
function toInt136(int256 value) internal pure returns (int136) {
require(value >= type(int136).min && value <= type(int136).max, "SafeCast: value doesn't fit in 136 bits");
return int136(value);
}
function toInt128(int256 value) internal pure returns (int128) {
require(value >= type(int128).min && value <= type(int128).max, "SafeCast: value doesn't fit in 128 bits");
return int128(value);
}
function toInt120(int256 value) internal pure returns (int120) {
require(value >= type(int120).min && value <= type(int120).max, "SafeCast: value doesn't fit in 120 bits");
return int120(value);
}
function toInt112(int256 value) internal pure returns (int112) {
require(value >= type(int112).min && value <= type(int112).max, "SafeCast: value doesn't fit in 112 bits");
return int112(value);
}
function toInt104(int256 value) internal pure returns (int104) {
require(value >= type(int104).min && value <= type(int104).max, "SafeCast: value doesn't fit in 104 bits");
return int104(value);
}
function toInt96(int256 value) internal pure returns (int96) {
require(value >= type(int96).min && value <= type(int96).max, "SafeCast: value doesn't fit in 96 bits");
return int96(value);
}
function toInt88(int256 value) internal pure returns (int88) {
require(value >= type(int88).min && value <= type(int88).max, "SafeCast: value doesn't fit in 88 bits");
return int88(value);
}
function toInt80(int256 value) internal pure returns (int80) {
require(value >= type(int80).min && value <= type(int80).max, "SafeCast: value doesn't fit in 80 bits");
return int80(value);
}
function toInt72(int256 value) internal pure returns (int72) {
require(value >= type(int72).min && value <= type(int72).max, "SafeCast: value doesn't fit in 72 bits");
return int72(value);
}
function toInt64(int256 value) internal pure returns (int64) {
require(value >= type(int64).min && value <= type(int64).max, "SafeCast: value doesn't fit in 64 bits");
return int64(value);
}
function toInt56(int256 value) internal pure returns (int56) {
require(value >= type(int56).min && value <= type(int56).max, "SafeCast: value doesn't fit in 56 bits");
return int56(value);
}
function toInt48(int256 value) internal pure returns (int48) {
require(value >= type(int48).min && value <= type(int48).max, "SafeCast: value doesn't fit in 48 bits");
return int48(value);
}
function toInt40(int256 value) internal pure returns (int40) {
require(value >= type(int40).min && value <= type(int40).max, "SafeCast: value doesn't fit in 40 bits");
return int40(value);
}
function toInt32(int256 value) internal pure returns (int32) {
require(value >= type(int32).min && value <= type(int32).max, "SafeCast: value doesn't fit in 32 bits");
return int32(value);
}
function toInt24(int256 value) internal pure returns (int24) {
require(value >= type(int24).min && value <= type(int24).max, "SafeCast: value doesn't fit in 24 bits");
return int24(value);
}
function toInt16(int256 value) internal pure returns (int16) {
require(value >= type(int16).min && value <= type(int16).max, "SafeCast: value doesn't fit in 16 bits");
return int16(value);
}
function toInt8(int256 value) internal pure returns (int8) {
require(value >= type(int8).min && value <= type(int8).max, "SafeCast: value doesn't fit in 8 bits");
return int8(value);
}
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);
}
}
文件 75 的 92:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/draft-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 newAllowance = token.allowance(address(this), spender) + value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
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");
uint256 newAllowance = oldAllowance - value;
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
}
}
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");
if (returndata.length > 0) {
require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
}
}
文件 76 的 92:SafeMath.sol
pragma solidity ^0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
return a + b;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
return a * b;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
return a % b;
}
function sub(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b <= a, errorMessage);
return a - b;
}
}
function div(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a / b;
}
}
function mod(
uint256 a,
uint256 b,
string memory errorMessage
) internal pure returns (uint256) {
unchecked {
require(b > 0, errorMessage);
return a % b;
}
}
}
文件 77 的 92: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);
}
}
}
文件 78 的 92:StrictBank.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "./Bank.sol";
contract StrictBank is Bank {
using SafeERC20 for IERC20;
mapping (address => uint256) public tokenBalances;
constructor(RoleStore _roleStore, DataStore _dataStore) Bank(_roleStore, _dataStore) {}
function recordTransferIn(address token) external onlyController returns (uint256) {
return _recordTransferIn(token);
}
function syncTokenBalance(address token) external onlyController returns (uint256) {
uint256 nextBalance = IERC20(token).balanceOf(address(this));
tokenBalances[token] = nextBalance;
return nextBalance;
}
function _recordTransferIn(address token) internal returns (uint256) {
uint256 prevBalance = tokenBalances[token];
uint256 nextBalance = IERC20(token).balanceOf(address(this));
tokenBalances[token] = nextBalance;
return nextBalance - prevBalance;
}
function _afterTransferOut(address token) internal override {
tokenBalances[token] = IERC20(token).balanceOf(address(this));
}
}
文件 79 的 92:Strings.sol
pragma solidity ^0.8.0;
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
文件 80 的 92:SwapHandler.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import "../role/RoleModule.sol";
import "./SwapUtils.sol";
contract SwapHandler is ReentrancyGuard, RoleModule {
constructor(RoleStore _roleStore) RoleModule(_roleStore) {}
function swap(
SwapUtils.SwapParams memory params
)
external
nonReentrant
onlyController
returns (address, uint256)
{
return SwapUtils.swap(params);
}
}
文件 81 的 92:SwapPricingUtils.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SignedMath.sol";
import "../market/MarketUtils.sol";
import "../utils/Precision.sol";
import "../utils/Calc.sol";
import "./PricingUtils.sol";
library SwapPricingUtils {
using SignedMath for int256;
using SafeCast for uint256;
using SafeCast for int256;
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;
struct GetPriceImpactUsdParams {
DataStore dataStore;
Market.Props market;
address tokenA;
address tokenB;
uint256 priceForTokenA;
uint256 priceForTokenB;
int256 usdDeltaForTokenA;
int256 usdDeltaForTokenB;
}
struct PoolParams {
uint256 poolUsdForTokenA;
uint256 poolUsdForTokenB;
uint256 nextPoolUsdForTokenA;
uint256 nextPoolUsdForTokenB;
}
struct SwapFees {
uint256 feeReceiverAmount;
uint256 feeAmountForPool;
uint256 amountAfterFees;
address uiFeeReceiver;
uint256 uiFeeReceiverFactor;
uint256 uiFeeAmount;
}
function getPriceImpactUsd(GetPriceImpactUsdParams memory params) internal view returns (int256) {
PoolParams memory poolParams = getNextPoolAmountsUsd(params);
int256 priceImpactUsd = _getPriceImpactUsd(params.dataStore, params.market, poolParams);
if (priceImpactUsd >= 0) { return priceImpactUsd; }
(bool hasVirtualInventory, uint256 virtualPoolAmountForLongToken, uint256 virtualPoolAmountForShortToken) = MarketUtils.getVirtualInventoryForSwaps(
params.dataStore,
params.market.marketToken
);
if (!hasVirtualInventory) {
return priceImpactUsd;
}
uint256 virtualPoolAmountForTokenA;
uint256 virtualPoolAmountForTokenB;
if (params.tokenA == params.market.longToken) {
virtualPoolAmountForTokenA = virtualPoolAmountForLongToken;
virtualPoolAmountForTokenB = virtualPoolAmountForShortToken;
} else {
virtualPoolAmountForTokenA = virtualPoolAmountForShortToken;
virtualPoolAmountForTokenB = virtualPoolAmountForLongToken;
}
PoolParams memory poolParamsForVirtualInventory = getNextPoolAmountsParams(
params,
virtualPoolAmountForTokenA,
virtualPoolAmountForTokenB
);
int256 priceImpactUsdForVirtualInventory = _getPriceImpactUsd(params.dataStore, params.market, poolParamsForVirtualInventory);
return priceImpactUsdForVirtualInventory < priceImpactUsd ? priceImpactUsdForVirtualInventory : priceImpactUsd;
}
function _getPriceImpactUsd(DataStore dataStore, Market.Props memory market, PoolParams memory poolParams) internal view returns (int256) {
uint256 initialDiffUsd = Calc.diff(poolParams.poolUsdForTokenA, poolParams.poolUsdForTokenB);
uint256 nextDiffUsd = Calc.diff(poolParams.nextPoolUsdForTokenA, poolParams.nextPoolUsdForTokenB);
bool isSameSideRebalance = (poolParams.poolUsdForTokenA <= poolParams.poolUsdForTokenB) == (poolParams.nextPoolUsdForTokenA <= poolParams.nextPoolUsdForTokenB);
uint256 impactExponentFactor = dataStore.getUint(Keys.swapImpactExponentFactorKey(market.marketToken));
if (isSameSideRebalance) {
bool hasPositiveImpact = nextDiffUsd < initialDiffUsd;
uint256 impactFactor = MarketUtils.getAdjustedSwapImpactFactor(dataStore, market.marketToken, hasPositiveImpact);
return PricingUtils.getPriceImpactUsdForSameSideRebalance(
initialDiffUsd,
nextDiffUsd,
impactFactor,
impactExponentFactor
);
} else {
(uint256 positiveImpactFactor, uint256 negativeImpactFactor) = MarketUtils.getAdjustedSwapImpactFactors(dataStore, market.marketToken);
return PricingUtils.getPriceImpactUsdForCrossoverRebalance(
initialDiffUsd,
nextDiffUsd,
positiveImpactFactor,
negativeImpactFactor,
impactExponentFactor
);
}
}
function getNextPoolAmountsUsd(
GetPriceImpactUsdParams memory params
) internal view returns (PoolParams memory) {
uint256 poolAmountForTokenA = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenA);
uint256 poolAmountForTokenB = MarketUtils.getPoolAmount(params.dataStore, params.market, params.tokenB);
return getNextPoolAmountsParams(
params,
poolAmountForTokenA,
poolAmountForTokenB
);
}
function getNextPoolAmountsParams(
GetPriceImpactUsdParams memory params,
uint256 poolAmountForTokenA,
uint256 poolAmountForTokenB
) internal pure returns (PoolParams memory) {
uint256 poolUsdForTokenA = poolAmountForTokenA * params.priceForTokenA;
uint256 poolUsdForTokenB = poolAmountForTokenB * params.priceForTokenB;
if (params.usdDeltaForTokenA < 0 && (-params.usdDeltaForTokenA).toUint256() > poolUsdForTokenA) {
revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenA, poolUsdForTokenA);
}
if (params.usdDeltaForTokenB < 0 && (-params.usdDeltaForTokenB).toUint256() > poolUsdForTokenB) {
revert Errors.UsdDeltaExceedsPoolValue(params.usdDeltaForTokenB, poolUsdForTokenB);
}
uint256 nextPoolUsdForTokenA = Calc.sumReturnUint256(poolUsdForTokenA, params.usdDeltaForTokenA);
uint256 nextPoolUsdForTokenB = Calc.sumReturnUint256(poolUsdForTokenB, params.usdDeltaForTokenB);
PoolParams memory poolParams = PoolParams(
poolUsdForTokenA,
poolUsdForTokenB,
nextPoolUsdForTokenA,
nextPoolUsdForTokenB
);
return poolParams;
}
function getSwapFees(
DataStore dataStore,
address marketToken,
uint256 amount,
bool forPositiveImpact,
address uiFeeReceiver
) internal view returns (SwapFees memory) {
SwapFees memory fees;
uint256 feeFactor = dataStore.getUint(Keys.swapFeeFactorKey(marketToken, forPositiveImpact));
uint256 swapFeeReceiverFactor = dataStore.getUint(Keys.SWAP_FEE_RECEIVER_FACTOR);
uint256 feeAmount = Precision.applyFactor(amount, feeFactor);
fees.feeReceiverAmount = Precision.applyFactor(feeAmount, swapFeeReceiverFactor);
fees.feeAmountForPool = feeAmount - fees.feeReceiverAmount;
fees.uiFeeReceiver = uiFeeReceiver;
fees.uiFeeReceiverFactor = MarketUtils.getUiFeeFactor(dataStore, uiFeeReceiver);
fees.uiFeeAmount = Precision.applyFactor(amount, fees.uiFeeReceiverFactor);
fees.amountAfterFees = amount - feeAmount - fees.uiFeeAmount;
return fees;
}
function emitSwapInfo(
EventEmitter eventEmitter,
bytes32 orderKey,
address market,
address receiver,
address tokenIn,
address tokenOut,
uint256 tokenInPrice,
uint256 tokenOutPrice,
uint256 amountIn,
uint256 amountInAfterFees,
uint256 amountOut,
int256 priceImpactUsd,
int256 priceImpactAmount
) internal {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "orderKey", orderKey);
eventData.addressItems.initItems(4);
eventData.addressItems.setItem(0, "market", market);
eventData.addressItems.setItem(1, "receiver", receiver);
eventData.addressItems.setItem(2, "tokenIn", tokenIn);
eventData.addressItems.setItem(3, "tokenOut", tokenOut);
eventData.uintItems.initItems(5);
eventData.uintItems.setItem(0, "tokenInPrice", tokenInPrice);
eventData.uintItems.setItem(1, "tokenOutPrice", tokenOutPrice);
eventData.uintItems.setItem(2, "amountIn", amountIn);
eventData.uintItems.setItem(3, "amountInAfterFees", amountInAfterFees);
eventData.uintItems.setItem(4, "amountOut", amountOut);
eventData.intItems.initItems(2);
eventData.intItems.setItem(0, "priceImpactUsd", priceImpactUsd);
eventData.intItems.setItem(1, "priceImpactAmount", priceImpactAmount);
eventEmitter.emitEventLog1(
"SwapInfo",
Cast.toBytes32(market),
eventData
);
}
function emitSwapFeesCollected(
EventEmitter eventEmitter,
bytes32 tradeKey,
address market,
address token,
uint256 tokenPrice,
bytes32 swapFeeType,
SwapFees memory fees
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(2);
eventData.bytes32Items.setItem(0, "tradeKey", tradeKey);
eventData.bytes32Items.setItem(1, "swapFeeType", swapFeeType);
eventData.addressItems.initItems(3);
eventData.addressItems.setItem(0, "uiFeeReceiver", fees.uiFeeReceiver);
eventData.addressItems.setItem(1, "market", market);
eventData.addressItems.setItem(2, "token", token);
eventData.uintItems.initItems(6);
eventData.uintItems.setItem(0, "tokenPrice", tokenPrice);
eventData.uintItems.setItem(1, "feeReceiverAmount", fees.feeReceiverAmount);
eventData.uintItems.setItem(2, "feeAmountForPool", fees.feeAmountForPool);
eventData.uintItems.setItem(3, "amountAfterFees", fees.amountAfterFees);
eventData.uintItems.setItem(4, "uiFeeReceiverFactor", fees.uiFeeReceiverFactor);
eventData.uintItems.setItem(5, "uiFeeAmount", fees.uiFeeAmount);
eventEmitter.emitEventLog1(
"SwapFeesCollected",
Cast.toBytes32(market),
eventData
);
}
}
文件 82 的 92:SwapUtils.sol
pragma solidity ^0.8.0;
import "../adl/AdlUtils.sol";
import "../data/DataStore.sol";
import "../event/EventEmitter.sol";
import "../oracle/Oracle.sol";
import "../pricing/SwapPricingUtils.sol";
import "../token/TokenUtils.sol";
import "../fee/FeeUtils.sol";
library SwapUtils {
using SafeCast for uint256;
using SafeCast for int256;
using Price for Price.Props;
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;
struct SwapParams {
DataStore dataStore;
EventEmitter eventEmitter;
Oracle oracle;
Bank bank;
bytes32 key;
address tokenIn;
uint256 amountIn;
Market.Props[] swapPathMarkets;
uint256 minOutputAmount;
address receiver;
address uiFeeReceiver;
bool shouldUnwrapNativeToken;
}
struct _SwapParams {
Market.Props market;
address tokenIn;
uint256 amountIn;
address receiver;
bool shouldUnwrapNativeToken;
}
struct SwapCache {
address tokenOut;
Price.Props tokenInPrice;
Price.Props tokenOutPrice;
uint256 amountIn;
uint256 amountOut;
uint256 poolAmountOut;
int256 priceImpactUsd;
int256 priceImpactAmount;
}
event SwapReverted(string reason, bytes reasonBytes);
function swap(SwapParams memory params) external returns (address, uint256) {
if (params.amountIn == 0) {
return (params.tokenIn, params.amountIn);
}
if (params.swapPathMarkets.length == 0) {
if (params.amountIn < params.minOutputAmount) {
revert Errors.InsufficientOutputAmount(params.amountIn, params.minOutputAmount);
}
if (address(params.bank) != params.receiver) {
params.bank.transferOut(
params.tokenIn,
params.receiver,
params.amountIn,
params.shouldUnwrapNativeToken
);
}
return (params.tokenIn, params.amountIn);
}
if (address(params.bank) != params.swapPathMarkets[0].marketToken) {
params.bank.transferOut(
params.tokenIn,
params.swapPathMarkets[0].marketToken,
params.amountIn,
false
);
}
address tokenOut = params.tokenIn;
uint256 outputAmount = params.amountIn;
for (uint256 i; i < params.swapPathMarkets.length; i++) {
Market.Props memory market = params.swapPathMarkets[i];
bool flagExists = params.dataStore.getBool(Keys.swapPathMarketFlagKey(market.marketToken));
if (flagExists) {
revert Errors.DuplicatedMarketInSwapPath(market.marketToken);
}
params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), true);
uint256 nextIndex = i + 1;
address receiver;
if (nextIndex < params.swapPathMarkets.length) {
receiver = params.swapPathMarkets[nextIndex].marketToken;
} else {
receiver = params.receiver;
}
_SwapParams memory _params = _SwapParams(
market,
tokenOut,
outputAmount,
receiver,
i == params.swapPathMarkets.length - 1 ? params.shouldUnwrapNativeToken : false
);
(tokenOut, outputAmount) = _swap(params, _params);
}
for (uint256 i; i < params.swapPathMarkets.length; i++) {
Market.Props memory market = params.swapPathMarkets[i];
params.dataStore.setBool(Keys.swapPathMarketFlagKey(market.marketToken), false);
}
if (outputAmount < params.minOutputAmount) {
revert Errors.InsufficientSwapOutputAmount(outputAmount, params.minOutputAmount);
}
return (tokenOut, outputAmount);
}
function _swap(SwapParams memory params, _SwapParams memory _params) internal returns (address, uint256) {
SwapCache memory cache;
if (_params.tokenIn != _params.market.longToken && _params.tokenIn != _params.market.shortToken) {
revert Errors.InvalidTokenIn(_params.tokenIn, _params.market.marketToken);
}
MarketUtils.validateSwapMarket(params.dataStore, _params.market);
cache.tokenOut = MarketUtils.getOppositeToken(_params.tokenIn, _params.market);
cache.tokenInPrice = params.oracle.getPrimaryPrice(_params.tokenIn);
cache.tokenOutPrice = params.oracle.getPrimaryPrice(cache.tokenOut);
cache.priceImpactUsd = SwapPricingUtils.getPriceImpactUsd(
SwapPricingUtils.GetPriceImpactUsdParams(
params.dataStore,
_params.market,
_params.tokenIn,
cache.tokenOut,
cache.tokenInPrice.midPrice(),
cache.tokenOutPrice.midPrice(),
(_params.amountIn * cache.tokenInPrice.midPrice()).toInt256(),
-(_params.amountIn * cache.tokenInPrice.midPrice()).toInt256()
)
);
SwapPricingUtils.SwapFees memory fees = SwapPricingUtils.getSwapFees(
params.dataStore,
_params.market.marketToken,
_params.amountIn,
cache.priceImpactUsd > 0,
params.uiFeeReceiver
);
FeeUtils.incrementClaimableFeeAmount(
params.dataStore,
params.eventEmitter,
_params.market.marketToken,
_params.tokenIn,
fees.feeReceiverAmount,
Keys.SWAP_FEE_TYPE
);
FeeUtils.incrementClaimableUiFeeAmount(
params.dataStore,
params.eventEmitter,
params.uiFeeReceiver,
_params.market.marketToken,
_params.tokenIn,
fees.uiFeeAmount,
Keys.UI_SWAP_FEE_TYPE
);
if (cache.priceImpactUsd > 0) {
cache.amountIn = fees.amountAfterFees;
cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
cache.poolAmountOut = cache.amountOut;
cache.priceImpactAmount = MarketUtils.applySwapImpactWithCap(
params.dataStore,
params.eventEmitter,
_params.market.marketToken,
cache.tokenOut,
cache.tokenOutPrice,
cache.priceImpactUsd
);
cache.amountOut += cache.priceImpactAmount.toUint256();
} else {
cache.priceImpactAmount = MarketUtils.applySwapImpactWithCap(
params.dataStore,
params.eventEmitter,
_params.market.marketToken,
_params.tokenIn,
cache.tokenInPrice,
cache.priceImpactUsd
);
if (fees.amountAfterFees <= (-cache.priceImpactAmount).toUint256()) {
revert Errors.SwapPriceImpactExceedsAmountIn(fees.amountAfterFees, cache.priceImpactAmount);
}
cache.amountIn = fees.amountAfterFees - (-cache.priceImpactAmount).toUint256();
cache.amountOut = cache.amountIn * cache.tokenInPrice.min / cache.tokenOutPrice.max;
cache.poolAmountOut = cache.amountOut;
}
if (_params.receiver != _params.market.marketToken) {
MarketToken(payable(_params.market.marketToken)).transferOut(
cache.tokenOut,
_params.receiver,
cache.amountOut,
_params.shouldUnwrapNativeToken
);
}
MarketUtils.applyDeltaToPoolAmount(
params.dataStore,
params.eventEmitter,
_params.market,
_params.tokenIn,
(cache.amountIn + fees.feeAmountForPool).toInt256()
);
MarketUtils.applyDeltaToPoolAmount(
params.dataStore,
params.eventEmitter,
_params.market,
cache.tokenOut,
-cache.poolAmountOut.toInt256()
);
MarketUtils.MarketPrices memory prices = MarketUtils.MarketPrices(
params.oracle.getPrimaryPrice(_params.market.indexToken),
_params.tokenIn == _params.market.longToken ? cache.tokenInPrice : cache.tokenOutPrice,
_params.tokenIn == _params.market.shortToken ? cache.tokenInPrice : cache.tokenOutPrice
);
MarketUtils.validatePoolAmount(
params.dataStore,
_params.market,
_params.tokenIn
);
MarketUtils.validateReserve(
params.dataStore,
_params.market,
prices,
cache.tokenOut == _params.market.longToken
);
MarketUtils.validateMaxPnl(
params.dataStore,
_params.market,
prices,
_params.tokenIn == _params.market.longToken ? Keys.MAX_PNL_FACTOR_FOR_DEPOSITS : Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS,
cache.tokenOut == _params.market.shortToken ? Keys.MAX_PNL_FACTOR_FOR_WITHDRAWALS : Keys.MAX_PNL_FACTOR_FOR_DEPOSITS
);
SwapPricingUtils.emitSwapInfo(
params.eventEmitter,
params.key,
_params.market.marketToken,
_params.receiver,
_params.tokenIn,
cache.tokenOut,
cache.tokenInPrice.min,
cache.tokenOutPrice.max,
_params.amountIn,
cache.amountIn,
cache.amountOut,
cache.priceImpactUsd,
cache.priceImpactAmount
);
SwapPricingUtils.emitSwapFeesCollected(
params.eventEmitter,
params.key,
_params.market.marketToken,
_params.tokenIn,
cache.tokenInPrice.min,
Keys.SWAP_FEE_TYPE,
fees
);
return (cache.tokenOut, cache.amountOut);
}
}
文件 83 的 92: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);
}
}
文件 84 的 92: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;
}
}
文件 85 的 92:Withdrawal.sol
pragma solidity ^0.8.0;
library Withdrawal {
struct Props {
Addresses addresses;
Numbers numbers;
Flags flags;
}
struct Addresses {
address account;
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address[] longTokenSwapPath;
address[] shortTokenSwapPath;
}
struct Numbers {
uint256 marketTokenAmount;
uint256 minLongTokenAmount;
uint256 minShortTokenAmount;
uint256 updatedAtBlock;
uint256 executionFee;
uint256 callbackGasLimit;
}
struct Flags {
bool shouldUnwrapNativeToken;
}
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 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 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 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 longTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
return props.addresses.longTokenSwapPath;
}
function setLongTokenSwapPath(Props memory props, address[] memory value) internal pure {
props.addresses.longTokenSwapPath = value;
}
function shortTokenSwapPath(Props memory props) internal pure returns (address[] memory) {
return props.addresses.shortTokenSwapPath;
}
function setShortTokenSwapPath(Props memory props, address[] memory value) internal pure {
props.addresses.shortTokenSwapPath = value;
}
function marketTokenAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.marketTokenAmount;
}
function setMarketTokenAmount(Props memory props, uint256 value) internal pure {
props.numbers.marketTokenAmount = value;
}
function minLongTokenAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.minLongTokenAmount;
}
function setMinLongTokenAmount(Props memory props, uint256 value) internal pure {
props.numbers.minLongTokenAmount = value;
}
function minShortTokenAmount(Props memory props) internal pure returns (uint256) {
return props.numbers.minShortTokenAmount;
}
function setMinShortTokenAmount(Props memory props, uint256 value) internal pure {
props.numbers.minShortTokenAmount = value;
}
function updatedAtBlock(Props memory props) internal pure returns (uint256) {
return props.numbers.updatedAtBlock;
}
function setUpdatedAtBlock(Props memory props, uint256 value) internal pure {
props.numbers.updatedAtBlock = value;
}
function executionFee(Props memory props) internal pure returns (uint256) {
return props.numbers.executionFee;
}
function setExecutionFee(Props memory props, uint256 value) internal pure {
props.numbers.executionFee = value;
}
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 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;
}
}
文件 86 的 92:WithdrawalEventUtils.sol
pragma solidity ^0.8.0;
import "../event/EventEmitter.sol";
import "../event/EventUtils.sol";
import "../utils/Cast.sol";
import "./Withdrawal.sol";
library WithdrawalEventUtils {
using Withdrawal for Withdrawal.Props;
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 emitWithdrawalCreated(
EventEmitter eventEmitter,
bytes32 key,
Withdrawal.Props memory withdrawal
) external {
EventUtils.EventLogData memory eventData;
eventData.addressItems.initItems(4);
eventData.addressItems.setItem(0, "account", withdrawal.account());
eventData.addressItems.setItem(1, "receiver", withdrawal.receiver());
eventData.addressItems.setItem(2, "callbackContract", withdrawal.callbackContract());
eventData.addressItems.setItem(3, "market", withdrawal.market());
eventData.addressItems.initArrayItems(2);
eventData.addressItems.setItem(0, "longTokenSwapPath", withdrawal.longTokenSwapPath());
eventData.addressItems.setItem(1, "shortTokenSwapPath", withdrawal.shortTokenSwapPath());
eventData.uintItems.initItems(6);
eventData.uintItems.setItem(0, "marketTokenAmount", withdrawal.marketTokenAmount());
eventData.uintItems.setItem(1, "minLongTokenAmount", withdrawal.minLongTokenAmount());
eventData.uintItems.setItem(2, "minShortTokenAmount", withdrawal.minShortTokenAmount());
eventData.uintItems.setItem(3, "updatedAtBlock", withdrawal.updatedAtBlock());
eventData.uintItems.setItem(4, "executionFee", withdrawal.executionFee());
eventData.uintItems.setItem(5, "callbackGasLimit", withdrawal.callbackGasLimit());
eventData.boolItems.initItems(1);
eventData.boolItems.setItem(0, "shouldUnwrapNativeToken", withdrawal.shouldUnwrapNativeToken());
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventEmitter.emitEventLog2(
"WithdrawalCreated",
key,
Cast.toBytes32(withdrawal.account()),
eventData
);
}
function emitWithdrawalExecuted(
EventEmitter eventEmitter,
bytes32 key,
address account
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventEmitter.emitEventLog2(
"WithdrawalExecuted",
key,
Cast.toBytes32(account),
eventData
);
}
function emitWithdrawalCancelled(
EventEmitter eventEmitter,
bytes32 key,
address account,
string memory reason,
bytes memory reasonBytes
) external {
EventUtils.EventLogData memory eventData;
eventData.bytes32Items.initItems(1);
eventData.bytes32Items.setItem(0, "key", key);
eventData.addressItems.initItems(1);
eventData.addressItems.setItem(0, "account", account);
eventData.stringItems.initItems(1);
eventData.stringItems.setItem(0, "reason", reason);
eventData.bytesItems.initItems(1);
eventData.bytesItems.setItem(0, "reasonBytes", reasonBytes);
eventEmitter.emitEventLog2(
"WithdrawalCancelled",
key,
Cast.toBytes32(account),
eventData
);
}
}
文件 87 的 92:WithdrawalHandler.sol
pragma solidity ^0.8.0;
import "../utils/GlobalReentrancyGuard.sol";
import "../error/ErrorUtils.sol";
import "./ExchangeUtils.sol";
import "../role/RoleModule.sol";
import "../feature/FeatureUtils.sol";
import "../market/Market.sol";
import "../market/MarketToken.sol";
import "../withdrawal/Withdrawal.sol";
import "../withdrawal/WithdrawalVault.sol";
import "../withdrawal/WithdrawalStoreUtils.sol";
import "../withdrawal/WithdrawalUtils.sol";
import "../withdrawal/ExecuteWithdrawalUtils.sol";
import "../oracle/Oracle.sol";
import "../oracle/OracleModule.sol";
import "./IWithdrawalHandler.sol";
contract WithdrawalHandler is IWithdrawalHandler, GlobalReentrancyGuard, RoleModule, OracleModule {
using Withdrawal for Withdrawal.Props;
EventEmitter public immutable eventEmitter;
WithdrawalVault public immutable withdrawalVault;
Oracle public immutable oracle;
constructor(
RoleStore _roleStore,
DataStore _dataStore,
EventEmitter _eventEmitter,
WithdrawalVault _withdrawalVault,
Oracle _oracle
) RoleModule(_roleStore) GlobalReentrancyGuard(_dataStore) {
eventEmitter = _eventEmitter;
withdrawalVault = _withdrawalVault;
oracle = _oracle;
}
function createWithdrawal(
address account,
WithdrawalUtils.CreateWithdrawalParams calldata params
) external override globalNonReentrant onlyController returns (bytes32) {
FeatureUtils.validateFeature(dataStore, Keys.createWithdrawalFeatureDisabledKey(address(this)));
return WithdrawalUtils.createWithdrawal(
dataStore,
eventEmitter,
withdrawalVault,
account,
params
);
}
function cancelWithdrawal(bytes32 key) external override globalNonReentrant onlyController {
uint256 startingGas = gasleft();
DataStore _dataStore = dataStore;
Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(_dataStore, key);
FeatureUtils.validateFeature(_dataStore, Keys.cancelWithdrawalFeatureDisabledKey(address(this)));
ExchangeUtils.validateRequestCancellation(
_dataStore,
withdrawal.updatedAtBlock(),
"Withdrawal"
);
WithdrawalUtils.cancelWithdrawal(
_dataStore,
eventEmitter,
withdrawalVault,
key,
withdrawal.account(),
startingGas,
Keys.USER_INITIATED_CANCEL,
""
);
}
function executeWithdrawal(
bytes32 key,
OracleUtils.SetPricesParams calldata oracleParams
)
external
globalNonReentrant
onlyOrderKeeper
withOraclePrices(oracle, dataStore, eventEmitter, oracleParams)
{
uint256 startingGas = gasleft();
Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);
GasUtils.validateExecutionGas(dataStore, startingGas, estimatedGasLimit);
uint256 executionGas = GasUtils.getExecutionGas(dataStore, startingGas);
try this._executeWithdrawal{ gas: executionGas }(
key,
withdrawal,
oracleParams,
msg.sender
) {
} catch (bytes memory reasonBytes) {
_handleWithdrawalError(
key,
startingGas,
reasonBytes
);
}
}
function simulateExecuteWithdrawal(
bytes32 key,
OracleUtils.SimulatePricesParams memory params
) external
override
onlyController
withSimulatedOraclePrices(oracle, params)
globalNonReentrant
{
OracleUtils.SetPricesParams memory oracleParams;
Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
this._executeWithdrawal(
key,
withdrawal,
oracleParams,
msg.sender
);
}
function _executeWithdrawal(
bytes32 key,
Withdrawal.Props memory withdrawal,
OracleUtils.SetPricesParams memory oracleParams,
address keeper
) external onlySelf {
uint256 startingGas = gasleft();
FeatureUtils.validateFeature(dataStore, Keys.executeWithdrawalFeatureDisabledKey(address(this)));
OracleUtils.RealtimeFeedReport[] memory reports = oracle.validateRealtimeFeeds(
dataStore,
oracleParams.realtimeFeedTokens,
oracleParams.realtimeFeedData
);
uint256[] memory minOracleBlockNumbers = OracleUtils.getUncompactedOracleBlockNumbers(
oracleParams.compactedMinOracleBlockNumbers,
oracleParams.tokens.length,
reports,
OracleUtils.OracleBlockNumberType.Min
);
uint256[] memory maxOracleBlockNumbers = OracleUtils.getUncompactedOracleBlockNumbers(
oracleParams.compactedMaxOracleBlockNumbers,
oracleParams.tokens.length,
reports,
OracleUtils.OracleBlockNumberType.Max
);
ExecuteWithdrawalUtils.ExecuteWithdrawalParams memory params = ExecuteWithdrawalUtils.ExecuteWithdrawalParams(
dataStore,
eventEmitter,
withdrawalVault,
oracle,
key,
minOracleBlockNumbers,
maxOracleBlockNumbers,
keeper,
startingGas
);
ExecuteWithdrawalUtils.executeWithdrawal(params, withdrawal);
}
function _handleWithdrawalError(
bytes32 key,
uint256 startingGas,
bytes memory reasonBytes
) internal {
GasUtils.validateExecutionErrorGas(dataStore, reasonBytes);
bytes4 errorSelector = ErrorUtils.getErrorSelectorFromData(reasonBytes);
if (
OracleUtils.isOracleError(errorSelector) ||
errorSelector == Errors.DisabledFeature.selector
) {
ErrorUtils.revertWithCustomError(reasonBytes);
}
(string memory reason, ) = ErrorUtils.getRevertMessage(reasonBytes);
WithdrawalUtils.cancelWithdrawal(
dataStore,
eventEmitter,
withdrawalVault,
key,
msg.sender,
startingGas,
reason,
reasonBytes
);
}
}
文件 88 的 92:WithdrawalStoreUtils.sol
pragma solidity ^0.8.0;
import "../data/Keys.sol";
import "../data/DataStore.sol";
import "./Withdrawal.sol";
library WithdrawalStoreUtils {
using Withdrawal for Withdrawal.Props;
bytes32 public constant ACCOUNT = keccak256(abi.encode("ACCOUNT"));
bytes32 public constant RECEIVER = keccak256(abi.encode("RECEIVER"));
bytes32 public constant CALLBACK_CONTRACT = keccak256(abi.encode("CALLBACK_CONTRACT"));
bytes32 public constant UI_FEE_RECEIVER = keccak256(abi.encode("UI_FEE_RECEIVER"));
bytes32 public constant MARKET = keccak256(abi.encode("MARKET"));
bytes32 public constant LONG_TOKEN_SWAP_PATH = keccak256(abi.encode("LONG_TOKEN_SWAP_PATH"));
bytes32 public constant SHORT_TOKEN_SWAP_PATH = keccak256(abi.encode("SHORT_TOKEN_SWAP_PATH"));
bytes32 public constant MARKET_TOKEN_AMOUNT = keccak256(abi.encode("MARKET_TOKEN_AMOUNT"));
bytes32 public constant MIN_LONG_TOKEN_AMOUNT = keccak256(abi.encode("MIN_LONG_TOKEN_AMOUNT"));
bytes32 public constant MIN_SHORT_TOKEN_AMOUNT = keccak256(abi.encode("MIN_SHORT_TOKEN_AMOUNT"));
bytes32 public constant UPDATED_AT_BLOCK = keccak256(abi.encode("UPDATED_AT_BLOCK"));
bytes32 public constant EXECUTION_FEE = keccak256(abi.encode("EXECUTION_FEE"));
bytes32 public constant CALLBACK_GAS_LIMIT = keccak256(abi.encode("CALLBACK_GAS_LIMIT"));
bytes32 public constant SHOULD_UNWRAP_NATIVE_TOKEN = keccak256(abi.encode("SHOULD_UNWRAP_NATIVE_TOKEN"));
function get(DataStore dataStore, bytes32 key) external view returns (Withdrawal.Props memory) {
Withdrawal.Props memory withdrawal;
if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {
return withdrawal;
}
withdrawal.setAccount(dataStore.getAddress(
keccak256(abi.encode(key, ACCOUNT))
));
withdrawal.setReceiver(dataStore.getAddress(
keccak256(abi.encode(key, RECEIVER))
));
withdrawal.setCallbackContract(dataStore.getAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT))
));
withdrawal.setUiFeeReceiver(dataStore.getAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER))
));
withdrawal.setMarket(dataStore.getAddress(
keccak256(abi.encode(key, MARKET))
));
withdrawal.setLongTokenSwapPath(dataStore.getAddressArray(
keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
));
withdrawal.setShortTokenSwapPath(dataStore.getAddressArray(
keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
));
withdrawal.setMarketTokenAmount(dataStore.getUint(
keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
));
withdrawal.setMinLongTokenAmount(dataStore.getUint(
keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))
));
withdrawal.setMinShortTokenAmount(dataStore.getUint(
keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))
));
withdrawal.setUpdatedAtBlock(dataStore.getUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK))
));
withdrawal.setExecutionFee(dataStore.getUint(
keccak256(abi.encode(key, EXECUTION_FEE))
));
withdrawal.setCallbackGasLimit(dataStore.getUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
));
withdrawal.setShouldUnwrapNativeToken(dataStore.getBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
));
return withdrawal;
}
function set(DataStore dataStore, bytes32 key, Withdrawal.Props memory withdrawal) external {
dataStore.addBytes32(
Keys.WITHDRAWAL_LIST,
key
);
dataStore.addBytes32(
Keys.accountWithdrawalListKey(withdrawal.account()),
key
);
dataStore.setAddress(
keccak256(abi.encode(key, ACCOUNT)),
withdrawal.account()
);
dataStore.setAddress(
keccak256(abi.encode(key, RECEIVER)),
withdrawal.receiver()
);
dataStore.setAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT)),
withdrawal.callbackContract()
);
dataStore.setAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER)),
withdrawal.uiFeeReceiver()
);
dataStore.setAddress(
keccak256(abi.encode(key, MARKET)),
withdrawal.market()
);
dataStore.setAddressArray(
keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH)),
withdrawal.longTokenSwapPath()
);
dataStore.setAddressArray(
keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH)),
withdrawal.shortTokenSwapPath()
);
dataStore.setUint(
keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT)),
withdrawal.marketTokenAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT)),
withdrawal.minLongTokenAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT)),
withdrawal.minShortTokenAmount()
);
dataStore.setUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK)),
withdrawal.updatedAtBlock()
);
dataStore.setUint(
keccak256(abi.encode(key, EXECUTION_FEE)),
withdrawal.executionFee()
);
dataStore.setUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT)),
withdrawal.callbackGasLimit()
);
dataStore.setBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN)),
withdrawal.shouldUnwrapNativeToken()
);
}
function remove(DataStore dataStore, bytes32 key, address account) external {
if (!dataStore.containsBytes32(Keys.WITHDRAWAL_LIST, key)) {
revert Errors.WithdrawalNotFound(key);
}
dataStore.removeBytes32(
Keys.WITHDRAWAL_LIST,
key
);
dataStore.removeBytes32(
Keys.accountWithdrawalListKey(account),
key
);
dataStore.removeAddress(
keccak256(abi.encode(key, ACCOUNT))
);
dataStore.removeAddress(
keccak256(abi.encode(key, RECEIVER))
);
dataStore.removeAddress(
keccak256(abi.encode(key, CALLBACK_CONTRACT))
);
dataStore.removeAddress(
keccak256(abi.encode(key, UI_FEE_RECEIVER))
);
dataStore.removeAddress(
keccak256(abi.encode(key, MARKET))
);
dataStore.removeAddressArray(
keccak256(abi.encode(key, LONG_TOKEN_SWAP_PATH))
);
dataStore.removeAddressArray(
keccak256(abi.encode(key, SHORT_TOKEN_SWAP_PATH))
);
dataStore.removeUint(
keccak256(abi.encode(key, MARKET_TOKEN_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, MIN_LONG_TOKEN_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, MIN_SHORT_TOKEN_AMOUNT))
);
dataStore.removeUint(
keccak256(abi.encode(key, UPDATED_AT_BLOCK))
);
dataStore.removeUint(
keccak256(abi.encode(key, EXECUTION_FEE))
);
dataStore.removeUint(
keccak256(abi.encode(key, CALLBACK_GAS_LIMIT))
);
dataStore.removeBool(
keccak256(abi.encode(key, SHOULD_UNWRAP_NATIVE_TOKEN))
);
}
function getWithdrawalCount(DataStore dataStore) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.WITHDRAWAL_LIST);
}
function getWithdrawalKeys(DataStore dataStore, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.WITHDRAWAL_LIST, start, end);
}
function getAccountWithdrawalCount(DataStore dataStore, address account) internal view returns (uint256) {
return dataStore.getBytes32Count(Keys.accountWithdrawalListKey(account));
}
function getAccountWithdrawalKeys(DataStore dataStore, address account, uint256 start, uint256 end) internal view returns (bytes32[] memory) {
return dataStore.getBytes32ValuesAt(Keys.accountWithdrawalListKey(account), start, end);
}
}
文件 89 的 92:WithdrawalUtils.sol
pragma solidity ^0.8.0;
import "../adl/AdlUtils.sol";
import "../data/DataStore.sol";
import "./WithdrawalVault.sol";
import "./WithdrawalStoreUtils.sol";
import "./WithdrawalEventUtils.sol";
import "../nonce/NonceUtils.sol";
import "../pricing/SwapPricingUtils.sol";
import "../oracle/Oracle.sol";
import "../oracle/OracleUtils.sol";
import "../gas/GasUtils.sol";
import "../callback/CallbackUtils.sol";
import "../utils/Array.sol";
import "../utils/AccountUtils.sol";
library WithdrawalUtils {
using SafeCast for uint256;
using SafeCast for int256;
using Array for uint256[];
using Price for Price.Props;
using Withdrawal for Withdrawal.Props;
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;
struct CreateWithdrawalParams {
address receiver;
address callbackContract;
address uiFeeReceiver;
address market;
address[] longTokenSwapPath;
address[] shortTokenSwapPath;
uint256 minLongTokenAmount;
uint256 minShortTokenAmount;
bool shouldUnwrapNativeToken;
uint256 executionFee;
uint256 callbackGasLimit;
}
function createWithdrawal(
DataStore dataStore,
EventEmitter eventEmitter,
WithdrawalVault withdrawalVault,
address account,
CreateWithdrawalParams memory params
) external returns (bytes32) {
AccountUtils.validateAccount(account);
address wnt = TokenUtils.wnt(dataStore);
uint256 wntAmount = withdrawalVault.recordTransferIn(wnt);
if (wntAmount < params.executionFee) {
revert Errors.InsufficientWntAmount(wntAmount, params.executionFee);
}
AccountUtils.validateReceiver(params.receiver);
uint256 marketTokenAmount = withdrawalVault.recordTransferIn(params.market);
if (marketTokenAmount == 0) {
revert Errors.EmptyWithdrawalAmount();
}
params.executionFee = wntAmount;
MarketUtils.validateEnabledMarket(dataStore, params.market);
MarketUtils.validateSwapPath(dataStore, params.longTokenSwapPath);
MarketUtils.validateSwapPath(dataStore, params.shortTokenSwapPath);
Withdrawal.Props memory withdrawal = Withdrawal.Props(
Withdrawal.Addresses(
account,
params.receiver,
params.callbackContract,
params.uiFeeReceiver,
params.market,
params.longTokenSwapPath,
params.shortTokenSwapPath
),
Withdrawal.Numbers(
marketTokenAmount,
params.minLongTokenAmount,
params.minShortTokenAmount,
Chain.currentBlockNumber(),
params.executionFee,
params.callbackGasLimit
),
Withdrawal.Flags(
params.shouldUnwrapNativeToken
)
);
CallbackUtils.validateCallbackGasLimit(dataStore, withdrawal.callbackGasLimit());
uint256 estimatedGasLimit = GasUtils.estimateExecuteWithdrawalGasLimit(dataStore, withdrawal);
GasUtils.validateExecutionFee(dataStore, estimatedGasLimit, params.executionFee);
bytes32 key = NonceUtils.getNextKey(dataStore);
WithdrawalStoreUtils.set(dataStore, key, withdrawal);
WithdrawalEventUtils.emitWithdrawalCreated(eventEmitter, key, withdrawal);
return key;
}
function cancelWithdrawal(
DataStore dataStore,
EventEmitter eventEmitter,
WithdrawalVault withdrawalVault,
bytes32 key,
address keeper,
uint256 startingGas,
string memory reason,
bytes memory reasonBytes
) external {
startingGas -= gasleft() / 63;
Withdrawal.Props memory withdrawal = WithdrawalStoreUtils.get(dataStore, key);
if (withdrawal.account() == address(0)) {
revert Errors.EmptyWithdrawal();
}
if (withdrawal.marketTokenAmount() == 0) {
revert Errors.EmptyWithdrawalAmount();
}
WithdrawalStoreUtils.remove(dataStore, key, withdrawal.account());
withdrawalVault.transferOut(
withdrawal.market(),
withdrawal.account(),
withdrawal.marketTokenAmount(),
false
);
WithdrawalEventUtils.emitWithdrawalCancelled(
eventEmitter,
key,
withdrawal.account(),
reason,
reasonBytes
);
EventUtils.EventLogData memory eventData;
CallbackUtils.afterWithdrawalCancellation(key, withdrawal, eventData);
GasUtils.payExecutionFee(
dataStore,
eventEmitter,
withdrawalVault,
withdrawal.executionFee(),
startingGas,
keeper,
withdrawal.account()
);
}
}
文件 90 的 92:WithdrawalVault.sol
pragma solidity ^0.8.0;
import "../bank/StrictBank.sol";
contract WithdrawalVault is StrictBank {
constructor(RoleStore _roleStore, DataStore _dataStore) StrictBank(_roleStore, _dataStore) {}
}
文件 91 的 92:console.sol
pragma solidity >= 0.4.22 <0.9.0;
library console {
address constant CONSOLE_ADDRESS = address(0x000000000000000000636F6e736F6c652e6c6f67);
function _sendLogPayload(bytes memory payload) private view {
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE_ADDRESS;
assembly {
let payloadStart := add(payload, 32)
let r := staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
function log() internal view {
_sendLogPayload(abi.encodeWithSignature("log()"));
}
function logInt(int256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int256)", p0));
}
function logUint(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function logString(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function logBool(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function logAddress(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function logBytes(bytes memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes)", p0));
}
function logBytes1(bytes1 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes1)", p0));
}
function logBytes2(bytes2 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes2)", p0));
}
function logBytes3(bytes3 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes3)", p0));
}
function logBytes4(bytes4 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes4)", p0));
}
function logBytes5(bytes5 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes5)", p0));
}
function logBytes6(bytes6 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes6)", p0));
}
function logBytes7(bytes7 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes7)", p0));
}
function logBytes8(bytes8 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes8)", p0));
}
function logBytes9(bytes9 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes9)", p0));
}
function logBytes10(bytes10 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes10)", p0));
}
function logBytes11(bytes11 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes11)", p0));
}
function logBytes12(bytes12 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes12)", p0));
}
function logBytes13(bytes13 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes13)", p0));
}
function logBytes14(bytes14 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes14)", p0));
}
function logBytes15(bytes15 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes15)", p0));
}
function logBytes16(bytes16 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes16)", p0));
}
function logBytes17(bytes17 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes17)", p0));
}
function logBytes18(bytes18 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes18)", p0));
}
function logBytes19(bytes19 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes19)", p0));
}
function logBytes20(bytes20 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes20)", p0));
}
function logBytes21(bytes21 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes21)", p0));
}
function logBytes22(bytes22 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes22)", p0));
}
function logBytes23(bytes23 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes23)", p0));
}
function logBytes24(bytes24 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes24)", p0));
}
function logBytes25(bytes25 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes25)", p0));
}
function logBytes26(bytes26 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes26)", p0));
}
function logBytes27(bytes27 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes27)", p0));
}
function logBytes28(bytes28 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes28)", p0));
}
function logBytes29(bytes29 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes29)", p0));
}
function logBytes30(bytes30 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes30)", p0));
}
function logBytes31(bytes31 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes31)", p0));
}
function logBytes32(bytes32 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bytes32)", p0));
}
function log(uint256 p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256)", p0));
}
function log(string memory p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
function log(bool p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool)", p0));
}
function log(address p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address)", p0));
}
function log(uint256 p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256)", p0, p1));
}
function log(uint256 p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string)", p0, p1));
}
function log(uint256 p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool)", p0, p1));
}
function log(uint256 p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address)", p0, p1));
}
function log(string memory p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
function log(string memory p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
function log(string memory p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool)", p0, p1));
}
function log(string memory p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address)", p0, p1));
}
function log(bool p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256)", p0, p1));
}
function log(bool p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string)", p0, p1));
}
function log(bool p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool)", p0, p1));
}
function log(bool p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address)", p0, p1));
}
function log(address p0, uint256 p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256)", p0, p1));
}
function log(address p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string)", p0, p1));
}
function log(address p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool)", p0, p1));
}
function log(address p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address)", p0, p1));
}
function log(uint256 p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool)", p0, p1, p2));
}
function log(uint256 p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address)", p0, p1, p2));
}
function log(uint256 p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256)", p0, p1, p2));
}
function log(uint256 p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string)", p0, p1, p2));
}
function log(uint256 p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool)", p0, p1, p2));
}
function log(uint256 p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address)", p0, p1, p2));
}
function log(uint256 p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256)", p0, p1, p2));
}
function log(uint256 p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string)", p0, p1, p2));
}
function log(uint256 p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool)", p0, p1, p2));
}
function log(uint256 p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool)", p0, p1, p2));
}
function log(string memory p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256)", p0, p1, p2));
}
function log(string memory p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string)", p0, p1, p2));
}
function log(string memory p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool)", p0, p1, p2));
}
function log(string memory p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address)", p0, p1, p2));
}
function log(string memory p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256)", p0, p1, p2));
}
function log(string memory p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string)", p0, p1, p2));
}
function log(string memory p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool)", p0, p1, p2));
}
function log(string memory p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address)", p0, p1, p2));
}
function log(string memory p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256)", p0, p1, p2));
}
function log(string memory p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string)", p0, p1, p2));
}
function log(string memory p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool)", p0, p1, p2));
}
function log(string memory p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address)", p0, p1, p2));
}
function log(bool p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256)", p0, p1, p2));
}
function log(bool p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string)", p0, p1, p2));
}
function log(bool p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool)", p0, p1, p2));
}
function log(bool p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256)", p0, p1, p2));
}
function log(bool p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string)", p0, p1, p2));
}
function log(bool p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool)", p0, p1, p2));
}
function log(bool p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address)", p0, p1, p2));
}
function log(bool p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256)", p0, p1, p2));
}
function log(bool p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string)", p0, p1, p2));
}
function log(bool p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool)", p0, p1, p2));
}
function log(bool p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address)", p0, p1, p2));
}
function log(bool p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256)", p0, p1, p2));
}
function log(bool p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string)", p0, p1, p2));
}
function log(bool p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool)", p0, p1, p2));
}
function log(bool p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address)", p0, p1, p2));
}
function log(address p0, uint256 p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256)", p0, p1, p2));
}
function log(address p0, uint256 p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string)", p0, p1, p2));
}
function log(address p0, uint256 p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool)", p0, p1, p2));
}
function log(address p0, uint256 p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256)", p0, p1, p2));
}
function log(address p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string)", p0, p1, p2));
}
function log(address p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool)", p0, p1, p2));
}
function log(address p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address)", p0, p1, p2));
}
function log(address p0, bool p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256)", p0, p1, p2));
}
function log(address p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string)", p0, p1, p2));
}
function log(address p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool)", p0, p1, p2));
}
function log(address p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address)", p0, p1, p2));
}
function log(address p0, address p1, uint256 p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256)", p0, p1, p2));
}
function log(address p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string)", p0, p1, p2));
}
function log(address p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool)", p0, p1, p2));
}
function log(address p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address)", p0, p1, p2));
}
function log(uint256 p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,uint256,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,string,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,bool,address,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,uint256,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,string,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,bool,address)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,uint256)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,string)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,bool)", p0, p1, p2, p3));
}
function log(uint256 p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint256,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint256,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint256,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint256)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint256,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint256,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint256)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint256 p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint256,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint256 p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint256,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, uint256 p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint256)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,address)", p0, p1, p2, p3));
}
}
文件 92 的 92:draft-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);
}
{
"compilationTarget": {
"contracts/exchange/WithdrawalHandler.sol": "WithdrawalHandler"
},
"evmVersion": "paris",
"libraries": {
"contracts/withdrawal/ExecuteWithdrawalUtils.sol:ExecuteWithdrawalUtils": "0xb54c8fb6b2f143dd58f5b00fde7da4fa05077b20",
"contracts/withdrawal/WithdrawalStoreUtils.sol:WithdrawalStoreUtils": "0x713c6a2479f6c079055a6ad3690d95dedcef9e1e",
"contracts/withdrawal/WithdrawalUtils.sol:WithdrawalUtils": "0x46088fa22988c40ce5abc0647a7638d27a8bf7d1"
},
"metadata": {
"bytecodeHash": "ipfs",
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 10
},
"remappings": []
}
[{"inputs":[{"internalType":"contract RoleStore","name":"_roleStore","type":"address"},{"internalType":"contract DataStore","name":"_dataStore","type":"address"},{"internalType":"contract EventEmitter","name":"_eventEmitter","type":"address"},{"internalType":"contract WithdrawalVault","name":"_withdrawalVault","type":"address"},{"internalType":"contract Oracle","name":"_oracle","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256[]","name":"compactedValues","type":"uint256[]"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"slotIndex","type":"uint256"},{"internalType":"string","name":"label","type":"string"}],"name":"CompactedArrayOutOfBounds","type":"error"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"DisabledFeature","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"EmptyCompactedBlockNumber","type":"error"},{"inputs":[],"name":"EndOfOracleSimulation","type":"error"},{"inputs":[{"internalType":"uint256","name":"startingGas","type":"uint256"},{"internalType":"uint256","name":"estimatedGasLimit","type":"uint256"},{"internalType":"uint256","name":"minAdditionalGasForExecution","type":"uint256"}],"name":"InsufficientExecutionGas","type":"error"},{"inputs":[{"internalType":"uint256","name":"startingGas","type":"uint256"},{"internalType":"uint256","name":"minHandleErrorGas","type":"uint256"}],"name":"InsufficientExecutionGasForErrorHandling","type":"error"},{"inputs":[{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"minHandleExecutionErrorGas","type":"uint256"}],"name":"InsufficientHandleExecutionErrorGas","type":"error"},{"inputs":[{"internalType":"uint256","name":"primaryTokensLength","type":"uint256"},{"internalType":"uint256","name":"primaryPricesLength","type":"uint256"}],"name":"InvalidPrimaryPricesForSimulation","type":"error"},{"inputs":[{"internalType":"uint256","name":"requestAge","type":"uint256"},{"internalType":"uint256","name":"requestExpirationAge","type":"uint256"},{"internalType":"string","name":"requestType","type":"string"}],"name":"RequestNotYetCancellable","type":"error"},{"inputs":[{"internalType":"address","name":"msgSender","type":"address"},{"internalType":"string","name":"role","type":"string"}],"name":"Unauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"oracleBlockNumberType","type":"uint256"}],"name":"UnsupportedOracleBlockNumberType","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"reason","type":"string"}],"name":"OracleError","type":"event"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"components":[{"internalType":"address","name":"account","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address[]","name":"longTokenSwapPath","type":"address[]"},{"internalType":"address[]","name":"shortTokenSwapPath","type":"address[]"}],"internalType":"struct Withdrawal.Addresses","name":"addresses","type":"tuple"},{"components":[{"internalType":"uint256","name":"marketTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minLongTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minShortTokenAmount","type":"uint256"},{"internalType":"uint256","name":"updatedAtBlock","type":"uint256"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"}],"internalType":"struct Withdrawal.Numbers","name":"numbers","type":"tuple"},{"components":[{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"}],"internalType":"struct Withdrawal.Flags","name":"flags","type":"tuple"}],"internalType":"struct Withdrawal.Props","name":"withdrawal","type":"tuple"},{"components":[{"internalType":"uint256","name":"signerInfo","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"compactedMinOracleBlockNumbers","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxOracleBlockNumbers","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedOracleTimestamps","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedDecimals","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMinPrices","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMinPricesIndexes","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxPrices","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxPricesIndexes","type":"uint256[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"},{"internalType":"address[]","name":"priceFeedTokens","type":"address[]"},{"internalType":"address[]","name":"realtimeFeedTokens","type":"address[]"},{"internalType":"bytes[]","name":"realtimeFeedData","type":"bytes[]"}],"internalType":"struct OracleUtils.SetPricesParams","name":"oracleParams","type":"tuple"},{"internalType":"address","name":"keeper","type":"address"}],"name":"_executeWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"}],"name":"cancelWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"components":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callbackContract","type":"address"},{"internalType":"address","name":"uiFeeReceiver","type":"address"},{"internalType":"address","name":"market","type":"address"},{"internalType":"address[]","name":"longTokenSwapPath","type":"address[]"},{"internalType":"address[]","name":"shortTokenSwapPath","type":"address[]"},{"internalType":"uint256","name":"minLongTokenAmount","type":"uint256"},{"internalType":"uint256","name":"minShortTokenAmount","type":"uint256"},{"internalType":"bool","name":"shouldUnwrapNativeToken","type":"bool"},{"internalType":"uint256","name":"executionFee","type":"uint256"},{"internalType":"uint256","name":"callbackGasLimit","type":"uint256"}],"internalType":"struct WithdrawalUtils.CreateWithdrawalParams","name":"params","type":"tuple"}],"name":"createWithdrawal","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","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":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"internalType":"uint256","name":"signerInfo","type":"uint256"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"compactedMinOracleBlockNumbers","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxOracleBlockNumbers","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedOracleTimestamps","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedDecimals","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMinPrices","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMinPricesIndexes","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxPrices","type":"uint256[]"},{"internalType":"uint256[]","name":"compactedMaxPricesIndexes","type":"uint256[]"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"},{"internalType":"address[]","name":"priceFeedTokens","type":"address[]"},{"internalType":"address[]","name":"realtimeFeedTokens","type":"address[]"},{"internalType":"bytes[]","name":"realtimeFeedData","type":"bytes[]"}],"internalType":"struct OracleUtils.SetPricesParams","name":"oracleParams","type":"tuple"}],"name":"executeWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracle","outputs":[{"internalType":"contract Oracle","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"roleStore","outputs":[{"internalType":"contract RoleStore","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"components":[{"internalType":"address[]","name":"primaryTokens","type":"address[]"},{"components":[{"internalType":"uint256","name":"min","type":"uint256"},{"internalType":"uint256","name":"max","type":"uint256"}],"internalType":"struct Price.Props[]","name":"primaryPrices","type":"tuple[]"}],"internalType":"struct OracleUtils.SimulatePricesParams","name":"params","type":"tuple"}],"name":"simulateExecuteWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalVault","outputs":[{"internalType":"contract WithdrawalVault","name":"","type":"address"}],"stateMutability":"view","type":"function"}]