编译器
0.8.17+commit.8df45f5f
文件 1 的 103: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 的 103:Address.sol
pragma solidity ^0.8.1;
library Address {
function isContract(address account) internal view returns (bool) {
return account.code.length > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
(bool success, bytes memory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
function verifyCallResultFromTarget(
address target,
bool success,
bytes memory returndata,
string memory errorMessage
) internal view returns (bytes memory) {
if (success) {
if (returndata.length == 0) {
require(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function _revert(bytes memory returndata, string memory errorMessage) private pure {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
文件 3 的 103:AggregateVault.sol
pragma solidity 0.8.17;
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { TransferUtils } from "../libraries/TransferUtils.sol";
import { Auth, GlobalACL, SWAP_KEEPER, KEEPER_ROLE, REQUEST_HANDLER } from "../Auth.sol";
import { AssetVault } from "./AssetVault.sol";
import { AggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
import { PositionManagerRouter, WhitelistedTokenRegistry } from "../position-managers/PositionManagerRouter.sol";
import { Multicall } from "../libraries/Multicall.sol";
import { NettingMath } from "../libraries/NettingMath.sol";
import { HookType } from "../interfaces/IHookExecutor.sol";
import { Emitter } from "../peripheral/Emitter.sol";
import { Delegatecall } from "../libraries/Delegatecall.sol";
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
import { AggregateVaultHelper } from "../peripheral/AggregateVaultHelper.sol";
import { IAssetVault } from "../interfaces/IAssetVault.sol";
import { IVaultFees } from "../interfaces/IVaultFees.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { IPositionManager } from "../interfaces/IPositionManager.sol";
import { Solarray } from "../libraries/Solarray.sol";
enum Peripheral {
HookHandler,
EventEmitter,
OracleWrapper,
GMI,
AggregateVaultHelper,
GmxV2Handler,
FeeHelper,
RequestHandler,
UniswapV3SwapManager
}
using Delegatecall for address;
using SafeTransferLib for ERC20;
contract AggregateVault is Multicall, AggregateVaultStorage, PositionManagerRouter, GlobalACL {
error ZeroAddress();
error MinGasRequirement();
error AmountEqualsZero();
error RebalanceOpen();
error RebalanceNotOpen();
error FailedNettingCheck();
error FailedConfigValidation();
error DelegateViewRevert();
error OraclePriceSizeInvalid();
error NotAssetVault();
error notRequestHandlerOrAssetVault();
constructor(Auth _auth, WhitelistedTokenRegistry _whitelistedTokenRegistry)
PositionManagerRouter(_whitelistedTokenRegistry)
GlobalACL(_auth)
{ }
function handleDeposit(uint256 assets, uint256 minOutAfterFees, address account, address sender, address callback)
external
payable
onlyAssetVault
{
if (assets == 0) revert AmountEqualsZero();
if (account == address(0)) revert ZeroAddress();
AVStorage storage stg = _getStorage();
uint256 gas = _gasRequirement(callback != address(0));
if (msg.value < gas * tx.gasprice) revert MinGasRequirement();
uint256 key = _saveRequest(sender, account, msg.sender, callback, true, assets, minOutAfterFees);
TransferUtils.transferNativeAsset(stg.rebalanceKeeper, msg.value);
_executeHook(HookType.DEPOSIT_HOOK, msg.data[4:]);
Emitter(stg.emitter).emitDepositRequest(key, account, msg.sender);
}
function handleWithdraw(uint256 shares, uint256 minOutAfterFees, address account, address sender, address callback)
external
payable
onlyAssetVault
{
if (shares == 0) revert AmountEqualsZero();
if (account == address(0)) revert ZeroAddress();
AVStorage storage stg = _getStorage();
uint256 gas = _gasRequirement(callback != address(0));
if (msg.value < gas * tx.gasprice) revert MinGasRequirement();
uint256 key = _saveRequest(sender, account, msg.sender, callback, false, shares, minOutAfterFees);
TransferUtils.transferNativeAsset(stg.rebalanceKeeper, msg.value);
_executeHook(HookType.WITHDRAW_HOOK, msg.data[4:]);
Emitter(stg.emitter).emitWithdrawalRequest(key, account, msg.sender);
}
function clearRequest(uint256 key) external onlyRequestHandlerOrAssetVault returns (OCRequest memory order) {
AVStorage storage stg = _getStorage();
order = stg.pendingRequests[key];
delete stg.pendingRequests[key];
}
function releaseWithdrawal(address underlyingToken, address account, uint256 assets, uint256 totalWithdrawalFee)
external
onlyRequestHandler
{
TransferUtils.transferAsset(underlyingToken, account, assets);
address feeEscrow = _getVaultState().withdrawalFeeEscrow;
if (totalWithdrawalFee > 0 && feeEscrow != address(0)) {
TransferUtils.transferAsset(underlyingToken, feeEscrow, totalWithdrawalFee);
}
}
function incrementEpochDelta(address asset, int256 amount) external onlyRequestHandler {
AssetVaultStorage storage vaultStg = _getVaultFromAsset(asset);
vaultStg.epochDelta += amount;
}
function multicall(bytes[] calldata data)
external
payable
onlyRole(KEEPER_ROLE)
returns (bytes[] memory results, uint256[] memory gasEstimates)
{
(results, gasEstimates) = _multicall(data);
}
function openRebalancePeriod(
uint256[2] memory nextVaultIndexAlloc,
uint256[2] memory nextIndexComposition,
int256 externalPosition,
SetPricesParams memory priceData,
bytes memory _hook
) external onlyRole(KEEPER_ROLE) setOraclePricing(priceData) {
_executeHook(HookType.OPEN_REBALANCE_HOOK, _hook);
VaultState storage vaultState = _getVaultState();
if (vaultState.rebalanceOpen) revert RebalanceOpen();
checkNettingConstraint(
Solarray.arraySum(nextVaultIndexAlloc), nextVaultIndexAlloc, nextIndexComposition, externalPosition
);
pauseDeposits();
RebalanceState storage rebalanceState = _getRebalanceState();
rebalanceState.indexAllocation = nextVaultIndexAlloc;
rebalanceState.indexComposition = nextIndexComposition;
rebalanceState.externalPosition = externalPosition;
rebalanceState.epoch = vaultState.epoch;
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
for (uint256 i = 0; i < 2; i++) {
vaultState.rebalancePPS[i] = getVaultPPS(assetVaults[i].vault, false, true);
}
vaultState.rebalanceOpen = true;
Emitter(_getEmitter()).emitOpenRebalance(
block.timestamp, nextVaultIndexAlloc, nextIndexComposition, externalPosition
);
}
function closeRebalancePeriod(SetPricesParams memory priceData, bytes memory _hook)
external
onlyRole(KEEPER_ROLE)
setOraclePricing(priceData)
{
VaultState storage vaultState = _getVaultState();
if (!vaultState.rebalanceOpen) revert RebalanceNotOpen();
RebalanceState storage rebalanceState = _getRebalanceState();
address aggregateVaultHelper = _getStorage().aggregateVaultHelper;
bytes memory gmiValue = aggregateVaultHelper.delegateCall(
abi.encodeCall(AggregateVaultHelper.getVaultsGmiValue, (vaultState.epoch, true))
);
uint256[2] memory vaultIndexAllocation = abi.decode(gmiValue, (uint256[2]));
checkNettingConstraint(
Solarray.arraySum(vaultIndexAllocation),
rebalanceState.indexAllocation,
rebalanceState.indexComposition,
rebalanceState.externalPosition
);
(int256[2][2] memory nettedMatrix,) = NettingMath.calculateNettedPositions(
rebalanceState.externalPosition, rebalanceState.indexComposition, vaultIndexAllocation
);
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
if (vaultState.epoch > 0) _collectVaultRebalanceFees(assetVaults);
_resetEpochDeltas();
vaultState.rebalanceOpen = false;
vaultState.indexAllocation = rebalanceState.indexAllocation;
_setPositions(nettedMatrix, rebalanceState.externalPosition);
_setCheckpointTvls(assetVaults);
vaultState.epoch += 1;
vaultState.lastRebalanceTime = block.timestamp;
_executeHook(HookType.CLOSE_REBALANCE_HOOK, _hook);
unpauseDeposits();
Emitter(_getEmitter()).emitCloseRebalance(block.timestamp);
}
function checkNettingConstraint(
uint256 vaultCumulativeHoldings,
uint256[2] memory vaultHoldings,
uint256[2] memory indexComposition,
int256 externalPosition
) internal view {
if (_getStorage().shouldCheckNetting) {
if (
!NettingMath.isNetted(
vaultCumulativeHoldings, indexComposition, vaultHoldings, externalPosition, _getNettedThreshold()
)
) {
revert FailedNettingCheck();
}
}
}
function rebalanceOpen() external view returns (bool) {
return _getVaultState().rebalanceOpen;
}
function getRequest(uint256 key) external view returns (OCRequest memory) {
return _getStorage().pendingRequests[key];
}
function getVaultPPS(address _assetVault, bool isDeposit, bool useLlo) public returns (uint256) {
address aggregateVaultHelper = _getStorage().aggregateVaultHelper;
bytes memory ret = aggregateVaultHelper.delegateCall(
abi.encodeCall(AggregateVaultHelper.getVaultPPS, (_assetVault, isDeposit, useLlo))
);
return abi.decode(ret, (uint256));
}
function getVaultTVL(address _assetVault, bool useLlo) public returns (uint256 _tvl) {
address aggregateVaultHelper = _getStorage().aggregateVaultHelper;
bytes memory ret =
aggregateVaultHelper.delegateCall(abi.encodeCall(AggregateVaultHelper.getVaultTVL, (_assetVault, useLlo)));
return abi.decode(ret, (uint256));
}
function previewDepositFee(address token, uint256 size, bool useLlo) external returns (uint256 totalDepositFee) {
address feeHelper = _getFeeHelper();
(bytes memory ret) = feeHelper.delegateCall(abi.encodeCall(IVaultFees.getDepositFee, (token, size, useLlo)));
(totalDepositFee) = abi.decode(ret, (uint256));
}
function previewWithdrawalFee(address token, uint256 size, bool useLlo)
external
returns (uint256 totalWithdrawalFee)
{
address feeHelper = _getFeeHelper();
(bytes memory ret) = feeHelper.delegateCall(abi.encodeCall(IVaultFees.getWithdrawalFee, (token, size, useLlo)));
(totalWithdrawalFee) = abi.decode(ret, (uint256));
}
function previewVaultCap(address _asset) external view returns (uint256) {
uint256 vidx = _getTokenToAssetVaultIndex()[_asset];
VaultState memory state = _getVaultState();
return state.vaultCaps[vidx];
}
function getVaultTimelockAddress(address _asset) external view returns (address timelock) {
AssetVaultStorage storage vaultStg = _getVaultFromAsset(_asset);
return vaultStg.timelockYieldBoost;
}
function readStorageSlots(bytes32[] calldata _slots) external view returns (bytes32[] memory _values) {
_values = new bytes32[](_slots.length);
for (uint256 i; i < _slots.length; i++) {
uint256 value;
bytes32 slot = _slots[i];
assembly {
value := sload(slot)
}
_values[i] = bytes32(value);
}
}
function setShouldCheckNetting(bool _newVal) external onlyConfigurator {
AVStorage storage stg = _getStorage();
stg.shouldCheckNetting = _newVal;
}
function setShouldUseGmxFee(bool _newVal) external onlyConfigurator {
AVStorage storage stg = _getStorage();
stg.shouldUseGmxFee = _newVal;
}
function setAssetVaults(AssetVaultStorage[2] calldata assetVaults) external onlyConfigurator {
AssetVaultStorage[2] storage vaults = _getAssetVaultEntries();
mapping(address => uint256) storage tokenToAssetVaultIndex = _getTokenToAssetVaultIndex();
mapping(address => uint256) storage vaultToAssetVaultIndex = _getVaultToAssetVaultIndex();
for (uint256 i = 0; i < 2; i++) {
vaults[i] = assetVaults[i];
tokenToAssetVaultIndex[assetVaults[i].token] = i;
vaultToAssetVaultIndex[assetVaults[i].vault] = i;
}
}
function setVaultFees(uint256 _performanceFee, uint256 _managementFee, uint256 _withdrawalFee, uint256 _depositFee)
external
onlyConfigurator
{
_getStorage().vaultFees = VaultFees({
performanceFee: _performanceFee,
managementFee: _managementFee,
withdrawalFee: _withdrawalFee,
depositFee: _depositFee
});
}
function setVaultTimelockPercent(address asset, uint256 newTimelockFeePercent) external onlyConfigurator {
if (newTimelockFeePercent >= 100 * 1e18) revert FailedConfigValidation();
AssetVaultStorage storage vaultStg = _getVaultFromAsset(asset);
vaultStg.timelockBoostPercent = newTimelockFeePercent;
}
function setPeripheral(Peripheral peripheral, address addr) external onlyConfigurator {
if (addr == address(0)) revert ZeroAddress();
AVStorage storage stg = _getStorage();
if (peripheral == Peripheral.HookHandler) {
stg.hookHandler = addr;
} else if (peripheral == Peripheral.EventEmitter) {
stg.emitter = addr;
} else if (peripheral == Peripheral.OracleWrapper) {
stg.oracleWrapper = addr;
} else if (peripheral == Peripheral.GMI) {
stg.gmi = payable(addr);
} else if (peripheral == Peripheral.AggregateVaultHelper) {
stg.aggregateVaultHelper = addr;
} else if (peripheral == Peripheral.GmxV2Handler) {
stg.gmxV2Handler = addr;
} else if (peripheral == Peripheral.FeeHelper) {
stg.feeHelper = addr;
} else if (peripheral == Peripheral.RequestHandler) {
stg.requestHandler = addr;
} else if (peripheral == Peripheral.UniswapV3SwapManager) {
stg.uniswapV3SwapManager = addr;
} else {
revert("AggregateVault: invalid peripheral");
}
}
function setThresholds(uint256 _newNettedThreshold, uint256 _zeroSumPnlThreshold, uint256 _swapSlippage)
external
onlyConfigurator
{
if (
_zeroSumPnlThreshold == 0 || _zeroSumPnlThreshold >= 1e18 || _newNettedThreshold == 0
|| _newNettedThreshold >= 10_000
) revert FailedConfigValidation();
AVStorage storage stg = _getStorage();
stg.zeroSumPnlThreshold = _zeroSumPnlThreshold;
stg.nettedThreshold = _newNettedThreshold;
stg.swapSlippage = _swapSlippage;
}
function setL1BlockTolerance(uint8 _newBlockTolerance) external onlyConfigurator {
_setL1BlockTolerance(_newBlockTolerance);
}
function setExecutionGasAmounts(uint256 executionGasAmount, uint256 executionGasAmountCallback)
external
onlyConfigurator
{
AVStorage storage stg = _getStorage();
stg.executionGasAmount = executionGasAmount;
stg.executionGasAmountCallback = executionGasAmountCallback;
}
function setRebalanceKeeper(address newKeeper) external onlyConfigurator {
if (newKeeper == address(0)) revert ZeroAddress();
_setRebalanceKeeper(newKeeper);
}
function addPositionManager(IPositionManager _manager) external onlyConfigurator {
IPositionManager[] storage positionManagers = _getPositionManagers();
positionManagers.push(_manager);
}
function setVaultCaps(uint256[2] memory _newCaps) external onlyConfigurator {
VaultState storage state = _getVaultState();
state.vaultCaps = _newCaps;
}
function setFeeRecipient(address _recipient, address _depositFeeEscrow, address _withdrawalFeeEscrow)
external
onlyConfigurator
{
if (_recipient == address(0) || _depositFeeEscrow == address(0) || _withdrawalFeeEscrow == address(0)) {
revert ZeroAddress();
}
VaultState storage state = _getVaultState();
state.feeRecipient = _recipient;
state.depositFeeEscrow = _depositFeeEscrow;
state.withdrawalFeeEscrow = _withdrawalFeeEscrow;
}
function delegateview(address _target, bytes calldata _data) external returns (bool _success, bytes memory _ret) {
(bool success, bytes memory ret) = address(this).call(abi.encodeCall(this.delegateviewRevert, (_target, _data)));
if (success) revert DelegateViewRevert();
(_success, _ret) = abi.decode(ret, (bool, bytes));
}
function delegateviewRevert(address _target, bytes memory _data) external {
(bool success, bytes memory ret) = _target.delegatecall(_data);
bytes memory encoded = abi.encode(success, ret);
assembly {
revert(add(encoded, 0x20), mload(encoded))
}
}
function _collectVaultRebalanceFees(AssetVaultStorage[2] memory assetVaults) internal {
uint256 performanceFeeInAsset;
uint256 managementFeeInAsset;
uint256 timelockYieldMintAmount;
uint256 totalVaultFee;
address feeHelper = _getFeeHelper();
VaultState storage vaultState = _getVaultState();
for (uint256 i = 0; i < 2; i++) {
(bytes memory ret) = feeHelper.delegateCall(
abi.encodeCall(IVaultFees.getVaultRebalanceFees, (assetVaults[i].token, vaultState.lastRebalanceTime))
);
(performanceFeeInAsset, managementFeeInAsset, timelockYieldMintAmount, totalVaultFee) =
abi.decode(ret, (uint256, uint256, uint256, uint256));
if (totalVaultFee > 0) {
TransferUtils.transferAsset(assetVaults[i].token, vaultState.feeRecipient, totalVaultFee);
}
if (timelockYieldMintAmount > 0 && assetVaults[i].timelockYieldBoost != address(0)) {
AssetVault(assetVaults[i].vault).mintTo(timelockYieldMintAmount, assetVaults[i].timelockYieldBoost);
}
Emitter(_getEmitter()).emitCollectVaultFees(
totalVaultFee,
performanceFeeInAsset,
managementFeeInAsset,
timelockYieldMintAmount,
assetVaults[i].vault
);
}
}
function _resetEpochDeltas() internal {
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
assetVaults[0].epochDelta = int256(0);
assetVaults[1].epochDelta = int256(0);
}
function _setCheckpointTvls(AssetVaultStorage[2] storage assetVaults) internal {
assetVaults[0].lastCheckpointTvl = getVaultTVL(assetVaults[0].vault, true);
assetVaults[1].lastCheckpointTvl = getVaultTVL(assetVaults[1].vault, true);
}
function depositEth() external payable onlyRole(KEEPER_ROLE) { }
function withdrawEth(uint256 amount) external payable onlyRole(KEEPER_ROLE) {
TransferUtils.transferNativeAsset(msg.sender, amount);
}
function pauseDeposits() public onlyRole(KEEPER_ROLE) {
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
for (uint256 i = 0; i < 2; i++) {
IAssetVault(assetVaults[i].vault).pauseDepositWithdraw();
}
}
function unpauseDeposits() public onlyRole(KEEPER_ROLE) {
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
for (uint256 i = 0; i < 2; i++) {
IAssetVault(assetVaults[i].vault).unpauseDepositWithdraw();
}
}
modifier setOraclePricing(SetPricesParams memory prices) {
if (prices.realtimeFeedTokens.length != prices.realtimeFeedData.length) revert OraclePriceSizeInvalid();
for (uint256 i = 0; i < prices.realtimeFeedTokens.length; i++) {
OracleWrapper(_getOracleWrapper()).setAndGetLloPrice(
prices.realtimeFeedTokens[i], prices.realtimeFeedData[i]
);
}
_;
}
modifier onlyAssetVault() {
if (!_isAssetVault()) revert NotAssetVault();
_;
}
modifier onlyRequestHandlerOrAssetVault() {
if (!(_isAssetVault() || AUTH.hasRole(REQUEST_HANDLER, msg.sender))) revert notRequestHandlerOrAssetVault();
_;
}
function _isAssetVault() internal view returns (bool) {
AssetVaultStorage[2] storage assetVaults = _getAssetVaultEntries();
for (uint256 i = 0; i < 2; ++i) {
if (msg.sender == assetVaults[i].vault) {
return true;
}
}
return false;
}
function _gasRequirement(bool _callback) internal view returns (uint256) {
return _callback ? _getStorage().executionGasAmountCallback : _getStorage().executionGasAmount;
}
function _onlyConfigurator() internal override onlyConfigurator { }
function _validateExecuteCallAuth() internal override onlyRole(KEEPER_ROLE) { }
function _onlySwapIssuer() internal override onlyRole(SWAP_KEEPER) { }
}
文件 4 的 103:AggregateVaultHelper.sol
pragma solidity 0.8.17;
import { AggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
import { BaseHandler } from "../BaseHandler.sol";
import { GMI } from "../index/GMI.sol";
import { Pricing } from "../libraries/Pricing.sol";
import { LibAggregateVaultUtils } from "../libraries/LibAggregateVaultUtils.sol";
import { TOKEN_USDC_NATIVE, TOKEN_WETH } from "../constants.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
import { IPositionManager } from "../interfaces/IPositionManager.sol";
import { PriceCast } from "../libraries/PriceCast.sol";
import { SafeCast } from "../libraries/SafeCast.sol";
import { NettedPositionTracker } from "../libraries/NettedPositionTracker.sol";
import { Delegatecall } from "../libraries/Delegatecall.sol";
import { Solarray } from "../libraries/Solarray.sol";
import { GmxStorage } from "../libraries/GmxStorage.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ISwapManager } from "../interfaces/ISwapManager.sol";
import { LibCycle } from "../libraries/LibCycle.sol";
import { GlobalACL, Auth } from "../Auth.sol";
using SafeCast for uint256;
using SafeCast for int256;
using PriceCast for uint256;
using Delegatecall for address;
using Solarray for uint256[2];
using SafeTransferLib for ERC20;
contract AggregateVaultViews is AggregateVaultStorage {
function getAssetVaultEntries() public view returns (AssetVaultStorage[2] memory _assetVaultEntry) {
_assetVaultEntry = _getStorage().vaults;
}
function tokenToAssetVaultIndex(address _token) public view returns (uint256 _idx) {
_idx = _getTokenToAssetVaultIndex()[_token];
}
function vaultToAssetVaultIndex(address _vault) public view returns (uint256 _idx) {
_idx = _getVaultToAssetVaultIndex()[_vault];
}
function getVaultState() public view returns (VaultState memory _vaultState) {
_vaultState = _getVaultState();
}
function getRebalanceState() public view returns (RebalanceState memory _rebalanceState) {
_rebalanceState = _getRebalanceState();
}
function getVaultGmiAttribution() public view returns (uint256[2] memory _gmiAttribution) {
_gmiAttribution = _getStorage().vaultGmiAttribution;
}
function getLastNettedPrice(uint256 _epoch) public view returns (int256[2] memory _nettedPrices) {
_nettedPrices = _getNettedPrices(_epoch);
}
function getPositionManagers() public view returns (IPositionManager[] memory _positionManagers) {
_positionManagers = _getPositionManagers();
}
function getNettedPositions() public view returns (int256[2][2] memory _nettedPositions) {
_nettedPositions = _getStorage().nettedPositions;
}
function getActiveExternalPosition() public view returns (int256 _activeExternalPosition) {
_activeExternalPosition = _getStorage().externalPosition;
}
}
contract AggregateVaultHelper is AggregateVaultStorage, AggregateVaultViews, BaseHandler, GlobalACL {
constructor(Auth _auth) GlobalACL(_auth) { }
function getVaultPPS(address _vault, bool isDeposit, bool useLlo) external onlyDelegateCall returns (uint256) {
VaultState memory vaultState = _getVaultState();
uint256 index = vaultToAssetVaultIndex(_vault);
if (vaultState.rebalanceOpen) return vaultState.rebalancePPS[index];
AssetVaultStorage storage vault = _getStorage().vaults[index];
uint256 vaultSupply = ERC20(vault.vault).totalSupply();
uint256 decimals = _vaultDecimals(index);
uint256 oneToken = 10 ** decimals;
if (vaultSupply == 0) return oneToken;
uint256 nativeTokenBalance = ERC20(vault.token).balanceOf(address(this));
uint256 gmiUsd = useLlo ? _vaultGmiBalanceUsd(index) : _vaultGmiBalanceUsdChainlink(index);
uint256 vaultTokenPrice = useLlo ? _vaultTokenPrice(index) : _vaultTokenPriceChainlink(index);
uint256 gmiToVaultToken = gmiUsd * 1e12 / vaultTokenPrice;
uint256 positionMargin =
_getAssetVaultHedgesInNativeToken(index, vaultTokenPrice.toInternalPrice(decimals), decimals);
uint256 totalBalance = nativeTokenBalance + gmiToVaultToken + positionMargin;
return isDeposit
? (totalBalance * oneToken + vaultSupply - 1) / vaultSupply
: totalBalance * oneToken / vaultSupply;
}
function getVaultTVL(address _vault, bool useLlo) external onlyDelegateCall returns (uint256) {
uint256 index = vaultToAssetVaultIndex(_vault);
uint256 decimals = _vaultDecimals(index);
if (_getStorage().vaultState.rebalanceOpen) {
uint256 totalSupply = ERC20(_vault).totalSupply();
return _getStorage().vaultState.rebalancePPS[index] * totalSupply / 10 ** decimals;
}
AssetVaultStorage storage vault = _getStorage().vaults[index];
uint256 gmiUsd = useLlo ? _vaultGmiBalanceUsd(index) : _vaultGmiBalanceUsdChainlink(index);
uint256 vaultTokenPrice = useLlo ? _vaultTokenPrice(index) : _vaultTokenPriceChainlink(index);
uint256 positionMargin =
_getAssetVaultHedgesInNativeToken(index, vaultTokenPrice.toInternalPrice(decimals), decimals);
uint256 gmiToVaultToken = gmiUsd * 1e12 / vaultTokenPrice;
uint256 nativeTokenBalance = ERC20(vault.token).balanceOf(address(this));
return nativeTokenBalance + gmiToVaultToken + positionMargin;
}
function getVaultPPSWithPrices(address _vault, bool isDeposit, GmxStorage.MarketPrices[] memory prices, bool max)
external
onlyDelegateCall
returns (uint256)
{
uint256 index = vaultToAssetVaultIndex(_vault);
AssetVaultStorage storage vault = _getStorage().vaults[index];
uint256 vaultSupply = ERC20(vault.vault).totalSupply();
uint256 decimals = _vaultDecimals(index);
uint256 oneToken = 10 ** decimals;
if (vaultSupply == 0) return oneToken;
uint256 gmiUsd;
uint256 vaultTokenPrice;
{
uint256 ethPrice = max ? prices[0].longTokenPrice.max : prices[0].longTokenPrice.min;
uint256 usdcPrice = max ? prices[0].shortTokenPrice.max : prices[0].shortTokenPrice.min;
uint256 gmiPPS = GMI(_getStorage().gmi).pps(prices);
uint256 gmiBalance = LibAggregateVaultUtils.getVaultGmiWithPrices(
index,
_getVaultState().epoch,
gmiPPS,
Solarray.int256s(usdcPrice.toInternalPrice(6).toInt256(), ethPrice.toInternalPrice(18).toInt256())
);
gmiUsd = gmiPPS * gmiBalance / 1e18;
vaultTokenPrice = vault.token == TOKEN_USDC_NATIVE ? usdcPrice : ethPrice;
}
uint256 gmiToVaultToken = gmiUsd * 1e12 / vaultTokenPrice;
uint256 positionMargin =
_getAssetVaultHedgesInNativeToken(index, vaultTokenPrice.toInternalPrice(decimals), decimals);
uint256 totalBalance = ERC20(vault.token).balanceOf(address(this)) + gmiToVaultToken + positionMargin;
return isDeposit
? (totalBalance * oneToken + vaultSupply - 1) / vaultSupply
: totalBalance * oneToken / vaultSupply;
}
function getVaultTVLWithPrices(address _vault, GmxStorage.MarketPrices[] memory prices, bool max)
external
onlyDelegateCall
returns (uint256)
{
uint256 index = vaultToAssetVaultIndex(_vault);
uint256 decimals = _vaultDecimals(index);
AssetVaultStorage storage vault = _getStorage().vaults[index];
uint256 ethPrice = max ? prices[0].longTokenPrice.max : prices[0].longTokenPrice.min;
uint256 usdcPrice = max ? prices[0].shortTokenPrice.max : prices[0].shortTokenPrice.min;
uint256 gmiPPS = GMI(_getStorage().gmi).pps(prices);
uint256 gmiBalance = LibAggregateVaultUtils.getVaultGmiWithPrices(
index,
_getVaultState().epoch,
gmiPPS,
Solarray.int256s(usdcPrice.toInternalPrice(6).toInt256(), ethPrice.toInternalPrice(18).toInt256())
);
uint256 gmiUsd = gmiPPS * gmiBalance / 1e18;
uint256 vaultTokenPrice = vault.token == TOKEN_USDC_NATIVE ? usdcPrice : ethPrice;
uint256 positionMargin =
_getAssetVaultHedgesInNativeToken(index, vaultTokenPrice.toInternalPrice(decimals), decimals);
uint256 gmiToVaultToken = gmiUsd * 1e12 / vaultTokenPrice;
uint256 nativeTokenBalance = ERC20(vault.token).balanceOf(address(this));
return nativeTokenBalance + gmiToVaultToken + positionMargin;
}
function getVaultGmi(uint256 currentEpoch, bool useLlo) public view returns (uint256[2] memory gmiAmounts) {
return _getVaultsGmi(currentEpoch, useLlo);
}
function getVaultsGmiValue(uint256 currentEpoch, bool useLlo)
external
view
onlyDelegateCall
returns (uint256[2] memory)
{
return _getVaultsGmiInUsd(currentEpoch, useLlo);
}
function getVaultsGmiValueWithPrices(GmxStorage.MarketPrices[] memory prices, bool max)
external
view
onlyDelegateCall
returns (uint256[2] memory gmiUsdAmounts)
{
uint256 currentEpoch = _getVaultState().epoch;
uint256 ethPrice = max ? prices[0].longTokenPrice.max : prices[0].longTokenPrice.min;
uint256 usdcPrice = max ? prices[0].shortTokenPrice.max : prices[0].shortTokenPrice.min;
uint256 gmiPPS = GMI(_getStorage().gmi).pps(prices);
gmiUsdAmounts = [
LibAggregateVaultUtils.getVaultGmiWithPrices(
0,
currentEpoch,
gmiPPS,
Solarray.int256s(usdcPrice.toInternalPrice(6).toInt256(), ethPrice.toInternalPrice(18).toInt256())
),
LibAggregateVaultUtils.getVaultGmiWithPrices(
1,
currentEpoch,
gmiPPS,
Solarray.int256s(usdcPrice.toInternalPrice(6).toInt256(), ethPrice.toInternalPrice(18).toInt256())
)
];
gmiUsdAmounts[0] = gmiUsdAmounts[0] * gmiPPS / 1e18;
gmiUsdAmounts[1] = gmiUsdAmounts[1] * gmiPPS / 1e18;
}
function cycle(bool shouldRebalanceGmi)
external
onlyDelegateCall
returns (LibCycle.GMIMintRequest[2] memory, LibCycle.GMIBurnRequest[2] memory)
{
require(getVaultState().rebalanceOpen, "!rebalanceOpen");
return LibCycle.cycle(shouldRebalanceGmi);
}
function fulfilRequests() external onlyDelegateCall {
require(getVaultState().rebalanceOpen, "!rebalanceOpen");
LibCycle.fulfilRequests();
}
function rebalanceGmi(uint256[2] memory _previous, uint256[2] memory _new)
external
onlyDelegateCall
returns (LibCycle.GMIMintRequest[2] memory _mintRequests, LibCycle.GMIBurnRequest[2] memory _burnRequests)
{
uint256 gmiPrice = Pricing.getIndexPps(_getStorage().oracleWrapper, GMI(_getStorage().gmi));
(_mintRequests, _burnRequests) = LibCycle.rebalanceGmi(_previous, _new, gmiPrice);
}
function setNettedPositions(int256[2][2] memory nettedPositions, int256 externalPosition)
public
onlyDelegateCall
onlyConfigurator
{
_setPositions(nettedPositions, externalPosition);
}
function setVaultGmiAttribution(uint256[2] memory _gmiAttribution) external onlyDelegateCall onlyConfigurator {
_getStorage().vaultGmiAttribution = _gmiAttribution;
}
function setLastNettedPrices(uint256 epoch, int256[2] memory _nettedPrices)
external
onlyDelegateCall
onlyConfigurator
{
_getStorage().lastNettedPrices[epoch] = _nettedPrices;
}
function setEpoch(uint256 epoch) external onlyDelegateCall onlyConfigurator {
_getStorage().vaultState.epoch = epoch;
}
function clearMintBurnRequests(uint256 start, uint256 end) external onlyDelegateCall onlyConfigurator {
for (uint256 i = start; i <= end; i++) {
LibCycle.clearMintBurnRequestForEpoch(i);
}
}
function setSwapSlippageTolerance(uint256 _slippage) external onlyDelegateCall onlyConfigurator {
_getStorage().swapSlippage = _slippage;
}
function getVaultTVLBreakdown(address _assetVault, bool _useLlo)
public
onlyDelegateCall
returns (uint256 _total, uint256 _buffer, uint256 _gmi, uint256 _hedges)
{
(_total, _buffer, _gmi, _hedges) =
_getAssetVaultTvl(_getAssetVaultEntry(vaultToAssetVaultIndex(_assetVault)), _useLlo);
}
function _getAssetVaultTvl(AssetVaultStorage storage _assetVault, bool _useLlo)
internal
returns (uint256 _totalTvl, uint256 _bufferTvl, uint256 _gmiTvl, uint256 _hedgesTvl)
{
uint256 index = vaultToAssetVaultIndex(_assetVault.vault);
_bufferTvl = ERC20(_assetVault.token).balanceOf(address(this));
uint256 vaultTokenPrice = _useLlo ? _vaultTokenPrice(index) : _vaultTokenPriceChainlink(index);
uint256 decimals = _vaultDecimals(index);
_gmiTvl = _useLlo ? _vaultGmiBalanceUsd(index) : _vaultGmiBalanceUsdChainlink(index);
_gmiTvl = _gmiTvl * 1e12 / vaultTokenPrice;
_hedgesTvl = _getAssetVaultHedgesInNativeToken(index, vaultTokenPrice.toInternalPrice(decimals), decimals);
_totalTvl = _bufferTvl + _gmiTvl + _hedgesTvl;
}
function _getAssetVaultHedgesInNativeToken(uint256 _vaultIdx, uint256 tokenPrice, uint256 tokenDecimals)
internal
returns (uint256 _hedgesToken)
{
uint256 hedgesUsd = _getAssetVaultHedgeInUsd(_vaultIdx);
_hedgesToken = (hedgesUsd * (10 ** tokenDecimals)) / tokenPrice;
}
function _getAssetVaultHedgeInUsd(uint256 _vaultIdx) internal returns (uint256 _hedgesUsd) {
AVStorage storage stg = _getStorage();
uint256 positionMargin;
if (stg.externalPosition > 0 && _vaultIdx == 0) {
(positionMargin,) = _getTotalMargin(TOKEN_WETH);
return positionMargin * 1e18 / 1e30;
} else if (stg.externalPosition < 0 && _vaultIdx == 1) {
(positionMargin,) = _getTotalMargin(TOKEN_WETH);
return positionMargin * 1e18 / 1e30;
} else {
return 0;
}
}
function _getTotalMargin(address _token) internal returns (uint256 _totalMargin, bool _isLong) {
IPositionManager[] storage positionManagers = _getPositionManagers();
uint256 length = positionManagers.length;
bool unset = true;
_isLong = false;
for (uint256 i = 0; i < length; ++i) {
bytes memory ret =
address(positionManagers[i]).delegateCall(abi.encodeWithSignature("positionMargin(address)", _token));
(uint256 margin, bool isLong_) = abi.decode(ret, (uint256, bool));
if (margin > 0) {
if (unset) {
_isLong = isLong_;
unset = false;
} else {
require(_isLong == isLong_, "AggregateVaultHelper: mixed long/short");
}
}
_totalMargin += margin;
}
}
function getTotalNotional(address _token) public returns (uint256 _totalNotional, bool _isLong) {
IPositionManager[] storage positionManagers = _getPositionManagers();
uint256 length = positionManagers.length;
bool unset = true;
_isLong = false;
for (uint256 i = 0; i < length; ++i) {
bytes memory ret =
address(positionManagers[i]).delegateCall(abi.encodeWithSignature("positionNotional(address)", _token));
(uint256 notional, bool isLong_) = abi.decode(ret, (uint256, bool));
if (notional > 0) {
if (unset) {
_isLong = isLong_;
unset = false;
} else {
require(_isLong == isLong_, "AggregateVaultHelper: mixed long/short");
}
}
_totalNotional += notional;
}
}
function _vaultGmiBalanceUsd(uint256 _idx) internal view returns (uint256) {
uint256 pps = Pricing.getIndexPps(_getStorage().oracleWrapper, GMI(_getStorage().gmi));
uint256 gmiBalance = LibAggregateVaultUtils.getVaultGmi(_idx, _getVaultState().epoch, true);
return pps * gmiBalance / 1e18;
}
function _vaultGmiBalanceUsdChainlink(uint256 _idx) internal view returns (uint256) {
uint256 pps = Pricing.getIndexPpsChainlink(_getStorage().oracleWrapper, GMI(_getStorage().gmi));
uint256 gmiBalance = LibAggregateVaultUtils.getVaultGmi(_idx, _getVaultState().epoch, false);
return pps * gmiBalance / 1e18;
}
function _getVaultsGmiInUsd(uint256 currentEpoch, bool useLlo)
internal
view
returns (uint256[2] memory gmiUsdAmounts)
{
gmiUsdAmounts = [
LibAggregateVaultUtils.getVaultGmi(0, currentEpoch, useLlo),
LibAggregateVaultUtils.getVaultGmi(1, currentEpoch, useLlo)
];
uint256 pps = useLlo
? Pricing.getIndexPps(_getStorage().oracleWrapper, GMI(_getStorage().gmi))
: Pricing.getIndexPpsChainlink(_getStorage().oracleWrapper, GMI(_getStorage().gmi));
gmiUsdAmounts[0] = gmiUsdAmounts[0] * pps / 1e18;
gmiUsdAmounts[1] = gmiUsdAmounts[1] * pps / 1e18;
}
function _getVaultsGmi(uint256 currentEpoch, bool useLlo) internal view returns (uint256[2] memory gmiAmounts) {
return LibAggregateVaultUtils.getVaultsGmi(currentEpoch, useLlo);
}
function _vaultTokenPrice(uint256 _idx) internal view returns (uint256) {
address token = _getStorage().vaults[_idx].token;
address oracle = _getStorage().oracleWrapper;
if (token == TOKEN_USDC_NATIVE) {
return OracleWrapper(oracle).getChainlinkPrice(token);
} else {
return OracleWrapper(oracle).getLloPriceWithinL1Blocks(token);
}
}
function _vaultTokenPriceChainlink(uint256 _idx) internal view returns (uint256) {
address token = _getStorage().vaults[_idx].token;
address oracle = _getStorage().oracleWrapper;
return OracleWrapper(oracle).getChainlinkPrice(token);
}
function _vaultDecimals(uint256 _idx) internal view returns (uint256) {
address token = _getStorage().vaults[_idx].token;
return token == TOKEN_USDC_NATIVE ? 6 : 18;
}
function callbackSigs() external pure returns (bytes4[] memory) {
bytes4[] memory sigs = new bytes4[](0);
return sigs;
}
}
文件 5 的 103:AggregateVaultStorage.sol
pragma solidity 0.8.17;
import { Delegatecall } from "../libraries/Delegatecall.sol";
import { IHookExecutor, HookType } from "../interfaces/IHookExecutor.sol";
import { IPositionManager } from "../interfaces/IPositionManager.sol";
import { IArbSys } from "../interfaces/IArbSys.sol";
import { ARBSYS } from "../constants.sol";
bytes32 constant STORAGE_SLOT = keccak256("AggregateVault.storage");
library LibAggregateVaultStorage {
function getStorage() internal pure returns (AggregateVaultStorage.AVStorage storage _storage) {
bytes32 slot = STORAGE_SLOT;
assembly {
_storage.slot := slot
}
}
function getTokenToAssetVaultIndex()
internal
view
returns (mapping(address => uint256) storage _tokenToAssetVaultIndex)
{
_tokenToAssetVaultIndex = getStorage().tokenToAssetVaultIndex;
}
function getVaultState() internal view returns (AggregateVaultStorage.VaultState storage _vaultState) {
_vaultState = getStorage().vaultState;
}
function getRebalanceState() internal view returns (AggregateVaultStorage.RebalanceState storage _rebalanceState) {
_rebalanceState = getStorage().rebalanceState;
}
function getEmitter() internal view returns (address _emitter) {
_emitter = getStorage().emitter;
}
}
abstract contract AggregateVaultStorage {
error InvalidAsset();
enum CallType {
Call,
DelegateCall
}
struct AssetVaultStorage {
address vault;
address token;
address timelockYieldBoost;
uint256 feeWatermarkPPS;
uint256 feeWatermarkDate;
int256 epochDelta;
uint256 lastCheckpointTvl;
uint256 timelockBoostPercent;
}
struct SetPricesParams {
address[] realtimeFeedTokens;
bytes[] realtimeFeedData;
}
struct RebalanceState {
uint256[2] indexAllocation;
uint256[2] indexComposition;
int256 externalPosition;
uint256 epoch;
}
struct VaultState {
uint256 epoch;
bool rebalanceOpen;
uint256 lastRebalanceTime;
address feeRecipient;
address depositFeeEscrow;
address withdrawalFeeEscrow;
uint256[2] indexAllocation;
uint256[2] vaultCaps;
uint256[2] rebalancePPS;
}
struct VaultFees {
uint256 performanceFee;
uint256 managementFee;
uint256 withdrawalFee;
uint256 depositFee;
}
struct OCRequest {
address sender;
address account;
address vault;
address callback;
bool isDeposit;
uint256 amount;
uint256 minOut;
uint256 requestBlock;
}
struct AVStorage {
VaultState vaultState;
AssetVaultStorage[2] vaults;
VaultFees vaultFees;
mapping(address => uint256) tokenToAssetVaultIndex;
mapping(address => uint256) vaultToAssetVaultIndex;
RebalanceState rebalanceState;
bytes32 hooksConfig;
address hookHandler;
address emitter;
uint256 requestNonce;
IPositionManager[] positionManagers;
int256 externalPosition;
int256[2][2] nettedPositions;
mapping(uint256 => OCRequest) pendingRequests;
address rebalanceKeeper;
address feeHelper;
uint256 executionGasAmount;
uint256 executionGasAmountCallback;
mapping(uint256 => int256[2]) lastNettedPrices;
uint256 zeroSumPnlThreshold;
uint8 L1BlockTolerance;
bool shouldCheckNetting;
uint256 nettedThreshold;
address oracleWrapper;
uint256[2] vaultGmiAttribution;
address payable gmi;
address aggregateVaultHelper;
address gmxV2Handler;
address requestHandler;
bool shouldUseGmxFee;
address uniswapV3SwapManager;
uint256 swapSlippage;
}
function _getStorage() internal pure returns (AVStorage storage _storage) {
_storage = LibAggregateVaultStorage.getStorage();
}
function _getVaultState() internal view returns (VaultState storage _vaultState) {
_vaultState = _getStorage().vaultState;
}
function _getEmitter() internal view returns (address _emitter) {
_emitter = _getStorage().emitter;
}
function _getRequestHandler() internal view returns (address _rhandler) {
_rhandler = _getStorage().requestHandler;
}
function _getOracleWrapper() internal view returns (address) {
return _getStorage().oracleWrapper;
}
function _getGmxV2Handler() internal view returns (address) {
return _getStorage().gmxV2Handler;
}
function _getShouldUseGmxFee() internal view returns (bool) {
return _getStorage().shouldUseGmxFee;
}
function _getL1BlockTolerance() internal view returns (uint8) {
return _getStorage().L1BlockTolerance;
}
function _getAssetVaultEntries() internal view returns (AssetVaultStorage[2] storage) {
return _getStorage().vaults;
}
function _setL1BlockTolerance(uint8 newTolerance) internal {
_getStorage().L1BlockTolerance = newTolerance;
}
function _setRebalanceKeeper(address newKeeper) internal {
_getStorage().rebalanceKeeper = newKeeper;
}
function _getRebalanceState() internal view returns (RebalanceState storage _rebalanceState) {
_rebalanceState = _getStorage().rebalanceState;
}
function _getNettedThreshold() internal view returns (uint256 _nettedThreshold) {
_nettedThreshold = _getStorage().nettedThreshold;
}
function _getPositionManagers() internal view returns (IPositionManager[] storage _positionManagers) {
_positionManagers = _getStorage().positionManagers;
}
function _getVaultToAssetVaultIndex()
internal
view
returns (mapping(address => uint256) storage _vaultToAssetVaultIndex)
{
_vaultToAssetVaultIndex = _getStorage().vaultToAssetVaultIndex;
}
function _getTokenToAssetVaultIndex()
internal
view
returns (mapping(address => uint256) storage _tokenToAssetVaultIndex)
{
_tokenToAssetVaultIndex = _getStorage().tokenToAssetVaultIndex;
}
function _getNettedPositions() internal view returns (int256[2][2] storage _nettedPositions) {
_nettedPositions = _getStorage().nettedPositions;
}
function _getNettedPrices(uint256 epoch) internal view returns (int256[2] storage _nettedPrices) {
_nettedPrices = _getStorage().lastNettedPrices[epoch];
}
function _getZeroSumPnlThreshold() internal view returns (uint256 _zeroSumPnlThreshold) {
_zeroSumPnlThreshold = _getStorage().zeroSumPnlThreshold;
}
function _getExternalPosition() internal view returns (int256 _extenralPosition) {
_extenralPosition = _getStorage().externalPosition;
}
function _getFeeHelper() internal view returns (address _feeHelper) {
_feeHelper = _getStorage().feeHelper;
}
function _getVaultFees() internal view returns (VaultFees storage _vaultFees) {
_vaultFees = _getStorage().vaultFees;
}
function _getVaultFromAsset(address asset) internal view returns (AssetVaultStorage storage vault) {
AssetVaultStorage[2] storage vaults = _getAssetVaultEntries();
if (vaults[0].token == asset) {
return vaults[0];
} else if (vaults[1].token == asset) {
return vaults[1];
} else {
revert InvalidAsset();
}
}
function _setPositions(int256[2][2] memory _nettedPositions, int256 _externalPosition) internal {
int256[2][2] storage nettedPositions = _getNettedPositions();
_getStorage().externalPosition = _externalPosition;
nettedPositions[0][0] = _nettedPositions[0][0];
nettedPositions[0][1] = _nettedPositions[0][1];
nettedPositions[1][0] = _nettedPositions[1][0];
nettedPositions[1][1] = _nettedPositions[1][1];
}
function _setVaultGmiAttribution(uint256[2] memory vaultGmiAttribution) internal {
uint256[2] storage gmiAttribution = _getStorage().vaultGmiAttribution;
gmiAttribution[0] = vaultGmiAttribution[0];
gmiAttribution[1] = vaultGmiAttribution[1];
}
function _getAssetVaultEntry(uint256 _idx) internal view returns (AssetVaultStorage storage _assetVault) {
_assetVault = _getAssetVaultEntries()[_idx];
}
function _isHookEnabledMask(HookType _type) internal pure returns (uint256) {
uint256 hookNum = uint256(_type);
return 1 << ((hookNum * 2) + 1);
}
function _hookCallTypeMask(HookType _type) internal pure returns (uint256) {
uint256 hookNum = uint256(_type);
return 1 << (hookNum * 2);
}
function _getHook(HookType _type) internal view returns (bool _isEnabled, bool _isDelegateHook) {
bytes32 config = _getStorage().hooksConfig;
uint256 isEnabledMask = _isHookEnabledMask(_type);
uint256 callTypeMask = _hookCallTypeMask(_type);
_isEnabled = (uint256(config) & isEnabledMask) != 0;
_isDelegateHook = (uint256(config) & callTypeMask) != 0;
}
function _enableHook(HookType _type, CallType _callType) internal {
bytes32 config = _getStorage().hooksConfig;
uint256 isEnabledMask = _isHookEnabledMask(_type);
uint256 callTypeMask = _hookCallTypeMask(_type);
config = bytes32(uint256(config) & ~(isEnabledMask | callTypeMask));
config = bytes32(uint256(config) | isEnabledMask | (_callType == CallType.DelegateCall ? callTypeMask : 0));
_getStorage().hooksConfig = config;
}
function _disableHook(HookType _type) internal {
bytes32 config = _getStorage().hooksConfig;
uint256 isEnabledMask = _isHookEnabledMask(_type);
uint256 callTypeMask = _hookCallTypeMask(_type);
config = bytes32(uint256(config) & ~(isEnabledMask | callTypeMask));
_getStorage().hooksConfig = config;
}
function _executeHook(HookType _hookType, bytes memory _cd) internal returns (bytes memory) {
(bool isEnabled, bool isDelegateHook) = _getHook(_hookType);
if (isEnabled) {
address hookHandler = _getStorage().hookHandler;
bytes memory hcd = abi.encodeCall(IHookExecutor.executeHook, (_hookType, _cd));
if (isDelegateHook) {
return Delegatecall.delegateCall(hookHandler, hcd);
} else {
(bool success, bytes memory ret) = hookHandler.call(hcd);
if (!success) {
assembly {
let length := mload(ret)
let start := add(ret, 0x20)
revert(start, length)
}
}
return ret;
}
}
return hex"";
}
function _getBlockNumber() internal view returns (uint256 _blockNumber) {
_blockNumber = IArbSys(ARBSYS).arbBlockNumber();
}
function _saveRequest(
address sender,
address account,
address vault,
address callback,
bool isDeposit,
uint256 amount,
uint256 minOut
) internal returns (uint256 requestNonce) {
AVStorage storage stg = _getStorage();
stg.pendingRequests[++stg.requestNonce] = OCRequest({
sender: sender,
account: account,
vault: vault,
callback: callback,
isDeposit: isDeposit,
amount: amount,
minOut: minOut,
requestBlock: _getBlockNumber()
});
return stg.requestNonce;
}
function _getRequest(uint256 key) internal view returns (OCRequest memory order) {
AVStorage storage stg = _getStorage();
order = stg.pendingRequests[key];
}
}
文件 6 的 103:ArbSys.sol
pragma solidity ^0.8.0;
interface ArbSys {
function arbBlockNumber() external view returns (uint256);
function arbBlockHash(uint256 blockNumber) external view returns (bytes32);
}
文件 7 的 103:Array.sol
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/utils/math/SafeCast.sol";
import "../error/Errors.sol";
library Array {
using SafeCast for int256;
function get(bytes32[] memory arr, uint256 index) internal pure returns (bytes32) {
if (index < arr.length) {
return arr[index];
}
return bytes32(0);
}
function areEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] != value) {
return false;
}
}
return true;
}
function areGreaterThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] <= value) {
return false;
}
}
return true;
}
function areGreaterThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] < value) {
return false;
}
}
return true;
}
function areLessThan(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] >= value) {
return false;
}
}
return true;
}
function areLessThanOrEqualTo(uint256[] memory arr, uint256 value) internal pure returns (bool) {
for (uint256 i; i < arr.length; i++) {
if (arr[i] > value) {
return false;
}
}
return true;
}
function getMedian(uint256[] memory arr) internal pure returns (uint256) {
if (arr.length % 2 == 1) {
return arr[arr.length / 2];
}
return (arr[arr.length / 2] + arr[arr.length / 2 - 1]) / 2;
}
function getUncompactedValue(
uint256[] memory compactedValues,
uint256 index,
uint256 compactedValueBitLength,
uint256 bitmask,
string memory label
) internal pure returns (uint256) {
uint256 compactedValuesPerSlot = 256 / compactedValueBitLength;
uint256 slotIndex = index / compactedValuesPerSlot;
if (slotIndex >= compactedValues.length) {
revert Errors.CompactedArrayOutOfBounds(compactedValues, index, slotIndex, label);
}
uint256 slotBits = compactedValues[slotIndex];
uint256 offset = (index - slotIndex * compactedValuesPerSlot) * compactedValueBitLength;
uint256 value = (slotBits >> offset) & bitmask;
return value;
}
}
文件 8 的 103:AssetVault.sol
pragma solidity 0.8.17;
import { BaseVault } from "./BaseVault.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ReentrancyGuard } from "solmate/utils/ReentrancyGuard.sol";
import { ShareMath } from "../libraries/ShareMath.sol";
import { GlobalACL, REQUEST_HANDLER, AGGREGATE_VAULT_ROLE } from "../Auth.sol";
import { PausableVault } from "../PausableVault.sol";
import { AggregateVault } from "./AggregateVault.sol";
import { AggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
contract AssetVault is BaseVault, PausableVault, GlobalACL, ReentrancyGuard {
using SafeTransferLib for ERC20;
AggregateVault public aggregateVault;
constructor(ERC20 _asset, string memory _name, string memory _symbol, address _aggregateVault)
BaseVault(_asset, _name, _symbol)
GlobalACL(AggregateVault(payable(_aggregateVault)).AUTH())
{
aggregateVault = AggregateVault(payable(_aggregateVault));
}
function deposit(uint256 assets, uint256 minOutAfterFees, address receiver)
public
payable
override
whenDepositNotPaused
nonReentrant
returns (uint256 shares)
{
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
require(
totalAssets() + assets <= previewVaultCap() + asset.balanceOf(address(this)), "AssetVault: over vault cap"
);
asset.safeTransferFrom(msg.sender, address(this), assets);
aggregateVault.handleDeposit{ value: msg.value }(assets, minOutAfterFees, receiver, msg.sender, address(0));
emit Deposit(msg.sender, receiver, assets, shares);
}
function redeem(uint256 shares, uint256 minOutAfterFees, address receiver, address owner)
public
payable
override
whenWithdrawalNotPaused
nonReentrant
returns (uint256 assets)
{
require(shares > 0, "AssetVault: !shares > 0");
assets = totalSupply == 0 ? shares : ShareMath.sharesToAsset(shares, pps(), decimals);
if (msg.sender != owner) _checkAllowance(owner, shares);
require(assets <= asset.balanceOf(address(aggregateVault)), "AssetVault: assets not available");
require(previewRedeem(shares) != 0, "ZERO_ASSETS");
ERC20(address(this)).safeTransferFrom(owner, address(this), shares);
aggregateVault.handleWithdraw{ value: msg.value }(shares, minOutAfterFees, receiver, msg.sender, address(0));
emit Withdraw(owner, receiver, owner, assets, shares);
}
function depositWithCallback(uint256 assets, uint256 minOutAfterFees, address receiver, address callback)
public
payable
whenDepositNotPaused
nonReentrant
returns (uint256 shares)
{
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
require(
totalAssets() + assets <= previewVaultCap() + asset.balanceOf(address(this)), "AssetVault: over vault cap"
);
asset.safeTransferFrom(msg.sender, address(this), assets);
aggregateVault.handleDeposit{ value: msg.value }(assets, minOutAfterFees, receiver, msg.sender, callback);
emit Deposit(msg.sender, receiver, assets, shares);
}
function redeemWithCallback(
uint256 shares,
uint256 minOutAfterFees,
address receiver,
address owner,
address callback
) public payable whenWithdrawalNotPaused nonReentrant returns (uint256 assets) {
require(shares > 0, "AssetVault: !shares > 0");
assets = totalSupply == 0 ? shares : ShareMath.sharesToAsset(shares, pps(), decimals);
if (msg.sender != owner) _checkAllowance(owner, shares);
require(previewRedeem(shares) != 0, "ZERO_ASSETS");
ERC20(address(this)).safeTransferFrom(owner, address(this), shares);
aggregateVault.handleWithdraw{ value: msg.value }(shares, minOutAfterFees, receiver, msg.sender, callback);
emit Withdraw(owner, receiver, owner, assets, shares);
}
function cancelRequest(uint256 key) external {
AggregateVaultStorage.OCRequest memory request = aggregateVault.getRequest(key);
require(request.vault == address(this), "AssetVault: invalid vault");
require(request.sender == msg.sender, "AssetVault: invalid account");
if (request.isDeposit) {
asset.safeTransfer(msg.sender, request.amount);
} else {
ERC20(address(this)).safeTransfer(msg.sender, request.amount);
}
aggregateVault.clearRequest(key);
}
function totalAssets() public view override returns (uint256 totalValueLocked) {
(bool success, bytes memory ret) =
address(aggregateVault).staticcall(abi.encodeCall(AggregateVault.getVaultTVL, (address(this), false)));
if (!success) {
assembly {
let length := mload(ret)
revert(add(32, ret), length)
}
}
totalValueLocked = abi.decode(ret, (uint256));
}
function pps() public view returns (uint256 pricePerShare) {
(bool success, bytes memory ret) =
address(aggregateVault).staticcall(abi.encodeCall(AggregateVault.getVaultPPS, (address(this), true, false)));
if (!success) {
assembly {
let length := mload(ret)
revert(add(32, ret), length)
}
}
pricePerShare = abi.decode(ret, (uint256));
}
function convertToShares(uint256 assets) public view override returns (uint256) {
return totalSupply == 0 ? assets : ShareMath.assetToShares(assets, pps(), decimals);
}
function convertToAssets(uint256 shares) public view override returns (uint256) {
return totalSupply == 0 ? shares : ShareMath.sharesToAsset(shares, pps(), decimals);
}
function previewDeposit(uint256 assets) public view override returns (uint256) {
uint256 assetFee = previewDepositFee(assets);
if (assetFee >= assets) return 0;
return convertToShares(assets - assetFee);
}
function previewRedeem(uint256 shares) public view override returns (uint256) {
uint256 assets = ShareMath.sharesToAsset(shares, pps(), decimals);
uint256 assetFee = previewWithdrawalFee(assets);
if (assetFee >= assets) return 0;
return assets - assetFee;
}
function maxDeposit(address) public view override returns (uint256) {
uint256 cap = previewVaultCap();
uint256 tvl_ = totalAssets();
return cap > tvl_ ? cap - tvl_ : 0;
}
function maxMint(address) public view override returns (uint256) {
uint256 cap = previewVaultCap();
uint256 tvl_ = totalAssets();
return cap > tvl_ ? convertToShares(cap - tvl_) : 0;
}
function maxWithdraw(address owner) public view override returns (uint256) {
uint256 aggBalance = asset.balanceOf(address(aggregateVault));
uint256 userMaxAssets = convertToAssets(balanceOf[owner]);
return aggBalance > userMaxAssets ? userMaxAssets : aggBalance;
}
function maxRedeem(address owner) public view override returns (uint256) {
uint256 aggBalance = convertToShares(asset.balanceOf(address(aggregateVault)));
return aggBalance > balanceOf[owner] ? balanceOf[owner] : aggBalance;
}
function pauseDepositWithdraw() external onlyAggregateVault {
_pause();
}
function unpauseDepositWithdraw() external onlyAggregateVault {
_unpause();
}
function pauseDeposits() external onlyConfigurator {
_pauseDeposit();
}
function unpauseDeposits() external onlyConfigurator {
_unpauseDeposit();
}
function pauseWithdrawals() external onlyConfigurator {
_pauseWithdrawal();
}
function unpauseWithdrawals() external onlyConfigurator {
_unpauseWithdrawal();
}
function updateAggregateVault(AggregateVault _newAggregateVault) external onlyConfigurator {
aggregateVault = _newAggregateVault;
}
function mintTo(uint256 _mintAmount, address _toAddress) external validateMintCallAuth(_toAddress) {
_mint(_toAddress, _mintAmount);
}
function burnShares(uint256 _burnAmount) external onlyRequestHandler {
_burn(address(this), _burnAmount);
}
function lodgeAssets(uint256 _assetAmount, address feeReciever, uint256 _depositFees) external onlyRequestHandler {
asset.safeTransfer(address(aggregateVault), _assetAmount);
if (_depositFees > 0 && feeReciever != address(0)) asset.safeTransfer(feeReciever, _depositFees);
}
function returnAssets(address _to, uint256 _amt) external onlyRequestHandler {
asset.safeTransfer(_to, _amt);
}
function returnShares(address _to, uint256 _amt) external onlyRequestHandler {
ERC20(address(this)).safeTransfer(_to, _amt);
}
function previewDepositFee(uint256 size) public view returns (uint256 totalDepositFee) {
(bool success, bytes memory ret) = address(aggregateVault).staticcall(
abi.encodeCall(AggregateVault.previewDepositFee, (address(asset), size, false))
);
if (!success) {
assembly {
let length := mload(ret)
revert(add(32, ret), length)
}
}
totalDepositFee = abi.decode(ret, (uint256));
}
function previewWithdrawalFee(uint256 size) public view returns (uint256 totalWithdrawalFee) {
(bool success, bytes memory ret) = address(aggregateVault).staticcall(
abi.encodeCall(AggregateVault.previewWithdrawalFee, (address(asset), size, false))
);
if (!success) {
assembly {
let length := mload(ret)
revert(add(32, ret), length)
}
}
totalWithdrawalFee = abi.decode(ret, (uint256));
}
function previewVaultCap() public view returns (uint256) {
return aggregateVault.previewVaultCap(address(asset));
}
function _checkAllowance(address owner, uint256 shares) internal {
uint256 allowed = allowance[owner][msg.sender];
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
modifier validateMintCallAuth(address _mintTo) {
require(
(_mintTo == aggregateVault.getVaultTimelockAddress(address(asset)) && address(aggregateVault) == msg.sender)
|| AUTH.hasRole(REQUEST_HANDLER, msg.sender),
"AssetVault: !validateMintCallAuth"
);
_;
}
}
文件 9 的 103:Auth.sol
pragma solidity 0.8.17;
bytes32 constant CONFIGURATOR_ROLE = keccak256("CONFIGURATOR");
bytes32 constant AGGREGATE_VAULT_ROLE = keccak256("AGGREGATE_VAULT");
bytes32 constant REQUEST_HANDLER = keccak256("REQUEST_HANDLER");
bytes32 constant KEEPER_ROLE = keccak256("KEEPER_ROLE");
bytes32 constant EXECUTION_KEEPER = keccak256("EXECUTION_KEEPER");
bytes32 constant SWAP_KEEPER = keccak256("SWAP_KEEPER");
contract Auth {
error NotAuthorized(bytes32 _role, address _user);
event RoleUpdated(bytes32 indexed role, address indexed user, bool authorized);
bytes32 public constant AUTH_MANAGER_ROLE = keccak256("AUTH_MANAGER");
mapping(bytes32 => mapping(address => bool)) public hasRole;
constructor() {
_updateRole(msg.sender, AUTH_MANAGER_ROLE, true);
}
function updateRole(address _user, bytes32 _role, bool _authorized) external {
onlyRole(AUTH_MANAGER_ROLE, msg.sender);
_updateRole(_user, _role, _authorized);
}
function onlyRole(bytes32 _role, address _user) public view {
if (!hasRole[_role][_user]) {
revert NotAuthorized(_role, _user);
}
}
function _updateRole(address _user, bytes32 _role, bool _authorized) internal {
hasRole[_role][_user] = _authorized;
emit RoleUpdated(_role, _user, _authorized);
}
}
abstract contract GlobalACL {
Auth public immutable AUTH;
constructor(Auth _auth) {
require(address(_auth) != address(0), "GlobalACL: zero address");
AUTH = _auth;
}
modifier onlyConfigurator() {
AUTH.onlyRole(CONFIGURATOR_ROLE, msg.sender);
_;
}
modifier onlyAggregateVault() {
AUTH.onlyRole(AGGREGATE_VAULT_ROLE, msg.sender);
_;
}
modifier onlyRequestHandler() {
AUTH.onlyRole(REQUEST_HANDLER, msg.sender);
_;
}
modifier onlyExecutionKeeper() {
AUTH.onlyRole(EXECUTION_KEEPER, msg.sender);
_;
}
modifier onlyRole(bytes32 _role) {
AUTH.onlyRole(_role, msg.sender);
_;
}
}
文件 10 的 103: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 {}
}
文件 11 的 103:BaseHandler.sol
pragma solidity 0.8.17;
import { IHandlerContract } from "./interfaces/IHandlerContract.sol";
import { ISwapManager } from "./interfaces/ISwapManager.sol";
import { PositionManagerRouter } from "./position-managers/PositionManagerRouter.sol";
abstract contract BaseHandler is IHandlerContract {
address immutable SELF;
error OnlyDelegateCall();
constructor() {
SELF = address(this);
}
function _executeSwap(
ISwapManager _swapManager,
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _minOut,
bytes memory _data
) internal returns (uint256 _amountOut) {
_amountOut = PositionManagerRouter(payable(address(this))).executeSwap(
_swapManager, _tokenIn, _tokenOut, _amountIn, _minOut, _data
);
}
modifier onlyDelegateCall() {
if (address(this) == SELF) {
revert OnlyDelegateCall();
}
_;
}
}
文件 12 的 103:BaseSwapManager.sol
pragma solidity 0.8.17;
import { BaseHandler } from "../BaseHandler.sol";
import { ISwapManager } from "../interfaces/ISwapManager.sol";
import { IHandlerContract } from "../interfaces/IHandlerContract.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
abstract contract BaseSwapManager is BaseHandler, ISwapManager {
error InsufficientOutput();
error InsufficientInput();
error InvalidInput();
error TooMuchInput();
function callbackSigs() external pure returns (bytes4[] memory _ret) {
_ret = new bytes4[](0);
}
modifier swapChecks(address _tokenIn, address _tokenOut, uint256 _amountIn, uint256 _minOut) {
uint256 tokenInBalance = ERC20(_tokenIn).balanceOf(address(this));
if (tokenInBalance < _amountIn) revert InsufficientInput();
uint256 tokenOutBalanceBefore = ERC20(_tokenOut).balanceOf(address(this));
_;
uint256 tokenOutBalanceAfter = ERC20(_tokenOut).balanceOf(address(this));
uint256 actualOut = tokenOutBalanceAfter - tokenOutBalanceBefore;
if (actualOut < _minOut) revert InsufficientOutput();
}
modifier swapChecksExactOutput(address _tokenIn, address _tokenOut, uint256 _amountOut, uint256 _maxIn) {
uint256 tokenInBalance = ERC20(_tokenIn).balanceOf(address(this));
uint256 tokenOutBalanceBefore = ERC20(_tokenOut).balanceOf(address(this));
_;
uint256 tokenOutBalanceAfter = ERC20(_tokenOut).balanceOf(address(this));
uint256 actualOut = tokenOutBalanceAfter - tokenOutBalanceBefore;
if (actualOut != _amountOut) revert InsufficientOutput();
uint256 actualIn = tokenInBalance - ERC20(_tokenIn).balanceOf(address(this));
if (actualIn > _maxIn) revert TooMuchInput();
}
}
文件 13 的 103:BaseVault.sol
pragma solidity 0.8.17;
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { FixedPointMathLib } from "solmate/utils/FixedPointMathLib.sol";
abstract contract BaseVault is ERC20 {
using SafeTransferLib for ERC20;
using FixedPointMathLib for uint256;
event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);
event Withdraw(
address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares
);
ERC20 public immutable asset;
constructor(ERC20 _asset, string memory _name, string memory _symbol) ERC20(_name, _symbol, _asset.decimals()) {
asset = _asset;
}
function deposit(uint256 assets, uint256, address receiver)
public
payable
virtual
returns (uint256 shares)
{
require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES");
asset.safeTransferFrom(msg.sender, address(this), assets);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, assets, shares);
afterDeposit(assets, shares);
}
function redeem(uint256 shares, uint256, address receiver, address owner)
public
payable
virtual
returns (uint256 assets)
{
if (msg.sender != owner) {
uint256 allowed = allowance[owner][msg.sender];
if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares;
}
require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS");
beforeWithdraw(assets, shares);
_burn(owner, shares);
emit Withdraw(msg.sender, receiver, owner, assets, shares);
asset.safeTransfer(receiver, assets);
}
function totalAssets() public view virtual returns (uint256);
function convertToShares(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}
function convertToAssets(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}
function previewDeposit(uint256 assets) public view virtual returns (uint256) {
return convertToShares(assets);
}
function previewMint(uint256 shares) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply);
}
function previewWithdraw(uint256 assets) public view virtual returns (uint256) {
uint256 supply = totalSupply;
return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets());
}
function previewRedeem(uint256 shares) public view virtual returns (uint256) {
return convertToAssets(shares);
}
function maxDeposit(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxMint(address) public view virtual returns (uint256) {
return type(uint256).max;
}
function maxWithdraw(address owner) public view virtual returns (uint256) {
return convertToAssets(balanceOf[owner]);
}
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}
function beforeWithdraw(uint256 assets, uint256 shares) internal virtual { }
function afterDeposit(uint256 assets, uint256 shares) internal virtual { }
}
文件 14 的 103: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);
}
文件 15 的 103: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();
}
}
}
文件 16 的 103:Cast.sol
pragma solidity ^0.8.0;
library Cast {
function toBytes32(address value) internal pure returns (bytes32) {
return bytes32(uint256(uint160(value)));
}
}
文件 17 的 103: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;
}
}
文件 18 的 103: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;
}
}
文件 19 的 103: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);
}
}
文件 20 的 103:Delegatecall.sol
pragma solidity 0.8.17;
library Delegatecall {
error EmptyContract(address);
function delegateCall(address _target, bytes memory _calldata) internal returns (bytes memory _ret) {
if (_target.code.length == 0) revert EmptyContract(_target);
bool success;
(success, _ret) = _target.delegatecall(_calldata);
if (!success) {
assembly {
let length := mload(_ret)
let start := add(_ret, 0x20)
revert(start, length)
}
}
}
}
文件 21 的 103: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");
}
}
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);
}
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 message) {
assembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32")
mstore(0x1c, hash)
message := keccak256(0x00, 0x3c)
}
}
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 data) {
assembly {
let ptr := mload(0x40)
mstore(ptr, "\x19\x01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
data := keccak256(ptr, 0x42)
}
}
function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) {
return keccak256(abi.encodePacked("\x19\x00", validator, data));
}
}
文件 22 的 103:ERC20.sol
pragma solidity >=0.8.0;
abstract contract ERC20 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
uint256 internal immutable INITIAL_CHAIN_ID;
bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public nonces;
constructor(
string memory _name,
string memory _symbol,
uint8 _decimals
) {
name = _name;
symbol = _symbol;
decimals = _decimals;
INITIAL_CHAIN_ID = block.chainid;
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
balanceOf[msg.sender] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(msg.sender, to, amount);
return true;
}
function transferFrom(
address from,
address to,
uint256 amount
) public virtual returns (bool) {
uint256 allowed = allowance[from][msg.sender];
if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;
balanceOf[from] -= amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(from, to, amount);
return true;
}
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) public virtual {
require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");
allowance[recoveredAddress][spender] = value;
}
emit Approval(owner, spender, value);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
function computeDomainSeparator() internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _mint(address to, uint256 amount) internal virtual {
totalSupply += amount;
unchecked {
balanceOf[to] += amount;
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
balanceOf[from] -= amount;
unchecked {
totalSupply -= amount;
}
emit Transfer(from, address(0), amount);
}
}
文件 23 的 103:Emitter.sol
pragma solidity 0.8.17;
import { Auth, GlobalACL, SWAP_KEEPER, KEEPER_ROLE } from "../Auth.sol";
import { LibCycle } from "../libraries/LibCycle.sol";
import { AggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
contract Emitter is GlobalACL {
event CollectVaultFees(
uint256 totalVaultFee,
uint256 performanceFeeInAsset,
uint256 managementFeeInAsset,
uint256 timelockYieldMintAmount,
address indexed assetVault
);
event RebalanceGmiFromState(uint256[2] targetUsd, uint256[2] targetShares, uint256[2] currentShares);
event MintRequest(address asset, uint256 epoch, LibCycle.GMIMintRequest _mintRequest);
event BurnRequest(address asset, uint256 epoch, LibCycle.GMIBurnRequest _mintRequest);
event FulfilGmiMintRequest(
uint256 targetGMIAmount, uint256 gmiMinted, uint256[] gmAmountsRequired, uint256[] gmAmountsMinted
);
event FulfilGmiBurnRequest(uint256 gmiAmount, uint256[4] usdcReceived, uint256[4] ethReceived);
event OpenRebalance(uint256 timestamp, uint256[2] nextVaultIndexAlloc, uint256[2] nextIndexComp, int256 position);
event CloseRebalance(uint256 timestamp);
event DepositRequest(uint256 indexed key, address indexed account, address indexed vault);
event WithdrawalRequest(uint256 indexed key, address indexed account, address indexed vault);
event RequestExecuted(uint256 indexed key, address indexed account, address indexed vault, address callback);
event ExecutionError(uint256 indexed key, address account, address vault, bool isDeposit, bytes error);
event CallbackExecutionError(uint256 indexed key, bytes error);
event CallbackExecutionSuccess(uint256 indexed key, AggregateVaultStorage.OCRequest request);
event UpdateNettingCheckpointPrice(int256[2] oldPrices, int256[2] newPrices);
event SettleNettedPositionPnl(
uint256[2] previousGlpAmount,
uint256[2] settledGlpAmount,
int256[2] glpPnl,
int256[2] dollarPnl,
int256[2] percentPriceChange
);
event SetCallback(bool status);
constructor(Auth auth) GlobalACL(auth) { }
function emitCollectVaultFees(
uint256 totalVaultFee,
uint256 performanceFeeInAsset,
uint256 managementFeeInAsset,
uint256 timelockYieldMintAmount,
address assetVault
) external onlyAggregateVault {
emit CollectVaultFees(
totalVaultFee, performanceFeeInAsset, managementFeeInAsset, timelockYieldMintAmount, assetVault
);
}
function emitOpenRebalance(
uint256 timestamp,
uint256[2] memory nextVaultIndexAlloc,
uint256[2] memory nextIndexComp,
int256 position
) external onlyAggregateVault {
emit OpenRebalance(timestamp, nextVaultIndexAlloc, nextIndexComp, position);
}
function emitCloseRebalance(uint256 timestamp) external onlyAggregateVault {
emit CloseRebalance(timestamp);
}
function emitDepositRequest(uint256 key, address account, address vault) external onlyAggregateVault {
emit DepositRequest(key, account, vault);
}
function emitWithdrawalRequest(uint256 key, address account, address vault) external onlyAggregateVault {
emit WithdrawalRequest(key, account, vault);
}
function emitRequestExecuted(uint256 key, address account, address vault, address callback)
external
onlyRequestHandler
{
emit RequestExecuted(key, account, vault, callback);
}
function emitExecutionError(uint256 key, address account, address vault, bool isDeposit, bytes memory err)
external
onlyRequestHandler
{
emit ExecutionError(key, account, vault, isDeposit, err);
}
function emitSetCallbackEnabled(bool status) external onlyRequestHandler {
emit SetCallback(status);
}
function emitRequestCallbackError(uint256 key, bytes memory err) external onlyRequestHandler {
emit CallbackExecutionError(key, err);
}
function emitRequestCallbackSuccess(uint256 key, AggregateVaultStorage.OCRequest memory request)
external
onlyRequestHandler
{
emit CallbackExecutionSuccess(key, request);
}
function emitSettleNettedPositionPnl(
uint256[2] memory previousIndexAmount,
uint256[2] memory settledIndexAmount,
int256[2] memory indexPnl,
int256[2] memory dollarPnl,
int256[2] memory percentPriceChange
) external onlyAggregateVault {
emit SettleNettedPositionPnl(previousIndexAmount, settledIndexAmount, indexPnl, dollarPnl, percentPriceChange);
}
function emitRebalanceGmiFromState(
uint256[2] memory targetUsd,
uint256[2] memory targetShares,
uint256[2] memory currentShares
) external onlyAggregateVault {
emit RebalanceGmiFromState(targetUsd, targetShares, currentShares);
}
function emitMintRequest(address _asset, uint256 _epoch, LibCycle.GMIMintRequest memory _mintRequest)
external
onlyAggregateVault
{
emit MintRequest(_asset, _epoch, _mintRequest);
}
function emitBurnRequest(address _asset, uint256 _epoch, LibCycle.GMIBurnRequest memory _burnRequest)
external
onlyAggregateVault
{
emit BurnRequest(_asset, _epoch, _burnRequest);
}
function emitFulfilGmiMintRequest(
uint256 targetGMIAmount,
uint256 gmiMinted,
uint256[] memory gmAmountsRequired,
uint256[] memory gmAmountsMinted
) external onlyAggregateVault {
emit FulfilGmiMintRequest(targetGMIAmount, gmiMinted, gmAmountsRequired, gmAmountsMinted);
}
function emitFulfilGmiBurnRequest(uint256 gmiAmount, uint256[4] memory usdcReceived, uint256[4] memory ethReceived)
external
onlyAggregateVault
{
emit FulfilGmiBurnRequest(gmiAmount, usdcReceived, ethReceived);
}
function emitUpdateNettingCheckpointPrice(int256[2] memory oldPrices, int256[2] memory newPrices)
external
onlyAggregateVault
{
emit UpdateNettingCheckpointPrice(oldPrices, newPrices);
}
}
文件 24 的 103:EnumerableSet.sol
pragma solidity ^0.8.0;
library EnumerableSet {
struct Set {
bytes32[] _values;
mapping(bytes32 => uint256) _indexes;
}
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
function _remove(Set storage set, bytes32 value) private returns (bool) {
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) {
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
if (lastIndex != toDeleteIndex) {
bytes32 lastValue = set._values[lastIndex];
set._values[toDeleteIndex] = lastValue;
set._indexes[lastValue] = valueIndex;
}
set._values.pop();
delete set._indexes[value];
return true;
} else {
return false;
}
}
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
struct Bytes32Set {
Set _inner;
}
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly {
result := store
}
return result;
}
struct AddressSet {
Set _inner;
}
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly {
result := store
}
return result;
}
struct UintSet {
Set _inner;
}
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly {
result := store
}
return result;
}
}
文件 25 的 103: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;
}
}
文件 26 的 103: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)
}
}
}
文件 27 的 103: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 ExternalCallFailed(bytes data);
error InvalidExternalCallInput(uint256 targetsLength, uint256 dataListLength);
error InvalidExternalReceiversInput(uint256 refundTokensLength, uint256 refundReceiversLength);
error InvalidExternalCallTarget(address target);
error InvalidGlpAmount(uint256 totalGlpAmountToRedeem, uint256 totalGlpAmount);
error InvalidExecutionFeeForMigration(uint256 totalExecutionFee, uint256 msgValue);
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);
}
文件 28 的 103: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)
}
}
}
文件 29 的 103: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;
}
}
文件 30 的 103:FixedPointMathLib.sol
pragma solidity >=0.8.0;
library FixedPointMathLib {
uint256 internal constant MAX_UINT256 = 2**256 - 1;
uint256 internal constant WAD = 1e18;
function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, y, WAD);
}
function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, y, WAD);
}
function divWadDown(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivDown(x, WAD, y);
}
function divWadUp(uint256 x, uint256 y) internal pure returns (uint256) {
return mulDivUp(x, WAD, y);
}
function mulDivDown(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := div(mul(x, y), denominator)
}
}
function mulDivUp(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 z) {
assembly {
if iszero(mul(denominator, iszero(mul(y, gt(x, div(MAX_UINT256, y)))))) {
revert(0, 0)
}
z := add(gt(mod(mul(x, y), denominator), 0), div(mul(x, y), denominator))
}
}
function rpow(
uint256 x,
uint256 n,
uint256 scalar
) internal pure returns (uint256 z) {
assembly {
switch x
case 0 {
switch n
case 0 {
z := scalar
}
default {
z := 0
}
}
default {
switch mod(n, 2)
case 0 {
z := scalar
}
default {
z := x
}
let half := shr(1, scalar)
for {
n := shr(1, n)
} n {
n := shr(1, n)
} {
if shr(128, x) {
revert(0, 0)
}
let xx := mul(x, x)
let xxRound := add(xx, half)
if lt(xxRound, xx) {
revert(0, 0)
}
x := div(xxRound, scalar)
if mod(n, 2) {
let zx := mul(z, x)
if iszero(eq(div(zx, x), z)) {
if iszero(iszero(x)) {
revert(0, 0)
}
}
let zxRound := add(zx, half)
if lt(zxRound, zx) {
revert(0, 0)
}
z := div(zxRound, scalar)
}
}
}
}
}
function sqrt(uint256 x) internal pure returns (uint256 z) {
assembly {
let y := x
z := 181
if iszero(lt(y, 0x10000000000000000000000000000000000)) {
y := shr(128, y)
z := shl(64, z)
}
if iszero(lt(y, 0x1000000000000000000)) {
y := shr(64, y)
z := shl(32, z)
}
if iszero(lt(y, 0x10000000000)) {
y := shr(32, y)
z := shl(16, z)
}
if iszero(lt(y, 0x1000000)) {
y := shr(16, y)
z := shl(8, z)
}
z := shr(18, mul(z, add(y, 65536)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := shr(1, add(z, div(x, z)))
z := sub(z, lt(div(x, z), z))
}
}
function unsafeMod(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := mod(x, y)
}
}
function unsafeDiv(uint256 x, uint256 y) internal pure returns (uint256 r) {
assembly {
r := div(x, y)
}
}
function unsafeDivUp(uint256 x, uint256 y) internal pure returns (uint256 z) {
assembly {
z := add(gt(mod(x, y), 0), div(x, y))
}
}
}
文件 31 的 103:GMI.sol
pragma solidity 0.8.17;
import { ERC20 as SolmateERC20 } from "solmate/tokens/ERC20.sol";
import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { GlobalACL, Auth, KEEPER_ROLE, SWAP_KEEPER } from "../Auth.sol";
import { Solarray } from "../libraries/Solarray.sol";
import { GmiUtils } from "./GmiUtils.sol";
import { IGmxV2Handler } from "../interfaces/IGmxV2Handler.sol";
import { PositionManagerRouter, WhitelistedTokenRegistry } from "../position-managers/PositionManagerRouter.sol";
import { GmiStorage } from "./GmiStorage.sol";
import { GmxStorage } from "../libraries/GmxStorage.sol";
import { TOKEN_USDC_NATIVE, TOKEN_WETH, TOKEN_ARB, GMX_V2_DATA_STORE } from "../constants.sol";
interface IDataStore {
function getUint(bytes32) external view returns (uint256);
}
IDataStore constant DATASTORE = IDataStore(GMX_V2_DATA_STORE);
bytes32 constant POOL_AMOUNT = keccak256(abi.encode("POOL_AMOUNT"));
contract GMI is GmiStorage, PositionManagerRouter, ERC20, GlobalACL {
using SafeTransferLib for SolmateERC20;
error InvalidMintAsset();
uint256 public constant INDEX_SIZE = 4;
bool private initialized = false;
event Deposit(address indexed caller, address indexed owner, uint256 value, uint256 shares);
event Withdraw(
address indexed caller, address indexed receiver, address indexed owner, uint256 value, uint256 shares
);
constructor(Auth auth, WhitelistedTokenRegistry registry)
ERC20("_UNUSED_", "_UNUSED_")
GlobalACL(auth)
PositionManagerRouter(registry)
{ }
function initStorage(
address gmHandler,
address[] memory _indexAssets,
uint256[] memory _weights,
uint256 _mintCapTolerance,
uint8 _fallbackPool
) external {
require(!initialized);
require(_indexAssets[0] != address(0));
require(_indexAssets[1] != address(0));
require(_indexAssets[2] != address(0));
require(_indexAssets[3] != address(0));
require(_indexAssets.length == _weights.length);
require(address(gmHandler) != address(0));
require(Solarray.arraySum(_weights) == 1e18);
require(INDEX_SIZE == _indexAssets.length);
_setIndexAssets(_indexAssets);
_setGmiV2Handler(gmHandler);
_setWeights(_weights);
_setMintCapTolerance(_mintCapTolerance);
_setFallbackMintPool(_fallbackPool);
initialized = true;
}
function deposit(uint256[] memory assets, GmxStorage.MarketPrices[] memory prices, address receiver)
public
onlyAggregateVault
returns (uint256 shares)
{
require(INDEX_SIZE == assets.length, "GMI: !INDEX_SIZE");
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory depositAssetsValue = appraiseAssets(assets, prices);
uint256 depositAssetValue = Solarray.arraySum(depositAssetsValue);
uint256 singleShare = 10 ** decimals();
uint256 depositPPS =
totalSupply() == 0 ? singleShare : (singleShare * tvl(prices) + totalSupply() - 1) / totalSupply();
shares = GmiUtils.valueToShares(depositAssetValue, depositPPS, decimals());
require(shares > 0, "GMI: !shares");
_transferIn(assets, msg.sender);
_mint(receiver, shares);
emit Deposit(msg.sender, receiver, depositAssetValue, shares);
}
function redeem(uint256 shares, address receiver, address owner, GmxStorage.MarketPrices[] memory prices)
public
onlyAggregateVault
returns (uint256[] memory assets)
{
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
require(shares > 0, "AssetVault: !shares > 0");
assets = previewRedeem(shares, prices);
if (msg.sender != owner) {
_checkAllowance(owner, shares);
}
_chechkAvailableTokenBalance(assets);
_burn(owner, shares);
_transferOut(assets, receiver);
uint256 withdrawalAssetValue = _appraiseAllAssets(assets, prices);
emit Withdraw(msg.sender, receiver, owner, withdrawalAssetValue, shares);
}
function depositEth() external payable onlyRole(KEEPER_ROLE) { }
function retrieveEth(uint256 amount) external payable onlyRole(KEEPER_ROLE) {
(bool success,) = msg.sender.call{ value: amount }("");
require(success);
}
function name() public view override returns (string memory) {
return "GMI";
}
function symbol() public view override returns (string memory) {
return "GMI";
}
function getWeights() external view returns (uint256[] memory) {
return _getWeights();
}
function previewMint(uint256 shares, address asset, GmxStorage.MarketPrices[] memory prices)
public
view
returns (uint256[] memory)
{
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory gmValueToMint = new uint256[](INDEX_SIZE);
uint256[] memory weights = _getWeights();
uint256[] memory marketTokenPrices = _getMarketTokenPrices(prices);
if (totalSupply() == 0) {
for (uint256 i = 0; i < INDEX_SIZE; i++) {
gmValueToMint[i] = (shares * weights[i]) / SCALE;
}
} else {
uint256[] memory bals = balances();
uint256[] memory currentAssetValue = appraiseAssets(bals, prices);
uint256 totalVaultValue = Solarray.arraySum(currentAssetValue);
uint256[] memory target = GmiUtils.findWeightedBalances(totalVaultValue, weights);
int256[] memory difference = Solarray.arrayDifference(target, currentAssetValue);
gmValueToMint =
GmiUtils.adjustToBalance(shares, totalVaultValue, difference, weights, totalSupply(), INDEX_SIZE);
}
return _toMarketTokenAmount(
_validateMintableAmounts(asset, gmValueToMint, prices[0].longTokenPrice, prices[0].shortTokenPrice),
marketTokenPrices
);
}
function previewRedeem(uint256 shares, GmxStorage.MarketPrices[] memory prices)
public
view
returns (uint256[] memory)
{
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory withdrawAmount = new uint256[](INDEX_SIZE);
if (totalSupply() == 0) {
return new uint256[](INDEX_SIZE);
} else if (shares == totalSupply()) {
return balances();
} else {
uint256[] memory weights = _getWeights();
uint256[] memory marketTokenPrices = _getMarketTokenPrices(prices);
uint256[] memory bal = balances();
uint256[] memory currentAssetValue = appraiseAssets(bal, prices);
uint256 totalValue = Solarray.arraySum(currentAssetValue);
uint256[] memory target = GmiUtils.findWeightedBalances(totalValue, weights);
int256[] memory difference = Solarray.arrayDifference(currentAssetValue, target);
uint256[] memory valueToBalance =
GmiUtils.adjustToBalance(shares, totalValue, difference, weights, totalSupply(), INDEX_SIZE);
withdrawAmount = _toMarketTokenAmount(valueToBalance, marketTokenPrices);
}
return withdrawAmount;
}
function sharesToMarketTokens(uint256 shares, GmxStorage.MarketPrices[] memory prices)
public
view
returns (uint256[] memory)
{
uint256[] memory gmAmount = new uint256[](INDEX_SIZE);
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory weights = _getWeights();
uint256[] memory marketTokenPrices = _getMarketTokenPrices(prices);
for (uint256 i = 0; i < INDEX_SIZE; i++) {
gmAmount[i] = (shares * 1e18 * weights[i]) / (SCALE * marketTokenPrices[i]);
}
return gmAmount;
}
function indexAssets() public view returns (address[] memory assetAddresses) {
assetAddresses = _getIndexAssets();
}
function pps(GmxStorage.MarketPrices[] memory prices) public view returns (uint256 pricePerShare) {
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256 singleShare = 10 ** decimals();
pricePerShare = totalSupply() == 0 ? singleShare : singleShare * tvl(prices) / totalSupply();
}
function tvl(GmxStorage.MarketPrices[] memory prices) public view returns (uint256 totalValueLocked) {
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory balOfGm = balances();
return _appraiseAllAssets(balOfGm, prices);
}
function balances() public view returns (uint256[] memory) {
address[] memory assets = _getIndexAssets();
uint256[] memory balOfGm = new uint256[](INDEX_SIZE);
for (uint256 i = 0; i < INDEX_SIZE; i++) {
balOfGm[i] = ERC20(assets[i]).balanceOf(address(this));
}
return balOfGm;
}
function appraiseAssets(uint256[] memory assetAmounts, GmxStorage.MarketPrices[] memory prices)
public
view
returns (uint256[] memory)
{
require(INDEX_SIZE == assetAmounts.length, "GMI: !INDEX_SIZE");
require(INDEX_SIZE == prices.length, "GMI: !INDEX_SIZE");
uint256[] memory assetsValue = new uint256[](INDEX_SIZE);
address[] memory assets = _getIndexAssets();
IGmxV2Handler handler = IGmxV2Handler(_getStorage().gmiV2Handler);
for (uint256 i = 0; i < INDEX_SIZE; i++) {
assetsValue[i] = assetAmounts[i] * handler.getGmMidPrice(assets[i], prices[i]) / 1e30;
}
return assetsValue;
}
function getUnderlyingMarketCompositions() public view returns (uint256[2] memory underlyingBalances) {
address[] memory assets = _getIndexAssets();
for (uint8 i = 0; i < INDEX_SIZE; i++) {
address gm = assets[i];
underlyingBalances[0] += DATASTORE.getUint(_poolAmountKey(gm, TOKEN_USDC_NATIVE));
underlyingBalances[1] += DATASTORE.getUint(_poolAmountKey(gm, TOKEN_WETH));
}
}
function getIndexComposition(uint256 usdcExternalPrice, uint256 ethExternalPrice)
external
view
returns (uint256[2] memory composition)
{
uint256[2] memory underlyingBalances = getUnderlyingMarketCompositions();
uint256 usdcUsd = underlyingBalances[0] * usdcExternalPrice;
uint256 ethUsd = underlyingBalances[1] * ethExternalPrice;
uint256 totalUsd = usdcUsd + ethUsd;
uint256 usdcComp = usdcUsd * 1e18 / totalUsd;
composition[0] = usdcComp;
composition[1] = 1e18 - usdcComp;
}
function _poolAmountKey(address _market, address _token) internal pure returns (bytes32) {
return keccak256(abi.encode(POOL_AMOUNT, _market, _token));
}
function collectArb() external onlyConfigurator {
uint256 arbBalance = ERC20(TOKEN_ARB).balanceOf(address(this));
if (arbBalance > 0) SolmateERC20(TOKEN_ARB).safeTransfer(msg.sender, arbBalance);
}
function setTargetWeights(uint256[] memory newWeights) external onlyConfigurator {
require(INDEX_SIZE == newWeights.length, "GMI: !INDEX_SIZE");
require(Solarray.arraySum(newWeights) == 1e18, "GMI: weights");
_setWeights(newWeights);
}
function setMintCapTolerance(uint256 newTolderance) external onlyConfigurator {
require(newTolderance <= 1e18, "GMI: !mintCapTolerance");
_setMintCapTolerance(newTolderance);
}
function setFallbackMintPool(uint8 poolIndex) external onlyConfigurator {
require(poolIndex < INDEX_SIZE, "GMI: !poolIndex");
_setFallbackMintPool(poolIndex);
}
function setGmiV2Handler(address gmiHandler) external onlyConfigurator {
_setGmiV2Handler(gmiHandler);
}
function _appraiseAllAssets(uint256[] memory assetAmounts, GmxStorage.MarketPrices[] memory prices)
internal
view
returns (uint256 assetsValue)
{
address[] memory assets = _getIndexAssets();
IGmxV2Handler handler = IGmxV2Handler(_getStorage().gmiV2Handler);
for (uint256 i = 0; i < INDEX_SIZE; i++) {
assetsValue += assetAmounts[i] * handler.getGmMidPrice(assets[i], prices[i]) / 1e30;
}
}
function _validateMintableAmounts(
address asset,
uint256[] memory gmUsdValue,
GmxStorage.Price memory ethPrice,
GmxStorage.Price memory usdcPrice
) internal view returns (uint256[] memory) {
IGmxV2Handler handler = IGmxV2Handler(_getStorage().gmiV2Handler);
address[] memory assets = _getIndexAssets();
uint256 mintCapTol = _getMintCapTolerance();
uint256[] memory gmUsdToMint = new uint256[](INDEX_SIZE);
uint256[] memory maxMintable = new uint256[](INDEX_SIZE);
bool[] memory canMintAll = new bool[](INDEX_SIZE);
uint256 mintableAmount;
uint256 totalMissed;
for (uint256 i = 0; i < INDEX_SIZE; i++) {
if (asset == TOKEN_WETH) {
mintableAmount = handler.getMaxDepositAmount(assets[i], TOKEN_WETH) * ethPrice.min * mintCapTol / 1e18;
} else if (asset == TOKEN_USDC_NATIVE) {
mintableAmount =
handler.getMaxDepositAmount(assets[i], TOKEN_USDC_NATIVE) * usdcPrice.min * mintCapTol / 1e18;
} else {
revert InvalidMintAsset();
}
maxMintable[i] = mintableAmount * 1e18 / 1e30;
canMintAll[i] = maxMintable[i] > gmUsdValue[i];
gmUsdToMint[i] = canMintAll[i] ? gmUsdValue[i] : maxMintable[i];
if (!canMintAll[i]) {
totalMissed += gmUsdValue[i] - maxMintable[i];
}
}
uint8 fallbackPool = _getFallbackMintPool();
if (totalMissed > 0) {
require(totalMissed < maxMintable[fallbackPool] - gmUsdToMint[fallbackPool], "GMI: over limit");
gmUsdToMint[fallbackPool] += totalMissed;
}
return gmUsdToMint;
}
function _chechkAvailableTokenBalance(uint256[] memory requestedTokenAmount) internal view {
uint256[] memory currentBalance = balances();
for (uint8 i = 0; i < INDEX_SIZE; i++) {
require(requestedTokenAmount[i] <= currentBalance[i], "GMI: !balance");
}
}
function _toMarketTokenAmount(uint256[] memory marketValueAmount, uint256[] memory prices)
internal
view
returns (uint256[] memory)
{
address[] memory assets = _getIndexAssets();
uint256[] memory marketTokenAmount = new uint256[](INDEX_SIZE);
for (uint256 i = 0; i < INDEX_SIZE; i++) {
marketTokenAmount[i] = (10 ** ERC20(assets[i]).decimals() * marketValueAmount[i]) / prices[i];
}
return marketTokenAmount;
}
function _getMarketTokenPrices(GmxStorage.MarketPrices[] memory prices) internal view returns (uint256[] memory) {
uint256[] memory marketPrices = new uint256[](INDEX_SIZE);
IGmxV2Handler handler = IGmxV2Handler(_getStorage().gmiV2Handler);
address[] memory assets = _getIndexAssets();
for (uint256 i = 0; i < INDEX_SIZE; i++) {
marketPrices[i] = handler.getGmMidPrice(assets[i], prices[i]) * 1e18 / 1e30;
}
return marketPrices;
}
function _checkAllowance(address owner, uint256 shares) internal {
uint256 approved = allowance(owner, msg.sender);
if (approved != type(uint256).max) _approve(owner, msg.sender, approved - shares);
}
function _transferIn(uint256[] memory assetAmounts, address sender) internal {
address[] memory assets = _getIndexAssets();
for (uint256 i = 0; i < INDEX_SIZE; i++) {
SolmateERC20(assets[i]).safeTransferFrom(sender, address(this), assetAmounts[i]);
}
}
function _transferOut(uint256[] memory assetAmounts, address receiver) internal {
address[] memory assets = _getIndexAssets();
for (uint256 i = 0; i < INDEX_SIZE; i++) {
SolmateERC20(assets[i]).safeTransfer(receiver, assetAmounts[i]);
}
}
function _onlyConfigurator() internal override onlyConfigurator { }
function _validateExecuteCallAuth() internal override onlyRole(KEEPER_ROLE) { }
function _onlySwapIssuer() internal override onlyRole(SWAP_KEEPER) { }
}
文件 32 的 103:GmiStorage.sol
pragma solidity 0.8.17;
abstract contract GmiStorage {
bytes32 public constant STORAGE_SLOT = keccak256("GmiStorage.storage");
uint256 constant SCALE = 1e18;
struct GmiStg {
address[] indexAssets;
uint256[] weights;
uint256 mintCapTolerance;
uint8 fallbackMintPool;
address gmiV2Handler;
mapping(bytes32 => bool) depositKeys;
mapping(bytes32 => bool) withdrawalKeys;
}
function _getStorage() internal pure returns (GmiStg storage _storage) {
bytes32 slot = STORAGE_SLOT;
assembly {
_storage.slot := slot
}
}
function _getIndexAssets() internal view returns (address[] storage) {
return _getStorage().indexAssets;
}
function _getMintCapTolerance() internal view returns (uint256) {
return _getStorage().mintCapTolerance;
}
function _getWeights() internal view returns (uint256[] storage) {
return _getStorage().weights;
}
function _getFallbackMintPool() internal view returns (uint8) {
return _getStorage().fallbackMintPool;
}
function _setWeights(uint256[] memory _weights) internal {
_getStorage().weights = _weights;
}
function _setIndexAssets(address[] memory _indexAssets) internal {
_getStorage().indexAssets = _indexAssets;
}
function _setGmiV2Handler(address gmiV2Handler) internal {
_getStorage().gmiV2Handler = gmiV2Handler;
}
function _setMintCapTolerance(uint256 newTolerance) internal {
_getStorage().mintCapTolerance = newTolerance;
}
function _setFallbackMintPool(uint8 poolIndex) internal {
_getStorage().fallbackMintPool = poolIndex;
}
}
文件 33 的 103:GmiUtils.sol
pragma solidity 0.8.17;
import { Solarray } from "../libraries/Solarray.sol";
import { SafeCast } from "../libraries/SafeCast.sol";
library GmiUtils {
error AboveDepositTolerance();
uint256 constant SCALE = 1e18;
function valueToShares(uint256 assetValue, uint256 pps, uint256 decimals) internal pure returns (uint256) {
return (10 ** decimals * assetValue) / pps;
}
function sharesToValue(uint256 shares, uint256 pps, uint256 decimals) internal pure returns (uint256) {
return (shares * pps) / 10 ** decimals;
}
function pricePerShare(uint256 totalSupply, uint256 totalBalance, uint256 decimals)
internal
pure
returns (uint256)
{
uint256 singleShare = 10 ** decimals;
return totalSupply > 0 ? (singleShare * totalBalance) / totalSupply : singleShare;
}
function findWeightedBalances(uint256 total, uint256[] memory weights) internal pure returns (uint256[] memory) {
uint256[] memory weightedBalances = new uint256[](weights.length);
for (uint256 i = 0; i < weights.length; i++) {
weightedBalances[i] = total * weights[i] / 1e18;
}
return weightedBalances;
}
function adjustToBalance(
uint256 shares,
uint256 tvl,
int256[] memory difference,
uint256[] memory weights,
uint256 totalSupply,
uint256 indexSize
) internal pure returns (uint256[] memory) {
uint256[] memory toBalanceAmount = new uint256[](indexSize);
require(indexSize == difference.length, "GMI: indexSize != difference.length");
uint256 shareValue = (shares * tvl + totalSupply - 1) / totalSupply;
uint256 underAllocation = SafeCast.toUint256(Solarray.directionalSum(difference, true));
if (shareValue <= underAllocation) {
return Solarray.arrayAddProportion(toBalanceAmount, shareValue, difference, underAllocation, true);
} else {
toBalanceAmount =
Solarray.arrayAddProportion(toBalanceAmount, underAllocation, difference, underAllocation, true);
shareValue -= underAllocation;
}
int256[] memory balanceWeightings = new int256[](indexSize);
for (uint256 i = 0; i < indexSize; i++) {
if (difference[i] < 0) {
for (uint256 j = 0; j < indexSize; j++) {
if (i != j) {
balanceWeightings[j] = balanceWeightings[j]
+ SafeCast.toInt256((weights[j] * SafeCast.toUint256(-difference[i]) / weights[i]));
}
}
}
}
uint256 sumOfWeights = Solarray.arraySumWithSafeCast(balanceWeightings);
if (sumOfWeights > shareValue) {
toBalanceAmount =
Solarray.arrayAddProportion(toBalanceAmount, shareValue, balanceWeightings, sumOfWeights, true);
return toBalanceAmount;
} else {
shareValue -= Solarray.arraySumWithSafeCast(balanceWeightings);
for (uint256 i = 0; i < indexSize; i++) {
toBalanceAmount[i] += SafeCast.toUint256(balanceWeightings[i]) + shareValue * weights[i] / SCALE;
}
return toBalanceAmount;
}
}
}
文件 34 的 103:GmxStorage.sol
pragma solidity 0.8.17;
import { PriceCast } from "./PriceCast.sol";
library GmxStorage {
struct MarketPrices {
Price indexTokenPrice;
Price longTokenPrice;
Price shortTokenPrice;
}
struct Price {
uint256 min;
uint256 max;
}
function castToPrice(uint256 min, uint256 max, uint256 decimals) internal pure returns (Price memory) {
return Price(PriceCast.toExternalPricing(min, decimals), PriceCast.toExternalPricing(max, decimals));
}
function castToMarketPrices(uint256[3] memory min, uint256[3] memory max, uint256[3] memory decimals)
internal
pure
returns (MarketPrices memory)
{
return MarketPrices(
castToPrice(min[0], max[0], decimals[0]),
castToPrice(min[1], max[1], decimals[1]),
castToPrice(min[2], max[2], decimals[2])
);
}
}
文件 35 的 103:IAggregatorV3Interface.sol
pragma solidity 0.8.17;
interface IAggregatorV3Interface {
function latestRoundData()
external
view
returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
function decimals() external view returns (uint8);
}
文件 36 的 103:IArbSys.sol
pragma solidity 0.8.17;
interface IArbSys {
function arbBlockNumber() external view returns (uint256);
}
文件 37 的 103:IAssetVault.sol
pragma solidity 0.8.17;
interface IAssetVault {
function asset() external returns (address);
function pauseDepositWithdraw() external;
function unpauseDepositWithdraw() external;
}
文件 38 的 103: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);
}
文件 39 的 103: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);
}
文件 40 的 103: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);
}
文件 41 的 103:IGmxV2Handler.sol
pragma solidity 0.8.17;
import { GmxStorage } from "../libraries/GmxStorage.sol";
interface IGmxV2Handler {
struct DepositRequestDetails {
address market;
uint256 wethAmountDeposited;
uint256 usdcAmountDeposited;
uint256 amountMinted;
bool executed;
bool success;
}
struct WithdrawRequestDetails {
address market;
uint256 gmAmountDeposited;
uint256 usdcAmountReceived;
uint256 wethAmountReceived;
bool executed;
bool success;
}
struct RequestDetails {
address market;
address withAsset;
uint256 amount;
bool isDeposit;
}
struct GmxV2Storage {
mapping(bytes32 => DepositRequestDetails) depositRequests;
mapping(bytes32 => WithdrawRequestDetails) withdrawRequests;
}
function getGmMidPrice(address market, GmxStorage.MarketPrices memory tokenPrices)
external
view
returns (uint256 price);
function getMaxDepositAmount(address _market, address _token) external view returns (uint256 maxDepositAmount);
function burnGmTokens(address _market, uint256 _amount, address _receiver)
external
returns (bytes32 _withdrawKey);
function mintGmTokens(address _market, uint256 _amountWeth, uint256 _amountUsdc, address _receiver)
external
payable
returns (bytes32 _depositKey);
function getDepositRequestDetails(bytes32 _key) external view returns (DepositRequestDetails memory);
function getWithdrawRequestDetails(bytes32 _key) external view returns (WithdrawRequestDetails memory);
}
文件 42 的 103:IHandlerContract.sol
pragma solidity 0.8.17;
interface IHandlerContract {
function callbackSigs() external pure returns (bytes4[] memory);
}
文件 43 的 103:IHookExecutor.sol
pragma solidity 0.8.17;
enum HookType {
DEPOSIT_HOOK,
WITHDRAW_HOOK,
OPEN_REBALANCE_HOOK,
CLOSE_REBALANCE_HOOK
}
interface IHookExecutor {
function executeHook(HookType _type, bytes calldata _data) external returns (bytes memory);
}
文件 44 的 103:IPositionManager.sol
pragma solidity 0.8.17;
import { IHandlerContract } from "./IHandlerContract.sol";
interface IPositionManager is IHandlerContract {
function positionNotional(address _indexToken) external view returns (uint256, bool);
function positionMargin(address _indexToken) external view returns (uint256, bool);
}
文件 45 的 103:IPriceFeed.sol
pragma solidity ^0.8.0;
interface IPriceFeed {
function latestRoundData() external view returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
}
文件 46 的 103:IRealtimeFeedVerifier.sol
pragma solidity ^0.8.0;
interface IRealtimeFeedVerifier {
function verify(bytes memory data) external returns (bytes memory);
}
文件 47 的 103:ISupraSValueFeed.sol
pragma solidity 0.8.17;
interface ISupraSValueFeed {
struct priceFeed {
uint256 round;
uint256 decimals;
uint256 time;
uint256 price;
}
struct derivedData {
int256 roundDifference;
uint256 derivedPrice;
uint256 decimals;
}
function getSvalue(uint256 _pairIndex) external view returns (priceFeed memory);
function getSvalues(uint256[] memory _pairIndexes) external view returns (priceFeed[] memory);
function getDerivedSvalue(uint256 pair_id_1, uint256 pair_id_2, uint256 operation)
external
view
returns (derivedData memory);
function getTimestamp(uint256 _tradingPair) external view returns (uint256);
}
文件 48 的 103:ISwapManager.sol
pragma solidity 0.8.17;
import { IHandlerContract } from "./IHandlerContract.sol";
interface ISwapManager is IHandlerContract {
function swap(address _tokenIn, address _tokenOut, uint256 _amountIn, uint256 _minOut, bytes calldata _data)
external
returns (uint256 _amountOut);
}
文件 49 的 103:ISwapRouter.sol
pragma solidity 0.8.17;
pragma abicoder v2;
interface ISwapRouter {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut);
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn);
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn);
}
文件 50 的 103:IUniswapV3Factory.sol
pragma solidity 0.8.17;
interface IUniswapV3Factory {
event OwnerChanged(address indexed oldOwner, address indexed newOwner);
event PoolCreated(
address indexed token0, address indexed token1, uint24 indexed fee, int24 tickSpacing, address pool
);
event FeeAmountEnabled(uint24 indexed fee, int24 indexed tickSpacing);
function owner() external view returns (address);
function feeAmountTickSpacing(uint24 fee) external view returns (int24);
function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address pool);
function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool);
function setOwner(address _owner) external;
function enableFeeAmount(uint24 fee, int24 tickSpacing) external;
}
文件 51 的 103:IUniswapV3Pool.sol
pragma solidity 0.8.17;
import { IUniswapV3PoolState } from "./IUniswapV3PoolState.sol";
interface IUniswapV3Pool is IUniswapV3PoolState {
function fee() external view returns (uint24);
function token0() external view returns (address);
function token1() external view returns (address);
}
文件 52 的 103:IUniswapV3PoolState.sol
pragma solidity 0.8.17;
interface IUniswapV3PoolState {
function slot0()
external
view
returns (
uint160 sqrtPriceX96,
int24 tick,
uint16 observationIndex,
uint16 observationCardinality,
uint16 observationCardinalityNext,
uint8 feeProtocol,
bool unlocked
);
function feeGrowthGlobal0X128() external view returns (uint256);
function feeGrowthGlobal1X128() external view returns (uint256);
function protocolFees() external view returns (uint128 token0, uint128 token1);
function liquidity() external view returns (uint128);
function ticks(int24 tick)
external
view
returns (
uint128 liquidityGross,
int128 liquidityNet,
uint256 feeGrowthOutside0X128,
uint256 feeGrowthOutside1X128,
int56 tickCumulativeOutside,
uint160 secondsPerLiquidityOutsideX128,
uint32 secondsOutside,
bool initialized
);
function tickBitmap(int16 wordPosition) external view returns (uint256);
function positions(bytes32 key)
external
view
returns (
uint128 _liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
);
function observations(uint256 index)
external
view
returns (
uint32 blockTimestamp,
int56 tickCumulative,
uint160 secondsPerLiquidityCumulativeX128,
bool initialized
);
}
文件 53 的 103:IVaultFees.sol
pragma solidity ^0.8.17;
interface IVaultFees {
function getVaultRebalanceFees(address vault, uint256 lastRebalance)
external
pure
returns (uint256, uint256, uint256, uint256);
function getWithdrawalFee(address vault, uint256 size, bool useLlo) external pure returns (uint256);
function getDepositFee(address vault, uint256 size, bool useLlo) external pure returns (uint256);
}
文件 54 的 103:IVerifierProxy.sol
pragma solidity 0.8.17;
interface IVerifierProxy {
function verify(bytes calldata) external returns (bytes memory);
function s_feeManager() external view returns (address);
}
文件 55 的 103:IWNT.sol
pragma solidity ^0.8.0;
interface IWNT {
function deposit() external payable;
function withdraw(uint256 amount) external;
}
文件 56 的 103: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_ORDER_ACTION = keccak256(abi.encode("SUBACCOUNT_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
));
}
}
文件 57 的 103:LibAggregateVaultUtils.sol
pragma solidity 0.8.17;
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { AggregateVaultStorage, LibAggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
import { NettedPositionTracker } from "./NettedPositionTracker.sol";
import { GMI } from "../index/GMI.sol";
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
import { TOKEN_USDC_NATIVE, TOKEN_WETH } from "../constants.sol";
import { Pricing } from "./Pricing.sol";
import { SafeCast } from "./SafeCast.sol";
import { PriceCast } from "./PriceCast.sol";
using SafeCast for uint256;
using SafeCast for int256;
using PriceCast for uint256;
library LibAggregateVaultUtils {
function getVaultGmi(uint256 _vaultIdx, uint256 _currentEpoch, bool useLlo)
internal
view
returns (uint256 _gmiAmount)
{
AggregateVaultStorage.AVStorage storage stg = _getStorage();
int256[2] memory currentAssetPrices = getVaultTokenPrices(useLlo);
uint256 indexPrice = useLlo
? Pricing.getIndexPps(stg.oracleWrapper, GMI(stg.gmi))
: Pricing.getIndexPpsChainlink(stg.oracleWrapper, GMI(stg.gmi));
return getVaultGmiWithPrices(_vaultIdx, _currentEpoch, indexPrice, currentAssetPrices);
}
function getVaultGmiWithPrices(
uint256 _vaultIdx,
uint256 _currentEpoch,
uint256 indexPrice,
int256[2] memory currentAssetPrices
) internal view returns (uint256 _gmiAmount) {
AggregateVaultStorage.AVStorage storage stg = _getStorage();
uint256[2] memory vaultsGmi = [vaultGmiBalanceToken(0), vaultGmiBalanceToken(1)];
if (_currentEpoch == 0) {
return vaultsGmi[_vaultIdx];
} else {
(,, int256[2] memory gmiPnl,) = NettedPositionTracker.settleNettingPositionPnl(
stg.nettedPositions,
currentAssetPrices,
stg.lastNettedPrices[_currentEpoch],
vaultsGmi,
indexPrice,
stg.zeroSumPnlThreshold
);
int256 gmiDelta = gmiPnl[_vaultIdx];
if (gmiPnl[_vaultIdx] < 0 && vaultsGmi[_vaultIdx] < (-gmiDelta).toUint256()) {
return 0;
} else {
return uint256(vaultsGmi[_vaultIdx].toInt256() + gmiDelta);
}
}
}
function getVaultGmiProportion(uint256 _idx) internal view returns (uint256 _proportion) {
uint256[2] memory gmiAttribution = _getStorage().vaultGmiAttribution;
uint256 totalAttribution = gmiAttribution[0] + gmiAttribution[1];
if (totalAttribution == 0) return 0;
uint256 vaultAttribution = gmiAttribution[_idx];
return vaultAttribution * 1e18 / totalAttribution;
}
function vaultGmiBalanceToken(uint256 _idx) internal view returns (uint256) {
uint256 gmiBalance = GMI(_getStorage().gmi).balanceOf(address(this));
return gmiBalance * getVaultGmiProportion(_idx) / 1e18;
}
function getVaultTokenPrices(bool useLlo) internal view returns (int256[2] memory tokenPrices) {
address oracle = _getStorage().oracleWrapper;
uint256 usdcPrice = OracleWrapper(oracle).getChainlinkPrice(TOKEN_USDC_NATIVE);
uint256 wethPrice = useLlo
? OracleWrapper(oracle).getLloPriceWithinL1Blocks(TOKEN_WETH)
: OracleWrapper(oracle).getChainlinkPrice(TOKEN_WETH);
return [usdcPrice.toInternalPrice(6).toInt256(), wethPrice.toInternalPrice(18).toInt256()];
}
function getVaultsGmi(uint256 epoch, bool useLlo) internal view returns (uint256[2] memory) {
return [getVaultGmi(0, epoch, useLlo), getVaultGmi(1, epoch, useLlo)];
}
function _getStorage() internal pure returns (AggregateVaultStorage.AVStorage storage stg) {
stg = LibAggregateVaultStorage.getStorage();
}
}
文件 58 的 103:LibCycle.sol
pragma solidity 0.8.17;
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
import { GMI } from "../index/GMI.sol";
import { IGmxV2Handler } from "../interfaces/IGmxV2Handler.sol";
import { AggregateVaultStorage, LibAggregateVaultStorage } from "../storage/AggregateVaultStorage.sol";
import { GmxStorage } from "./GmxStorage.sol";
import { Pricing } from "./Pricing.sol";
import { Delegatecall } from "./Delegatecall.sol";
import { TOKEN_WETH, TOKEN_USDC_NATIVE } from "../constants.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { ISwapManager } from "../interfaces/ISwapManager.sol";
import { PositionManagerRouter } from "../position-managers/PositionManagerRouter.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { UniswapV3SwapManager } from "../handlers/UniswapV3SwapManager.sol";
import { NettedPositionTracker } from "./NettedPositionTracker.sol";
import { SafeCast } from "./SafeCast.sol";
import { Emitter } from "../peripheral/Emitter.sol";
import { LibAggregateVaultUtils } from "./LibAggregateVaultUtils.sol";
using SafeCast for uint256;
using SafeCast for int256;
using SafeTransferLib for ERC20;
library LibCycle {
error OnlyOneRequestPerAssetPerEpoch();
error RequestAlreadyFulfilled(bytes32);
error RequestNotExecuted();
error RequestNotSucceded();
bytes32 constant CYCLE_STORAGE_SLOT = keccak256("AggregateVaultHelper.cycleStorage");
struct GMIMintRequest {
bytes32[] depositKeys;
uint256[] assetAmounts;
uint256[] gmAmountsRequired;
uint256[] gmAmountsMinted;
address[] markets;
address asset;
uint256 targetGMIAmount;
uint256 gmiMinted;
bool fulfilled;
}
struct GMIBurnRequest {
bytes32[] withdrawalKeys;
uint256[] gmAmounts;
address[] markets;
address asset;
uint256 gmiAmount;
uint256[] usdcReceived;
uint256[] ethReceived;
bool fulfilled;
}
struct StorageCycle {
mapping(bytes32 => GMIMintRequest) mintRequests;
mapping(bytes32 => GMIBurnRequest) burnRequests;
}
function _getCycleStorage() internal pure returns (StorageCycle storage _storage) {
bytes32 slot = CYCLE_STORAGE_SLOT;
assembly {
_storage.slot := slot
}
}
function _getMintBurnRequestKey(address _asset, uint256 _epoch) internal pure returns (bytes32) {
return keccak256(abi.encode(_asset, _epoch));
}
function _setMintRequest(address _asset, uint256 _epoch, GMIMintRequest memory _mintRequest) internal {
bytes32 key = _getMintBurnRequestKey(_asset, _epoch);
if (_getCycleStorage().mintRequests[key].asset != address(0)) revert OnlyOneRequestPerAssetPerEpoch();
_getCycleStorage().mintRequests[key] = _mintRequest;
_emitter().emitMintRequest(_asset, _epoch, _mintRequest);
}
function _setBurnRequest(address _asset, uint256 _epoch, GMIBurnRequest memory _burnRequest) internal {
bytes32 key = _getMintBurnRequestKey(_asset, _epoch);
if (_getCycleStorage().burnRequests[key].asset != address(0)) revert OnlyOneRequestPerAssetPerEpoch();
_getCycleStorage().burnRequests[key] = _burnRequest;
_emitter().emitBurnRequest(_asset, _epoch, _burnRequest);
}
function clearMintBurnRequestForEpoch(uint256 _epoch) external {
bytes32 usdcKey = _getMintBurnRequestKey(TOKEN_USDC_NATIVE, _epoch);
bytes32 ethKey = _getMintBurnRequestKey(TOKEN_WETH, _epoch);
GMIMintRequest memory gmiMintRequest;
GMIBurnRequest memory gmiBurnRequest;
_getCycleStorage().mintRequests[usdcKey] = gmiMintRequest;
_getCycleStorage().burnRequests[usdcKey] = gmiBurnRequest;
_getCycleStorage().mintRequests[ethKey] = gmiMintRequest;
_getCycleStorage().burnRequests[ethKey] = gmiBurnRequest;
}
function cycle(bool shouldRebalanceGmi)
external
returns (GMIMintRequest[2] memory mintRequests, GMIBurnRequest[2] memory burnRequests)
{
AggregateVaultStorage.VaultState storage vaultState = LibAggregateVaultStorage.getVaultState();
int256[2] memory prices = LibAggregateVaultUtils.getVaultTokenPrices(true);
uint256 gmiPrice = Pricing.getIndexPps(_getOracleWrapper(), _gmi());
if (vaultState.epoch > 0) {
_settleInternalPnl(prices, gmiPrice);
}
_updateNettingCheckpointPrice(prices, vaultState.epoch + 1);
return shouldRebalanceGmi ? rebalanceGmiFromRebalanceState(gmiPrice) : (mintRequests, burnRequests);
}
function rebalanceGmiFromRebalanceState(uint256 _gmiPrice)
public
returns (GMIMintRequest[2] memory _mintRequests, GMIBurnRequest[2] memory _burnRequests)
{
AggregateVaultStorage.RebalanceState storage rebalanceState = LibAggregateVaultStorage.getRebalanceState();
uint256[2] memory targetUsd = rebalanceState.indexAllocation;
uint256[2] memory targetShares = [targetUsd[0] * 1e18 / _gmiPrice, targetUsd[1] * 1e18 / _gmiPrice];
uint256[2] memory currentShares = LibAggregateVaultUtils.getVaultsGmi(0, true);
_emitter().emitRebalanceGmiFromState(targetUsd, targetShares, currentShares);
return rebalanceGmi(currentShares, targetShares, _gmiPrice);
}
function rebalanceGmiUsd(uint256[2] memory _current, uint256[2] memory _target, uint256 _gmiPrice)
public
returns (GMIMintRequest[2] memory _mintRequests, GMIBurnRequest[2] memory _burnRequests)
{
uint256[2] memory targetShares = [_target[0] * 1e18 / _gmiPrice, _target[1] * 1e18 / _gmiPrice];
uint256[2] memory currentShares = [_current[0] * 1e18 / _gmiPrice, _current[1] * 1e18 / _gmiPrice];
return rebalanceGmi(currentShares, targetShares, _gmiPrice);
}
function rebalanceGmi(uint256[2] memory _current, uint256[2] memory _target, uint256 _gmiPrice)
public
returns (GMIMintRequest[2] memory _mintRequests, GMIBurnRequest[2] memory _burnRequests)
{
bool isUsdcBurn = _target[0] < _current[0];
bool isEthBurn = _target[1] < _current[1];
bool isOppositeDirection = isUsdcBurn != isEthBurn;
if (isOppositeDirection) {
uint256 deltaUsdc = isUsdcBurn ? _current[0] - _target[0] : _target[0] - _current[0];
uint256 deltaEth = isEthBurn ? _current[1] - _target[1] : _target[1] - _current[1];
uint256 internalNet = deltaUsdc > deltaEth ? deltaEth : deltaUsdc;
uint256 internalNetUsd = internalNet * _gmiPrice / 1e18;
int256[2] memory prices = LibAggregateVaultUtils.getVaultTokenPrices(true);
if (isUsdcBurn) {
uint256 ethAmount = internalNetUsd * 1e18 / uint256(prices[1]);
_swap(true, ethAmount);
} else {
uint256 usdcAmount = internalNetUsd * 1e6 / uint256(prices[0]);
_swap(false, usdcAmount);
}
uint256 totalGmi = _gmi().balanceOf(address(this));
if (isUsdcBurn) {
_current[0] = _current[0] - internalNet;
_commitGmiDeltaProportions(0, -int256(internalNet), totalGmi);
totalGmi = totalGmi - internalNet;
_current[1] = _current[1] + internalNet;
_commitGmiDeltaProportions(1, int256(internalNet), totalGmi);
} else {
_current[0] = _current[0] + internalNet;
_commitGmiDeltaProportions(0, int256(internalNet), totalGmi);
totalGmi = totalGmi + internalNet;
_current[1] = _current[1] - internalNet;
_commitGmiDeltaProportions(1, -int256(internalNet), totalGmi);
}
}
for (uint256 i = 0; i < 2; i++) {
AggregateVaultStorage.AssetVaultStorage storage assetVault = _getStorage().vaults[i];
address asset = assetVault.token;
if (_target[i] > _current[i]) {
_mintRequests[i] = _increaseGMI(asset, _target[i] - _current[i]);
}
else if (_target[i] < _current[i]) {
uint256 gmiDelta = _current[i] - _target[i];
_burnRequests[i] = _decreaseGMI(asset, gmiDelta);
GMI gmi = GMI(_getStorage().gmi);
uint256 prevTotal = gmi.balanceOf(address(this)) + gmiDelta;
_commitGmiDeltaProportions(i, -int256(gmiDelta), prevTotal);
}
}
}
function _increaseGMI(address _asset, uint256 _delta) internal returns (GMIMintRequest memory _mintRequest) {
GMI gmi = GMI(_getStorage().gmi);
address oracle = _getStorage().oracleWrapper;
GmxStorage.MarketPrices[] memory marketPrices = Pricing.getMarketPrices(oracle, gmi, true);
uint256[] memory gmSharesRequired = gmi.previewMint(_delta, _asset, marketPrices);
address[] memory markets = gmi.indexAssets();
bytes32[] memory depositKeys = new bytes32[](markets.length);
uint256[] memory assetAmounts = new uint256[](markets.length);
uint256 epoch = LibAggregateVaultStorage.getVaultState().epoch;
require(markets.length == 4, "markets.length != 4");
for (uint256 i = 0; i < markets.length; i++) {
if (gmSharesRequired[i] > 0) {
uint256 assetAmountRequired = _previewGmMint(markets[i], gmSharesRequired[i], _asset);
if (assetAmountRequired == 0) {
gmSharesRequired[i] = 0;
continue;
}
assetAmounts[i] = assetAmountRequired;
depositKeys[i] = _mintGmWithAsset(markets[i], _asset, assetAmountRequired);
}
}
_mintRequest = GMIMintRequest({
depositKeys: depositKeys,
assetAmounts: assetAmounts,
gmAmountsRequired: gmSharesRequired,
gmAmountsMinted: new uint256[](markets.length),
markets: markets,
asset: _asset,
targetGMIAmount: _delta,
fulfilled: false,
gmiMinted: 0
});
_setMintRequest(_asset, epoch, _mintRequest);
}
function _decreaseGMI(address _asset, uint256 _delta) internal returns (GMIBurnRequest memory _burnRequest) {
GMI gmi = GMI(_getStorage().gmi);
address oracle = _getStorage().oracleWrapper;
GmxStorage.MarketPrices[] memory marketPrices = Pricing.getMarketPrices(oracle, gmi, true);
uint256[] memory gmSharesReceived = gmi.redeem(_delta, address(this), address(this), marketPrices);
address[] memory markets = gmi.indexAssets();
bytes32[] memory withdrawalKeys = new bytes32[](markets.length);
for (uint256 i = 0; i < markets.length; i++) {
if (gmSharesReceived[i] > 0) {
withdrawalKeys[i] = _burnGMForAsset(markets[i], gmSharesReceived[i]);
}
}
uint256 epoch = LibAggregateVaultStorage.getVaultState().epoch;
_burnRequest = GMIBurnRequest({
withdrawalKeys: withdrawalKeys,
gmAmounts: gmSharesReceived,
asset: _asset,
markets: markets,
gmiAmount: _delta,
usdcReceived: new uint256[](4),
ethReceived: new uint256[](4),
fulfilled: false
});
_setBurnRequest(_asset, epoch, _burnRequest);
}
function _burnGMForAsset(address _market, uint256 _amt) internal returns (bytes32 _withdrawKey) {
bytes memory cd = abi.encodeCall(IGmxV2Handler.burnGmTokens, (_market, _amt, address(this)));
bytes memory ret = Delegatecall.delegateCall(address(_gmxV2Handler()), cd);
_withdrawKey = abi.decode(ret, (bytes32));
}
function _mintGmWithAsset(address _market, address _asset, uint256 _amt) internal returns (bytes32 _depositKey) {
(uint256 amountEth, uint256 amountUsdc) = _asset == TOKEN_WETH ? (_amt, uint256(0)) : (uint256(0), _amt);
bytes memory cd = abi.encodeCall(IGmxV2Handler.mintGmTokens, (_market, amountEth, amountUsdc, address(this)));
bytes memory ret = Delegatecall.delegateCall(address(_gmxV2Handler()), cd);
_depositKey = abi.decode(ret, (bytes32));
}
function _previewGmMint(address _gm, uint256 _gmAmount, address _asset) internal returns (uint256 _assetAmount) {
address oracle = _getStorage().oracleWrapper;
uint256 gmPrice = _gmTokenPrice(oracle, _gm, true);
uint256 tokenPrice = Pricing.getTokenPrice(oracle, _asset, true);
_assetAmount = (_gmAmount * gmPrice / 1e18) / tokenPrice;
}
function _gmTokenPrice(address _oracleWrapper, address _gm, bool _withLlo) internal returns (uint256) {
GmxStorage.MarketPrices memory marketPrice = Pricing.getMarketPrice(_oracleWrapper, _gm, _withLlo);
IGmxV2Handler gmxV2Handler = _gmxV2Handler();
bytes memory gmMidPriceCalldata = abi.encodeCall(IGmxV2Handler.getGmMidPrice, (_gm, marketPrice));
bytes memory ret = Delegatecall.delegateCall(address(gmxV2Handler), gmMidPriceCalldata);
return abi.decode(ret, (uint256));
}
function _gmxV2Handler() internal view returns (IGmxV2Handler) {
return IGmxV2Handler(_getStorage().gmxV2Handler);
}
function fulfilRequests() external {
uint256 epoch = LibAggregateVaultStorage.getVaultState().epoch;
address[2] memory assets = [_getStorage().vaults[0].token, _getStorage().vaults[1].token];
for (uint256 i = 0; i < assets.length; i++) {
bytes32 mintBurnKey = _getMintBurnRequestKey(assets[i], epoch);
GMIMintRequest memory mintRequest = _getCycleStorage().mintRequests[mintBurnKey];
if (mintRequest.asset != address(0)) {
_fulfilMintRequest(mintBurnKey, mintRequest);
}
GMIBurnRequest memory burnRequest = _getCycleStorage().burnRequests[mintBurnKey];
if (burnRequest.asset != address(0)) {
_fulfilBurnRequest(mintBurnKey, burnRequest);
}
}
}
function _fulfilMintRequest(bytes32 _key, GMIMintRequest memory _mintRequest) internal {
if (_mintRequest.fulfilled) revert RequestAlreadyFulfilled(_key);
GMI gmi = GMI(_getStorage().gmi);
uint256 indexSize = gmi.INDEX_SIZE();
uint256[] memory gmReceived = new uint256[](indexSize);
for (uint256 i = 0; i < indexSize; i++) {
if (_mintRequest.gmAmountsRequired[i] > 0 && _mintRequest.assetAmounts[i] > 0) {
IGmxV2Handler.DepositRequestDetails memory depositRequestDetails =
_getDepositRequestDetails(_mintRequest.depositKeys[i]);
if (!depositRequestDetails.executed) revert RequestNotExecuted();
if (!depositRequestDetails.success) revert RequestNotSucceded();
gmReceived[i] = depositRequestDetails.amountMinted;
ERC20(_mintRequest.markets[i]).safeApprove(address(gmi), gmReceived[i]);
}
}
GmxStorage.MarketPrices[] memory marketPrices = Pricing.getMarketPrices(_getStorage().oracleWrapper, gmi, true);
uint256 gmiMinted = gmi.deposit(gmReceived, marketPrices, address(this));
uint256 prevTotal = gmi.balanceOf(address(this)) - gmiMinted;
uint256 vaultIdx = LibAggregateVaultStorage.getTokenToAssetVaultIndex()[_mintRequest.asset];
_commitGmiDeltaProportions(vaultIdx, int256(gmiMinted), prevTotal);
GMIMintRequest storage s_mintRequest = _getCycleStorage().mintRequests[_key];
s_mintRequest.gmiMinted = gmiMinted;
s_mintRequest.fulfilled = true;
s_mintRequest.gmAmountsMinted = gmReceived;
_emitter().emitFulfilGmiMintRequest(
s_mintRequest.targetGMIAmount, gmiMinted, s_mintRequest.gmAmountsRequired, gmReceived
);
}
function _fulfilBurnRequest(bytes32 _key, GMIBurnRequest memory _burnRequest) internal {
if (_burnRequest.fulfilled) revert RequestAlreadyFulfilled(_key);
bool isUsdc = _burnRequest.asset == TOKEN_USDC_NATIVE;
uint256[4] memory usdcReceived;
uint256[4] memory ethReceived;
for (uint256 i = 0; i < 4; i++) {
if (_burnRequest.gmAmounts[i] > 0) {
IGmxV2Handler.WithdrawRequestDetails memory withdrawRequestDetails =
_getWithdrawalRequestDetails(_burnRequest.withdrawalKeys[i]);
if (!withdrawRequestDetails.executed) revert RequestNotExecuted();
if (!withdrawRequestDetails.success) revert RequestNotSucceded();
usdcReceived[i] = withdrawRequestDetails.usdcAmountReceived;
ethReceived[i] = withdrawRequestDetails.wethAmountReceived;
if (isUsdc) _swap(true, ethReceived[i]);
else _swap(false, usdcReceived[i]);
}
}
GMIBurnRequest storage s_burnRequest = _getCycleStorage().burnRequests[_key];
s_burnRequest.usdcReceived = usdcReceived;
s_burnRequest.ethReceived = ethReceived;
s_burnRequest.fulfilled = true;
_emitter().emitFulfilGmiBurnRequest(s_burnRequest.gmiAmount, usdcReceived, ethReceived);
}
function _getDepositRequestDetails(bytes32 _key)
internal
returns (IGmxV2Handler.DepositRequestDetails memory)
{
address handler = address(_getStorage().gmxV2Handler);
bytes memory cd = abi.encodeCall(IGmxV2Handler.getDepositRequestDetails, (_key));
bytes memory ret = Delegatecall.delegateCall(handler, cd);
return abi.decode(ret, (IGmxV2Handler.DepositRequestDetails));
}
function _getWithdrawalRequestDetails(bytes32 _key)
internal
returns (IGmxV2Handler.WithdrawRequestDetails memory)
{
address handler = address(_getStorage().gmxV2Handler);
bytes memory cd = abi.encodeCall(IGmxV2Handler.getWithdrawRequestDetails, (_key));
bytes memory ret = Delegatecall.delegateCall(handler, cd);
return abi.decode(ret, (IGmxV2Handler.WithdrawRequestDetails));
}
function _swap(bool _ethForUsdc, uint256 _amount) internal {
(address tokenIn, address tokenOut) =
_ethForUsdc ? (TOKEN_WETH, TOKEN_USDC_NATIVE) : (TOKEN_USDC_NATIVE, TOKEN_WETH);
OracleWrapper ow = OracleWrapper(_getOracleWrapper());
uint256 ethPrice = ow.getChainlinkPrice(TOKEN_WETH);
uint256 usdcPrice = ow.getChainlinkPrice(TOKEN_USDC_NATIVE);
uint256 minOut = _ethForUsdc ? _amount * ethPrice / usdcPrice : _amount * usdcPrice / ethPrice;
PositionManagerRouter(payable(address(this))).executeSwap(
ISwapManager(_getStorage().uniswapV3SwapManager),
tokenIn,
tokenOut,
_amount,
minOut * (1e18 - _getStorage().swapSlippage) / 1e18,
hex""
);
}
function _commitGmiDeltaProportions(uint256 _vaultIdx, int256 _amt, uint256 _prevTotal) internal {
uint256[2] memory currentAttribution = _getStorage().vaultGmiAttribution;
uint256 totalAttribution = currentAttribution[0] + currentAttribution[1];
uint256[2] memory currentProportions;
if (totalAttribution == 0) {
currentProportions = [uint256(0), uint256(0)];
} else {
currentProportions =
[currentAttribution[0] * 1e18 / totalAttribution, currentAttribution[1] * 1e18 / totalAttribution];
}
uint256[2] memory prevAmounts =
[_prevTotal * currentProportions[0] / 1e18, _prevTotal * currentProportions[1] / 1e18];
if (_amt > 0) {
prevAmounts[_vaultIdx] += uint256(_amt);
uint256 newTotal = _prevTotal + uint256(_amt);
currentProportions[0] = prevAmounts[0] * 1e18 / newTotal;
currentProportions[1] = prevAmounts[1] * 1e18 / newTotal;
} else {
prevAmounts[_vaultIdx] -= uint256(-_amt);
uint256 newTotal = _prevTotal - uint256(-_amt);
currentProportions[0] = prevAmounts[0] * 1e18 / newTotal;
currentProportions[1] = prevAmounts[1] * 1e18 / newTotal;
}
_getStorage().vaultGmiAttribution = currentProportions;
}
function _getStorage() internal pure returns (AggregateVaultStorage.AVStorage storage _storage) {
_storage = LibAggregateVaultStorage.getStorage();
}
function _getOracleWrapper() internal view returns (address _oracleWrapper) {
_oracleWrapper = _getStorage().oracleWrapper;
}
function _gmi() internal view returns (GMI gmIndex) {
gmIndex = GMI(_getStorage().gmi);
}
function _emitter() internal view returns (Emitter emitter) {
emitter = Emitter(_getStorage().emitter);
}
function _settleInternalPnl(int256[2] memory currentAssetPrices, uint256 gmiPrice) internal {
uint256[2] memory settledVaultIndexAmount;
int256[2] memory nettedPnl;
int256[2] memory indexPnl;
int256[2] memory percentPriceChange;
uint256[2] memory vaultsGmi = LibAggregateVaultUtils.getVaultsGmi(0, true);
AggregateVaultStorage.AVStorage storage avs = _getStorage();
(settledVaultIndexAmount, nettedPnl, indexPnl, percentPriceChange) = NettedPositionTracker
.settleNettingPositionPnl(
avs.nettedPositions,
currentAssetPrices,
_getNettedPrices(LibAggregateVaultStorage.getVaultState().epoch),
vaultsGmi,
gmiPrice,
avs.zeroSumPnlThreshold
);
avs.vaultGmiAttribution = settledVaultIndexAmount;
Emitter(avs.emitter).emitSettleNettedPositionPnl(
vaultsGmi, settledVaultIndexAmount, indexPnl, nettedPnl, percentPriceChange
);
}
function _getNettedPrices(uint256 _epoch) internal view returns (int256[2] memory _nettedPrices) {
_nettedPrices = _getStorage().lastNettedPrices[_epoch];
}
function _updateNettingCheckpointPrice(int256[2] memory _prices, uint256 epochId) internal {
int256[2] memory prices = _getStorage().lastNettedPrices[epochId];
require(prices[0] == 0, "AggregateVault: lastNettedPrices already inited for given epoch");
AggregateVaultStorage.AVStorage storage avs = _getStorage();
avs.lastNettedPrices[epochId] = _prices;
Emitter(avs.emitter).emitUpdateNettingCheckpointPrice(_getStorage().lastNettedPrices[epochId - 1], _prices);
}
}
文件 59 的 103:Market.sol
pragma solidity ^0.8.0;
library Market {
struct Props {
address marketToken;
address indexToken;
address longToken;
address shortToken;
}
}
文件 60 的 103: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
);
}
}
文件 61 的 103: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;
}
}
文件 62 的 103: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);
}
}
文件 63 的 103: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);
}
}
文件 64 的 103: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) {
int256 impactAmount;
if (priceImpactUsd > 0) {
impactAmount = priceImpactUsd / tokenPrice.max.toInt256();
int256 maxImpactAmount = getSwapImpactPoolAmount(dataStore, market, token).toInt256();
if (impactAmount > maxImpactAmount) {
impactAmount = maxImpactAmount;
}
} else {
impactAmount = Calc.roundUpMagnitudeDivision(priceImpactUsd, tokenPrice.min);
}
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;
}
}
文件 65 的 103:Math.sol
pragma solidity ^0.8.0;
library Math {
enum Rounding {
Down,
Up,
Zero
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
require(denominator > prod1, "Math: mulDiv overflow");
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (~denominator + 1);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}
文件 66 的 103:Multicall.sol
pragma solidity 0.8.17;
abstract contract Multicall {
function _multicall(bytes[] calldata data)
internal
returns (bytes[] memory results, uint256[] memory gasEstimates)
{
results = new bytes[](data.length);
gasEstimates = new uint256[](data.length);
unchecked {
for (uint256 i = 0; i < data.length; ++i) {
uint256 startGas = gasleft();
(bool success, bytes memory result) = address(this).delegatecall(data[i]);
if (!success) {
assembly {
let resultLength := mload(result)
revert(add(result, 0x20), resultLength)
}
}
results[i] = result;
uint256 endGas = gasleft();
gasEstimates[i] = startGas - endGas;
}
}
}
}
文件 67 的 103:NettedPositionTracker.sol
pragma solidity 0.8.17;
import { Solarray } from "../libraries/Solarray.sol";
library NettedPositionTracker {
function getNettedPnl(int256[2][2] memory internalPositions, int256[2] memory assetPriceChange)
internal
pure
returns (int256[2] memory pnl)
{
int256[2] memory iPnl;
int256[2] memory nettingCollumnSum = Solarray.sumColumns(internalPositions);
nettingCollumnSum[0] -= internalPositions[0][0];
nettingCollumnSum[1] -= internalPositions[1][1];
iPnl[0] += nettingCollumnSum[0] * assetPriceChange[0] / 1e18;
iPnl[1] += nettingCollumnSum[1] * assetPriceChange[1] / 1e18;
pnl[0] = nettingCollumnSum[1] != 0
? iPnl[0] + (-iPnl[1] * (internalPositions[0][1] * 1e18 / nettingCollumnSum[1])) / 1e18
: iPnl[0];
pnl[1] = nettingCollumnSum[0] != 0
? iPnl[1] + (-iPnl[0] * (internalPositions[1][0] * 1e18 / nettingCollumnSum[0])) / 1e18
: iPnl[1];
}
function settleNettingPositionPnl(
int256[2][2] memory internalPositions,
int256[2] memory currentAssetPrices,
int256[2] memory nettedAssetPrices,
uint256[2] memory vaultIndexAmount,
uint256 indexPrice,
uint256 pnlSumThreshold
)
internal
pure
returns (
uint256[2] memory settledVaultIndexAmount,
int256[2] memory nettedPnl,
int256[2] memory indexPnl,
int256[2] memory percentPriceChange
)
{
_validatePrices(currentAssetPrices, nettedAssetPrices);
require(indexPrice > 0, "NettedPositionTracker: indexPrice must be greater than 0");
percentPriceChange = calculatePriceChange(currentAssetPrices, nettedAssetPrices);
nettedPnl = getNettedPnl(internalPositions, percentPriceChange);
checkZeroSum(nettedPnl, pnlSumThreshold);
indexPnl = pnlToIndex(int256(indexPrice), nettedPnl);
int256[2] memory indexPnlDifference = Solarray.arrayDifference(vaultIndexAmount, indexPnl);
checkNegativeDifference(indexPnlDifference);
settledVaultIndexAmount = Solarray.intToUintArray(indexPnlDifference);
}
function calculatePriceChange(int256[2] memory currentPrices, int256[2] memory nettedPrices)
internal
pure
returns (int256[2] memory percentPriceChange)
{
percentPriceChange[0] = ((currentPrices[0] - nettedPrices[0]) * 1e18 / nettedPrices[0]);
percentPriceChange[1] = ((currentPrices[1] - nettedPrices[1]) * 1e18 / nettedPrices[1]);
}
function pnlToIndex(int256 indexPrice, int256[2] memory pnl) internal pure returns (int256[2] memory indexAmount) {
indexAmount[0] = (pnl[0] * 1e18 / indexPrice);
indexAmount[1] = (pnl[1] * 1e18 / indexPrice);
}
function checkZeroSum(int256[2] memory nettingPositionPnl, uint256 zeroSumThreshold) internal pure {
uint256 absoluteSum = Solarray.arraySumAbsolute(nettingPositionPnl);
int256 pnlDifference = Solarray.arraySum(nettingPositionPnl);
uint256 pnlAbsoluteDifference = pnlDifference > 0 ? uint256(pnlDifference) : uint256(-pnlDifference);
uint256 buffer = (absoluteSum * zeroSumThreshold) / 1e18;
if (absoluteSum == 0) return;
require(pnlAbsoluteDifference < buffer, "NettedPositionTracker: greater than threshold");
}
function checkNegativeDifference(int256[2] memory differenceArray) internal pure {
require(differenceArray[0] >= 0 && differenceArray[1] >= 0, "NettedPositionTracker: differenceArray[i] < 0");
}
function _validatePrices(int256[2] memory _a, int256[2] memory _b) internal pure {
require(_a[0] > 0 && _a[1] > 0, "NettedPositionTracker: _a[i] must be greater than 0");
require(_b[0] > 0 && _b[1] > 0, "NettedPositionTracker: _b[i] must be greater than 0");
}
}
文件 68 的 103:NettingMath.sol
pragma solidity 0.8.17;
import { SafeCast } from "./SafeCast.sol";
import { Solarray } from "./Solarray.sol";
library NettingMath {
function vaultDeltaAdjustment(
uint256 vaultCumulativeHoldings,
uint256[2] memory indexComposition,
uint256[2] memory vaultHoldings,
int256 externalPosition
) public pure returns (uint256[2] memory indexExposure, uint256 vaultRatio) {
indexExposure[0] = vaultCumulativeHoldings * indexComposition[0] / 1e18;
indexExposure[1] = vaultCumulativeHoldings * indexComposition[1] / 1e18;
if (externalPosition < 0) {
indexExposure[1] += uint256(-externalPosition);
} else {
indexExposure[1] -= uint256(externalPosition);
}
vaultRatio = indexExposure[1] * 1e18 / vaultHoldings[1];
}
function calculateNettedPositions(
int256 externalPosition,
uint256[2] memory indexComposition,
uint256[2] memory indexHeldDollars
) public pure returns (int256[2][2] memory nettedMatrix, int256[2][2] memory exposureMatrix) {
exposureMatrix[0] = _vaultExposureInt(indexHeldDollars[0], indexComposition);
exposureMatrix[1] = _vaultExposureInt(indexHeldDollars[1], indexComposition);
nettedMatrix[0][0] = exposureMatrix[0][0];
nettedMatrix[1][1] = exposureMatrix[1][1];
if (externalPosition > 0) {
nettedMatrix[0][1] = exposureMatrix[0][1] - externalPosition;
nettedMatrix[1][0] = exposureMatrix[1][0];
} else {
nettedMatrix[0][1] = exposureMatrix[0][1];
nettedMatrix[1][0] = exposureMatrix[1][0] + externalPosition;
}
}
function isNetted(
uint256 vaultCumulativeHoldings,
uint256[2] memory indexComposition,
uint256[2] memory vaultHoldings,
int256 externalPosition,
uint256 nettedThreshold
) public pure returns (bool netted) {
uint256[2] memory indexExposure;
uint256 vaultRatio;
if (vaultCumulativeHoldings < 1e18) return true;
(indexExposure, vaultRatio) =
vaultDeltaAdjustment(vaultCumulativeHoldings, indexComposition, vaultHoldings, externalPosition);
uint256 upper = 1e18 * (10_000 + nettedThreshold) / 10_000;
uint256 lower = 1e18 * (10_000 - nettedThreshold) / 10_000;
netted = true;
if (vaultRatio > upper || vaultRatio < lower) {
netted = false;
}
}
function _vaultExposureInt(uint256 glpHeldDollars, uint256[2] memory indexComposition)
internal
pure
returns (int256[2] memory exposure)
{
for (uint256 i = 0; i < 2; i++) {
exposure[i] = SafeCast.toInt256((glpHeldDollars * indexComposition[i]) / 1e18);
}
}
}
文件 69 的 103: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
);
}
}
文件 70 的 103: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);
}
}
文件 71 的 103: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;
}
}
文件 72 的 103:OracleWrapper.sol
pragma solidity 0.8.17;
import { GlobalACL, Auth, REQUEST_HANDLER, AGGREGATE_VAULT_ROLE, KEEPER_ROLE } from "../Auth.sol";
import { IAggregatorV3Interface } from "../interfaces/IAggregatorV3Interface.sol";
import { IVerifierProxy } from "../interfaces/IVerifierProxy.sol";
import { IArbSys } from "../interfaces/IArbSys.sol";
import { ARBSYS, GMX_V2_LTC_INDEX_TOKEN, TOKEN_USDC_NATIVE } from "../constants.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ISupraSValueFeed } from "../interfaces/ISupraSValueFeed.sol";
import { StorageViewer } from "./StorageViewer.sol";
using SafeTransferLib for ERC20;
library LLOReportDecoder {
struct SignedReportData {
bytes32[3] context;
bytes blob;
bytes32[] rawRs;
bytes32[] rawSs;
bytes32 rawVs;
}
struct ReportData {
bytes32 feedId;
uint32 validFromTimestamp;
uint32 observationsTimestamp;
uint192 nativeFee;
uint192 linkFee;
uint32 expiresAt;
int192 benchmarkPrice;
}
function decodeSignedReport(bytes memory _signedReportData)
internal
pure
returns (SignedReportData memory _reportData)
{
(_reportData.context, _reportData.blob, _reportData.rawRs, _reportData.rawSs, _reportData.rawVs) =
abi.decode(_signedReportData, (bytes32[3], bytes, bytes32[], bytes32[], bytes32));
}
function decodeReportBlob(bytes memory _reportBlob) internal pure returns (ReportData memory _reportData) {
(
_reportData.feedId,
_reportData.validFromTimestamp,
_reportData.observationsTimestamp,
_reportData.nativeFee,
_reportData.linkFee,
_reportData.expiresAt,
_reportData.benchmarkPrice
) = abi.decode(_reportBlob, (bytes32, uint32, uint32, uint192, uint192, uint32, int192));
}
}
contract OracleWrapper is GlobalACL {
error ZeroAddress();
error InvalidPrice();
error FailedDeviationCheck(uint256);
error InvalidToken();
error PriceOutsideTolerance();
event UpdateTokenDetails(address indexed _token, TokenDetails _tokenDetails);
struct TokenDetails {
uint96 decimals;
address chainlinkPriceFeed;
bytes32 lloFeedId;
}
struct LLOConfiguration {
IVerifierProxy verifierProxy;
address feeManager;
address rewardManager;
}
struct PriceDetails {
uint32 validFrom;
uint32 validTill;
uint192 price;
uint128 lastUpdatedBlockNumber;
uint128 lastUpdatedBlockNumberL2;
uint128 lastUpdatedBlockTimestamp;
bytes32 feedId;
}
mapping(address => TokenDetails) tokenDetails;
LLOConfiguration public lloConfiguration;
address public immutable LINK;
mapping(address => PriceDetails) lloPriceDetails;
StorageViewer public storageViewer;
uint256 public lloDeviationFactor;
constructor(
Auth _auth,
StorageViewer viewer,
address _verifierProxy,
address _feeManager,
address _rewardManager,
address _link
) GlobalACL(_auth) {
lloConfiguration = LLOConfiguration({
verifierProxy: IVerifierProxy(_verifierProxy),
feeManager: _feeManager,
rewardManager: _rewardManager
});
LINK = _link;
require(address(viewer) != address(0));
storageViewer = viewer;
}
function updateViewer(StorageViewer viewer) external onlyConfigurator {
require(address(viewer) != address(0));
storageViewer = viewer;
}
function updateDeviationFactor(uint256 _newDeviationFactor) external onlyConfigurator {
require(_newDeviationFactor < 1e18);
lloDeviationFactor = _newDeviationFactor;
}
function updateTokenDetails(address _token, address _chainlinkPriceFeed, uint256 _decimals, bytes32 _lloFeedId)
external
onlyConfigurator
{
TokenDetails storage deets = tokenDetails[_token];
deets.chainlinkPriceFeed = _chainlinkPriceFeed;
uint96 decimals = _decimals > 0 ? uint96(_decimals) : _token.code.length > 0 ? ERC20(_token).decimals() : 0;
deets.decimals = decimals;
deets.lloFeedId = _lloFeedId;
emit UpdateTokenDetails(_token, deets);
}
function updateLLOConfiguration(address _verifierProxy, address _feeManager, address _rewardManager)
external
onlyConfigurator
{
lloConfiguration = LLOConfiguration({
verifierProxy: IVerifierProxy(_verifierProxy),
feeManager: _feeManager,
rewardManager: _rewardManager
});
}
function getChainlinkPrice(address _token) public view returns (uint256 _price) {
TokenDetails storage deets = tokenDetails[_token];
uint256 tokenDecimals = deets.decimals;
uint256 priceDecimal;
if (_token == GMX_V2_LTC_INDEX_TOKEN) {
return _getLtcPrice();
} else {
address priceFeed = deets.chainlinkPriceFeed;
if (priceFeed == address(0)) revert ZeroAddress();
(, int256 price,,,) = IAggregatorV3Interface(priceFeed).latestRoundData();
if (price < 0) revert InvalidPrice();
_price = uint256(price);
priceDecimal = IAggregatorV3Interface(priceFeed).decimals();
}
uint256 targetDecimals = 30;
if (priceDecimal + tokenDecimals < targetDecimals) {
_price = _price * (10 ** (targetDecimals - priceDecimal - tokenDecimals));
} else {
_price = _price / (10 ** (priceDecimal + tokenDecimals - targetDecimals));
}
}
function getChainlinkPriceInternal(address _token) public view returns (uint256) {
uint256 externalPrice = getChainlinkPrice(_token);
TokenDetails storage deets = tokenDetails[_token];
uint256 tokenDecimals = deets.decimals;
uint256 oneToken = 10 ** tokenDecimals;
return externalPrice * oneToken / 1e12;
}
function setAndGetLloPrice(address _token, bytes calldata _report)
public
validateSetPriceAuth
returns (uint256 _price)
{
_price = _setAndGetPriceInternal(_token, _report);
}
function getLloPriceWithinL1Blocks(address _token) public view returns (uint256 _price) {
if (_token == TOKEN_USDC_NATIVE) return getChainlinkPrice(_token);
PriceDetails storage priceDeets = lloPriceDetails[_token];
if (priceDeets.feedId == bytes32(0)) revert InvalidToken();
uint256 minBlockNumber = block.number - storageViewer.getBlockTolerance();
if (priceDeets.lastUpdatedBlockNumber < minBlockNumber) revert PriceOutsideTolerance();
_price = priceDeets.price;
}
function getLloPriceWithinL2Blocks(address _token) public view returns (uint256 _price) {
if (_token == TOKEN_USDC_NATIVE) return getChainlinkPrice(_token);
PriceDetails storage priceDeets = lloPriceDetails[_token];
if (priceDeets.feedId == bytes32(0)) revert InvalidToken();
uint256 minBlockNumber = _getBlockNumber() - storageViewer.getBlockTolerance();
if (priceDeets.lastUpdatedBlockNumberL2 < minBlockNumber) revert PriceOutsideTolerance();
_price = priceDeets.price;
}
function getLloPriceWithinSeconds(address _token, uint256 _seconds) public view returns (uint256 _price) {
if (_token == TOKEN_USDC_NATIVE) return getChainlinkPrice(_token);
PriceDetails storage priceDeets = lloPriceDetails[_token];
if (priceDeets.feedId == bytes32(0)) revert InvalidToken();
uint256 minTimestamp = block.timestamp - _seconds;
if (priceDeets.lastUpdatedBlockTimestamp < minTimestamp) revert PriceOutsideTolerance();
_price = priceDeets.price;
}
function _getLloPrice18Decimals(address _token) public view returns (uint256 _price) {
uint256 lloPrice = this.getLloPriceWithinL1Blocks(_token);
TokenDetails storage deets = tokenDetails[_token];
uint256 tokenDecimals = deets.decimals;
uint256 oneToken = uint256(10) ** tokenDecimals;
_price = lloPrice * oneToken / 1e12;
}
function _approveTokens(bytes memory _report) internal {
LLOReportDecoder.SignedReportData memory signedReportData = LLOReportDecoder.decodeSignedReport(_report);
LLOReportDecoder.ReportData memory reportData = LLOReportDecoder.decodeReportBlob(signedReportData.blob);
ERC20(LINK).safeApprove(lloConfiguration.rewardManager, reportData.linkFee);
}
function _getBlockNumber() internal view returns (uint256 _blockNumber) {
_blockNumber = IArbSys(ARBSYS).arbBlockNumber();
}
function _getLtcPrice() internal view returns (uint256 _price) {
_price = lloPriceDetails[GMX_V2_LTC_INDEX_TOKEN].price;
}
function _setAndGetPriceInternal(address _token, bytes memory _report) internal returns (uint256 _price) {
_price = abi.decode(_report, (uint256));
_checkPriceDeviation(_token, _price);
lloPriceDetails[_token] = PriceDetails({
validFrom: uint32(block.timestamp),
validTill: uint32(block.timestamp + 5 minutes),
price: uint192(_price),
lastUpdatedBlockNumberL2: uint128(_getBlockNumber()),
lastUpdatedBlockNumber: uint128(block.number),
lastUpdatedBlockTimestamp: uint128(block.timestamp),
feedId: bytes32(type(uint256).max)
});
}
function _setAndGetPriceLlo(address _token, bytes memory _report) internal returns (uint256 _price) {
bytes32 lloFeedId = tokenDetails[_token].lloFeedId;
if (lloFeedId == bytes32(0)) revert InvalidToken();
_approveTokens(_report);
bytes memory verifiedData = lloConfiguration.verifierProxy.verify(_report);
LLOReportDecoder.ReportData memory reportData = LLOReportDecoder.decodeReportBlob(verifiedData);
if (reportData.benchmarkPrice < 0) revert InvalidPrice();
if (reportData.feedId != lloFeedId) revert InvalidToken();
_price = uint256(uint192(reportData.benchmarkPrice));
lloPriceDetails[_token] = PriceDetails({
validFrom: reportData.validFromTimestamp,
validTill: reportData.expiresAt,
price: uint192(_price),
lastUpdatedBlockNumberL2: uint128(_getBlockNumber()),
lastUpdatedBlockNumber: uint128(block.number),
lastUpdatedBlockTimestamp: uint128(block.timestamp),
feedId: lloFeedId
});
}
function _checkPriceDeviation(address _token, uint256 _newPrice) internal {
uint256 externalPrice = getChainlinkPrice(_token);
uint256 deviation = _newPrice * 1e18 / externalPrice;
if (deviation < 1e18 - lloDeviationFactor || deviation > 1e18 + lloDeviationFactor) {
revert FailedDeviationCheck(deviation);
}
}
modifier validateSetPriceAuth() {
require(
AUTH.hasRole(AGGREGATE_VAULT_ROLE, msg.sender) || AUTH.hasRole(REQUEST_HANDLER, msg.sender)
|| AUTH.hasRole(KEEPER_ROLE, msg.sender),
"OracleWrapper: !authorized"
);
_;
}
}
文件 73 的 103: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());
}
}
文件 74 的 103: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;
}
}
}
文件 75 的 103: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;
}
}
}
文件 76 的 103:PausableVault.sol
pragma solidity 0.8.17;
abstract contract PausableVault {
event Paused(address account);
event Unpaused(address account);
event DepositsPaused(address account);
event DepositsUnpaused(address account);
event WithdrawalsPaused(address account);
event WithdrawalsUnpaused(address account);
bool private _depositsPaused;
bool private _withdrawalPaused;
constructor() {
_depositsPaused = false;
_withdrawalPaused = false;
}
modifier whenDepositNotPaused() {
_requireDepositNotPaused();
_;
}
modifier whenWithdrawalNotPaused() {
_requireWithdrawalNotPaused();
_;
}
modifier whenDepositPaused() {
_requireDepositPaused();
_;
}
modifier whenWithdrawalPaused() {
_requireWithdrawalPaused();
_;
}
function depositPaused() public view virtual returns (bool) {
return _depositsPaused;
}
function withdrawalPaused() public view virtual returns (bool) {
return _withdrawalPaused;
}
function _requireDepositNotPaused() internal view virtual {
require(!depositPaused(), "Pausable: deposit paused");
}
function _requireWithdrawalNotPaused() internal view virtual {
require(!withdrawalPaused(), "Pausable: withdrawal paused");
}
function _requireDepositPaused() internal view virtual {
require(depositPaused(), "Pausable: deposit not paused");
}
function _requireWithdrawalPaused() internal view virtual {
require(withdrawalPaused(), "Pausable: withdrawal not paused");
}
function _pause() internal virtual {
if (!depositPaused()) {
_pauseDeposit();
}
if (!withdrawalPaused()) {
_pauseWithdrawal();
}
}
function _unpause() internal virtual {
if (depositPaused()) {
_unpauseDeposit();
}
if (withdrawalPaused()) {
_unpauseWithdrawal();
}
}
function _pauseDeposit() internal virtual whenDepositNotPaused {
_depositsPaused = true;
emit DepositsPaused(msg.sender);
}
function _unpauseDeposit() internal virtual whenDepositPaused {
_depositsPaused = false;
emit DepositsUnpaused(msg.sender);
}
function _pauseWithdrawal() internal virtual whenWithdrawalNotPaused {
_withdrawalPaused = true;
emit WithdrawalsPaused(msg.sender);
}
function _unpauseWithdrawal() internal virtual whenWithdrawalPaused {
_withdrawalPaused = false;
emit WithdrawalsUnpaused(msg.sender);
}
}
文件 77 的 103: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;
}
}
文件 78 的 103:PositionManagerRouter.sol
pragma solidity 0.8.17;
import { Auth, GlobalACL } from "../Auth.sol";
import { Multicall } from "../libraries/Multicall.sol";
import { IPositionManager } from "../interfaces/IPositionManager.sol";
import { IHandlerContract } from "../interfaces/IHandlerContract.sol";
import { ISwapManager } from "../interfaces/ISwapManager.sol";
import { Delegatecall } from "../libraries/Delegatecall.sol";
contract WhitelistedTokenRegistry is GlobalACL {
event UpdatedWhitelistedToken(address indexed _token, bool _isWhitelisted);
event UpdatedIsWhitelistingEnabled(bool _isEnabled);
mapping(address => bool) public whitelistedTokens;
bool public isWhitelistingEnabled = true;
constructor(Auth _auth) GlobalACL(_auth) { }
function updateWhitelistedToken(address _token, bool _isWhitelisted) external onlyConfigurator {
whitelistedTokens[_token] = _isWhitelisted;
emit UpdatedWhitelistedToken(_token, _isWhitelisted);
}
function updateIsWhitelistingEnabled(bool _isWhitelistingEnabled) external onlyConfigurator {
isWhitelistingEnabled = _isWhitelistingEnabled;
emit UpdatedIsWhitelistingEnabled(_isWhitelistingEnabled);
}
function isWhitelistedToken(address _token) external view returns (bool) {
if (isWhitelistingEnabled) {
return whitelistedTokens[_token];
}
return true;
}
}
library PositionManagerRouterLib {
error NotWhitelistedToken();
error UnknownHandlerContract();
function executeSwap(
ISwapManager _swapManager,
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _minOut,
bytes calldata _data,
WhitelistedTokenRegistry whitelistedTokenRegistry,
mapping(ISwapManager => bool) storage swapHandlers,
mapping(IHandlerContract => bool) storage handlerContracts
) external returns (uint256 _amountOut) {
if (
!whitelistedTokenRegistry.isWhitelistedToken(_tokenIn)
|| !whitelistedTokenRegistry.isWhitelistedToken(_tokenOut)
) revert NotWhitelistedToken();
bool isSwapHandler = swapHandlers[_swapManager];
bool isHandler = handlerContracts[_swapManager];
if (!isSwapHandler || !isHandler) {
revert UnknownHandlerContract();
}
bytes memory ret = _delegatecall(
address(_swapManager), abi.encodeCall(ISwapManager.swap, (_tokenIn, _tokenOut, _amountIn, _minOut, _data))
);
(_amountOut) = abi.decode(ret, (uint256));
}
function _delegatecall(address _target, bytes memory _data) internal returns (bytes memory ret) {
bool success;
(success, ret) = _target.delegatecall(_data);
if (!success) {
assembly {
let length := mload(ret)
let start := add(ret, 0x20)
revert(start, length)
}
}
return ret;
}
}
abstract contract PositionManagerRouter {
using Delegatecall for address;
error UnknownCallback();
error CallbackHandlerNotSet();
error UnknownHandlerContract();
error OnlySelf();
error NotWhitelistedToken();
event CallbackHandlerUpdated(bytes4 indexed _sig, address indexed _handler, bool _enabled);
event HandlerContractUpdated(address indexed _contract, bool _enabled);
event DefaultHandlerContractUpdated(bytes4 indexed _sig, address indexed _handler);
event SwapHandlerUpdated(address indexed _handled, bool _enabled);
event WhitelistedTokenUpdated(address indexed _token, bool _isWhitelisted);
mapping(IHandlerContract => mapping(bytes4 => bool)) public handlerContractCallbacks;
mapping(IHandlerContract => bool) public handlerContracts;
address public currentCallbackHandler;
mapping(bytes4 => IHandlerContract) public defaultHandlers;
mapping(ISwapManager => bool) public swapHandlers;
WhitelistedTokenRegistry immutable whitelistedTokenRegistry;
constructor(WhitelistedTokenRegistry _registry) {
whitelistedTokenRegistry = _registry;
}
function updateHandlerContract(IHandlerContract _handler, bool _enabled) public {
_onlyConfigurator();
handlerContracts[_handler] = _enabled;
emit HandlerContractUpdated(address(_handler), _enabled);
_updateHandlerContractCallbacks(_handler, _enabled);
}
function updateDefaultHandlerContract(bytes4 _sig, IHandlerContract _handler) external {
_onlyConfigurator();
defaultHandlers[_sig] = _handler;
emit DefaultHandlerContractUpdated(_sig, address(_handler));
}
function updateSwapHandler(ISwapManager _manager, bool _enabled) external {
_onlyConfigurator();
updateHandlerContract(_manager, _enabled);
swapHandlers[_manager] = _enabled;
emit SwapHandlerUpdated(address(_manager), _enabled);
}
function execute(address _handler, bytes calldata data) public payable returns (bytes memory ret) {
bool isSwapHandler = swapHandlers[ISwapManager(_handler)];
if (isSwapHandler) {
if (msg.sender != address(this)) {
revert OnlySelf();
}
} else {
_validateExecuteCallAuth();
}
bool isHandler = handlerContracts[IHandlerContract(_handler)];
if (!isHandler) revert UnknownHandlerContract();
ret = _handler.delegateCall(data);
}
function executeWithCallbackHandler(address _handler, bytes calldata data, address _callbackHandler)
external
payable
withHandler(_callbackHandler)
returns (bytes memory ret)
{
ret = execute(_handler, data);
}
function executeSwap(
ISwapManager _swapManager,
address _tokenIn,
address _tokenOut,
uint256 _amountIn,
uint256 _minOut,
bytes calldata _data
) external returns (uint256 _amountOut) {
if (msg.sender != address(this)) {
_onlySwapIssuer();
}
_amountOut = PositionManagerRouterLib.executeSwap(
_swapManager,
_tokenIn,
_tokenOut,
_amountIn,
_minOut,
_data,
whitelistedTokenRegistry,
swapHandlers,
handlerContracts
);
}
fallback() external payable {
bytes memory _ret = _handleCallback();
assembly {
let length := mload(_ret)
return(add(_ret, 0x20), length)
}
}
function _onlyConfigurator() internal virtual;
function _onlySwapIssuer() internal virtual;
function _validateExecuteCallAuth() internal virtual;
function _updateHandlerContractCallbacks(IHandlerContract _handler, bool _enabled) internal {
bytes4[] memory handlerSigs = _handler.callbackSigs();
unchecked {
for (uint256 i = 0; i < handlerSigs.length; ++i) {
bytes4 sig = handlerSigs[i];
handlerContractCallbacks[_handler][sig] = _enabled;
emit CallbackHandlerUpdated(sig, address(_handler), _enabled);
}
}
}
function _handleCallback() internal returns (bytes memory ret) {
IHandlerContract handler = IHandlerContract(currentCallbackHandler);
if (address(handler) == address(0)) {
handler = defaultHandlers[msg.sig];
if (handler == IHandlerContract(address(0))) {
revert CallbackHandlerNotSet();
}
}
if (!handlerContracts[handler]) revert UnknownHandlerContract();
if (!handlerContractCallbacks[handler][msg.sig]) {
revert UnknownCallback();
}
ret = address(handler).delegateCall(msg.data);
}
modifier withHandler(address _handler) {
if (!handlerContracts[IHandlerContract(_handler)]) {
revert UnknownHandlerContract();
}
currentCallbackHandler = _handler;
_;
currentCallbackHandler = address(0);
}
modifier onlySelf() {
if (msg.sender != address(this)) revert OnlySelf();
_;
}
receive() external payable { }
}
文件 79 的 103: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;
}
}
文件 80 的 103: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;
}
}
文件 81 的 103:PriceCast.sol
pragma solidity 0.8.17;
library PriceCast {
function toExternalPricing(uint256 internalPrice, uint256 decimals) internal pure returns (uint256 externalPrice) {
externalPrice = (internalPrice * 1e12) / 10 ** decimals;
}
function toInternalPrice(uint256 externalPrice, uint256 decimals) internal pure returns (uint256 internalPrice) {
internalPrice = (externalPrice * 1e18) / 10 ** (30 - decimals);
}
}
文件 82 的 103:Pricing.sol
pragma solidity 0.8.17;
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
import { GMI } from "../index/GMI.sol";
import { GmxStorage } from "./GmxStorage.sol";
import { PriceCast } from "./PriceCast.sol";
import { MarketUtils, DataStore, Market } from "@gmx/market/MarketUtils.sol";
import { TOKEN_WETH, TOKEN_USDC_NATIVE, GMX_V2_DATA_STORE } from "../constants.sol";
library GMPricing {
function getMarketPrice(address _oracle, address _gm, bool _useLlo)
internal
view
returns (GmxStorage.MarketPrices memory)
{
uint256 ethPrice = getTokenPrice(_oracle, TOKEN_WETH, _useLlo);
uint256 usdcPrice = OracleWrapper(_oracle).getChainlinkPrice(TOKEN_USDC_NATIVE);
return getMarketPrice(_oracle, _gm, ethPrice, usdcPrice, _useLlo);
}
function getMarketPrice(address _oracle, address _gm, uint256 _ethPrice, uint256 _usdcPrice, bool _useLlo)
internal
view
returns (GmxStorage.MarketPrices memory marketPrice)
{
address indexToken = MarketUtils.getEnabledMarket(DataStore(GMX_V2_DATA_STORE), _gm).indexToken;
marketPrice.longTokenPrice = GmxStorage.Price({ min: _ethPrice, max: _ethPrice });
marketPrice.shortTokenPrice = GmxStorage.Price({ min: _usdcPrice, max: _usdcPrice });
uint256 indexTokenPrice = getTokenPrice(_oracle, indexToken, _useLlo);
marketPrice.indexTokenPrice = GmxStorage.Price({ min: indexTokenPrice, max: indexTokenPrice });
}
function getTokenPrice(address _oracle, address _token, bool _withLlo) internal view returns (uint256) {
return _withLlo
? OracleWrapper(_oracle).getLloPriceWithinL1Blocks(_token)
: OracleWrapper(_oracle).getChainlinkPrice(_token);
}
}
library Pricing {
function getMarketPrices(address _oracle, GMI _gmi, bool _useLlo)
internal
view
returns (GmxStorage.MarketPrices[] memory marketPrices)
{
uint256 indexSize = _gmi.INDEX_SIZE();
marketPrices = new GmxStorage.MarketPrices[](indexSize);
address[] memory marketTokens = _gmi.indexAssets();
uint256 ethPrice = getTokenPrice(_oracle, TOKEN_WETH, _useLlo);
uint256 usdcPrice = OracleWrapper(_oracle).getChainlinkPrice(TOKEN_USDC_NATIVE);
for (uint256 i = 0; i < indexSize; i++) {
marketPrices[i] = getMarketPrice(_oracle, marketTokens[i], ethPrice, usdcPrice, _useLlo);
}
return marketPrices;
}
function getIndexTvl(address _oracle, GMI _gmi) internal view returns (uint256) {
return _gmi.tvl(getMarketPrices(_oracle, _gmi, true));
}
function getIndexTvlChainlink(address _oracle, GMI _gmi) internal view returns (uint256) {
return _gmi.tvl(getMarketPrices(_oracle, _gmi, false));
}
function getIndexPps(address _oracle, GMI _gmi) internal view returns (uint256) {
return _gmi.pps(getMarketPrices(_oracle, _gmi, true));
}
function getIndexPpsChainlink(address _oracle, GMI _gmi) internal view returns (uint256) {
return _gmi.pps(getMarketPrices(_oracle, _gmi, false));
}
function getMarketPrice(address _oracle, address _gm, bool _useLlo)
internal
view
returns (GmxStorage.MarketPrices memory)
{
return GMPricing.getMarketPrice(_oracle, _gm, _useLlo);
}
function getMarketPrice(address _oracle, address _gm, uint256 _ethPrice, uint256 _usdcPrice, bool _useLlo)
internal
view
returns (GmxStorage.MarketPrices memory marketPrice)
{
return GMPricing.getMarketPrice(_oracle, _gm, _ethPrice, _usdcPrice, _useLlo);
}
function getTokenPrice(address _oracle, address _token, bool _withLlo) internal view returns (uint256) {
return GMPricing.getTokenPrice(_oracle, _token, _withLlo);
}
}
文件 83 的 103: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()
);
}
}
}
文件 84 的 103:ReentrancyGuard.sol
pragma solidity >=0.8.0;
abstract contract ReentrancyGuard {
uint256 private locked = 1;
modifier nonReentrant() virtual {
require(locked == 1, "REENTRANCY");
locked = 2;
_;
locked = 1;
}
}
文件 85 的 103: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 GOV_TOKEN_CONTROLLER = keccak256(abi.encode("GOV_TOKEN_CONTROLLER"));
bytes32 public constant ROUTER_PLUGIN = keccak256(abi.encode("ROUTER_PLUGIN"));
bytes32 public constant MARKET_KEEPER = keccak256(abi.encode("MARKET_KEEPER"));
bytes32 public constant FEE_KEEPER = keccak256(abi.encode("FEE_KEEPER"));
bytes32 public constant 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"));
}
文件 86 的 103: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 onlyGovTokenController() {
_validateRole(Role.GOV_TOKEN_CONTROLLER, "GOV_TOKEN_CONTROLLER");
_;
}
modifier onlyRouterPlugin() {
_validateRole(Role.ROUTER_PLUGIN, "ROUTER_PLUGIN");
_;
}
modifier onlyMarketKeeper() {
_validateRole(Role.MARKET_KEEPER, "MARKET_KEEPER");
_;
}
modifier onlyFeeKeeper() {
_validateRole(Role.FEE_KEEPER, "FEE_KEEPER");
_;
}
modifier 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);
}
}
}
文件 87 的 103: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();
}
}
}
}
文件 88 的 103:SafeCast.sol
pragma solidity ^0.8.0;
library SafeCast {
function toUint248(uint256 value) internal pure returns (uint248) {
require(value <= type(uint248).max, "SafeCast: value doesn't fit in 248 bits");
return uint248(value);
}
function toUint240(uint256 value) internal pure returns (uint240) {
require(value <= type(uint240).max, "SafeCast: value doesn't fit in 240 bits");
return uint240(value);
}
function toUint232(uint256 value) internal pure returns (uint232) {
require(value <= type(uint232).max, "SafeCast: value doesn't fit in 232 bits");
return uint232(value);
}
function toUint224(uint256 value) internal pure returns (uint224) {
require(value <= type(uint224).max, "SafeCast: value doesn't fit in 224 bits");
return uint224(value);
}
function toUint216(uint256 value) internal pure returns (uint216) {
require(value <= type(uint216).max, "SafeCast: value doesn't fit in 216 bits");
return uint216(value);
}
function toUint208(uint256 value) internal pure returns (uint208) {
require(value <= type(uint208).max, "SafeCast: value doesn't fit in 208 bits");
return uint208(value);
}
function toUint200(uint256 value) internal pure returns (uint200) {
require(value <= type(uint200).max, "SafeCast: value doesn't fit in 200 bits");
return uint200(value);
}
function toUint192(uint256 value) internal pure returns (uint192) {
require(value <= type(uint192).max, "SafeCast: value doesn't fit in 192 bits");
return uint192(value);
}
function toUint184(uint256 value) internal pure returns (uint184) {
require(value <= type(uint184).max, "SafeCast: value doesn't fit in 184 bits");
return uint184(value);
}
function toUint176(uint256 value) internal pure returns (uint176) {
require(value <= type(uint176).max, "SafeCast: value doesn't fit in 176 bits");
return uint176(value);
}
function toUint168(uint256 value) internal pure returns (uint168) {
require(value <= type(uint168).max, "SafeCast: value doesn't fit in 168 bits");
return uint168(value);
}
function toUint160(uint256 value) internal pure returns (uint160) {
require(value <= type(uint160).max, "SafeCast: value doesn't fit in 160 bits");
return uint160(value);
}
function toUint152(uint256 value) internal pure returns (uint152) {
require(value <= type(uint152).max, "SafeCast: value doesn't fit in 152 bits");
return uint152(value);
}
function toUint144(uint256 value) internal pure returns (uint144) {
require(value <= type(uint144).max, "SafeCast: value doesn't fit in 144 bits");
return uint144(value);
}
function toUint136(uint256 value) internal pure returns (uint136) {
require(value <= type(uint136).max, "SafeCast: value doesn't fit in 136 bits");
return uint136(value);
}
function toUint128(uint256 value) internal pure returns (uint128) {
require(value <= type(uint128).max, "SafeCast: value doesn't fit in 128 bits");
return uint128(value);
}
function toUint120(uint256 value) internal pure returns (uint120) {
require(value <= type(uint120).max, "SafeCast: value doesn't fit in 120 bits");
return uint120(value);
}
function toUint112(uint256 value) internal pure returns (uint112) {
require(value <= type(uint112).max, "SafeCast: value doesn't fit in 112 bits");
return uint112(value);
}
function toUint104(uint256 value) internal pure returns (uint104) {
require(value <= type(uint104).max, "SafeCast: value doesn't fit in 104 bits");
return uint104(value);
}
function toUint96(uint256 value) internal pure returns (uint96) {
require(value <= type(uint96).max, "SafeCast: value doesn't fit in 96 bits");
return uint96(value);
}
function toUint88(uint256 value) internal pure returns (uint88) {
require(value <= type(uint88).max, "SafeCast: value doesn't fit in 88 bits");
return uint88(value);
}
function toUint80(uint256 value) internal pure returns (uint80) {
require(value <= type(uint80).max, "SafeCast: value doesn't fit in 80 bits");
return uint80(value);
}
function toUint72(uint256 value) internal pure returns (uint72) {
require(value <= type(uint72).max, "SafeCast: value doesn't fit in 72 bits");
return uint72(value);
}
function toUint64(uint256 value) internal pure returns (uint64) {
require(value <= type(uint64).max, "SafeCast: value doesn't fit in 64 bits");
return uint64(value);
}
function toUint56(uint256 value) internal pure returns (uint56) {
require(value <= type(uint56).max, "SafeCast: value doesn't fit in 56 bits");
return uint56(value);
}
function toUint48(uint256 value) internal pure returns (uint48) {
require(value <= type(uint48).max, "SafeCast: value doesn't fit in 48 bits");
return uint48(value);
}
function toUint40(uint256 value) internal pure returns (uint40) {
require(value <= type(uint40).max, "SafeCast: value doesn't fit in 40 bits");
return uint40(value);
}
function toUint32(uint256 value) internal pure returns (uint32) {
require(value <= type(uint32).max, "SafeCast: value doesn't fit in 32 bits");
return uint32(value);
}
function toUint24(uint256 value) internal pure returns (uint24) {
require(value <= type(uint24).max, "SafeCast: value doesn't fit in 24 bits");
return uint24(value);
}
function toUint16(uint256 value) internal pure returns (uint16) {
require(value <= type(uint16).max, "SafeCast: value doesn't fit in 16 bits");
return uint16(value);
}
function toUint8(uint256 value) internal pure returns (uint8) {
require(value <= type(uint8).max, "SafeCast: value doesn't fit in 8 bits");
return uint8(value);
}
function toUint256(int256 value) internal pure returns (uint256) {
require(value >= 0, "SafeCast: value must be positive");
return uint256(value);
}
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
require(downcasted == value, "SafeCast: value doesn't fit in 248 bits");
}
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
require(downcasted == value, "SafeCast: value doesn't fit in 240 bits");
}
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
require(downcasted == value, "SafeCast: value doesn't fit in 232 bits");
}
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
require(downcasted == value, "SafeCast: value doesn't fit in 224 bits");
}
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
require(downcasted == value, "SafeCast: value doesn't fit in 216 bits");
}
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
require(downcasted == value, "SafeCast: value doesn't fit in 208 bits");
}
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
require(downcasted == value, "SafeCast: value doesn't fit in 200 bits");
}
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
require(downcasted == value, "SafeCast: value doesn't fit in 192 bits");
}
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
require(downcasted == value, "SafeCast: value doesn't fit in 184 bits");
}
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
require(downcasted == value, "SafeCast: value doesn't fit in 176 bits");
}
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
require(downcasted == value, "SafeCast: value doesn't fit in 168 bits");
}
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
require(downcasted == value, "SafeCast: value doesn't fit in 160 bits");
}
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
require(downcasted == value, "SafeCast: value doesn't fit in 152 bits");
}
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
require(downcasted == value, "SafeCast: value doesn't fit in 144 bits");
}
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
require(downcasted == value, "SafeCast: value doesn't fit in 136 bits");
}
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
require(downcasted == value, "SafeCast: value doesn't fit in 128 bits");
}
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
require(downcasted == value, "SafeCast: value doesn't fit in 120 bits");
}
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
require(downcasted == value, "SafeCast: value doesn't fit in 112 bits");
}
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
require(downcasted == value, "SafeCast: value doesn't fit in 104 bits");
}
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
require(downcasted == value, "SafeCast: value doesn't fit in 96 bits");
}
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
require(downcasted == value, "SafeCast: value doesn't fit in 88 bits");
}
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
require(downcasted == value, "SafeCast: value doesn't fit in 80 bits");
}
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
require(downcasted == value, "SafeCast: value doesn't fit in 72 bits");
}
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
require(downcasted == value, "SafeCast: value doesn't fit in 64 bits");
}
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
require(downcasted == value, "SafeCast: value doesn't fit in 56 bits");
}
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
require(downcasted == value, "SafeCast: value doesn't fit in 48 bits");
}
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
require(downcasted == value, "SafeCast: value doesn't fit in 40 bits");
}
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
require(downcasted == value, "SafeCast: value doesn't fit in 32 bits");
}
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
require(downcasted == value, "SafeCast: value doesn't fit in 24 bits");
}
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
require(downcasted == value, "SafeCast: value doesn't fit in 16 bits");
}
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
require(downcasted == value, "SafeCast: value doesn't fit in 8 bits");
}
function toInt256(uint256 value) internal pure returns (int256) {
require(value <= uint256(type(int256).max), "SafeCast: value doesn't fit in an int256");
return int256(value);
}
}
文件 89 的 103:SafeERC20.sol
pragma solidity ^0.8.0;
import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";
library SafeERC20 {
using Address for address;
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
function safeApprove(IERC20 token, address spender, uint256 value) internal {
require(
(value == 0) || (token.allowance(address(this), spender) == 0),
"SafeERC20: approve from non-zero to non-zero allowance"
);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
}
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
}
function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
unchecked {
uint256 oldAllowance = token.allowance(address(this), spender);
require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
}
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);
if (!_callOptionalReturnBool(token, approvalCall)) {
_callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
_callOptionalReturn(token, approvalCall);
}
}
function safePermit(
IERC20Permit token,
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) internal {
uint256 nonceBefore = token.nonces(owner);
token.permit(owner, spender, value, deadline, v, r, s);
uint256 nonceAfter = token.nonces(owner);
require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
}
function _callOptionalReturn(IERC20 token, bytes memory data) private {
bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
}
function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
(bool success, bytes memory returndata) = address(token).call(data);
return
success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
}
}
文件 90 的 103: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;
}
}
}
文件 91 的 103:SafeTransferLib.sol
pragma solidity >=0.8.0;
import {ERC20} from "../tokens/ERC20.sol";
library SafeTransferLib {
function safeTransferETH(address to, uint256 amount) internal {
bool success;
assembly {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
require(success, "ETH_TRANSFER_FAILED");
}
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 68), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
)
}
require(success, "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool success;
assembly {
let freeMemoryPointer := mload(0x40)
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff))
mstore(add(freeMemoryPointer, 36), amount)
success := and(
or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
)
}
require(success, "APPROVE_FAILED");
}
}
文件 92 的 103:ShareMath.sol
pragma solidity 0.8.17;
library ShareMath {
uint256 internal constant PLACEHOLDER_UINT = 1;
function assetToShares(uint256 assetAmount, uint256 assetPerShare, uint256 decimals)
internal
pure
returns (uint256)
{
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return (assetAmount * 10 ** decimals) / assetPerShare;
}
function sharesToAsset(uint256 shares, uint256 assetPerShare, uint256 decimals) internal pure returns (uint256) {
require(assetPerShare > PLACEHOLDER_UINT, "Invalid assetPerShare");
return (shares * assetPerShare) / 10 ** decimals;
}
function pricePerShare(uint256 totalSupply, uint256 totalBalance, uint256 decimals)
internal
pure
returns (uint256)
{
uint256 singleShare = 10 ** decimals;
return totalSupply > 0 ? (singleShare * totalBalance) / totalSupply : singleShare;
}
}
文件 93 的 103: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);
}
}
}
文件 94 的 103:Solarray.sol
pragma solidity 0.8.17;
import { SafeCast } from "./SafeCast.sol";
library Solarray {
using SafeCast for int256;
function uint256s(uint256 a, uint256 b) internal pure returns (uint256[2] memory arr) {
arr[0] = a;
arr[1] = b;
}
function int256s(int256 a, int256 b) internal pure returns (int256[2] memory arr) {
arr[0] = a;
arr[1] = b;
}
function addresss(address a, address b) internal pure returns (address[2] memory arr) {
arr[0] = a;
arr[1] = b;
}
function variableAddresss(address a, address b, address c, address d) internal pure returns (address[] memory) {
address[] memory arr = new address[](4);
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
return arr;
}
function addresss(address a, address b, address c, address d) internal pure returns (address[4] memory arr) {
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
}
function uint256s(uint256 a, uint256 b, uint256 c, uint256 d) internal pure returns (uint256[4] memory arr) {
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
}
function variableUint256s(uint256 a, uint256 b, uint256 c, uint256 d)
internal
pure
returns (uint256[] memory arr)
{
arr = new uint256[](4);
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
return arr;
}
function int256s(int256 a, int256 b, int256 c, int256 d) internal pure returns (int256[4] memory arr) {
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
}
function variableInt256s(int256 a, int256 b, int256 c, int256 d) internal pure returns (int256[] memory arr) {
arr = new int256[](4);
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
return arr;
}
function intToUintArray(int256[2] memory array) internal pure returns (uint256[2] memory uintArray) {
require(array[0] >= 0 && array[1] >= 0, "Solarray: intToUintArray: negative value");
uintArray = [uint256(array[0]), uint256(array[1])];
}
function arraySum(int256[2] memory array) internal pure returns (int256 sum) {
for (uint256 i = 0; i < 2; i++) {
sum += array[i];
}
}
function arraySum(uint256[2] memory array) internal pure returns (uint256 sum) {
for (uint256 i = 0; i < 2; i++) {
sum += array[i];
}
}
function arraySum(uint256[] memory array) internal pure returns (uint256 sum) {
for (uint256 i = 0; i < array.length; i++) {
sum += array[i];
}
}
function arraySumWithSafeCast(int256[] memory array) internal pure returns (uint256 sum) {
int256 intSum;
for (uint256 i = 0; i < array.length; i++) {
intSum += array[i];
}
sum = SafeCast.toUint256(intSum);
}
function arraySumAbsolute(int256[2] memory array) internal pure returns (uint256 sum) {
for (uint256 i = 0; i < 2; i++) {
sum += array[i] > 0 ? uint256(array[i]) : uint256(-array[i]);
}
}
function arrayDifference(uint256[2] memory base, int256[2] memory difference)
internal
pure
returns (int256[2] memory result)
{
for (uint256 i = 0; i < 2; i++) {
result[i] = SafeCast.toInt256(base[i]) + difference[i];
}
}
function arrayDifference(uint256[4] memory base, uint256[4] memory difference)
internal
pure
returns (int256[4] memory result)
{
for (uint256 i = 0; i < 4; i++) {
result[i] = SafeCast.toInt256(base[i]) - SafeCast.toInt256(difference[i]);
}
}
function arrayDifference(uint256[] memory base, int256[] memory difference)
internal
pure
returns (int256[] memory)
{
require(base.length == difference.length);
int256[] memory result = new int256[](base.length);
for (uint256 i = 0; i < base.length; i++) {
result[i] = SafeCast.toInt256(base[i]) + difference[i];
}
return result;
}
function arrayDifference(uint256[] memory base, uint256[] memory difference)
internal
pure
returns (int256[] memory)
{
require(base.length == difference.length);
int256[] memory result = new int256[](base.length);
for (uint256 i = 0; i < base.length; i++) {
result[i] = SafeCast.toInt256(base[i]) - SafeCast.toInt256(difference[i]);
}
return result;
}
function arrayAddProportion(
uint256[] memory base,
uint256 amount,
int256[] memory proportions,
uint256 divisor,
bool positive
) internal pure returns (uint256[] memory) {
require(base.length == proportions.length);
uint256 proportion;
bool direction;
uint256[] memory result = new uint256[](base.length);
for (uint256 i = 0; i < 4; i++) {
direction = proportions[i] > 0;
proportion = direction ? SafeCast.toUint256(proportions[i]) : SafeCast.toUint256(-proportions[i]);
result[i] = direction == positive ? base[i] + (amount * proportion / divisor) : base[i];
}
return result;
}
function arrayRemoveDirection(int256[] memory base, bool positive) internal pure returns (uint256[] memory) {
uint256[] memory result = new uint256[](base.length);
bool direction;
for (uint256 i = 0; i < base.length; i++) {
direction = base[i] > 0;
result[i] =
direction == positive ? 0 : direction ? SafeCast.toUint256(base[i]) : SafeCast.toUint256(-base[i]);
}
return result;
}
function directionalSum(int256[] memory _array, bool positive) public pure returns (int256 sum) {
for (uint256 i = 0; i < _array.length; i++) {
if (_array[i] > 0 && positive) {
sum += _array[i];
} else if (_array[i] < 0 && !positive) {
sum += _array[i];
}
}
}
function sumColumns(int256[2][2] memory array) internal pure returns (int256[2] memory retArray) {
for (uint256 i = 0; i < 2; i++) {
for (uint256 j = 0; j < 2; j++) {
retArray[i] += array[j][i];
}
}
}
function int2FixedToDynamic(int256[2] memory arr) public view returns (int256[] memory retArr) {
bytes memory ret = fixedToDynamicArray(abi.encode(arr), 2);
assembly {
retArr := ret
}
}
function uint2FixedToDynamic(uint256[2] memory arr) internal view returns (uint256[] memory retArr) {
bytes memory ret = fixedToDynamicArray(abi.encode(arr), 2);
assembly {
retArr := ret
}
}
function uint4FixedToDynamic(uint256[4] memory arr) internal view returns (uint256[] memory retArr) {
bytes memory ret = fixedToDynamicArray(abi.encode(arr), 4);
assembly {
retArr := ret
}
}
function int4FixedToDynamic(int256[4] memory arr) internal view returns (int256[] memory retArr) {
bytes memory ret = fixedToDynamicArray(abi.encode(arr), 4);
assembly {
retArr := ret
}
}
function fixedToDynamicArray(bytes memory arr, uint256 fixedSize) public view returns (bytes memory retArray) {
(bool success, bytes memory data) = address(0x04).staticcall(arr);
require(success, "identity precompile failed");
assembly {
retArray := data
mstore(retArray, fixedSize)
}
}
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;
}
}
文件 95 的 103:StorageViewer.sol
pragma solidity 0.8.17;
import { AggregateVaultStorage, IPositionManager } from "../storage/AggregateVaultStorage.sol";
import { Emitter } from "../peripheral/Emitter.sol";
import { OracleWrapper } from "../peripheral/OracleWrapper.sol";
contract StorageViewer is AggregateVaultStorage {
function getRequest(uint256 key) external view returns (OCRequest memory order) {
return _getRequest(key);
}
function getEmitter() external view returns (Emitter) {
return Emitter(_getStorage().emitter);
}
function rebalanceOpen() external view returns (bool) {
return _getVaultState().rebalanceOpen;
}
function getOracleWrapper() external view returns (OracleWrapper) {
return OracleWrapper(_getStorage().oracleWrapper);
}
function getVaultState() external view returns (VaultState memory) {
return _getStorage().vaultState;
}
function getAssetVaults() external view returns (AssetVaultStorage[2] memory _vaults) {
_vaults = _getStorage().vaults;
}
function getTokenToAssetVaultIndex(address _token) external view returns (uint256 _index) {
_index = _getStorage().tokenToAssetVaultIndex[_token];
}
function getVaultToAssetVaultIndex(address _vault) external view returns (uint256 _index) {
_index = _getStorage().vaultToAssetVaultIndex[_vault];
}
function getRebalanceState() external view returns (RebalanceState memory _rebalanceState) {
_rebalanceState = _getStorage().rebalanceState;
}
function getVaultFees() external view returns (VaultFees memory _vaultFees) {
_vaultFees = _getStorage().vaultFees;
}
function getEpoch() external view returns (uint256 _epoch) {
_epoch = _getStorage().vaultState.epoch;
}
function getBlockTolerance() external view returns (uint8 _blockTolerance) {
_blockTolerance = _getStorage().L1BlockTolerance;
}
function getPositionManagers() external view returns (IPositionManager[] memory) {
return _getStorage().positionManagers;
}
function getHookHandler() external view returns (address) {
return _getStorage().hookHandler;
}
function getRebalanceKeeper() external view returns (address) {
return _getStorage().rebalanceKeeper;
}
function getNettedThreshold() external view returns (uint256) {
return _getStorage().nettedThreshold;
}
function getFeeHelper() external view returns (address) {
return _getStorage().feeHelper;
}
function getGmi() external view returns (address) {
return _getStorage().gmi;
}
function getAggregateVaultHelper() external view returns (address) {
return _getStorage().aggregateVaultHelper;
}
function getGmxV2Handler() external view returns (address) {
return _getStorage().gmxV2Handler;
}
function getRequestHandler() external view returns (address) {
return _getStorage().requestHandler;
}
function getUniswapV3SwapManager() external view returns (address) {
return _getStorage().uniswapV3SwapManager;
}
function getRequestNonce() external view returns (uint256) {
return _getStorage().requestNonce;
}
function getExecutionGasAmount() external view returns (uint256) {
return _getStorage().executionGasAmount;
}
function getExecutionGasAmountCallback() external view returns (uint256) {
return _getStorage().executionGasAmountCallback;
}
function getZeroSumPnlThreshold() external view returns (uint256) {
return _getStorage().zeroSumPnlThreshold;
}
function getL1BlockTolerance() external view returns (uint256) {
return _getStorage().L1BlockTolerance;
}
function getShouldCheckNetting() external view returns (bool) {
return _getStorage().shouldCheckNetting;
}
function getShouldUseGmxFee() external view returns (bool) {
return _getStorage().shouldUseGmxFee;
}
function getEpochStorageKey() external view returns (bytes32 _key) {
VaultState storage vaultState = _getStorage().vaultState;
assembly {
_key := vaultState.slot
}
}
function readStorageSlots(bytes32[] calldata _slots) external view returns (bytes32[] memory _values) {
_values = new bytes32[](_slots.length);
for (uint256 i; i < _slots.length; i++) {
uint256 value;
bytes32 slot = _slots[i];
assembly {
value := sload(slot)
}
_values[i] = bytes32(value);
}
}
function gasRequirement(bool _callback) external view returns (uint256) {
return _callback ? _getStorage().executionGasAmountCallback : _getStorage().executionGasAmount;
}
function getExternalPosition() external view returns (int256) {
return _getStorage().externalPosition;
}
function getLastNettedPrice(uint256 _epoch) external view returns (int256[2] memory _prices) {
_prices = _getStorage().lastNettedPrices[_epoch];
}
function getVaultGmiAttribution() external view returns (uint256[2] memory _vaultGmiAttribution) {
_vaultGmiAttribution = _getStorage().vaultGmiAttribution;
}
}
文件 96 的 103: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));
}
}
文件 97 的 103:Strings.sol
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
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] = _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);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}
文件 98 的 103: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);
}
}
文件 99 的 103:TransferUtils.sol
pragma solidity 0.8.17;
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
library TransferUtils {
using SafeTransferLib for ERC20;
function transferAsset(address asset, address recipient, uint256 amount) internal {
ERC20(asset).safeTransfer(recipient, amount);
}
function transferNativeAsset(address recipient, uint256 amount) internal {
(bool success,) = recipient.call{ value: amount }("");
require(success, "TransferUtils: failed native token transfer");
}
}
文件 100 的 103: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;
}
}
文件 101 的 103:UniswapV3SwapManager.sol
pragma solidity 0.8.17;
import { BaseSwapManager } from "./BaseSwapManager.sol";
import { ERC20 } from "solmate/tokens/ERC20.sol";
import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol";
import { ISwapRouter } from "../interfaces/uniswap/ISwapRouter.sol";
import { IUniswapV3Pool } from "../interfaces/uniswap/IUniswapV3Pool.sol";
import { IUniswapV3Factory } from "../interfaces/uniswap/IUniswapV3Factory.sol";
import { UNISWAP_SWAP_ROUTER, UNISWAP_FACTORY } from "../constants.sol";
contract UniswapV3SwapManager is BaseSwapManager {
using SafeTransferLib for ERC20;
struct Config {
uint24[] feeTiers;
address intermediaryAsset;
}
ISwapRouter public constant uniV3Router = ISwapRouter(UNISWAP_SWAP_ROUTER);
IUniswapV3Factory public constant uniV3factory = IUniswapV3Factory(UNISWAP_FACTORY);
bytes32 public constant CONFIG_SLOT = keccak256("swapManagers.UniswapV3.config");
constructor(address _intermediaryAsset) {
require(_intermediaryAsset != address(0), "!_intermediaryAsset");
Config storage config = _configStorage();
config.intermediaryAsset = _intermediaryAsset;
}
function swap(address _tokenIn, address _tokenOut, uint256 _amountIn, uint256 _minOut, bytes calldata)
external
onlyDelegateCall
swapChecks(_tokenIn, _tokenOut, _amountIn, _minOut)
returns (uint256 _amountOut)
{
bytes memory path = _getSwapPath(_tokenIn, _tokenOut);
_amountOut = _swapTokenExactInput(_tokenIn, _amountIn, _minOut, path);
}
function exactOutputSwap(address _tokenIn, address _tokenOut, uint256 _amountOut, uint256 _maxIn)
external
onlyDelegateCall
swapChecksExactOutput(_tokenIn, _tokenOut, _amountOut, _maxIn)
returns (uint256 _amountIn)
{
bytes memory path = _getSwapPath(_tokenOut, _tokenIn);
_amountIn = _swapTokenExactOutput(_tokenIn, _amountOut, _maxIn, path);
}
function addFeeTier(uint24 _feeTier) external onlyDelegateCall {
require(_feeTier > 0 && _feeTier < 100_000, "UniswapV3SwapManager: !_feeTier");
Config storage config = _configStorage();
config.feeTiers.push(_feeTier);
}
function removeFeeTierAt(uint24 _feeTierToRemove, uint256 _idx) external onlyDelegateCall {
Config storage config = _configStorage();
require(config.feeTiers[_idx] == _feeTierToRemove, "UniswapV3SwapManager: invalid idx");
config.feeTiers[_idx] = config.feeTiers[config.feeTiers.length - 1];
config.feeTiers.pop();
}
function setIntermediaryAsset(address _newAsset) external onlyDelegateCall {
require(_newAsset != address(0), "UniswapV3SwapManager: !_newAsset");
Config storage config = _configStorage();
config.intermediaryAsset = _newAsset;
}
function _swapTokenExactInput(address _tokenIn, uint256 _amountIn, uint256 _minOut, bytes memory _path)
internal
returns (uint256 _out)
{
ISwapRouter.ExactInputParams memory params = ISwapRouter.ExactInputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp,
amountIn: _amountIn,
amountOutMinimum: _minOut
});
ERC20(_tokenIn).safeApprove(address(uniV3Router), _amountIn);
return uniV3Router.exactInput(params);
}
function _swapTokenExactOutput(address _tokenIn, uint256 _amountOut, uint256 _maxIn, bytes memory _path)
internal
returns (uint256 _in)
{
ISwapRouter.ExactOutputParams memory params = ISwapRouter.ExactOutputParams({
path: _path,
recipient: address(this),
deadline: block.timestamp,
amountOut: _amountOut,
amountInMaximum: _maxIn
});
ERC20(_tokenIn).safeApprove(address(uniV3Router), _maxIn);
return uniV3Router.exactOutput(params);
}
function _getSwapPath(address _tokenIn, address _tokenOut) internal view returns (bytes memory path) {
Config storage config = _configStorage();
uint24 tokenInFee = _getSwapFee(_tokenIn);
uint24 tokenOutFee = _getSwapFee(_tokenOut);
require(_tokenIn != _tokenOut, "UniswapV3SwapManager: !unique tokens");
if (_tokenIn == config.intermediaryAsset || _tokenOut == config.intermediaryAsset) {
require(tokenInFee > 0 || tokenOutFee > 0, "UniswapV3SwapManager: !_tokenOut");
uint24 fee = tokenInFee > 0 ? tokenInFee : tokenOutFee;
path = abi.encodePacked(_tokenIn, fee, _tokenOut);
} else {
require(tokenInFee > 0, "UniswapV3SwapManager: !_tokenIn");
require(tokenOutFee > 0, "UniswapV3SwapManager: !_tokenOut");
path = abi.encodePacked(_tokenIn, tokenInFee, config.intermediaryAsset, tokenOutFee, _tokenOut);
}
}
function _getSwapFee(address _targetToken) internal view returns (uint24 swapFee) {
Config storage config = _configStorage();
address bestSwapPool;
address iterSwapPool;
for (uint256 i = 0; i < config.feeTiers.length; i++) {
iterSwapPool = uniV3factory.getPool(_targetToken, config.intermediaryAsset, config.feeTiers[i]);
if (bestSwapPool == address(0) && iterSwapPool != address(0)) {
swapFee = config.feeTiers[i];
bestSwapPool = iterSwapPool;
}
if (
iterSwapPool != address(0)
&& IUniswapV3Pool(bestSwapPool).liquidity() < IUniswapV3Pool(iterSwapPool).liquidity()
) {
swapFee = config.feeTiers[i];
bestSwapPool = iterSwapPool;
}
}
}
function _configStorage() internal pure returns (Config storage config) {
bytes32 slot = CONFIG_SLOT;
assembly {
config.slot := slot
}
}
}
文件 102 的 103: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(int p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(int)", p0));
}
function logUint(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", 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(uint p0) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint)", 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(uint p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint)", p0, p1));
}
function log(uint p0, string memory p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string)", p0, p1));
}
function log(uint p0, bool p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool)", p0, p1));
}
function log(uint p0, address p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address)", p0, p1));
}
function log(string memory p0, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint)", 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, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint)", 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, uint p1) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint)", 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(uint p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint)", p0, p1, p2));
}
function log(uint p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string)", p0, p1, p2));
}
function log(uint p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool)", p0, p1, p2));
}
function log(uint p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address)", p0, p1, p2));
}
function log(uint p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint)", p0, p1, p2));
}
function log(uint p0, string memory p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string)", p0, p1, p2));
}
function log(uint p0, string memory p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool)", p0, p1, p2));
}
function log(uint p0, string memory p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address)", p0, p1, p2));
}
function log(uint p0, bool p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint)", p0, p1, p2));
}
function log(uint p0, bool p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string)", p0, p1, p2));
}
function log(uint p0, bool p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool)", p0, p1, p2));
}
function log(uint p0, bool p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address)", p0, p1, p2));
}
function log(uint p0, address p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint)", p0, p1, p2));
}
function log(uint p0, address p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string)", p0, p1, p2));
}
function log(uint p0, address p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool)", p0, p1, p2));
}
function log(uint p0, address p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address)", p0, p1, p2));
}
function log(string memory p0, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint)", p0, p1, p2));
}
function log(string memory p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string)", p0, p1, p2));
}
function log(string memory p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool)", p0, p1, p2));
}
function log(string memory p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address)", p0, p1, p2));
}
function log(string memory p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint)", 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, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint)", p0, p1, p2));
}
function log(bool p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string)", p0, p1, p2));
}
function log(bool p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool)", p0, p1, p2));
}
function log(bool p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address)", p0, p1, p2));
}
function log(bool p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint)", 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, uint p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint)", p0, p1, p2));
}
function log(address p0, uint p1, string memory p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string)", p0, p1, p2));
}
function log(address p0, uint p1, bool p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool)", p0, p1, p2));
}
function log(address p0, uint p1, address p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address)", p0, p1, p2));
}
function log(address p0, string memory p1, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint)", 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, uint p2) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint)", 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(uint p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,string,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,string)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,uint,address,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,string,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,string)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, string memory p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,string,address,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,string,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,string)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, bool p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,bool,address,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,uint,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,string,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,bool,address)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,uint)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,string)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,bool)", p0, p1, p2, p3));
}
function log(uint p0, address p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(uint,address,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,string,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,bool,address)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,uint)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,string)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,bool)", p0, p1, p2, p3));
}
function log(string memory p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,uint,address,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,uint)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,string)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,bool)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,uint,address)", p0, p1, p2, p3));
}
function log(string memory p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(string,address,address,uint)", 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, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,string,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,bool,address)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,uint)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,string)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,bool)", p0, p1, p2, p3));
}
function log(bool p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,uint,address,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,uint)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,string)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,bool)", p0, p1, p2, p3));
}
function log(bool p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,uint,address)", p0, p1, p2, p3));
}
function log(bool p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(bool,address,address,uint)", 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, uint p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,uint,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, string memory p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,string,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, bool p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,bool,address)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,uint)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,string)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,bool)", p0, p1, p2, p3));
}
function log(address p0, uint p1, address p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,uint,address,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,string)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,uint,address)", p0, p1, p2, p3));
}
function log(address p0, string memory p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,string,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,string)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, bool p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,uint,address)", p0, p1, p2, p3));
}
function log(address p0, bool p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,bool,address,uint)", 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, uint p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,uint)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, string memory p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,string)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, bool p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,bool)", p0, p1, p2, p3));
}
function log(address p0, address p1, uint p2, address p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,uint,address)", p0, p1, p2, p3));
}
function log(address p0, address p1, string memory p2, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,string,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,bool,uint)", 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, uint p3) internal view {
_sendLogPayload(abi.encodeWithSignature("log(address,address,address,uint)", 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));
}
}
文件 103 的 103:constants.sol
pragma solidity 0.8.17;
address constant GMX_POSITION_ROUTER = 0xb87a436B93fFE9D75c5cFA7bAcFff96430b09868;
address constant GMX_VAULT = 0x489ee077994B6658eAfA855C308275EAd8097C4A;
address constant GMX_ROUTER = 0xaBBc5F99639c9B6bCb58544ddf04EFA6802F4064;
address constant GMX_GLP_REWARD_ROUTER = 0xB95DB5B167D75e6d04227CfFFA61069348d271F5;
address constant TOKEN_FRAX = 0x17FC002b466eEc40DaE837Fc4bE5c67993ddBd6F;
address constant DATA_STORE = 0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8;
address constant READER = 0x38d91ED96283d62182Fc6d990C24097A918a4d9b;
address constant TOKEN_USDC_BRIDGED = 0xFF970A61A04b1cA14834A43f5dE4533eBDDB5CC8;
address constant TOKEN_WETH = 0x82aF49447D8a07e3bd95BD0d56f35241523fBab1;
address constant TOKEN_USDC_NATIVE = 0xaf88d065e77c8cC2239327C5EDb3A432268e5831;
address constant TOKEN_XRP = 0xc14e065b0067dE91534e032868f5Ac6ecf2c6868;
address constant TOKEN_LINK = 0xf97f4df75117a78c1A5a0DBb814Af92458539FB4;
address constant TOKEN_ARB = 0x912CE59144191C1204E64559FE8253a0e49E6548;
uint256 constant DECIMALS_WETH = 18;
uint256 constant DECIMALS_USDC_NATIVE = 6;
uint256 constant DECIMALS_XRP = 6;
uint256 constant DECIMALS_LTC = 8;
uint256 constant DECIMALS_DOGE = 8;
bool constant CONFIG_GMI_UPGRADABLE = true;
bool constant CONFIG_AGGREGATE_VAULT_UPGRADABLE = true;
address constant CONFIG_PROXY_ADMIN = 0x4e5645bee4eD80C6FEe04DCC15D14A3AC956748A;
address constant CONFIG_UI_FEE_RECEIVER = CONFIG_PROXY_ADMIN;
uint256 constant CONFIG_DEPOSIT_CALLBACK_GASLIMIT = 500_000;
uint256 constant CONFIG_WITHDRAWAL_CALLBACK_GASLIMIT = 500_000;
uint256 constant CONFIG_GMI_DEPOSIT_TOLERANCE = 0.1e18;
uint256 constant CONFIG_GMI_MINT_CAP_TOLERANCE = 0.9e18;
uint256 constant CONFIG_SWAP_SLIPPAGE_TOLERANCE = 500;
uint16 constant CONFIG_MAX_COPY_UNTRUSTED_CALL = 500;
address constant GMX_V2_EXCHANGE_ROUTER = 0x7C68C7866A64FA2160F78EEaE12217FFbf871fa8;
address constant GMX_V2_MARKET_UTILS = 0x7ffF7ef2fc8Db5159B0046ad49d018A5aB40dB11;
address constant GMX_V2_DATA_STORE = 0xFD70de6b91282D8017aA4E741e9Ae325CAb992d8;
address constant GMX_V2_XRP_INDEX_TOKEN = 0xc14e065b0067dE91534e032868f5Ac6ecf2c6868;
address constant GMX_V2_LTC_INDEX_TOKEN = 0xB46A094Bc4B0adBD801E14b9DB95e05E28962764;
address constant GMX_V2_DOGE_INDEX_TOKEN = 0xC4da4c24fd591125c3F47b340b6f4f76111883d8;
address constant CHAINLINK_ETH_PRICE_FEED = 0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612;
address constant CHAINLINK_XRP_PRICE_FEED = 0xB4AD57B52aB9141de9926a3e0C8dc6264c2ef205;
address constant CHAINLINK_USDC_PRICE_FEED = 0x50834F3163758fcC1Df9973b6e91f0F0F0434aD3;
address constant CHAINLINK_DOGE_PRICE_FEED = 0x9A7FB1b3950837a8D9b40517626E11D4127C098C;
bytes32 constant MAX_PNL_FACTOR_FOR_DEPOSITS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_DEPOSITS"));
bytes32 constant MAX_PNL_FACTOR_FOR_WITHDRAWALS = keccak256(abi.encode("MAX_PNL_FACTOR_FOR_WITHDRAWALS"));
address constant MARKET_ETH = 0x70d95587d40A2caf56bd97485aB3Eec10Bee6336;
address constant MARKET_XRP = 0x0CCB4fAa6f1F1B30911619f1184082aB4E25813c;
address constant MARKET_DOGE = 0x6853EA96FF216fAb11D2d930CE3C508556A4bdc4;
address constant MARKET_LTC = 0xD9535bB5f58A1a75032416F2dFe7880C30575a41;
address constant UNISWAP_SWAP_ROUTER = 0xE592427A0AEce92De3Edee1F18E0157C05861564;
address constant UNISWAP_FACTORY = 0x1F98431c8aD98523631AE4a59f267346ea31F984;
address constant TESTNET_CHAINLINK_LLO_VERIFIER_PROXY = 0xea9B98Be000FBEA7f6e88D08ebe70EbaAD10224c;
address constant TESTNET_CHAINLINK_LLO_REWARD_MANAGER = 0x86F3659e02Bd3eDE216356BED9361DD70Be53897;
address constant TESTNET_CHAINLINK_LLO_FEE_MANAGER = 0x75DBc8Db499e69b6990cd5576850a8D71cD5E670;
bytes32 constant TESTNET_CHAINLINK_LLO_ETH_FEEDID = 0x00023496426b520583ae20a66d80484e0fc18544866a5b0bfee15ec771963274;
address constant TESTNET_TOKEN_WETH = 0xe39Ab88f8A4777030A534146A9Ca3B52bd5D43A3;
address constant TESTNET_TOKEN_LINK = 0xd14838A68E8AFBAdE5efb411d5871ea0011AFd28;
address constant ARBSYS = address(0x64);
address constant SUPRA_FEED = 0x8a358F391d93f7558D5F5E61BDf533e2cc3Cf7a3;
address constant DEPLOYMENT_MULTISIG = 0xb137d135Dc8482B633265c21191F50a4bA26145d;
{
"compilationTarget": {
"src/vaults/AssetVault.sol": "AssetVault"
},
"evmVersion": "london",
"libraries": {
"lib/gmx-synthetics/contracts/gas/GasUtils.sol:GasUtils": "0x3d0453036f3e39ff9384f0e1c8a59b17e05277d0",
"lib/gmx-synthetics/contracts/market/MarketStoreUtils.sol:MarketStoreUtils": "0x9511fab77c8d7acf56c9d8ae9278cd3bd8bd9d5c",
"lib/gmx-synthetics/contracts/market/MarketUtils.sol:MarketUtils": "0xecdf2ce74e19d4921cc89fefb963d35e0e5171d3"
},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 888
},
"remappings": [
":@chainlink/=lib/chainlink/",
":@gmx/=lib/gmx-synthetics/contracts/",
":@openzeppelin/=lib/openzeppelin-contracts/",
":@solady/=lib/solady/src/",
":ExcessivelySafeCall/=lib/ExcessivelySafeCall/src/",
":ds-test/=lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":gmx-synthetics/=lib/gmx-synthetics/contracts/",
":hardhat/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/",
":openzeppelin/=lib/openzeppelin-contracts/contracts/",
":prb-math/=lib/prb-math/contracts/",
":solady/=lib/solady/",
":solmate/=lib/solmate/src/",
"lib/gmx-synthetics/contracts/:hardhat/=lib/forge-std/src/",
"lib/gmx-synthetics/contracts/:prb-math/=lib/prb-math/"
]
}
[{"inputs":[{"internalType":"contract ERC20","name":"_asset","type":"address"},{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"address","name":"_aggregateVault","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"DepositsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"DepositsUnpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"assets","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"shares","type":"uint256"}],"name":"Withdraw","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"WithdrawalsPaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"WithdrawalsUnpaused","type":"event"},{"inputs":[],"name":"AUTH","outputs":[{"internalType":"contract Auth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"aggregateVault","outputs":[{"internalType":"contract AggregateVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"asset","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_burnAmount","type":"uint256"}],"name":"burnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"key","type":"uint256"}],"name":"cancelRequest","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"convertToAssets","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"convertToShares","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"minOutAfterFees","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"deposit","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"depositPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"},{"internalType":"uint256","name":"minOutAfterFees","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"callback","type":"address"}],"name":"depositWithCallback","outputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_assetAmount","type":"uint256"},{"internalType":"address","name":"feeReciever","type":"address"},{"internalType":"uint256","name":"_depositFees","type":"uint256"}],"name":"lodgeAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"maxWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_mintAmount","type":"uint256"},{"internalType":"address","name":"_toAddress","type":"address"}],"name":"mintTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pauseDepositWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pauseWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pps","outputs":[{"internalType":"uint256","name":"pricePerShare","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewDeposit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"size","type":"uint256"}],"name":"previewDepositFee","outputs":[{"internalType":"uint256","name":"totalDepositFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewMint","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"}],"name":"previewRedeem","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"previewVaultCap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"name":"previewWithdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"size","type":"uint256"}],"name":"previewWithdrawalFee","outputs":[{"internalType":"uint256","name":"totalWithdrawalFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"minOutAfterFees","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"redeem","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"shares","type":"uint256"},{"internalType":"uint256","name":"minOutAfterFees","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"callback","type":"address"}],"name":"redeemWithCallback","outputs":[{"internalType":"uint256","name":"assets","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amt","type":"uint256"}],"name":"returnAssets","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amt","type":"uint256"}],"name":"returnShares","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalAssets","outputs":[{"internalType":"uint256","name":"totalValueLocked","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDepositWithdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseDeposits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpauseWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract AggregateVault","name":"_newAggregateVault","type":"address"}],"name":"updateAggregateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawalPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]