diff --git a/simulations/vip-617/abi/AccessControlManager.json b/simulations/vip-617/abi/AccessControlManager.json new file mode 100644 index 000000000..4a118fcc4 --- /dev/null +++ b/simulations/vip-617/abi/AccessControlManager.json @@ -0,0 +1,360 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToPermit", + "type": "address" + } + ], + "name": "giveCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "hasPermission", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "isAllowedToCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToRevoke", + "type": "address" + } + ], + "name": "revokeCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/Comptroller.json b/simulations/vip-617/abi/Comptroller.json new file mode 100644 index 000000000..8d3130ed7 --- /dev/null +++ b/simulations/vip-617/abi/Comptroller.json @@ -0,0 +1,4697 @@ +[ + { + "inputs": [], + "name": "AlreadyInSelectedPool", + "type": "error" + }, + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowNotAllowedInPool", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPoolLabel", + "type": "error" + }, + { + "inputs": [], + "name": "ExecuteFlashLoanFailed", + "type": "error" + }, + { + "inputs": [], + "name": "FailedToCreateDebtPosition", + "type": "error" + }, + { + "inputs": [], + "name": "FlashLoanNotEnabled", + "type": "error" + }, + { + "inputs": [], + "name": "FlashLoanPausedSystemWide", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "InactivePool", + "type": "error" + }, + { + "inputs": [], + "name": "IncompatibleBorrowedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidFlashLoanParams", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOperationForCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WeightFunction", + "name": "strategy", + "type": "uint8" + } + ], + "name": "InvalidWeightingStrategy", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "name": "LiquidityCheckFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketConfigNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotListedInCorePool", + "type": "error" + }, + { + "inputs": [], + "name": "NoAssetsRequested", + "type": "error" + }, + { + "inputs": [], + "name": "NotAnApprovedDelegate", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repaid", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "required", + "type": "uint256" + } + ], + "name": "NotEnoughRepayment", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "PoolDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "ReentrancyGuardReentrantCall", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "SenderNotAuthorizedForFlashLoan", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximum", + "type": "uint256" + } + ], + "name": "TooManyAssetsRequested", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "ActionProtocolPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "BorrowAllowedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "approver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "DelegateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VToken[]", + "name": "assets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "FlashLoanExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "oldPaused", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newPaused", + "type": "bool" + } + ], + "name": "FlashLoanPauseChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "onBehalf", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repaidAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "remainingDebt", + "type": "uint256" + } + ], + "name": "FlashLoanRepaid", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "bool", + "name": "isWhitelisted", + "type": "bool" + } + ], + "name": "IsAccountFlashLoanWhitelisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledForUserUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketUnlisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldComptrollerLens", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newComptrollerLens", + "type": "address" + } + ], + "name": "NewComptrollerLens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationThresholdMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldLiquidatorContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newLiquidatorContract", + "type": "address" + } + ], + "name": "NewLiquidatorContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "oldVAIController", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "newVAIController", + "type": "address" + } + ], + "name": "NewVAIController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVAIMintRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "NewVAIMintRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseInterval_", + "type": "uint256" + } + ], + "name": "NewVAIVaultInfo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIVaultRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIVaultRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIVaultRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVS", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVS", + "type": "address" + } + ], + "name": "NewXVSToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVSVToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVSVToken", + "type": "address" + } + ], + "name": "NewXVSVToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolActiveStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolFallbackStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldLabel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "PoolLabelUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "PoolMarketInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "previousPoolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "uint96", + "name": "newPoolId", + "type": "uint96" + } + ], + "name": "PoolSelected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusSeized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusSupplySpeedUpdated", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [], + "name": "MAX_FLASHLOAN_ASSETS", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "_grantXVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "_setAccessControl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "_setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptrollerLens_", + "type": "address" + } + ], + "name": "_setComptrollerLens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidationForUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newLiquidatorContract_", + "type": "address" + } + ], + "name": "_setLiquidatorContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "_setPauseGuardian", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "_setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "_setProtocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "vaiController_", + "type": "address" + } + ], + "name": "_setVAIController", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "_setVAIMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minReleaseAmount_", + "type": "uint256" + } + ], + "name": "_setVAIVaultInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "_setVenusSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "venusVAIVaultRate_", + "type": "uint256" + } + ], + "name": "_setVenusVAIVaultRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvs_", + "type": "address" + } + ], + "name": "_setXVSToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvsVToken_", + "type": "address" + } + ], + "name": "_setXVSVToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96[]", + "name": "poolIds", + "type": "uint96[]" + }, + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "addPoolMarkets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "authorizedFlashLoan", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "collateral", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenusAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "corePoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "onBehalf", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "enterMarketBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "enterPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "onBehalf", + "type": "address" + }, + { + "internalType": "address payable", + "name": "receiver", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "underlyingAmounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "param", + "type": "bytes" + } + ], + "name": "executeFlashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getBorrowingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getEffectiveLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "enum WeightFunction", + "name": "weightingStrategy", + "type": "uint8" + } + ], + "name": "getEffectiveLtvFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getPoolMarketIndex", + "outputs": [ + { + "internalType": "PoolMarketId", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "getPoolVTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSVTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint96", + "name": "targetPoolId", + "type": "uint96" + } + ], + "name": "hasValidPoolBorrows", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabledForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateVAICalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "poolMarkets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "allowCorePoolFallback", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "removePoolMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "seizeVenus", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "allowFallback", + "type": "bool" + } + ], + "name": "setAllowCorePoolFallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "paused", + "type": "bool" + } + ], + "name": "setFlashLoanPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "borrowAllowed", + "type": "bool" + } + ], + "name": "setIsBorrowAllowed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMintedVAIOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "name": "setPoolActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "setPoolLabel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bool", + "name": "isWhiteListed", + "type": "bool" + } + ], + "name": "setWhiteListFlashLoanAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "unlistMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "deviationBoundedOracle", + "outputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPendingImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newPendingImplementation", + "type": "address" + } + ], + "name": "_setPendingImplementation", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "oldDeviationBoundedOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "NewDeviationBoundedOracle", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract IDeviationBoundedOracle", + "name": "newDeviationBoundedOracle", + "type": "address" + } + ], + "name": "setDeviationBoundedOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/DeviationBoundedOracle.json b/simulations/vip-617/abi/DeviationBoundedOracle.json new file mode 100644 index 000000000..9984f9c99 --- /dev/null +++ b/simulations/vip-617/abi/DeviationBoundedOracle.json @@ -0,0 +1,1374 @@ +[ + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "_resilientOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeMarketAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "lastProtectionTriggeredAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + } + ], + "name": "CooldownNotElapsed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "action", + "type": "uint8" + } + ], + "name": "InvalidKeeperAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "currentSpot", + "type": "uint256" + } + ], + "name": "InvalidMaxPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "currentSpot", + "type": "uint256" + } + ], + "name": "InvalidMinPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + } + ], + "name": "InvalidResetThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "MarketAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "MarketNotInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "PriceExceedsUint128", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentRangeRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + } + ], + "name": "PriceRangeNotConverged", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectedPriceActive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectedPriceInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximum", + "type": "uint256" + } + ], + "name": "ThresholdAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimum", + "type": "uint256" + } + ], + "name": "ThresholdBelowMinimum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "VAINotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroPriceNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "whitelisted", + "type": "bool" + } + ], + "name": "BoundedPricingWhitelistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldEnabled", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newEnabled", + "type": "bool" + } + ], + "name": "CachingEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "oldCooldown", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newCooldown", + "type": "uint64" + } + ], + "name": "CooldownPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "oldMax", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + } + ], + "name": "MaxPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "oldMin", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + } + ], + "name": "MinPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + } + ], + "name": "ProtectionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectionModeExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "spotPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + } + ], + "name": "ProtectionTriggered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldExitThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newExitThreshold", + "type": "uint256" + } + ], + "name": "ResetThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newThreshold", + "type": "uint256" + } + ], + "name": "TriggerThresholdSet", + "type": "event" + }, + { + "inputs": [], + "name": "COLLATERAL_PRICE_CACHE_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEBT_PRICE_CACHE_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEEPER_DEADBAND", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allAssets", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "assetProtectionConfig", + "outputs": [ + { + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "currentlyUsingProtectedPrice", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBoundedPricingEnabled", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "lastProtectionTriggeredAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "triggerThreshold", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "resetThreshold", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "cachingEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "canExitProtection", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint128[]", + "name": "proposedMins", + "type": "uint128[]" + }, + { + "internalType": "uint128[]", + "name": "proposedMaxs", + "type": "uint128[]" + } + ], + "name": "checkAndGetWindowDrift", + "outputs": [ + { + "internalType": "bool[]", + "name": "needsMinUpdate", + "type": "bool[]" + }, + { + "internalType": "bool[]", + "name": "needsMaxUpdate", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "currentlyUsingProtectedPrice", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "exitProtectionMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllBoundedPricingEnabledAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedCollateralPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedCollateralPriceView", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedDebtPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedDebtPriceView", + "outputs": [ + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedPrices", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedPricesView", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializedAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "isBoundedPricingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setAssetBoundedPricingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setCachingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "newCooldown", + "type": "uint64" + } + ], + "name": "setCooldownPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTriggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newResetThreshold", + "type": "uint256" + } + ], + "name": "setThresholds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enableBoundedPricing", + "type": "bool" + }, + { + "internalType": "bool", + "name": "enableCaching", + "type": "bool" + } + ], + "internalType": "struct IDeviationBoundedOracle.TokenConfigInput", + "name": "tokenConfig_", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enableBoundedPricing", + "type": "bool" + }, + { + "internalType": "bool", + "name": "enableCaching", + "type": "bool" + } + ], + "internalType": "struct IDeviationBoundedOracle.TokenConfigInput[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IDeviationBoundedOracle.KeeperAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IDeviationBoundedOracle.KeeperActionItem[]", + "name": "actions", + "type": "tuple[]" + } + ], + "name": "syncPriceBoundsAndProtections", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + } + ], + "name": "updateMaxPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + } + ], + "name": "updateMinPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateProtectionState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/Diamond.json b/simulations/vip-617/abi/Diamond.json new file mode 100644 index 000000000..3c6f08008 --- /dev/null +++ b/simulations/vip-617/abi/Diamond.json @@ -0,0 +1,957 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "payable": true, + "stateMutability": "payable", + "type": "fallback" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabledForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract PriceOracle", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/Liquidator.json b/simulations/vip-617/abi/Liquidator.json new file mode 100644 index 000000000..f57031703 --- /dev/null +++ b/simulations/vip-617/abi/Liquidator.json @@ -0,0 +1,1074 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "AllowlistEntryNotFound", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "AlreadyAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "AlreadyRestricted", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidationFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "LiquidationNotAllowed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "NoRestrictionsExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxTreasuryPercentMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "treasuryPercentMantissa_", + "type": "uint256" + } + ], + "name": "TreasuryPercentTooHigh", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "vaiDebt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableVAI", + "type": "uint256" + } + ], + "name": "VAIDebtTooHigh", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VTokenTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "WrongTransactionAmount", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "AllowlistEntryAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "AllowlistEntryRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ForceVAILiquidationPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ForceVAILiquidationResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokensForTreasury", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokensForLiquidator", + "type": "uint256" + } + ], + "name": "LiquidateBorrowedTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "LiquidationRestricted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "LiquidationRestrictionsDisabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPercent", + "type": "uint256" + } + ], + "name": "NewLiquidationTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMinLiquidatableVAI", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinLiquidatableVAI", + "type": "uint256" + } + ], + "name": "NewMinLiquidatableVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldPendingRedeemChunkLength", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPendingRedeemChunkLength", + "type": "uint256" + } + ], + "name": "NewPendingRedeemChunkLength", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserves", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reducedAmount", + "type": "uint256" + } + ], + "name": "ProtocolLiquidationIncentiveTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "addToAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowedLiquidatorsByAccount", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract IComptroller", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "forceVAILiquidate", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "treasuryPercentMantissa_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "internalType": "address", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract IVToken", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "liquidationRestricted", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minLiquidatableVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseForceVAILiquidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "pendingRedeem", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + } + ], + "name": "removeFromAllowlist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "restrictLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "resumeForceVAILiquidate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "minLiquidatableVAI_", + "type": "uint256" + } + ], + "name": "setMinLiquidatableVAI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newLength_", + "type": "uint256" + } + ], + "name": "setPendingRedeemChunkLength", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newTreasuryPercentMantissa", + "type": "uint256" + } + ], + "name": "setTreasuryPercent", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryPercentMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "unrestrictLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBnb", + "outputs": [ + { + "internalType": "contract IVBNB", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract IVAIController", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "wBNB", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] diff --git a/simulations/vip-617/abi/ProxyAdmin.json b/simulations/vip-617/abi/ProxyAdmin.json new file mode 100644 index 000000000..b4c51d8df --- /dev/null +++ b/simulations/vip-617/abi/ProxyAdmin.json @@ -0,0 +1,151 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/VAIController.json b/simulations/vip-617/abi/VAIController.json new file mode 100644 index 000000000..8f43cbf06 --- /dev/null +++ b/simulations/vip-617/abi/VAIController.json @@ -0,0 +1,1189 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeAmount", + "type": "uint256" + } + ], + "name": "MintFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldImplementation", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "previousMintEnabledOnlyForPrimeHolder", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newMintEnabledOnlyForPrimeHolder", + "type": "bool" + } + ], + "name": "MintOnlyForPrimeHolder", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "MintVAI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPrime", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPrime", + "type": "address" + } + ], + "name": "NewPrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldBaseRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIBaseRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldFloatRateMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newFlatRateMantissa", + "type": "uint256" + } + ], + "name": "NewVAIFloatRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMintCap", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMintCap", + "type": "uint256" + } + ], + "name": "NewVAIMintCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldReceiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "NewVAIReceiver", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldVaiToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newVaiToken", + "type": "address" + } + ], + "name": "NewVaiToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayVAIAmount", + "type": "uint256" + } + ], + "name": "RepayVAI", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "INITIAL_VAI_MINT_INDEX", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract VAIUnitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + } + ], + "name": "_setComptroller", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "accessControl", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "accrueVAIInterest", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "baseRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "floatRateMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getBlocksPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "getMintableVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "getVAICalculateRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "getVAIMinterInterestIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getVAIRepayAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getVAIRepayRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "initialize", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isVenusVAIInitialized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintCap", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "mintEnabledOnlyForPrimeHolder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "mintVAIAmount", + "type": "uint256" + } + ], + "name": "mintVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "pastVAIInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "receiver", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "repayVAI", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "repayVAIBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "setAccessControl", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newBaseRateMantissa", + "type": "uint256" + } + ], + "name": "setBaseRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "newFloatRateMantissa", + "type": "uint256" + } + ], + "name": "setFloatRate", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "uint256", + "name": "_mintCap", + "type": "uint256" + } + ], + "name": "setMintCap", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "prime_", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "newReceiver", + "type": "address" + } + ], + "name": "setReceiver", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "vai_", + "type": "address" + } + ], + "name": "setVAIToken", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "toggleOnlyPrimeHolderMint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiMintIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusVAIMinterIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "venusVAIState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/VAIUnitroller.json b/simulations/vip-617/abi/VAIUnitroller.json new file mode 100644 index 000000000..99d02ff85 --- /dev/null +++ b/simulations/vip-617/abi/VAIUnitroller.json @@ -0,0 +1,122 @@ +[ + { "inputs": [], "payable": false, "stateMutability": "nonpayable", "type": "constructor" }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "error", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "info", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "detail", "type": "uint256" } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAdmin", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldImplementation", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newImplementation", "type": "address" } + ], + "name": "NewImplementation", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldPendingAdmin", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newPendingAdmin", "type": "address" } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldPendingImplementation", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newPendingImplementation", "type": "address" } + ], + "name": "NewPendingImplementation", + "type": "event" + }, + { "payable": true, "stateMutability": "payable", "type": "fallback" }, + { + "constant": false, + "inputs": [], + "name": "_acceptAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "_acceptImplementation", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "newPendingAdmin", "type": "address" }], + "name": "_setPendingAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "newPendingImplementation", "type": "address" }], + "name": "_setPendingImplementation", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "pendingVAIControllerImplementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "vaiControllerImplementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/abi/resilientOracle.json b/simulations/vip-617/abi/resilientOracle.json new file mode 100644 index 000000000..373eb14e9 --- /dev/null +++ b/simulations/vip-617/abi/resilientOracle.json @@ -0,0 +1,320 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "nativeMarketAddress", "type": "address" }, + { "internalType": "address", "name": "vaiAddress", "type": "address" }, + { "internalType": "contract BoundValidatorInterface", "name": "_boundValidator", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "calledContract", "type": "address" }, + { "internalType": "string", "name": "methodSignature", "type": "string" } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "name": "CachedEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAccessControlManager", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlManager", "type": "address" } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "role", "type": "uint256" }, + { "indexed": true, "internalType": "bool", "name": "enable", "type": "bool" } + ], + "name": "OracleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "oracle", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "role", "type": "uint256" } + ], + "name": "OracleSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "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": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "mainOracle", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "pivotOracle", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "fallbackOracle", "type": "address" } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "address", "name": "account", "type": "address" }], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "CACHE_SLOT", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INVALID_PRICE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boundValidator", + "outputs": [{ "internalType": "contract BoundValidatorInterface", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" }, + { "internalType": "bool", "name": "enable", "type": "bool" } + ], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" } + ], + "name": "getOracle", + "outputs": [ + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "getPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "getTokenConfig", + "outputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], + "name": "getUnderlyingPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "pause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "paused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "unpause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "updateAssetPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-617/bscmainnet.ts b/simulations/vip-617/bscmainnet.ts new file mode 100644 index 000000000..b80bf781d --- /dev/null +++ b/simulations/vip-617/bscmainnet.ts @@ -0,0 +1,1001 @@ +import { TransactionResponse } from "@ethersproject/providers"; +import { time } from "@nomicfoundation/hardhat-network-helpers"; +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { + expectEvents, + initMainnetUser, + pinResilientOraclePriceViaRedstone, + setMaxStalePeriod, + setMaxStalePeriodForAllAssets, +} from "src/utils"; +import { forking, testVip } from "src/vip-framework"; +import CHAINLINK_ORACLE_ABI from "src/vip-framework/abi/chainlinkOracle.json"; +import ERC20_ABI from "src/vip-framework/abi/erc20.json"; +import VTOKEN_ABI from "src/vip-framework/abi/vToken.json"; + +import vip617, { + ASSET_CONFIGS, + COMPTROLLER_DBO_SETTER, + COMPTROLLER_LENS, + DBO_GOVERNANCE_FUNCTIONS_3TL, + DBO_GOVERNANCE_FUNCTIONS_3TL_GUARDIAN, + DBO_KEEPER_FUNCTIONS, + DEVIATION_BOUNDED_ORACLE, + KEEPER, + KEEPER_CALLERS, + TIMELOCKS, + UNITROLLER_IMPLEMENTATION, + VAI_CONTROLLER_IMPL, +} from "../../vips/vip-617/bscmainnet"; +import { cutParams } from "../../vips/vip-617/utils/cut-params-bscmainnet.json"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import DBO_ABI from "./abi/DeviationBoundedOracle.json"; +import DIAMOND_ABI from "./abi/Diamond.json"; +import LIQUIDATOR_ABI from "./abi/Liquidator.json"; +import VAI_UNITROLLER_ABI from "./abi/VAIUnitroller.json"; +import RESILIENT_ORACLE_ABI from "./abi/resilientOracle.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; +const { + NORMAL_TIMELOCK, + FAST_TRACK_TIMELOCK, + CRITICAL_TIMELOCK, + GUARDIAN, + ACCESS_CONTROL_MANAGER, + UNITROLLER, + VAI_UNITROLLER, +} = bscmainnet; + +const FORK_BLOCK = 96687252; +const SUPPORTER = "0xe5e62386933b74ea81bfd73a6a6591598e7f8ced"; + +// Step 1 grants: 4×3 (3TL) + 2×4 (3TL+G) + 4×5 (3TL+G+K) + 1×2 (Normal+G) = 42 +// + 1 extra RoleGranted from grantRole(DEFAULT_ADMIN_ROLE, ACMCommandsAggregator) = 43 +const EXPECTED_ROLE_GRANTED_EVENTS = 43; + +const SET_DBO_SELECTOR = ethers.utils.id("setDeviationBoundedOracle(address)").slice(0, 10); +// Hardcoded from the ADD entry in cut-params-bscmainnet.json: the SetterFacet address +// that gains the new setDeviationBoundedOracle selector. +const SETTER_FACET = "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0"; + +// BSC mainnet ACM exposes hasRole(bytes32, address) only; role = keccak256(packed target+sig). +const roleHash = (target: string, signature: string): string => + ethers.utils.keccak256(ethers.utils.solidityPack(["address", "string"], [target, signature])); + +const getAssetConfig = (name: string): { asset: string; vToken: string } => { + const cfg = ASSET_CONFIGS.find(c => c.name === name); + if (!cfg) throw new Error(`Asset "${name}" not present in asset-configs-bscmainnet.json`); + return { asset: cfg.asset, vToken: cfg.vToken }; +}; +const getAsset = (name: string): string => getAssetConfig(name).asset; +const ETH_ASSET = getAssetConfig("ETH").asset; +const ETH_VTOKEN = getAssetConfig("ETH").vToken; +const TRX_UNDERLYING = getAssetConfig("TRX").asset; +const TRX_VTOKEN = getAssetConfig("TRX").vToken; + +type Signer = Awaited>; + +// Fixed VIP-1 rollout parameters. +const FIXED_COOLDOWN = 3600; // 1h +const FIXED_RESET_THRESHOLD = BigNumber.from("50000000000000000"); // 5% +const TRIGGER_DEFAULT_BORROW_ONLY = BigNumber.from("166700000000000000"); // 16.67% — used when CF=0 + +// Manual triggerThreshold overrides (deviate from the ((1/LTV)-1)/2 formula). +const TRIGGER_OVERRIDES: Record = { + CAKE: BigNumber.from("300000000000000000"), // 30% — tightened +}; + +// Assets whose ResilientOracle price drifts between block N (VIP seeding) and +// later reads (e.g. yield-bearing PT tokens). Compared with 1bp tolerance. +const TIME_VARYING_ORACLE_ASSETS = new Set(["vPT-clisBNB-25JUN2026"]); +const PRICE_DRIFT_TOLERANCE_BPS = BigNumber.from(1); // 0.01% +const expectClose = (actual: BigNumber, expected: BigNumber, label: string) => { + const tolerance = expected.mul(PRICE_DRIFT_TOLERANCE_BPS).div(10000).add(1); + const diff = actual.sub(expected).abs(); + expect(diff.lte(tolerance), `${label}: |${actual} - ${expected}| = ${diff} > tol ${tolerance}`).to.equal(true); +}; + +// triggerThreshold = ((1/LTV) - 1) / 2 → (1e36/cf - 1e18) / 2 +const ONE_E18 = BigNumber.from(10).pow(18); +const ONE_E36 = BigNumber.from(10).pow(36); +const triggerFromCF = (cf: BigNumber): BigNumber => ONE_E36.div(cf).sub(ONE_E18).div(2); + +forking(FORK_BLOCK, async () => { + const provider = ethers.provider; + + let comptroller: Contract; + let acm: Contract; + let dbo: Contract; + let vaiUnitroller: Contract; + + let oldComptrollerLens: string; + let oldVaiImpl: string; + let oldDiamondImpl: string; + let oldFacetAddresses: string[]; + let oldSelectorsByFacet: Record; + + // V1 storage slots — must remain unchanged through V19 upgrade. + // Restricted to getters confirmed exposed on the pre-VIP Diamond; most newer + // Comptroller fields (e.g. liquidationIncentiveMantissa, protocolPaused) are + // only added by this VIP's facet replacement and would revert if probed early. + let oldAdmin: string; + let oldCloseFactorMantissa: BigNumber; + let oldMaxAssets: BigNumber; + let oldPendingAdmin: string; + let oldEthMarket: { isListed: boolean; collateralFactorMantissa: BigNumber }; + + before(async () => { + comptroller = new ethers.Contract(UNITROLLER, COMPTROLLER_ABI, provider); + acm = new ethers.Contract(ACCESS_CONTROL_MANAGER, ACM_ABI, provider); + dbo = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, DBO_ABI, provider); + vaiUnitroller = new ethers.Contract(VAI_UNITROLLER, VAI_UNITROLLER_ABI, provider); + + oldComptrollerLens = await comptroller.comptrollerLens(); + oldVaiImpl = await vaiUnitroller.vaiControllerImplementation(); + oldDiamondImpl = await comptroller.comptrollerImplementation(); + oldFacetAddresses = [...(await comptroller.facetAddresses())]; + + oldSelectorsByFacet = {}; + for (const facet of oldFacetAddresses) { + oldSelectorsByFacet[facet] = [...(await comptroller.facetFunctionSelectors(facet))]; + } + + oldAdmin = await comptroller.admin(); + oldCloseFactorMantissa = await comptroller.closeFactorMantissa(); + oldMaxAssets = await comptroller.maxAssets(); + oldPendingAdmin = await comptroller.pendingAdmin(); + const ethVToken = ASSET_CONFIGS.find(c => c.name === "ETH")!.vToken; + const m = await comptroller.markets(ethVToken); + oldEthMarket = { isListed: m.isListed, collateralFactorMantissa: m.collateralFactorMantissa }; + + // Stretch every DBO-configured asset's resilient-oracle freshness window + // out to 1y on the fork. The proposal lifecycle (propose→queue→execute) + // mines blocks past real-world heartbeats, so a CF/price check during + // execution would otherwise revert with "invalid resilient oracle price". + // Fork-only — does not become part of the on-chain VIP. + const resilientOracle = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, provider); + const assetContracts = await Promise.all(ASSET_CONFIGS.map(c => ethers.getContractAt(ERC20_ABI, c.asset))); + await setMaxStalePeriodForAllAssets(resilientOracle, assetContracts); + + // SolvBTC, xSolvBTC, and TWT use feeds that enforce their own internal + // staleness window — the check lives inside the feed contract itself, not in + // the ResilientOracle config that setMaxStalePeriod writes to. Bumping the + // ResilientOracle's freshness window therefore has no effect on these feeds, + // and they still revert as stale across the proposal lifecycle. Rewrite their + // token configs fork-side to a Redstone-only feed pinned at the live spot. + const REDSTONE_PIN_ASSETS = [getAsset("SolvBTC"), getAsset("xSolvBTC"), getAsset("TWT")]; + for (const asset of REDSTONE_PIN_ASSETS) { + await pinResilientOraclePriceViaRedstone(resilientOracle, asset); + } + }); + + describe("Pre-VIP state", () => { + describe("Step 1 — ACM permissions are NOT yet granted", () => { + it("3-timelock governance setters are not callable by any timelock", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS_3TL) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of TIMELOCKS) { + expect( + await acm.hasRole(role, caller), + `${caller} should NOT be allowed to call ${sig} on DBO pre-VIP`, + ).to.equal(false); + } + } + }); + + it("3TL+Guardian setters are not callable by timelocks or guardian", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS_3TL_GUARDIAN) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of [...TIMELOCKS, GUARDIAN]) { + expect(await acm.hasRole(role, caller)).to.equal(false); + } + } + }); + + it("keeper actions are not callable by 3 timelocks + Guardian + Keeper", async () => { + for (const sig of DBO_KEEPER_FUNCTIONS) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of KEEPER_CALLERS) { + expect( + await acm.hasRole(role, caller), + `${caller} should NOT be allowed to call ${sig} on DBO pre-VIP`, + ).to.equal(false); + } + } + }); + + it("setDeviationBoundedOracle is not callable by Normal or Guardian", async () => { + const role = roleHash(UNITROLLER, COMPTROLLER_DBO_SETTER); + for (const caller of [NORMAL_TIMELOCK, GUARDIAN]) { + expect(await acm.hasRole(role, caller)).to.equal(false); + } + }); + }); + + describe("Steps 2–5 — Comptroller / VAI upgrades have NOT been applied", () => { + it("Unitroller does not yet point at the new Diamond implementation", async () => { + expect(oldDiamondImpl).to.not.equal(UNITROLLER_IMPLEMENTATION); + }); + + it("setDeviationBoundedOracle selector resolves to the zero address", async () => { + const facet = await comptroller.facetAddress(SET_DBO_SELECTOR); + expect(facet.facetAddress).to.equal(ethers.constants.AddressZero); + }); + + it("current comptrollerLens is NOT the newly deployed one", async () => { + expect(oldComptrollerLens).to.not.equal(COMPTROLLER_LENS); + }); + + it("VaiUnitroller does not yet point at the new implementation", async () => { + expect(oldVaiImpl).to.not.equal(VAI_CONTROLLER_IMPL); + }); + }); + + describe("Steps 6–7 — DBO wiring has NOT happened yet", () => { + it("DBO pendingOwner is the normal timelock", async () => { + expect(await dbo.pendingOwner()).to.equal(NORMAL_TIMELOCK); + }); + + it("DBO owner is not yet the normal timelock", async () => { + expect(await dbo.owner()).to.not.equal(NORMAL_TIMELOCK); + }); + + it("Comptroller.deviationBoundedOracle() reverts — selector not installed pre-cut", async () => { + await expect(comptroller.deviationBoundedOracle()).to.be.reverted; + }); + }); + + describe("Step 8 — DBO has no initialized assets yet", () => { + it("getInitializedAssets() is empty", async () => { + expect((await dbo.getInitializedAssets()).length).to.equal(0); + }); + }); + }); + + testVip("VIP-617 DBO Rollout on BSC mainnet", await vip617(), { + supporter: SUPPORTER, + callbackAfterExecution: async (txResponse: TransactionResponse) => { + // Step 1 — ACM grants (BSC mainnet ACM emits OZ RoleGranted, not PermissionGranted) + await expectEvents(txResponse, [ACM_ABI], ["RoleGranted"], [EXPECTED_ROLE_GRANTED_EVENTS]); + + // Steps 2 + 5 — Unitroller & VAIController upgrades (each pair emits 1 NewImpl + 2 NewPendingImpl). + // VaiUnitroller emits the same Comptroller-style event signatures, so a single ABI suffices — + // adding VAI_UNITROLLER_ABI here would double-count any log that matches both ABIs. + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewImplementation", "NewPendingImplementation"], [2, 4]); + + // Step 3 — diamondCut + await expectEvents(txResponse, [DIAMOND_ABI], ["DiamondCut"], [1]); + + // Step 4 — ComptrollerLens swap + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewComptrollerLens"], [1]); + + // Step 6 — DBO ownership accept + await expectEvents(txResponse, [DBO_ABI], ["OwnershipTransferred"], [1]); + + // Step 7 — DBO wired into Comptroller + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewDeviationBoundedOracle"], [1]); + + // Step 8 — one ProtectionInitialized + BoundedPricingWhitelistUpdated per asset + const N = ASSET_CONFIGS.length; + await expectEvents(txResponse, [DBO_ABI], ["ProtectionInitialized", "BoundedPricingWhitelistUpdated"], [N, N]); + }, + }); + + describe("Post-VIP state", () => { + describe("Step 1 — ACM matrix matches the spec", () => { + it("3-timelock governance setters callable by every timelock; not by Guardian/Keeper", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS_3TL) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of TIMELOCKS) { + expect(await acm.hasRole(role, caller)).to.equal(true); + } + for (const caller of [GUARDIAN, KEEPER]) { + expect(await acm.hasRole(role, caller), `${caller} should NOT have ${sig} (3TL-only)`).to.equal(false); + } + } + }); + + it("3TL+Guardian setters callable by 3 timelocks + Guardian; not by Keeper", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS_3TL_GUARDIAN) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of [...TIMELOCKS, GUARDIAN]) { + expect(await acm.hasRole(role, caller)).to.equal(true); + } + expect(await acm.hasRole(role, KEEPER)).to.equal(false); + } + }); + + it("keeper actions callable by 3 timelocks + Guardian + Keeper", async () => { + for (const sig of DBO_KEEPER_FUNCTIONS) { + const role = roleHash(DEVIATION_BOUNDED_ORACLE, sig); + for (const caller of KEEPER_CALLERS) { + expect(await acm.hasRole(role, caller), `${caller} should be allowed to call ${sig} on DBO`).to.equal(true); + } + } + }); + + it("setDeviationBoundedOracle callable by Normal + Guardian only", async () => { + const role = roleHash(UNITROLLER, COMPTROLLER_DBO_SETTER); + expect(await acm.hasRole(role, NORMAL_TIMELOCK)).to.equal(true); + expect(await acm.hasRole(role, GUARDIAN)).to.equal(true); + for (const caller of [FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, KEEPER]) { + expect(await acm.hasRole(role, caller), `${caller} should NOT have setDeviationBoundedOracle`).to.equal( + false, + ); + } + }); + }); + + describe("Steps 2–5 — Comptroller / VAI upgrades applied", () => { + it("Unitroller points at the new Diamond implementation", async () => { + expect(await comptroller.comptrollerImplementation()).to.equal(UNITROLLER_IMPLEMENTATION); + }); + + it("every selector in cutParams resolves to its new facet address", async () => { + for (const [facetAddr, , selectors] of cutParams as [string, number, string[]][]) { + for (const sel of selectors) { + expect((await comptroller.facetAddress(sel)).facetAddress).to.equal(facetAddr); + } + } + }); + + it("setDeviationBoundedOracle selector is installed on the SetterFacet", async () => { + const resolved = (await comptroller.facetAddress(SET_DBO_SELECTOR)).facetAddress; + expect(resolved).to.equal(SETTER_FACET); + const setterSels = await comptroller.facetFunctionSelectors(SETTER_FACET); + expect(setterSels).to.include(SET_DBO_SELECTOR); + }); + + it("all old facet addresses have been replaced", async () => { + for (const oldFacet of oldFacetAddresses) { + const selectorsOnOldFacet = await comptroller.facetFunctionSelectors(oldFacet); + expect(selectorsOnOldFacet).to.deep.equal([]); + } + }); + + it("each old facet's selectors are preserved on its replacement (SetterFacet gains setDeviationBoundedOracle)", async () => { + for (const [oldFacet, oldSels] of Object.entries(oldSelectorsByFacet)) { + const newFacet = (await comptroller.facetAddress(oldSels[0])).facetAddress; + const newSels = [...(await comptroller.facetFunctionSelectors(newFacet))].sort(); + const newSelsBaseline = newSels.filter(s => s !== SET_DBO_SELECTOR); + expect( + newSelsBaseline, + `Selectors drifted between facet roles for old facet ${oldFacet} → new facet ${newFacet}`, + ).to.deep.equal([...oldSels].sort()); + } + }); + + it("comptrollerLens points at the new contract", async () => { + expect(await comptroller.comptrollerLens()).to.equal(COMPTROLLER_LENS); + }); + + it("VaiUnitroller points at the new implementation", async () => { + expect(await vaiUnitroller.vaiControllerImplementation()).to.equal(VAI_CONTROLLER_IMPL); + }); + + describe("Storage layout preserved across Diamond upgrade", () => { + it("admin slot unchanged", async () => { + expect(await comptroller.admin()).to.equal(oldAdmin); + }); + + it("closeFactorMantissa slot unchanged", async () => { + expect(await comptroller.closeFactorMantissa()).to.equal(oldCloseFactorMantissa); + }); + + it("maxAssets slot unchanged", async () => { + expect(await comptroller.maxAssets()).to.equal(oldMaxAssets); + }); + + it("pendingAdmin slot unchanged", async () => { + expect(await comptroller.pendingAdmin()).to.equal(oldPendingAdmin); + }); + + it("markets[vETH] entry unchanged (isListed, collateralFactorMantissa)", async () => { + const ethVToken = ASSET_CONFIGS.find(c => c.name === "ETH")!.vToken; + const m = await comptroller.markets(ethVToken); + expect(m.isListed).to.equal(oldEthMarket.isListed); + expect(m.collateralFactorMantissa).to.equal(oldEthMarket.collateralFactorMantissa); + }); + }); + }); + + describe("Steps 6–7 — DBO wiring complete", () => { + it("DBO owner is the normal timelock", async () => { + expect(await dbo.owner()).to.equal(NORMAL_TIMELOCK); + }); + + it("DBO pendingOwner is cleared", async () => { + expect(await dbo.pendingOwner()).to.equal(ethers.constants.AddressZero); + }); + + it("Comptroller.deviationBoundedOracle() returns the deployed DBO", async () => { + expect(await comptroller.deviationBoundedOracle()).to.equal(DEVIATION_BOUNDED_ORACLE); + }); + }); + + describe("Step 8 — Asset configs seeded", () => { + it("getInitializedAssets() returns every configured asset", async () => { + const initialized = await dbo.getInitializedAssets(); + expect(initialized.length).to.equal(ASSET_CONFIGS.length); + const set = new Set(initialized.map((a: string) => a.toLowerCase())); + for (const c of ASSET_CONFIGS) { + expect(set.has(c.asset.toLowerCase()), `${c.name} (${c.asset}) missing from getInitializedAssets`).to.equal( + true, + ); + } + }); + + it("every asset has cooldownPeriod=3600 (1H) and resetThreshold=5%", async () => { + for (const c of ASSET_CONFIGS) { + const cfg = await dbo.assetProtectionConfig(c.asset); + expect(cfg.cooldownPeriod, `${c.name}.cooldownPeriod`).to.equal(FIXED_COOLDOWN); + expect(cfg.resetThreshold, `${c.name}.resetThreshold`).to.equal(FIXED_RESET_THRESHOLD); + expect(cfg.currentlyUsingProtectedPrice, `${c.name}.currentlyUsingProtectedPrice`).to.equal(false); + } + }); + + // Borrow-only markets (CF=0) use the 16.67% default since the formula is undefined for LTV=0. + // Some assets carry a manual override (TRIGGER_OVERRIDES) that bypasses the formula. + it("triggerThreshold per asset matches ((1/LTV)-1)/2 from live Comptroller CF", async () => { + for (const c of ASSET_CONFIGS) { + const market = await comptroller.markets(c.vToken); + const cf: BigNumber = market.collateralFactorMantissa; + const expected = TRIGGER_OVERRIDES[c.name] ?? (cf.isZero() ? TRIGGER_DEFAULT_BORROW_ONLY : triggerFromCF(cf)); + const cfg = await dbo.assetProtectionConfig(c.asset); + expect(cfg.triggerThreshold, `${c.name}.triggerThreshold (vToken=${c.vToken}, CF=${cf.toString()})`).to.equal( + expected, + ); + } + }); + + it("vTRX is the only asset with isBoundedPricingEnabled=true; all others false", async () => { + for (const c of ASSET_CONFIGS) { + const expected = c.asset.toLowerCase() === TRX_UNDERLYING.toLowerCase(); + expect(await dbo.isBoundedPricingEnabled(c.asset), `${c.name}.isBoundedPricingEnabled`).to.equal(expected); + } + }); + + it("cachingEnabled is false for every asset", async () => { + for (const c of ASSET_CONFIGS) { + const cfg = await dbo.assetProtectionConfig(c.asset); + expect(cfg.cachingEnabled, `${c.name}.cachingEnabled`).to.equal(false); + } + }); + }); + + // Wrapped in evm_snapshot/evm_revert because the tests in this block + // mutate DBO state (setCooldownPeriod, setAssetBoundedPricingEnabled, + // updateMaxPrice). Without isolation those mutations leak into the + // "DBO pass-through behaviour" and "Comptroller post-upgrade smoke" + // blocks that follow, which assert against the VIP-seeded state. + describe("Functional ACM verification", () => { + let acmSnapshotId: string; + before(async () => { + acmSnapshotId = await provider.send("evm_snapshot", []); + }); + after(async () => { + await provider.send("evm_revert", [acmSnapshotId]); + }); + + it("Normal Timelock can call setCooldownPeriod (3TL governance)", async () => { + const signer = await initMainnetUser(NORMAL_TIMELOCK, ethers.utils.parseEther("1")); + await expect(dbo.connect(signer).setCooldownPeriod(ETH_ASSET, 7200)).to.not.be.reverted; + const cfg = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfg.cooldownPeriod).to.equal(7200); + }); + + it("Guardian can call setAssetBoundedPricingEnabled (3TL+G)", async () => { + const signer = await initMainnetUser(GUARDIAN, ethers.utils.parseEther("1")); + // Toggle on→off so we end disabled regardless of starting flag. + await dbo.connect(signer).setAssetBoundedPricingEnabled(ETH_ASSET, true); + await dbo.connect(signer).setAssetBoundedPricingEnabled(ETH_ASSET, false); + expect(await dbo.isBoundedPricingEnabled(ETH_ASSET)).to.equal(false); + }); + + it("Keeper can call updateMaxPrice (keeper band)", async () => { + const keeperSigner = await initMainnetUser(KEEPER, ethers.utils.parseEther("1")); + const { maxPrice } = await dbo.assetProtectionConfig(ETH_ASSET); + await expect(dbo.connect(keeperSigner).updateMaxPrice(ETH_ASSET, maxPrice)).to.not.be.reverted; + }); + + it("Random address CANNOT call any keeper function", async () => { + const signer = await initMainnetUser( + NETWORK_ADDRESSES.bscmainnet.GENERIC_TEST_USER_ACCOUNT, + ethers.utils.parseEther("1"), + ); + await expect(dbo.connect(signer).updateMinPrice(ETH_ASSET, 1)).to.be.reverted; + await expect(dbo.connect(signer).updateMaxPrice(ETH_ASSET, 1)).to.be.reverted; + await expect(dbo.connect(signer).exitProtectionMode(ETH_ASSET)).to.be.reverted; + }); + + it("Critical Timelock CANNOT call setDeviationBoundedOracle on Unitroller (Normal+Guardian only)", async () => { + const signer = await initMainnetUser(CRITICAL_TIMELOCK, ethers.utils.parseEther("1")); + await expect(comptroller.connect(signer).setDeviationBoundedOracle(DEVIATION_BOUNDED_ORACLE)).to.be.reverted; + }); + }); + + describe("DBO pass-through behaviour", () => { + const resilientOracle = () => + new ethers.Contract( + NETWORK_ADDRESSES.bscmainnet.RESILIENT_ORACLE, + [ + "function getPrice(address asset) view returns (uint256)", + "function getUnderlyingPrice(address vToken) view returns (uint256)", + ], + provider, + ); + + it("disabled assets: getBoundedPricesView returns (spot, spot) from ResilientOracle", async () => { + const ro = resilientOracle(); + for (const c of ASSET_CONFIGS) { + if (c.isBoundedPricingEnabled) continue; + const spot: BigNumber = await ro.getUnderlyingPrice(c.vToken); + const [collateral, debt] = await dbo.getBoundedPricesView(c.vToken); + expect(collateral, `${c.name}.collateralPrice`).to.equal(spot); + expect(debt, `${c.name}.debtPrice`).to.equal(spot); + } + }); + + it("disabled assets: window seeded at spot (minPrice == maxPrice == spot, protection inactive)", async () => { + const ro = resilientOracle(); + for (const c of ASSET_CONFIGS) { + if (c.isBoundedPricingEnabled) continue; + const spot: BigNumber = await ro.getPrice(c.asset); + const cfg = await dbo.assetProtectionConfig(c.asset); + expect(cfg.minPrice, `${c.name}.minPrice`).to.equal(spot); + expect(cfg.maxPrice, `${c.name}.maxPrice`).to.equal(spot); + expect(cfg.currentlyUsingProtectedPrice, `${c.name}.currentlyUsingProtectedPrice`).to.equal(false); + } + }); + + it("vTRX (enabled): window seeded at spot and getBoundedPricesView returns (spot, spot) at activation", async () => { + const ro = resilientOracle(); + const spotAsset: BigNumber = await ro.getPrice(TRX_UNDERLYING); + const spotVToken: BigNumber = await ro.getUnderlyingPrice(TRX_VTOKEN); + const cfg = await dbo.assetProtectionConfig(TRX_UNDERLYING); + expect(cfg.minPrice, "TRX.minPrice").to.equal(spotAsset); + expect(cfg.maxPrice, "TRX.maxPrice").to.equal(spotAsset); + expect(cfg.currentlyUsingProtectedPrice, "TRX.currentlyUsingProtectedPrice").to.equal(false); + const [collateral, debt] = await dbo.getBoundedPricesView(TRX_VTOKEN); + expect(collateral, "TRX.collateralPrice").to.equal(spotVToken); + expect(debt, "TRX.debtPrice").to.equal(spotVToken); + }); + }); + }); + + // ──────────────────────────────────────────────────────────────────── + // E2E scenarios — full DBO lifecycle on a representative asset (ETH). + // + // Spot price is driven on the live ResilientOracle by writing into the + // ChainlinkOracle (the MAIN oracle for ETH on BSC) via setDirectPrice. + // PIVOT validation is disabled for ETH on the ResilientOracle so the + // BoundValidator does not reject manipulated prices. + // + // The whole block is wrapped in evm_snapshot/evm_revert so it does not + // leak fork state to anything that runs after it. + // ──────────────────────────────────────────────────────────────────── + describe("E2E scenarios — DBO lifecycle on ETH", () => { + const ORACLE_ROLE_PIVOT = 1; + + let chainlink: Contract; + let resilient: Contract; + let timelockSigner: Signer; + let guardianSigner: Signer; + let keeperSigner: Signer; + let snapshotId: string; + let originalEthSpot: BigNumber; + + before(async () => { + snapshotId = await provider.send("evm_snapshot", []); + + chainlink = new ethers.Contract(bscmainnet.CHAINLINK_ORACLE, CHAINLINK_ORACLE_ABI, provider); + resilient = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, provider); + + timelockSigner = await initMainnetUser(NORMAL_TIMELOCK, ethers.utils.parseEther("1")); + guardianSigner = await initMainnetUser(GUARDIAN, ethers.utils.parseEther("1")); + keeperSigner = await initMainnetUser(KEEPER, ethers.utils.parseEther("1")); + + // Disable PIVOT for ETH so a deviated MAIN price is returned through. + await resilient.connect(timelockSigner).enableOracle(ETH_ASSET, ORACLE_ROLE_PIVOT, false); + + // Pin ChainlinkOracle storage to the live spot. Chainlink is the MAIN + // oracle for ETH on BSC, so setDirectPrice fully drives ResilientOracle's + // reading; ETH is 18 decimals so the value passes through unchanged. + // Once pinned, every subsequent price move in this block can be driven + // by a single setDirectPrice call on Chainlink — no need to touch the + // ResilientOracle or the underlying Chainlink aggregator separately. + originalEthSpot = await resilient.getPrice(ETH_ASSET); + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, originalEthSpot); + expect(await resilient.getPrice(ETH_ASSET)).to.equal(originalEthSpot); + }); + + after(async () => { + await provider.send("evm_revert", [snapshotId]); + }); + + describe("E2E-1: default behaviour at activation", () => { + it("every disabled asset has minPrice == maxPrice == spot and bounded == (spot, spot)", async () => { + for (const c of ASSET_CONFIGS) { + if (c.isBoundedPricingEnabled) continue; + const spot: BigNumber = await resilient.getPrice(c.asset); + const cfg = await dbo.assetProtectionConfig(c.asset); + if (TIME_VARYING_ORACLE_ASSETS.has(c.name)) { + expectClose(cfg.minPrice, spot, `${c.name}.minPrice`); + expectClose(cfg.maxPrice, spot, `${c.name}.maxPrice`); + } else { + expect(cfg.minPrice, `${c.name}.minPrice`).to.equal(spot); + expect(cfg.maxPrice, `${c.name}.maxPrice`).to.equal(spot); + } + expect(cfg.currentlyUsingProtectedPrice, `${c.name}.currentlyUsingProtectedPrice`).to.equal(false); + + const [collateral, debt] = await dbo.getBoundedPricesView(c.vToken); + if (TIME_VARYING_ORACLE_ASSETS.has(c.name)) { + expectClose(collateral, spot, `${c.name}.collateralPrice`); + expectClose(debt, spot, `${c.name}.debtPrice`); + } else { + expect(collateral, `${c.name}.collateralPrice`).to.equal(spot); + expect(debt, `${c.name}.debtPrice`).to.equal(spot); + } + } + }); + }); + + describe("E2E-2: enable bounded pricing → trigger → divergence", () => { + // 50% pump — well above the ~16.67% triggerThreshold seeded for ETH. + let pumpedSpot: BigNumber; + + before(async () => { + pumpedSpot = originalEthSpot.mul(150).div(100); + }); + + it("Guardian enables ETH whitelist; window seeds at current spot", async () => { + await dbo.connect(guardianSigner).setAssetBoundedPricingEnabled(ETH_ASSET, true); + const cfg = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfg.minPrice).to.equal(originalEthSpot); + expect(cfg.maxPrice).to.equal(originalEthSpot); + expect(cfg.currentlyUsingProtectedPrice).to.equal(false); + expect(await dbo.isBoundedPricingEnabled(ETH_ASSET)).to.equal(true); + }); + + it("oracle pump + updateProtectionState activates protection", async () => { + // Pre-pump: spot == window bounds, deviation is zero, so getBoundedPricesView + // is a pure passthrough — (spot, spot). + const [collateralBefore, debtBefore] = await dbo.getBoundedPricesView(ETH_VTOKEN); + expect(collateralBefore).to.equal(originalEthSpot); + expect(debtBefore).to.equal(originalEthSpot); + + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, pumpedSpot); + expect(await resilient.getPrice(ETH_ASSET)).to.equal(pumpedSpot); + + // Pre-call storage: window still seeded at originalEthSpot and the protection + // flag is unset — updateProtectionState has not run, so nothing has been latched. + const cfgBefore = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfgBefore.minPrice).to.equal(originalEthSpot); + expect(cfgBefore.maxPrice).to.equal(originalEthSpot); + expect(cfgBefore.currentlyUsingProtectedPrice).to.equal(false); + + const tx = await dbo.connect(keeperSigner).updateProtectionState(ETH_VTOKEN); + await expect(tx).to.emit(dbo, "ProtectionTriggered"); + expect(await dbo.currentlyUsingProtectedPrice(ETH_ASSET)).to.equal(true); + + // Post-call storage: maxPrice latches to pumpedSpot, minPrice stays at originalEthSpot, + // and currentlyUsingProtectedPrice is set so the whitelist can no longer be flipped off. + const cfgAfter = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfgAfter.minPrice).to.equal(originalEthSpot); + expect(cfgAfter.maxPrice).to.equal(pumpedSpot); + expect(cfgAfter.minPrice).to.not.equal(cfgAfter.maxPrice); + + // Post-call view: now clips. collateral = min(spot, minPrice) = min(pumped, original) = original; + // debt = max(spot, maxPrice) = max(pumped, pumped) = pumped. The view has shifted away from + // the pre-pump passthrough — collateral is pinned at the seed and debt tracks the pump. + const [collateralAfter, debtAfter] = await dbo.getBoundedPricesView(ETH_VTOKEN); + expect(collateralAfter).to.equal(originalEthSpot); + expect(debtAfter).to.equal(pumpedSpot); + expect(collateralAfter).to.equal(collateralBefore); // collateral unchanged: still pinned at original + expect(debtAfter).to.not.equal(debtBefore); // debt diverged: original → pumped + }); + + it("getBoundedPricesView clips both sides — spot strictly between minPrice and maxPrice", async () => { + // Dip spot below the pumped peak so three distinct prices are in play: + // originalEthSpot (low / minPrice) < dippedSpot (current) < pumpedSpot (high / maxPrice). + // Without this, debt == spot trivially and the upper-bound clip isn't exercised. + const dippedSpot = pumpedSpot.mul(95).div(100); + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, dippedSpot); + expect(await resilient.getPrice(ETH_ASSET)).to.equal(dippedSpot); + + const cfg = await dbo.assetProtectionConfig(ETH_ASSET); + // Window unchanged: min still at originalEthSpot, max latched at pumpedSpot from the trigger. + expect(cfg.minPrice).to.equal(originalEthSpot); + expect(cfg.maxPrice).to.equal(pumpedSpot); + + const [collateral, debt] = await dbo.getBoundedPricesView(ETH_VTOKEN); + // collateral = min(spot, minPrice) = min(dipped, original) = original + expect(collateral).to.equal(originalEthSpot); + // debt = max(spot, maxPrice) = max(dipped, pumped) = pumped + expect(debt).to.equal(pumpedSpot); + // Both bounds diverge from the live ResilientOracle spot — clipping is doing + // work on each side rather than passing spot through. + const liveSpot = await resilient.getPrice(ETH_ASSET); + expect(liveSpot).to.equal(dippedSpot); + expect(collateral).to.not.equal(liveSpot); + expect(debt).to.not.equal(liveSpot); + }); + }); + + describe("E2E-3: disable bounded pricing → spot fallback", () => { + it("Guardian CANNOT flip whitelist off while protection is active", async () => { + expect(await dbo.currentlyUsingProtectedPrice(ETH_ASSET)).to.equal(true); + await expect(dbo.connect(guardianSigner).setAssetBoundedPricingEnabled(ETH_ASSET, false)).to.be.reverted; + expect(await dbo.currentlyUsingProtectedPrice(ETH_ASSET)).to.equal(true); + }); + + it("keeper narrows window + cooldown elapses + exitProtectionMode succeeds", async () => { + // Restore spot so keeper bounds (newMin ≤ spot, newMax ≥ spot) accept ±1%. + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, originalEthSpot); + + const tightMin = originalEthSpot.mul(99).div(100); + const tightMax = originalEthSpot.mul(101).div(100); + await dbo.connect(keeperSigner).updateMinPrice(ETH_ASSET, tightMin); + await dbo.connect(keeperSigner).updateMaxPrice(ETH_ASSET, tightMax); + + // Pre-exit: window is still narrowed but offset from spot on both sides. + const spotBeforeExit = await resilient.getPrice(ETH_ASSET); + const cfgBeforeExit = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfgBeforeExit.minPrice).to.equal(tightMin); + expect(cfgBeforeExit.maxPrice).to.equal(tightMax); + expect(cfgBeforeExit.minPrice).to.not.equal(spotBeforeExit); + expect(cfgBeforeExit.maxPrice).to.not.equal(spotBeforeExit); + + await time.increase(BigNumber.from(cfgBeforeExit.cooldownPeriod).toNumber() + 1); + + await dbo.connect(keeperSigner).exitProtectionMode(ETH_ASSET); + expect(await dbo.currentlyUsingProtectedPrice(ETH_ASSET)).to.equal(false); + + // Post-exit: protection inactive — bounded pricing bypasses the window and returns + // (spot, spot). The keeper-set tightMin/tightMax remain in storage; exitProtectionMode + // only clears the protection flag, it does not reset the window. + const spotAfterExit = await resilient.getPrice(ETH_ASSET); + const [collateralAfterExit, debtAfterExit] = await dbo.getBoundedPricesView(ETH_VTOKEN); + expect(collateralAfterExit).to.equal(spotAfterExit); + expect(debtAfterExit).to.equal(spotAfterExit); + }); + + it("Guardian flips ETH whitelist off (allowed because protection is inactive)", async () => { + await dbo.connect(guardianSigner).setAssetBoundedPricingEnabled(ETH_ASSET, false); + expect(await dbo.isBoundedPricingEnabled(ETH_ASSET)).to.equal(false); + }); + + it("subsequent oracle pump produces (spot, spot) — bounded pricing bypassed", async () => { + const movedSpot = originalEthSpot.mul(2); // +100%, would clearly trigger if enabled + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, movedSpot); + expect(await resilient.getPrice(ETH_ASSET)).to.equal(movedSpot); + + const [collateral, debt] = await dbo.getBoundedPricesView(ETH_VTOKEN); + expect(collateral).to.equal(movedSpot); + expect(debt).to.equal(movedSpot); + + // Whitelist is off, so the +100% move must not arm protection — confirms the + // disable path actually short-circuits the trigger logic, not just the view. + expect(await dbo.currentlyUsingProtectedPrice(ETH_ASSET)).to.equal(false); + }); + }); + + describe("E2E-4: oracle-driven update flow re-arms protection", () => { + let priorTriggerTimestamp: BigNumber; + let droppedSpot: BigNumber; + + it("re-enable resets window at current spot", async () => { + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, originalEthSpot); + await dbo.connect(guardianSigner).setAssetBoundedPricingEnabled(ETH_ASSET, true); + + const cfg = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfg.minPrice).to.equal(originalEthSpot); + expect(cfg.maxPrice).to.equal(originalEthSpot); + priorTriggerTimestamp = cfg.lastProtectionTriggeredAt; + }); + + it("oracle drop + updateProtectionState mutates state and re-activates protection", async () => { + // 50% drop — well below the ~16.67% triggerThreshold seeded for ETH. + // E2E-2 covered the upward-spike path; this exercises the symmetric downside. + droppedSpot = originalEthSpot.mul(50).div(100); + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, droppedSpot); + + const tx = await dbo.connect(keeperSigner).updateProtectionState(ETH_VTOKEN); + await expect(tx).to.emit(dbo, "ProtectionTriggered"); + + const cfg = await dbo.assetProtectionConfig(ETH_ASSET); + expect(cfg.currentlyUsingProtectedPrice).to.equal(true); + expect(cfg.lastProtectionTriggeredAt).to.be.gt(priorTriggerTimestamp); + // minPrice latches down to the dropped spot; maxPrice stays at originalEthSpot. + expect(cfg.minPrice).to.equal(droppedSpot); + expect(cfg.maxPrice).to.equal(originalEthSpot); + }); + + it("bounded prices reflect the new window — collateral pinned at dropped, debt at original", async () => { + const [collateral, debt] = await dbo.getBoundedPricesView(ETH_VTOKEN); + // collateral = min(spot, minPrice) = min(dropped, dropped) = dropped + expect(collateral).to.equal(droppedSpot); + // debt = max(spot, maxPrice) = max(dropped, original) = original + expect(debt).to.equal(originalEthSpot); + }); + }); + + describe("E2E-5: multi-asset independence", () => { + it("TRX state is unaffected by the ETH protection lifecycle", async () => { + const trxCfg = await dbo.assetProtectionConfig(TRX_UNDERLYING); + expect(trxCfg.currentlyUsingProtectedPrice, "TRX.currentlyUsingProtectedPrice").to.equal(false); + expect(await dbo.isBoundedPricingEnabled(TRX_UNDERLYING), "TRX.isBoundedPricingEnabled").to.equal(true); + }); + + it("TRX bounded prices still pass through to spot — independent of ETH lifecycle", async () => { + const spot: BigNumber = await resilient.getUnderlyingPrice(TRX_VTOKEN); + const [collateral, debt] = await dbo.getBoundedPricesView(TRX_VTOKEN); + expect(collateral, "TRX.collateralPrice").to.equal(spot); + expect(debt, "TRX.debtPrice").to.equal(spot); + }); + }); + }); + + // ──────────────────────────────────────────────────────────────────── + // E2E scenarios — verify the core Comptroller still services the + // standard lending operations after the Diamond + VAIController + // upgrades and the new SetterFacet selector. Uses vETH (collateral) + // and vUSDT (borrow) on the live core pool. The liquidation step + // crashes ETH spot via ChainlinkOracle.setDirectPrice with PIVOT + // disabled on the ResilientOracle so BoundValidator does not reject + // the manipulated price. Wrapped in evm_snapshot/evm_revert. + // ──────────────────────────────────────────────────────────────────── + describe("E2E scenarios — Comptroller core lending operations", () => { + const VUSDT = "0xfD5840Cd36d94D7229439859C0112a4185BC0255"; + const USDT_ASSET = "0x55d398326f99059fF775485246999027B3197955"; + // Venus restricts vToken.liquidateBorrow to this contract; direct EOA calls return UNAUTHORIZED. + const LIQUIDATOR_CONTRACT = "0x0870793286aaDA55D39CE7f82fb2766e8004cF43"; + // ETH whale on BSC — supplies vETH and borrows vUSDT. + const BORROWER = NETWORK_ADDRESSES.bscmainnet.GENERIC_ETH_ACCOUNT; + // Binance hot wallet — holds USDT, used as the liquidator. + const LIQUIDATOR = NETWORK_ADDRESSES.bscmainnet.GENERIC_TEST_USER_ACCOUNT; + const ORACLE_ROLE_PIVOT = 1; + + let snapshotId: string; + let veth: Contract; + let vusdt: Contract; + let eth: Contract; + let usdt: Contract; + let chainlink: Contract; + let resilient: Contract; + let borrowerSigner: Signer; + let liquidatorSigner: Signer; + let timelockSigner: Signer; + let originalEthSpot: BigNumber; + let usdtDecimals: number; + let supplyAmount: BigNumber; + let borrowAmount: BigNumber; + + before(async () => { + snapshotId = await provider.send("evm_snapshot", []); + + timelockSigner = await initMainnetUser(NORMAL_TIMELOCK, ethers.utils.parseEther("1")); + borrowerSigner = await initMainnetUser(BORROWER, ethers.utils.parseEther("1")); + liquidatorSigner = await initMainnetUser(LIQUIDATOR, ethers.utils.parseEther("1")); + + veth = new ethers.Contract(ETH_VTOKEN, VTOKEN_ABI, provider); + vusdt = new ethers.Contract(VUSDT, VTOKEN_ABI, provider); + eth = new ethers.Contract(ETH_ASSET, ERC20_ABI, provider); + usdt = new ethers.Contract(USDT_ASSET, ERC20_ABI, provider); + chainlink = new ethers.Contract(bscmainnet.CHAINLINK_ORACLE, CHAINLINK_ORACLE_ABI, provider); + resilient = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, provider); + + usdtDecimals = await usdt.decimals(); + supplyAmount = ethers.utils.parseEther("1"); + borrowAmount = ethers.utils.parseUnits("100", usdtDecimals); + + // USDT isn't in ASSET_CONFIGS, so the outer `before` did not extend its + // resilient-oracle staleness — the proposal lifecycle mines past its real + // heartbeat and the borrow leg would revert with "invalid resilient oracle price". + await setMaxStalePeriod(resilient, usdt); + + // Lift the USDT borrow cap so the borrow leg is not bounded by it. + await comptroller + .connect(timelockSigner) + ._setMarketBorrowCaps([VUSDT], [ethers.utils.parseUnits("10000000000", usdtDecimals)]); + + // PIVOT must be off for ETH so the crashed Chainlink price flows + // through the ResilientOracle during the liquidation step. + await resilient.connect(timelockSigner).enableOracle(ETH_ASSET, ORACLE_ROLE_PIVOT, false); + + // Pin Chainlink storage to the live ETH spot — ETH is 18 decimals, + // so setDirectPrice value passes through getPrice unchanged. + originalEthSpot = await resilient.getPrice(ETH_ASSET); + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, originalEthSpot); + }); + + after(async () => { + await provider.send("evm_revert", [snapshotId]); + }); + + it("mint: supplying ETH increases the borrower's vETH balance", async () => { + const before = await veth.balanceOf(BORROWER); + await eth.connect(borrowerSigner).approve(ETH_VTOKEN, supplyAmount); + await veth.connect(borrowerSigner).mint(supplyAmount); + expect(await veth.balanceOf(BORROWER)).to.be.gt(before); + }); + + it("borrow: enterMarkets + borrow transfers USDT to the borrower", async () => { + await comptroller.connect(borrowerSigner).enterMarkets([ETH_VTOKEN]); + const before = await usdt.balanceOf(BORROWER); + await vusdt.connect(borrowerSigner).borrow(borrowAmount); + expect(await usdt.balanceOf(BORROWER)).to.equal(before.add(borrowAmount)); + }); + + it("redeem: redeemUnderlying returns ETH to the borrower", async () => { + const redeemAmount = ethers.utils.parseEther("0.1"); + const before = await eth.balanceOf(BORROWER); + await veth.connect(borrowerSigner).redeemUnderlying(redeemAmount); + expect(await eth.balanceOf(BORROWER)).to.equal(before.add(redeemAmount)); + }); + + // Mirrors Compound liquidity math: tokensToDenom = exchangeRate × CF × price / 1e36; + // sumCollateral = tokensToDenom × vTokenBalance / 1e18; sumBorrows = borrowBalance × price / 1e18. + // Returns the expected (sumCollateral − sumBorrows) at the live oracle prices. + const expectedLiquidityDelta = async (): Promise => { + const ONE = ethers.constants.WeiPerEther; + const [, ethVTokenBal, , ethExchangeRate] = await veth.getAccountSnapshot(BORROWER); + const [, , usdtBorrowBal] = await vusdt.getAccountSnapshot(BORROWER); + const ethCF = (await comptroller.markets(ETH_VTOKEN)).collateralFactorMantissa; + const ethPrice = await resilient.getUnderlyingPrice(ETH_VTOKEN); + const usdtPrice = await resilient.getUnderlyingPrice(VUSDT); + const tokensToDenom = ethExchangeRate.mul(ethCF).div(ONE).mul(ethPrice).div(ONE); + const sumCollateral = tokensToDenom.mul(ethVTokenBal).div(ONE); + const sumBorrows = usdtBorrowBal.mul(usdtPrice).div(ONE); + return sumCollateral.sub(sumBorrows); + }; + + // Tolerance: $1 in 1e18 — covers rounding-order differences between this + // computation and the on-chain lens, while staying well under any real-bug delta + // on ~$1500 of liquidity / ~$80 of shortfall. + const LIQUIDITY_TOLERANCE = ethers.utils.parseEther("1"); + + it("pre-crash: getAccountLiquidity matches expected (ComptrollerLens path)", async () => { + const expected = await expectedLiquidityDelta(); + expect(expected).to.be.gt(0); + + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(BORROWER); + expect(err).to.equal(0); + expect(shortfall).to.equal(0); + expect(liquidity).to.be.closeTo(expected, LIQUIDITY_TOLERANCE); + }); + + it("liquidate: ETH price crash puts the borrower into shortfall and liquidator seizes vETH", async () => { + // 1 ETH supply × $2239 × CF ≈ $1500 collateral vs $100 debt — a 10× crash + // still leaves ~$150 of borrow capacity. Crash to 1% of spot to force shortfall. + const crashedSpot = originalEthSpot.div(100); + await chainlink.connect(timelockSigner).setDirectPrice(ETH_ASSET, crashedSpot); + expect(await resilient.getPrice(ETH_ASSET)).to.equal(crashedSpot); + + const expectedDelta = await expectedLiquidityDelta(); + expect(expectedDelta).to.be.lt(0); + + const [err, liquidity, shortfall] = await comptroller.getAccountLiquidity(BORROWER); + expect(err).to.equal(0); + expect(liquidity).to.equal(0); + expect(shortfall).to.be.closeTo(expectedDelta.mul(-1), LIQUIDITY_TOLERANCE); + + const liquidator = new ethers.Contract(LIQUIDATOR_CONTRACT, LIQUIDATOR_ABI, provider); + const repayAmount = ethers.utils.parseUnits("10", usdtDecimals); + // Fund LIQUIDATOR from BORROWER's just-borrowed USDT — at this fork block the + // Binance hot wallet doesn't hold any. + await usdt.connect(borrowerSigner).transfer(LIQUIDATOR, repayAmount); + await usdt.connect(liquidatorSigner).approve(LIQUIDATOR_CONTRACT, repayAmount); + + const liquidatorVethBefore = await veth.balanceOf(LIQUIDATOR); + await expect( + liquidator.connect(liquidatorSigner).liquidateBorrow(VUSDT, BORROWER, repayAmount, ETH_VTOKEN), + ).to.emit(vusdt, "LiquidateBorrow"); + expect(await veth.balanceOf(LIQUIDATOR)).to.be.gt(liquidatorVethBefore); + }); + }); +}); diff --git a/simulations/vip-617/bsctestnet-addendum.ts b/simulations/vip-617/bsctestnet-addendum.ts new file mode 100644 index 000000000..72e0f0f41 --- /dev/null +++ b/simulations/vip-617/bsctestnet-addendum.ts @@ -0,0 +1,213 @@ +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { DEVIATION_BOUNDED_ORACLE } from "../../vips/vip-617/bsctestnet"; +import vip665Addendum, { + NEW_DBO_IMPLEMENTATION, + NEW_SET_TOKEN_CONFIG_SIGS, + OLD_SET_TOKEN_CONFIG_SIGS, + PROXY_ADMIN, + TIMELOCKS, +} from "../../vips/vip-617/bsctestnet-addendum"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import DBO_ABI from "./abi/DeviationBoundedOracle.json"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { ACCESS_CONTROL_MANAGER } = bsctestnet; + +const FORK_BLOCK = 104867823; + +// The currently deployed DBO impl returns the 9-field struct (no `cachingEnabled`). +// The new impl appends `cachingEnabled` as a 10th field. We use this minimal ABI +// to snapshot the original 9 fields pre-upgrade; the post-upgrade comparison +// uses the full 10-field ABI from `abi/DeviationBoundedOracle.json`. +const OLD_DBO_ABI = [ + { + inputs: [{ type: "address", name: "" }], + name: "assetProtectionConfig", + outputs: [ + { type: "uint128", name: "minPrice" }, + { type: "uint128", name: "maxPrice" }, + { type: "bool", name: "currentlyUsingProtectedPrice" }, + { type: "bool", name: "isBoundedPricingEnabled" }, + { type: "uint64", name: "lastProtectionTriggeredAt" }, + { type: "uint64", name: "cooldownPeriod" }, + { type: "address", name: "asset" }, + { type: "uint128", name: "triggerThreshold" }, + { type: "uint128", name: "resetThreshold" }, + ], + stateMutability: "view", + type: "function", + }, +]; + +interface OldConfig { + minPrice: BigNumber; + maxPrice: BigNumber; + currentlyUsingProtectedPrice: boolean; + isBoundedPricingEnabled: boolean; + lastProtectionTriggeredAt: BigNumber; + cooldownPeriod: BigNumber; + asset: string; + triggerThreshold: BigNumber; + resetThreshold: BigNumber; +} + +forking(FORK_BLOCK, async () => { + let dbo: Contract; + let dboOld: Contract; + let proxyAdmin: Contract; + let acm: Contract; + + let oldImpl: string; + let initializedAssets: string[]; + const oldConfigs: Record = {}; + let oldCollateralCacheSlot: string; + let oldDebtCacheSlot: string; + + before(async () => { + dbo = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, DBO_ABI, ethers.provider); + dboOld = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, OLD_DBO_ABI, ethers.provider); + proxyAdmin = new ethers.Contract(PROXY_ADMIN, PROXY_ADMIN_ABI, ethers.provider); + acm = new ethers.Contract(ACCESS_CONTROL_MANAGER, ACM_ABI, ethers.provider); + + oldImpl = await proxyAdmin.getProxyImplementation(DEVIATION_BOUNDED_ORACLE); + initializedAssets = [...(await dbo.getInitializedAssets())]; + + for (const asset of initializedAssets) { + const c = await dboOld.assetProtectionConfig(asset); + oldConfigs[asset] = { + minPrice: c.minPrice, + maxPrice: c.maxPrice, + currentlyUsingProtectedPrice: c.currentlyUsingProtectedPrice, + isBoundedPricingEnabled: c.isBoundedPricingEnabled, + lastProtectionTriggeredAt: c.lastProtectionTriggeredAt, + cooldownPeriod: c.cooldownPeriod, + asset: c.asset, + triggerThreshold: c.triggerThreshold, + resetThreshold: c.resetThreshold, + }; + } + + oldCollateralCacheSlot = await dbo.COLLATERAL_PRICE_CACHE_SLOT(); + oldDebtCacheSlot = await dbo.DEBT_PRICE_CACHE_SLOT(); + }); + + describe("Pre-VIP state", () => { + it("DBO proxy does not yet point to the new implementation", () => { + expect(oldImpl).to.not.equal(NEW_DBO_IMPLEMENTATION); + }); + + it("old (multi-arg) setTokenConfig/setTokenConfigs permissions are still granted to all 3 timelocks", async () => { + for (const sig of OLD_SET_TOKEN_CONFIG_SIGS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should still have permission for old sig ${sig} pre-VIP`, + ).to.equal(true); + } + } + }); + + it("new (struct-based) setTokenConfig/setTokenConfigs permissions are NOT yet granted to any timelock", async () => { + for (const sig of NEW_SET_TOKEN_CONFIG_SIGS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should NOT have permission for new sig ${sig} pre-VIP`, + ).to.equal(false); + } + } + }); + }); + + testVip("VIP-665 Addendum — Upgrade DBO implementation on BNB Chain Testnet", await vip665Addendum(), { + callbackAfterExecution: async txResponse => { + // 2 old sigs × 3 timelocks = 6 revokes + // 2 new sigs × 3 timelocks = 6 grants + await expectEvents(txResponse, [ACM_ABI], ["PermissionRevoked", "PermissionGranted"], [6, 6]); + }, + }); + + describe("Post-VIP state", () => { + it("DBO proxy points to the new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(DEVIATION_BOUNDED_ORACLE)).to.equal(NEW_DBO_IMPLEMENTATION); + }); + + describe("ACM permissions re-aligned to new struct-based signatures", () => { + it("old (multi-arg) setTokenConfig/setTokenConfigs permissions are revoked for all 3 timelocks", async () => { + for (const sig of OLD_SET_TOKEN_CONFIG_SIGS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should NOT have permission for old sig ${sig} post-VIP`, + ).to.equal(false); + } + } + }); + + it("new (struct-based) setTokenConfig/setTokenConfigs permissions are granted to all 3 timelocks", async () => { + for (const sig of NEW_SET_TOKEN_CONFIG_SIGS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should have permission for new sig ${sig} post-VIP`, + ).to.equal(true); + } + } + }); + }); + + describe("Storage layout preserved across implementation upgrade", () => { + it("initialized assets list unchanged", async () => { + const after = [...(await dbo.getInitializedAssets())]; + expect(after).to.deep.equal(initializedAssets); + }); + + it("per-asset token configs unchanged (original 9 fields preserved)", async () => { + for (const asset of initializedAssets) { + const before = oldConfigs[asset]; + const after = await dbo.assetProtectionConfig(asset); + expect(after.minPrice).to.equal(before.minPrice); + expect(after.maxPrice).to.equal(before.maxPrice); + expect(after.currentlyUsingProtectedPrice).to.equal(before.currentlyUsingProtectedPrice); + expect(after.isBoundedPricingEnabled).to.equal(before.isBoundedPricingEnabled); + expect(after.lastProtectionTriggeredAt).to.equal(before.lastProtectionTriggeredAt); + expect(after.cooldownPeriod).to.equal(before.cooldownPeriod); + expect(after.asset).to.equal(before.asset); + expect(after.triggerThreshold).to.equal(before.triggerThreshold); + expect(after.resetThreshold).to.equal(before.resetThreshold); + } + }); + + it("new cachingEnabled field defaults to false for existing assets", async () => { + for (const asset of initializedAssets) { + const after = await dbo.assetProtectionConfig(asset); + expect(after.cachingEnabled).to.equal(false); + } + }); + + it("cache storage slot getters still resolve (cache mechanism present)", async () => { + // The new impl may rebase its namespaced cache slot constants; we only + // require that both getters remain callable and return non-zero values, + // i.e. the cache subsystem is still wired up post-upgrade. + const collateralSlot = await dbo.COLLATERAL_PRICE_CACHE_SLOT(); + const debtSlot = await dbo.DEBT_PRICE_CACHE_SLOT(); + expect(collateralSlot).to.not.equal(ethers.constants.HashZero); + expect(debtSlot).to.not.equal(ethers.constants.HashZero); + expect(collateralSlot).to.not.equal(debtSlot); + // Surface any slot rebase so reviewers can confirm it is intentional. + if (collateralSlot !== oldCollateralCacheSlot || debtSlot !== oldDebtCacheSlot) { + console.log( + ` note: cache slots changed across upgrade (collateral: ${oldCollateralCacheSlot} → ${collateralSlot}, debt: ${oldDebtCacheSlot} → ${debtSlot})`, + ); + } + }); + }); + }); +}); diff --git a/simulations/vip-617/bsctestnet.ts b/simulations/vip-617/bsctestnet.ts new file mode 100644 index 000000000..b85151401 --- /dev/null +++ b/simulations/vip-617/bsctestnet.ts @@ -0,0 +1,343 @@ +import { TransactionResponse } from "@ethersproject/providers"; +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import vip665, { + COMPTROLLER_DBO_SETTER, + COMPTROLLER_LENS, + DBO_GOVERNANCE_FUNCTIONS, + DBO_KEEPER_FUNCTIONS, + DEVIATION_BOUNDED_ORACLE, + EXPECTED_PERMISSION_GRANTED_EVENTS, + TIMELOCKS, + UNITROLLER_IMPLEMENTATION, + VAI_CONTROLLER_IMPL, +} from "../../vips/vip-617/bsctestnet"; +import { cutParams } from "../../vips/vip-617/utils/cut-params-bsctestnet.json"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import DBO_ABI from "./abi/DeviationBoundedOracle.json"; +import DIAMOND_ABI from "./abi/Diamond.json"; +import VAI_UNITROLLER_ABI from "./abi/VAIUnitroller.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { NORMAL_TIMELOCK, GUARDIAN, ACCESS_CONTROL_MANAGER, UNITROLLER, VAI_UNITROLLER } = bsctestnet; + +const FORK_BLOCK = 102810984; + +// Function selector for setDeviationBoundedOracle(address), used to verify the +// new selector is installed on the new SetterFacet after the diamondCut. +const SET_DBO_SELECTOR = ethers.utils.id("setDeviationBoundedOracle(address)").slice(0, 10); + +forking(FORK_BLOCK, async () => { + const provider = ethers.provider; + + let comptroller: Contract; + let acm: Contract; + let dbo: Contract; + let vaiUnitroller: Contract; + + let oldComptrollerLens: string; + let oldVaiImpl: string; + let oldDiamondImpl: string; + let oldFacetAddresses: string[]; + let oldSelectorsByFacet: Record; + + // Storage-layout spot-check snapshots (V1 storage — unchanged through V19). + let oldAdmin: string; + let oldCloseFactorMantissa: BigNumber; + let oldMaxAssets: BigNumber; + + before(async () => { + comptroller = new ethers.Contract(UNITROLLER, COMPTROLLER_ABI, provider); + acm = new ethers.Contract(ACCESS_CONTROL_MANAGER, ACM_ABI, provider); + dbo = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, DBO_ABI, provider); + vaiUnitroller = new ethers.Contract(VAI_UNITROLLER, VAI_UNITROLLER_ABI, provider); + + oldComptrollerLens = await comptroller.comptrollerLens(); + oldVaiImpl = await vaiUnitroller.vaiControllerImplementation(); + oldDiamondImpl = await comptroller.comptrollerImplementation(); + oldFacetAddresses = [...(await comptroller.facetAddresses())]; + + oldSelectorsByFacet = {}; + for (const facet of oldFacetAddresses) { + oldSelectorsByFacet[facet] = [...(await comptroller.facetFunctionSelectors(facet))]; + } + + oldAdmin = await comptroller.admin(); + oldCloseFactorMantissa = await comptroller.closeFactorMantissa(); + oldMaxAssets = await comptroller.maxAssets(); + }); + + // ──────────────────────────────────────────────────────────────────────── + // PRE-VIP STATE — verify each phase's starting condition + // ──────────────────────────────────────────────────────────────────────── + + describe("Pre-VIP state", () => { + describe("Phase 1 — ACM permissions are NOT yet granted", () => { + it("governance setters are not callable by any timelock", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should NOT be allowed to call ${sig} on DBO pre-VIP`, + ).to.equal(false); + } + } + }); + + it("keeper actions are not callable by timelocks or guardian", async () => { + for (const sig of DBO_KEEPER_FUNCTIONS) { + for (const caller of [...TIMELOCKS, GUARDIAN]) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should NOT be allowed to call ${sig} on DBO pre-VIP`, + ).to.equal(false); + } + } + }); + + it("setDeviationBoundedOracle is not callable by any timelock", async () => { + for (const timelock of TIMELOCKS) { + expect(await acm.hasPermission(timelock, UNITROLLER, COMPTROLLER_DBO_SETTER)).to.equal(false); + } + }); + }); + + describe("Phase 2 — Comptroller updates have NOT been applied", () => { + describe("Step 1 — Unitroller implementation not yet swapped", () => { + it("Unitroller does not yet point at the new Diamond implementation", async () => { + expect(oldDiamondImpl).to.not.equal(UNITROLLER_IMPLEMENTATION); + }); + + it("Unitroller has no pending implementation set", async () => { + expect(await comptroller.pendingComptrollerImplementation()).to.equal(ethers.constants.AddressZero); + }); + }); + + describe("Step 2 — new facet selectors are NOT yet installed", () => { + it("setDeviationBoundedOracle selector resolves to the zero address", async () => { + const facet = await comptroller.facetAddress(SET_DBO_SELECTOR); + expect(facet.facetAddress).to.equal(ethers.constants.AddressZero); + }); + }); + + describe("Step 3 — ComptrollerLens is still the old one", () => { + it("current comptrollerLens is NOT the newly deployed one", async () => { + expect(oldComptrollerLens).to.not.equal(COMPTROLLER_LENS); + }); + }); + + describe("Step 4 — VAIController implementation has not been swapped", () => { + it("VaiUnitroller does not yet point at the new implementation", async () => { + expect(oldVaiImpl).to.not.equal(VAI_CONTROLLER_IMPL); + }); + + it("VaiUnitroller has no pending implementation set", async () => { + expect(await vaiUnitroller.pendingVAIControllerImplementation()).to.equal(ethers.constants.AddressZero); + }); + }); + }); + + describe("Phase 3 — Wiring has NOT happened yet", () => { + describe("Step 1 — DBO ownership is pending", () => { + it("owner is still the deployer (not the timelock)", async () => { + expect(await dbo.owner()).to.not.equal(NORMAL_TIMELOCK); + }); + + it("pendingOwner is the normal timelock", async () => { + expect(await dbo.pendingOwner()).to.equal(NORMAL_TIMELOCK); + }); + }); + + describe("Step 2 — DBO is not yet wired on Comptroller", () => { + it("deviationBoundedOracle() reverts — selector not installed pre-cut", async () => { + await expect(comptroller.deviationBoundedOracle()).to.be.reverted; + }); + }); + }); + }); + + // ──────────────────────────────────────────────────────────────────────── + // EXECUTE VIP — and assert emitted events for each phase + // ──────────────────────────────────────────────────────────────────────── + + testVip("VIP-665 DBO Rollout on BNB Chain Testnet", await vip665(), { + callbackAfterExecution: async (txResponse: TransactionResponse) => { + // Phase 1 — PermissionGranted events (see EXPECTED_PERMISSION_GRANTED_EVENTS in vip-665/bsctestnet.ts) + await expectEvents(txResponse, [ACM_ABI], ["PermissionGranted"], [EXPECTED_PERMISSION_GRANTED_EVENTS]); + + // Phase 2 Step 1 + Step 4 — Unitroller and VaiUnitroller impl swaps. + // NewImplementation = 2 (Unitroller + VaiUnitroller) + // NewPendingImplementation = 4 (2 per proxy) + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewImplementation", "NewPendingImplementation"], [2, 4]); + + // Phase 2 Step 2 — DiamondCut + await expectEvents(txResponse, [DIAMOND_ABI], ["DiamondCut"], [1]); + + // Phase 2 Step 3 — NewComptrollerLens + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewComptrollerLens"], [1]); + + // Phase 3 Step 1 — DBO OwnershipTransferred + await expectEvents(txResponse, [DBO_ABI], ["OwnershipTransferred"], [1]); + + // Phase 3 Step 2 — NewDeviationBoundedOracle + await expectEvents(txResponse, [COMPTROLLER_ABI], ["NewDeviationBoundedOracle"], [1]); + }, + }); + + // ──────────────────────────────────────────────────────────────────────── + // POST-VIP STATE — verify each phase and step landed + // ──────────────────────────────────────────────────────────────────────── + + describe("Post-VIP state", () => { + describe("Phase 1 — ACM permissions granted for every target/caller tuple", () => { + it("governance setters callable by 3 timelocks", async () => { + for (const sig of DBO_GOVERNANCE_FUNCTIONS) { + for (const caller of TIMELOCKS) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should be allowed to call ${sig} on DBO`, + ).to.equal(true); + } + } + }); + + it("keeper actions callable by 3 timelocks + Guardian", async () => { + for (const sig of DBO_KEEPER_FUNCTIONS) { + for (const caller of [...TIMELOCKS, GUARDIAN]) { + expect( + await acm.hasPermission(caller, DEVIATION_BOUNDED_ORACLE, sig), + `${caller} should be allowed to call ${sig} on DBO`, + ).to.equal(true); + } + } + }); + + it("setDeviationBoundedOracle callable by all 3 timelocks", async () => { + for (const timelock of TIMELOCKS) { + expect(await acm.hasPermission(timelock, UNITROLLER, COMPTROLLER_DBO_SETTER)).to.equal(true); + } + }); + }); + + describe("Phase 2 — Comptroller updates applied", () => { + describe("Step 1 — Unitroller implementation swapped", () => { + it("Unitroller points at the new Diamond implementation", async () => { + expect(await comptroller.comptrollerImplementation()).to.equal(UNITROLLER_IMPLEMENTATION); + }); + + it("pending implementation slot is cleared", async () => { + expect(await comptroller.pendingComptrollerImplementation()).to.equal(ethers.constants.AddressZero); + }); + }); + + describe("Step 2 — diamondCut applied", () => { + it("every selector in cutParams resolves to its new facet address", async () => { + for (const [facetAddr, , selectors] of cutParams as [string, number, string[]][]) { + for (const sel of selectors) { + expect((await comptroller.facetAddress(sel)).facetAddress).to.equal(facetAddr); + } + } + }); + + it("setDeviationBoundedOracle selector resolves to a non-zero facet", async () => { + const resolved = (await comptroller.facetAddress(SET_DBO_SELECTOR)).facetAddress; + expect(resolved).to.not.equal(ethers.constants.AddressZero); + }); + + it("all old facet addresses have been replaced", async () => { + for (const oldFacet of oldFacetAddresses) { + const selectorsOnOldFacet = await comptroller.facetFunctionSelectors(oldFacet); + expect(selectorsOnOldFacet).to.deep.equal([]); + } + }); + + it("selectors preserve their pre-VIP facet role (only addresses changed)", async () => { + // For each Replace entry, the new facet's selector set must equal some + // old facet's selector set exactly — catching any FacetBase-driven drift + // that would quietly reassign a selector to a different facet role. + const remaining: Record = {}; + for (const [addr, sels] of Object.entries(oldSelectorsByFacet)) { + remaining[addr] = [...sels].sort(); + } + + for (const [newFacet, action, selectors] of cutParams as [string, number, string[]][]) { + if (action !== 1) continue; // Replace only; the new `Add` entry is not expected to match any old facet + const newSels = [...(await comptroller.facetFunctionSelectors(newFacet))].sort(); + // The SetterFacet also has the newly-added selector — strip it before comparing. + const newSelsWithoutAdd = newSels.filter(s => s !== SET_DBO_SELECTOR); + + const match = Object.entries(remaining).find( + ([, oldSels]) => + oldSels.length === newSelsWithoutAdd.length && oldSels.every((s, i) => s === newSelsWithoutAdd[i]), + ); + expect( + match, + `No old facet's selector set matches new facet ${newFacet}. ` + + `new=${JSON.stringify(newSelsWithoutAdd)}. ` + + `Selector has drifted between facet roles — check cut-params vs. pre-VIP facet mapping.`, + ).to.not.be.undefined; + + delete remaining[match![0]]; + expect(selectors.length).to.be.greaterThan(0); + } + }); + }); + + describe("Step 3 — ComptrollerLens swapped", () => { + it("comptrollerLens points at the new contract", async () => { + expect(await comptroller.comptrollerLens()).to.equal(COMPTROLLER_LENS); + }); + }); + + describe("Step 4 — VAIController implementation swapped", () => { + it("VaiUnitroller points at the new implementation", async () => { + expect(await vaiUnitroller.vaiControllerImplementation()).to.equal(VAI_CONTROLLER_IMPL); + }); + + it("pending implementation slot is cleared", async () => { + expect(await vaiUnitroller.pendingVAIControllerImplementation()).to.equal(ethers.constants.AddressZero); + }); + }); + + describe("Storage layout preserved across Diamond upgrade", () => { + // Spot-check V1 storage slots (declared before V19's `deviationBoundedOracle` + // addition) to catch any accidental slot shift in the new implementation. + it("admin slot unchanged", async () => { + expect(await comptroller.admin()).to.equal(oldAdmin); + }); + + it("closeFactorMantissa slot unchanged", async () => { + expect(await comptroller.closeFactorMantissa()).to.equal(oldCloseFactorMantissa); + }); + + it("maxAssets slot unchanged", async () => { + expect(await comptroller.maxAssets()).to.equal(oldMaxAssets); + }); + }); + }); + + describe("Phase 3 — Wiring complete", () => { + describe("Step 1 — DBO ownership accepted", () => { + it("owner is the normal timelock", async () => { + expect(await dbo.owner()).to.equal(NORMAL_TIMELOCK); + }); + + it("pendingOwner is cleared", async () => { + expect(await dbo.pendingOwner()).to.equal(ethers.constants.AddressZero); + }); + }); + + describe("Step 2 — DBO wired on Comptroller", () => { + it("Comptroller.deviationBoundedOracle() returns the deployed DBO", async () => { + expect(await comptroller.deviationBoundedOracle()).to.equal(DEVIATION_BOUNDED_ORACLE); + }); + }); + }); + }); +}); diff --git a/src/utils.ts b/src/utils.ts index eee4e3da3..8348c1e6f 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,6 +1,5 @@ import { JsonFragment, defaultAbiCoder } from "@ethersproject/abi"; import { JsonRpcProvider, TransactionResponse } from "@ethersproject/providers"; -import { mine } from "@nomicfoundation/hardhat-network-helpers"; import { NumberLike } from "@nomicfoundation/hardhat-network-helpers/dist/src/types"; import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; import { expect } from "chai"; @@ -370,77 +369,67 @@ export const getForkedNetworkAddress = (contractName: string) => { throw new Error(`${contractName} address not found on forked ${FORKED_NETWORK}`); }; -export const setMaxStalePeriod = async ( - resilientOracle: Contract, - underlyingAsset: Contract, - maxStalePeriodInSeconds: number = 31536000 /* 1 year */, -) => { - let binanceOracle: string = ethers.constants.AddressZero; - let chainlinkOracle: string = ethers.constants.AddressZero; - let redstoneOracle: string = ethers.constants.AddressZero; +const NORMAL_TIMELOCK_NETWORKS = [ + "bscmainnet", + "bsctestnet", + "arbitrumone", + "arbitrumsepolia", + "ethereum", + "sepolia", + "opbnbmainnet", + "opbnbtestnet", + "opmainnet", + "opsepolia", + "zksyncmainnet", + "zksyncsepolia", + "basemainnet", + "basesepolia", +]; +const tryGetForkedNetworkAddress = (name: string): string => { try { - binanceOracle = getForkedNetworkAddress("BINANCE_ORACLE"); + return getForkedNetworkAddress(name); } catch { - console.log(`Binance Oracle is not available on ${FORKED_NETWORK}`); + return ethers.constants.AddressZero; } +}; - try { - chainlinkOracle = getForkedNetworkAddress("CHAINLINK_ORACLE"); - } catch { - console.log(`Chainlink Oracle is not available on ${FORKED_NETWORK}`); - } +export const setMaxStalePeriod = async ( + resilientOracle: Contract, + underlyingAsset: Contract, + maxStalePeriodInSeconds: number = 31536000 /* 1 year */, +) => { + const knownOracles = { + binance: tryGetForkedNetworkAddress("BINANCE_ORACLE"), + chainlink: tryGetForkedNetworkAddress("CHAINLINK_ORACLE"), + redstone: tryGetForkedNetworkAddress("REDSTONE_ORACLE"), + }; - try { - redstoneOracle = getForkedNetworkAddress("REDSTONE_ORACLE"); - } catch { - console.log(`Redstone Oracle is not available on ${FORKED_NETWORK}`); - } + const adminKey = NORMAL_TIMELOCK_NETWORKS.includes(FORKED_NETWORK ?? "") ? "NORMAL_TIMELOCK" : "GUARDIAN"; + const admin = getForkedNetworkAddress(adminKey); - const normalTimelock = - FORKED_NETWORK == "bscmainnet" || - FORKED_NETWORK == "bsctestnet" || - FORKED_NETWORK == "arbitrumone" || - FORKED_NETWORK == "arbitrumsepolia" || - FORKED_NETWORK == "ethereum" || - FORKED_NETWORK == "sepolia" || - FORKED_NETWORK == "opbnbmainnet" || - FORKED_NETWORK == "opbnbtestnet" || - FORKED_NETWORK == "opmainnet" || - FORKED_NETWORK == "opsepolia" || - FORKED_NETWORK == "zksyncmainnet" || - FORKED_NETWORK == "zksyncsepolia" || - FORKED_NETWORK == "basemainnet" || - FORKED_NETWORK == "basesepolia" - ? getForkedNetworkAddress("NORMAL_TIMELOCK") - : getForkedNetworkAddress("GUARDIAN"); const tokenConfig: TokenConfig = await resilientOracle.getTokenConfig(underlyingAsset.address); - if (tokenConfig.asset !== ethers.constants.AddressZero) { - const mainOracle = tokenConfig.oracles[0]; - if (mainOracle === binanceOracle) { - const symbol = await underlyingAsset.symbol(); - await setMaxStalePeriodInBinanceOracle(binanceOracle, symbol, maxStalePeriodInSeconds); - } else if (mainOracle === chainlinkOracle || mainOracle === redstoneOracle) { + if (tokenConfig.asset === ethers.constants.AddressZero) return; + + for (let i = 0; i < tokenConfig.oracles.length; i++) { + const oracle = tokenConfig.oracles[i]; + const enabled = tokenConfig.enableFlagsForOracles[i]; + if (!enabled || oracle === ethers.constants.AddressZero) continue; + + if (oracle === knownOracles.binance) { + const symbol = + underlyingAsset.address.toLowerCase() === ORACLE_BNB.toLowerCase() ? "BNB" : await underlyingAsset.symbol(); + await setMaxStalePeriodInBinanceOracle(oracle, symbol, maxStalePeriodInSeconds); + } else if (oracle === knownOracles.chainlink || oracle === knownOracles.redstone) { await setMaxStalePeriodInChainlinkOracle( - mainOracle, + oracle, underlyingAsset.address, ethers.constants.AddressZero, - normalTimelock, + admin, maxStalePeriodInSeconds, ); - - if (underlyingAsset.address === ORACLE_BNB) { - await setMaxStalePeriodInChainlinkOracle( - tokenConfig.oracles[1], - underlyingAsset.address, - ethers.constants.AddressZero, - normalTimelock, - maxStalePeriodInSeconds, - ); - } } } - await mine(100); }; export const setMaxStalePeriodForAllAssets = async (resilientOracle: Contract, assets: Contract[]): Promise => { @@ -449,6 +438,37 @@ export const setMaxStalePeriodForAllAssets = async (resilientOracle: Contract, a } }; +// Fork-only escape hatch: destructively rewrites the asset's token config and pins the price via Redstone — use only when setMaxStalePeriod is insufficient (e.g. main feed broken or unrecognizable oracle type). +export const pinResilientOraclePriceViaRedstone = async (resilientOracle: Contract, asset: string): Promise => { + const currentPrice: BigNumber = await resilientOracle.getPrice(asset); + + const redstoneOracleAddr = getForkedNetworkAddress("REDSTONE_ORACLE"); + const adminKey = NORMAL_TIMELOCK_NETWORKS.includes(FORKED_NETWORK ?? "") ? "NORMAL_TIMELOCK" : "GUARDIAN"; + const admin = await initMainnetUser(getForkedNetworkAddress(adminKey), ethers.utils.parseEther("1")); + + const tokenConfig: Record = { + asset, + oracles: [redstoneOracleAddr, ethers.constants.AddressZero, ethers.constants.AddressZero], + enableFlagsForOracles: [true, false, false], + }; + // Newer ResilientOracle adds a cachingEnabled flag — include it only when the ABI declares it. + const setTokenConfigInput = resilientOracle.interface.getFunction("setTokenConfig").inputs[0]; + if (setTokenConfigInput.components?.some(c => c.name === "cachingEnabled")) { + tokenConfig.cachingEnabled = false; + } + await resilientOracle.connect(admin).setTokenConfig(tokenConfig); + + const tokenDecimals: number = + asset.toLowerCase() === ORACLE_BNB.toLowerCase() + ? 18 + : await new ethers.Contract(asset, ["function decimals() view returns (uint8)"], ethers.provider).decimals(); + const decimalDelta = 18 - tokenDecimals; + const storedPrice = decimalDelta > 0 ? currentPrice.div(parseUnits("1", decimalDelta)) : currentPrice; + + const redstoneOracle = new ethers.Contract(redstoneOracleAddr, CHAINLINK_ORACLE_ABI, ethers.provider); + await redstoneOracle.connect(admin).setDirectPrice(asset, storedPrice); +}; + export const expectEvents = async ( txResponse: TransactionResponse, abis: (string | JsonFragment[])[], diff --git a/vips/vip-617/bscmainnet.ts b/vips/vip-617/bscmainnet.ts new file mode 100644 index 000000000..4afefbba0 --- /dev/null +++ b/vips/vip-617/bscmainnet.ts @@ -0,0 +1,250 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +import { assetConfigs } from "./utils/asset-configs-bscmainnet.json"; +import { cutParams } from "./utils/cut-params-bscmainnet.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; +const { + NORMAL_TIMELOCK, + FAST_TRACK_TIMELOCK, + CRITICAL_TIMELOCK, + GUARDIAN, + ACCESS_CONTROL_MANAGER, + UNITROLLER, + VAI_UNITROLLER, +} = bscmainnet; + +// ────────────────────────────────────────────────────────────────────────── +// Newly deployed addresses +// ────────────────────────────────────────────────────────────────────────── + +export const DEVIATION_BOUNDED_ORACLE = "0xc79Cb7efEBd121DC4B39eA141C214606595D665A"; +export const COMPTROLLER_LENS = "0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8"; +export const VAI_CONTROLLER_IMPL = "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56"; +export const UNITROLLER_IMPLEMENTATION = "0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08"; +export const KEEPER = "0xa44eb88198a7a94dc6d2507bc0e5a216c2410d79"; + +// ────────────────────────────────────────────────────────────────────────── +// ACM-gated function signatures — DeviationBoundedOracle +// ────────────────────────────────────────────────────────────────────────── + +// Granted to all 3 timelocks +export const DBO_GOVERNANCE_FUNCTIONS_3TL = [ + "setTokenConfig((address,uint64,uint256,uint256,bool,bool))", + "setTokenConfigs((address,uint64,uint256,uint256,bool,bool)[])", + "setCooldownPeriod(address,uint64)", + "setThresholds(address,uint256,uint256)", +]; + +// Granted to all 3 timelocks + Guardian +export const DBO_GOVERNANCE_FUNCTIONS_3TL_GUARDIAN = [ + "setAssetBoundedPricingEnabled(address,bool)", + "setCachingEnabled(address,bool)", +]; + +// Granted to all 3 timelocks + Guardian + Keeper +export const DBO_KEEPER_FUNCTIONS = [ + "updateMinPrice(address,uint128)", + "updateMaxPrice(address,uint128)", + "exitProtectionMode(address)", + "syncPriceBoundsAndProtections((address,uint8,uint256)[])", +]; + +export const COMPTROLLER_DBO_SETTER = "setDeviationBoundedOracle(address)"; + +export const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; +export const TIMELOCKS_AND_GUARDIAN = [...TIMELOCKS, GUARDIAN]; +export const KEEPER_CALLERS = [...TIMELOCKS_AND_GUARDIAN, KEEPER]; + +// ────────────────────────────────────────────────────────────────────────── +// ACMCommandsAggregator — batches all 42 ACM grants into 4 commands +// (populate → grant admin role → execute → revoke admin role). +// Audit: governance-contracts/audits/118_ACMCommandsAggregator_certik_20241007.pdf +// ────────────────────────────────────────────────────────────────────────── + +export const BSC_ACM_AGGREGATOR = "0x8b443Ea6726E56DF4C4F62f80F0556bB9B2a7c64"; +export const DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000"; + +// Index assigned to the batch pushed by this VIP. +export const GRANT_PERMISSIONS_INDEX = 1; + +type AcmTuple = [string, string, string]; // (contractAddress, functionSig, account) + +const buildAcmGrants = (target: string, signatures: string[], callers: string[]): AcmTuple[] => + signatures.flatMap(signature => callers.map(caller => [target, signature, caller] as AcmTuple)); + +export const ACM_GRANTS: AcmTuple[] = [ + // DBO governance setters → 3 timelocks (12) + ...buildAcmGrants(DEVIATION_BOUNDED_ORACLE, DBO_GOVERNANCE_FUNCTIONS_3TL, TIMELOCKS), + // DBO 3TL+Guardian setters → 3 timelocks + Guardian ( 8) + ...buildAcmGrants(DEVIATION_BOUNDED_ORACLE, DBO_GOVERNANCE_FUNCTIONS_3TL_GUARDIAN, TIMELOCKS_AND_GUARDIAN), + // DBO keeper actions → 3 timelocks + Guardian + K (20) + ...buildAcmGrants(DEVIATION_BOUNDED_ORACLE, DBO_KEEPER_FUNCTIONS, KEEPER_CALLERS), + // Comptroller setDBO → Normal + Guardian ( 2) + ...buildAcmGrants(UNITROLLER, [COMPTROLLER_DBO_SETTER], [NORMAL_TIMELOCK, GUARDIAN]), +]; + +export type AssetConfig = { + name: string; + asset: string; + vToken: string; + cooldownPeriod: number; + triggerThreshold: string; + resetThreshold: string; + isBoundedPricingEnabled: boolean; + cachingEnabled: boolean; +}; + +export const ASSET_CONFIGS: AssetConfig[] = assetConfigs as AssetConfig[]; + +export const vip617 = () => { + const meta = { + version: "v2", + title: "VIP-617 [BNB Chain] Oracle Dynamic Protection Mode", + description: `#### Summary + +Deploys the new DeviationBoundedOracle (DBO) on BNB Chain mainnet and upgrades the Core Pool Comptroller (Diamond), VAIController, and ComptrollerLens to integrate it. The DBO wraps the existing ResilientOracle with a per-market rolling 15-minute min/max price window, returning protected (min(spot, windowMin), max(spot, windowMax)) pricing on the borrow path when spot deviates beyond the per-market threshold. Phase 1 ships DBO inactive for 23 of 24 assets and active only for **TRX** as a low-liquidity pilot — Phase 2 (separate future VIP) will activate the remaining assets after the keeper and parameters are validated. + +#### Description + +This VIP performs a one-shot deployment of the DBO infrastructure plus the Comptroller and VAIController upgrades required to integrate it. The Comptroller upgrade routes borrow-path pricing through DBO; the liquidation path is unchanged and continues to use the existing ResilientOracle spot price. ACM permissions are granted in a single batch via ACMCommandsAggregator (42 grants total), adding a Keeper role and Guardian-callable governance setters on top of the testnet permission set. Per-asset configs are seeded in step 13: 23 assets with isBoundedPricingEnabled = false (DBO returns (spot, spot) → no behavioural change), TRX with isBoundedPricingEnabled = true (live protection active). + +For full design details and the threshold worked example, see the PR: [VenusProtocol/vips#697](https://github.com/VenusProtocol/vips/pull/697). + +#### Actions + +This VIP performs the following 13 actions on BNB Chain: + +1. **ACMCommandsAggregator: push permission batch** — load the 42 grants for the Keeper role and Guardian-callable governance setters. +2. **Grant aggregator DEFAULT_ADMIN_ROLE** on the AccessControlManager so it can execute the grants in step 3. +3. **Execute the batched permission grants** via ACMCommandsAggregator. +4. **Revoke DEFAULT_ADMIN_ROLE** from the aggregator after execution. +5. **Upgrade Unitroller implementation** to the new Diamond-based implementation (0x82cA18785BBbacBeD1C4f482921E2B2E989D8C08). +6. **Set the new Unitroller implementation** on the Comptroller proxy. +7. **diamondCut** — apply the facet cut from vips/vip-617/utils/cut-params-bscmainnet.json. +8. **Wire new ComptrollerLens** (0x75A71Ad878f6f24616A2AE21d046C0C8E72f67F8) on the Comptroller. +9. **Upgrade VAIController implementation** to 0x8A7d8589A597619A7842d3BC284b9a5a276FaE56. +10. **Set the new VAIController implementation** on the VAIUnitroller. +11. **Accept ownership** of the deployed DeviationBoundedOracle (0xc79Cb7efEBd121DC4B39eA141C214606595D665A) by calling acceptOwnership(). +12. **Wire DBO into Comptroller** — set the DBO address as the borrow-path price source. +13. **Seed per-asset configs** via setTokenConfigs on DBO with 24 entries from vips/vip-617/utils/asset-configs-bscmainnet.json — 23 with isBoundedPricingEnabled = false, TRX with isBoundedPricingEnabled = true. + +#### Deployed contracts (populated prior to proposal) + +- **DeviationBoundedOracle** (proxy): ${DEVIATION_BOUNDED_ORACLE} +- **ComptrollerLens**: ${COMPTROLLER_LENS} +- **VAIController implementation**: ${VAI_CONTROLLER_IMPL} +- **Unitroller implementation (new Diamond)**: ${UNITROLLER_IMPLEMENTATION} +- **Keeper**: ${KEEPER} +- **Unitroller**: ${UNITROLLER} +- **VaiUnitroller**: ${VAI_UNITROLLER} +`, + forDescription: "I agree that Venus Protocol should proceed with this proposal", + againstDescription: "I do not think that Venus Protocol should proceed with this proposal", + abstainDescription: "I am indifferent to whether Venus Protocol proceeds or not", + }; + + return makeProposal( + [ + // Step 1 — ACM permissions (42 grants) via ACMCommandsAggregator + // 1.1. Push the batch of grants into the aggregator + // 1.2. Grant the aggregator DEFAULT_ADMIN_ROLE on ACM + // 1.3. Execute the batch (aggregator calls giveCallPermission for each grant) + // 1.4. Revoke DEFAULT_ADMIN_ROLE from the aggregator + { + target: BSC_ACM_AGGREGATOR, + signature: "addGrantPermissions((address,string,address)[])", + params: [ACM_GRANTS], + }, + { + target: ACCESS_CONTROL_MANAGER, + signature: "grantRole(bytes32,address)", + params: [DEFAULT_ADMIN_ROLE, BSC_ACM_AGGREGATOR], + }, + { + target: BSC_ACM_AGGREGATOR, + signature: "executeGrantPermissions(uint256)", + params: [GRANT_PERMISSIONS_INDEX], + }, + { + target: ACCESS_CONTROL_MANAGER, + signature: "revokeRole(bytes32,address)", + params: [DEFAULT_ADMIN_ROLE, BSC_ACM_AGGREGATOR], + }, + + // Step 2 — Unitroller implementation upgrade + { + target: UNITROLLER, + signature: "_setPendingImplementation(address)", + params: [UNITROLLER_IMPLEMENTATION], + }, + { + target: UNITROLLER_IMPLEMENTATION, + signature: "_become(address)", + params: [UNITROLLER], + }, + + // Step 3 — diamondCut: 5 facets replaced + new `setDeviationBoundedOracle` selector added + { + target: UNITROLLER, + signature: "diamondCut((address,uint8,bytes4[])[])", + params: [cutParams], + }, + + // Step 4 — Wire new ComptrollerLens (admin-gated; timelock is Unitroller admin) + { + target: UNITROLLER, + signature: "_setComptrollerLens(address)", + params: [COMPTROLLER_LENS], + }, + + // Step 5 — VAIController implementation upgrade + { + target: VAI_UNITROLLER, + signature: "_setPendingImplementation(address)", + params: [VAI_CONTROLLER_IMPL], + }, + { + target: VAI_CONTROLLER_IMPL, + signature: "_become(address)", + params: [VAI_UNITROLLER], + }, + + // Step 6 — Accept DBO ownership (Ownable2Step handshake) + { + target: DEVIATION_BOUNDED_ORACLE, + signature: "acceptOwnership()", + params: [], + }, + + // Step 7 — Wire DBO into Comptroller (uses ACM permission granted in Step 1.4) + { + target: UNITROLLER, + signature: "setDeviationBoundedOracle(address)", + params: [DEVIATION_BOUNDED_ORACLE], + }, + + // Step 8 — Seed per-asset configs + { + target: DEVIATION_BOUNDED_ORACLE, + signature: "setTokenConfigs((address,uint64,uint256,uint256,bool,bool)[])", + params: [ + ASSET_CONFIGS.map(c => [ + c.asset, + c.cooldownPeriod, + c.triggerThreshold, + c.resetThreshold, + c.isBoundedPricingEnabled, + c.cachingEnabled, + ]), + ], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip617; diff --git a/vips/vip-617/bsctestnet-addendum.ts b/vips/vip-617/bsctestnet-addendum.ts new file mode 100644 index 000000000..9d45bdc25 --- /dev/null +++ b/vips/vip-617/bsctestnet-addendum.ts @@ -0,0 +1,82 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +import { DEVIATION_BOUNDED_ORACLE } from "./bsctestnet"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, ACCESS_CONTROL_MANAGER } = bsctestnet; + +// DBO proxy admin on BSC Testnet — owned by NormalTimelock. +export const PROXY_ADMIN = "0xef480a5654b231ff7d80A0681F938f3Db71a6Ca6"; + +// New DBO implementation to install behind the proxy. +export const NEW_DBO_IMPLEMENTATION = "0x90c9756446ebA9E1762811c239Fe10029019e35e"; + +export const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; + +// Old (multi-arg) setTokenConfig signatures granted by VIP-665 — to be revoked. +export const OLD_SET_TOKEN_CONFIG_SIGS = [ + "setTokenConfig(address,uint64,uint256,uint256,bool)", + "setTokenConfigs(address[],uint64[],uint256[],uint256[],bool[])", +]; + +// New (struct-based) setTokenConfig signatures introduced by the new DBO impl. +export const NEW_SET_TOKEN_CONFIG_SIGS = [ + "setTokenConfig((address,uint64,uint256,uint256,bool,bool))", + "setTokenConfigs((address,uint64,uint256,uint256,bool,bool)[])", +]; + +export const vip665Addendum = () => { + const meta = { + version: "v2", + title: "VIP-665 Addendum [BNB Chain Testnet] Upgrade DeviationBoundedOracle implementation", + description: `#### Summary + +If passed, this VIP will upgrade the **DeviationBoundedOracle (DBO)** logic contract behind the proxy at \`${DEVIATION_BOUNDED_ORACLE}\` to a new implementation at \`${NEW_DBO_IMPLEMENTATION}\`, and re-align the ACM permissions for \`setTokenConfig\` / \`setTokenConfigs\` to match the new struct-based function signatures exposed by the new implementation. + +The upgrade is storage-layout-compatible: existing per-asset token configs (price bounds, thresholds, cooldown, caching state) and the cache storage slots used by \`getBoundedCollateralPrice\` / \`getBoundedDebtPrice\` are preserved. No per-asset configuration is changed by this proposal. + +#### Action + +1. Call \`upgrade(${DEVIATION_BOUNDED_ORACLE}, ${NEW_DBO_IMPLEMENTATION})\` on the proxy admin at \`${PROXY_ADMIN}\`. +2. Revoke the previously-granted ACM permissions for the old multi-arg \`setTokenConfig(address,uint64,uint256,uint256,bool)\` and \`setTokenConfigs(address[],uint64[],uint256[],uint256[],bool[])\` for the 3 timelocks. +3. Grant ACM permissions for the new struct-based \`setTokenConfig((address,uint64,uint256,uint256,bool,bool))\` and \`setTokenConfigs((address,uint64,uint256,uint256,bool,bool)[])\` to the 3 timelocks.`, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // Step 1 — Upgrade DBO implementation + { + target: PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [DEVIATION_BOUNDED_ORACLE, NEW_DBO_IMPLEMENTATION], + }, + + // Step 2 — Revoke old (multi-arg) setTokenConfig / setTokenConfigs permissions for 3 timelocks + ...OLD_SET_TOKEN_CONFIG_SIGS.flatMap(sig => + TIMELOCKS.map(caller => ({ + target: ACCESS_CONTROL_MANAGER, + signature: "revokeCallPermission(address,string,address)", + params: [DEVIATION_BOUNDED_ORACLE, sig, caller], + })), + ), + + // Step 3 — Grant new (struct-based) setTokenConfig / setTokenConfigs permissions for 3 timelocks + ...NEW_SET_TOKEN_CONFIG_SIGS.flatMap(sig => + TIMELOCKS.map(caller => ({ + target: ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [DEVIATION_BOUNDED_ORACLE, sig, caller], + })), + ), + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip665Addendum; diff --git a/vips/vip-617/bsctestnet.ts b/vips/vip-617/bsctestnet.ts new file mode 100644 index 000000000..946f5ddde --- /dev/null +++ b/vips/vip-617/bsctestnet.ts @@ -0,0 +1,203 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +import { cutParams } from "./utils/cut-params-bsctestnet.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { + NORMAL_TIMELOCK, + FAST_TRACK_TIMELOCK, + CRITICAL_TIMELOCK, + GUARDIAN, + ACCESS_CONTROL_MANAGER, + UNITROLLER, + VAI_UNITROLLER, +} = bsctestnet; + +// ────────────────────────────────────────────────────────────────────────── +// Newly deployed addresses. + +export const DEVIATION_BOUNDED_ORACLE = "0xE0dafC97895B3c98d3B96D3f8739AaC73166beB8"; +export const COMPTROLLER_LENS = "0xdBD0992dEd0a1EC14CE0532e60ea023F79372eD9"; +export const VAI_CONTROLLER_IMPL = "0xd2848305b0ee7646C930240D79549D50d6Ed024F"; +export const UNITROLLER_IMPLEMENTATION = "0xf00Ba2930E43C96719Ca40c8B5a48F4c9A004c52"; + +// ────────────────────────────────────────────────────────────────────────── +// ACM-gated function signatures — DeviationBoundedOracle +// ────────────────────────────────────────────────────────────────────────── + +export const DBO_GOVERNANCE_FUNCTIONS = [ + "setTokenConfig(address,uint64,uint256,uint256,bool)", + "setTokenConfigs(address[],uint64[],uint256[],uint256[],bool[])", + "setCooldownPeriod(address,uint64)", + "setThresholds(address,uint256,uint256)", + "setAssetBoundedPricingEnabled(address,bool)", +]; + +export const DBO_KEEPER_FUNCTIONS = [ + "updateMinPrice(address,uint128)", + "updateMaxPrice(address,uint128)", + "exitProtectionMode(address)", +]; + +export const COMPTROLLER_DBO_SETTER = "setDeviationBoundedOracle(address)"; + +export const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; + +// Expected event counts for post-VIP verification. +// Phase 1: 15 (governance × 3 timelocks) + 12 (keeper × [3 timelocks + Guardian]) + 3 (comptroller setter × 3 timelocks) = 30 +export const EXPECTED_PERMISSION_GRANTED_EVENTS = 30; + +export const vip665 = () => { + const meta = { + version: "v2", + title: "VIP-665 [BNB Chain Testnet] Deploy and wire the DeviationBoundedOracle into the Core Comptroller", + description: `#### Summary + +If passed, this VIP will roll out the new **DeviationBoundedOracle (DBO)** on BNB Chain Testnet and wire it into the Core Pool Comptroller so that CF-path pricing is protected against short-term price manipulation on low-liquidity collateral tokens. + +The DBO maintains a per-market rolling min/max price window and, when the spot price deviates beyond a configured threshold, values collateral at \`min(spot, windowMin)\` and debt at \`max(spot, windowMax)\`. Per-asset configuration is intentionally excluded from this proposal — it will follow in a separate VIP once per-asset thresholds and cooldown periods are finalized. + +#### Deployed contracts (populated prior to proposal) + +- **DeviationBoundedOracle** (proxy): ${DEVIATION_BOUNDED_ORACLE} +- **ComptrollerLens**: ${COMPTROLLER_LENS} +- **VAIController implementation**: ${VAI_CONTROLLER_IMPL} +- **Unitroller implementation (new Diamond)**: ${UNITROLLER_IMPLEMENTATION} +- **Unitroller**: ${UNITROLLER} +- **VaiUnitroller**: ${VAI_UNITROLLER} + +#### Actions + +**Phase 1 — ACM permissions (30 grants)** + +| Step | Target | Signatures (count) | Callers | Grants | +|------|------------------------|----------------------------------------|-------------------------|--------| +| 1 | DeviationBoundedOracle | 5 governance setters | 3 timelocks | 15 | +| 2 | DeviationBoundedOracle | 3 keeper actions | 3 timelocks + Guardian | 12 | +| 3 | Unitroller | \`setDeviationBoundedOracle(address)\` | 3 timelocks | 3 | + +**Phase 2 — Comptroller updates** + +- **Step 1 — Unitroller implementation upgrade.** The Unitroller proxy is repointed at the freshly deployed \`Unitroller_Implementation\` (Diamond) that inherits the new \`ComptrollerV19Storage\`. Uses the classic \`_setPendingImplementation\` + \`_become\` handshake. Must land before \`diamondCut\` so the new Diamond's cut logic processes the facet installation. +- **Step 2 — Comptroller facet upgrade (\`diamondCut\`).** Installs the five upgraded facets (PolicyFacet, SetterFacet, MarketFacet, RewardFacet, FlashLoanFacet). The new \`setDeviationBoundedOracle(address)\` selector is added to the new SetterFacet; every other existing selector on the five facets is replaced to point at its new facet address, preserving the pre-VIP selector → facet-role assignment exactly. +- **Step 3 — Wire the new ComptrollerLens.** The new \`ComptrollerLens\` uses DBO-bounded prices on the CF path; it is installed via the admin-gated \`_setComptrollerLens\` setter. +- **Step 4 — VAIController implementation upgrade.** \`VAIController.mintVAI\` and \`getMintableVAI\` now read \`comptroller.deviationBoundedOracle()\`, so the logic contract behind the \`VaiUnitroller\` proxy is upgraded via \`_setPendingImplementation\` + \`_become\`. + +**Phase 3 — Wiring** + +- **Step 1 — Accept DBO ownership.** The deployment script calls \`transferOwnership(NORMAL_TIMELOCK)\`; this step completes the Ownable2Step handshake with \`acceptOwnership()\`. +- **Step 2 — Wire the DBO into the Comptroller.** Calls \`setDeviationBoundedOracle\` on the Unitroller to set the V19 storage slot consumed by the upgraded facets and VAIController. Uses the ACM permission granted in Phase 1 Step 3. +`, + forDescription: "I agree that Venus Protocol should proceed with this proposal", + againstDescription: "I do not think that Venus Protocol should proceed with this proposal", + abstainDescription: "I am indifferent to whether Venus Protocol proceeds or not", + }; + + return makeProposal( + [ + // ────────────────────────────────────────────────────────────────── + // PHASE 1 — ACM permissions (30 grants) + // Step 1. DBO governance setters → 3 timelocks (15) + // Step 2. DBO keeper actions → 3 timelocks + Guardian (12) + // Step 3. Comptroller DBO setter → 3 timelocks (3) + // ────────────────────────────────────────────────────────────────── + + // Step 1 — DBO governance setters for 3 timelocks + ...DBO_GOVERNANCE_FUNCTIONS.flatMap(sig => + TIMELOCKS.map(caller => ({ + target: ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [DEVIATION_BOUNDED_ORACLE, sig, caller], + })), + ), + + // Step 2 — DBO keeper actions for 3 timelocks + Guardian + ...DBO_KEEPER_FUNCTIONS.flatMap(sig => + [...TIMELOCKS, GUARDIAN].map(caller => ({ + target: ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [DEVIATION_BOUNDED_ORACLE, sig, caller], + })), + ), + + // Step 3 — Comptroller setDeviationBoundedOracle for 3 timelocks + ...TIMELOCKS.map(timelock => ({ + target: ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [UNITROLLER, COMPTROLLER_DBO_SETTER, timelock], + })), + + // ────────────────────────────────────────────────────────────────── + // PHASE 2 — Comptroller updates + // Step 1. Unitroller implementation upgrade (new Diamond) + // Step 2. diamondCut (5 facets + new DBO setter) + // Step 3. Wire new ComptrollerLens + // Step 4. VAIController implementation upgrade + // ────────────────────────────────────────────────────────────────── + + // Step 1 — Unitroller implementation upgrade + { + target: UNITROLLER, + signature: "_setPendingImplementation(address)", + params: [UNITROLLER_IMPLEMENTATION], + }, + { + target: UNITROLLER_IMPLEMENTATION, + signature: "_become(address)", + params: [UNITROLLER], + }, + + // Step 2 — diamondCut: 5 facets replaced + new `setDeviationBoundedOracle` selector added + { + target: UNITROLLER, + signature: "diamondCut((address,uint8,bytes4[])[])", + params: [cutParams], + }, + + // Step 3 — Wire new ComptrollerLens (admin-gated; timelock is Unitroller admin) + { + target: UNITROLLER, + signature: "_setComptrollerLens(address)", + params: [COMPTROLLER_LENS], + }, + + // Step 4 — VAIController implementation upgrade + { + target: VAI_UNITROLLER, + signature: "_setPendingImplementation(address)", + params: [VAI_CONTROLLER_IMPL], + }, + { + target: VAI_CONTROLLER_IMPL, + signature: "_become(address)", + params: [VAI_UNITROLLER], + }, + + // ────────────────────────────────────────────────────────────────── + // PHASE 3 — Wiring + // Step 1. Accept DBO ownership (Ownable2Step handshake) + // Step 2. Wire DBO into Comptroller + // ────────────────────────────────────────────────────────────────── + + // Step 1 — Accept DBO ownership + { + target: DEVIATION_BOUNDED_ORACLE, + signature: "acceptOwnership()", + params: [], + }, + + // Step 2 — Wire DBO into Comptroller (uses ACM permission granted in Phase 1 Step 3) + { + target: UNITROLLER, + signature: "setDeviationBoundedOracle(address)", + params: [DEVIATION_BOUNDED_ORACLE], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip665; diff --git a/vips/vip-617/utils/asset-configs-bscmainnet.json b/vips/vip-617/utils/asset-configs-bscmainnet.json new file mode 100644 index 000000000..47cb8ef71 --- /dev/null +++ b/vips/vip-617/utils/asset-configs-bscmainnet.json @@ -0,0 +1,244 @@ +{ + "assetConfigs": [ + { + "name": "AAVE", + "asset": "0xfb6115445Bff7b52FeB98650C87f44907E58f802", + "vToken": "0x26DA28954763B92139ED49283625ceCAf52C6f94", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "ADA", + "asset": "0x3EE2200Efb3400fAbB9AacF31297cBdD1d435D47", + "vToken": "0x9A0AF7FDb2065Ce470D72664DE73cAE409dA28Ec", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "asBNB", + "asset": "0x77734e70b6E88b4d82fE632a168EDf6e700912b6", + "vToken": "0xCC1dB43a06d97f736C7B045AedD03C6707c09BDF", + "cooldownPeriod": 3600, + "triggerThreshold": "194444444444444444", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "BCH", + "asset": "0x8fF795a6F4D97E7887C79beA79aba5cc76444aDf", + "vToken": "0x5F0388EBc2B94FA8E123F404b79cCF5f40b29176", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "BNB", + "asset": "0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB", + "vToken": "0xA07c5b74C9B40447a954e1466938b865b6BBea36", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "BTCB", + "asset": "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c", + "vToken": "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "CAKE", + "asset": "0x0E09FaBB73Bd3Ade0a17ECC321fD13a19e81cE82", + "vToken": "0x86aC3974e2BD0d60825230fa6F355fF11409df5c", + "cooldownPeriod": 3600, + "triggerThreshold": "300000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "DOGE", + "asset": "0xbA2aE424d960c26247Dd6c32edC70B295c744C43", + "vToken": "0xec3422Ef92B2fb59e84c8B02Ba73F1fE84Ed8D71", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "ETH", + "asset": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8", + "vToken": "0xf508fCD89b8bd15579dc79A6827cB4686A3592c8", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "LINK", + "asset": "0xF8A0BF9cF54Bb92F17374d9e9A321E6a111a51bD", + "vToken": "0x650b940a1033B8A1b1873f78730FcFC73ec11f1f", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "LTC", + "asset": "0x4338665CBB7B2485A8855A139b75D5e34AB0DB94", + "vToken": "0x57A5297F2cB2c0AaC9D554660acd6D385Ab50c6B", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "slisBNB", + "asset": "0xB0b84D294e0C75A6abe60171b70edEb2EFd14A1B", + "vToken": "0x89c910Eb8c90df818b4649b508Ba22130Dc73Adc", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "SOL", + "asset": "0x570A5D26f7765Ecb712C0924E4De545B89fD43dF", + "vToken": "0xBf515bA4D1b52FFdCeaBF20d31D705Ce789F2cEC", + "cooldownPeriod": 3600, + "triggerThreshold": "194444444444444444", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "SolvBTC", + "asset": "0x4aae823a6a0b376De6A78e74eCC5b079d38cBCf7", + "vToken": "0xf841cb62c19fCd4fF5CD0AaB5939f3140BaaC3Ea", + "cooldownPeriod": 3600, + "triggerThreshold": "166666666666666666", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "TRX", + "asset": "0xCE7de646e7208a4Ef112cb6ed5038FA6cC6b12e3", + "vToken": "0xC5D3466aA484B040eE977073fcF337f2c00071c1", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": true, + "cachingEnabled": false + }, + { + "name": "TWT", + "asset": "0x4B0F1812e5Df2A09796481Ff14017e6005508003", + "vToken": "0x4d41a36D04D97785bcEA57b057C412b278e6Edcc", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "UNI", + "asset": "0xBf5140A22578168FD562DCcF235E5D43A02ce9B1", + "vToken": "0x27FF564707786720C71A2e5c1490A63266683612", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "vPT-clisBNB-25JUN2026", + "asset": "0xe052823b4aefc6e230FAf46231A57d0905E30AE0", + "vToken": "0x6d3BD68E90B42615cb5abF4B8DE92b154ADc435e", + "cooldownPeriod": 3600, + "triggerThreshold": "166700000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "WBETH", + "asset": "0xa2E3356610840701BDf5611a53974510Ae27E2e1", + "vToken": "0x6CFdEc747f37DAf3b87a35a1D9c8AD3063A1A8A0", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "WBNB", + "asset": "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c", + "vToken": "0x6bCa74586218dB34cdB402295796b79663d816e9", + "cooldownPeriod": 3600, + "triggerThreshold": "125000000000000000", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "XAUM", + "asset": "0x23AE4fd8E7844cdBc97775496eBd0E8248656028", + "vToken": "0x92e6Ea74a1A3047DabF4186405a21c7D63a0612A", + "cooldownPeriod": 3600, + "triggerThreshold": "269230769230769230", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "XRP", + "asset": "0x1D2F0da169ceB9fC7B3144628dB156f3F6c60dBE", + "vToken": "0xB248a295732e0225acd3337607cc01068e3b9c10", + "cooldownPeriod": 3600, + "triggerThreshold": "269230769230769230", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "xSolvBTC", + "asset": "0x1346b618dC92810EC74163e4c27004c921D446a5", + "vToken": "0xd804dE60aFD05EE6B89aab5D152258fD461B07D5", + "cooldownPeriod": 3600, + "triggerThreshold": "194444444444444444", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + }, + { + "name": "XVS", + "asset": "0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63", + "vToken": "0x151B1e2635A717bcDc836ECd6FbB62B674FE3E1D", + "cooldownPeriod": 3600, + "triggerThreshold": "333333333333333333", + "resetThreshold": "50000000000000000", + "isBoundedPricingEnabled": false, + "cachingEnabled": false + } + ] +} diff --git a/vips/vip-617/utils/cut-params-bscmainnet.json b/vips/vip-617/utils/cut-params-bscmainnet.json new file mode 100644 index 000000000..c5c51de5e --- /dev/null +++ b/vips/vip-617/utils/cut-params-bscmainnet.json @@ -0,0 +1,127 @@ +{ + "cutParams": [ + [ + "0x7397B6bcFA9332Cc8791c886F339B4D114651719", + 1, + [ + "0xa76b3fda", + "0x89c13be0", + "0x929fe9a1", + "0xd0d13036", + "0xd585c3c6", + "0xc2998238", + "0xf9682732", + "0xede4edd0", + "0xb0772d0b", + "0xabfceffc", + "0x23617585", + "0xafd3783b", + "0x19ef3e8b", + "0xd686e9ee", + "0x7b86e42c", + "0x63e0d634", + "0xf02fdf97", + "0x007e3dd2", + "0x3d98a1e5", + "0x0ef332ca", + "0xc488847b", + "0xa78dc775", + "0x8e8f294b", + "0x3093c11e", + "0xd137f36e", + "0xcab4f84c", + "0x0686dab6", + "0xddbf54fd", + "0xd463654c", + "0x4d99c776", + "0xc5b4db55" + ] + ], + [ + "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", + 1, + [ + "0xead1a8a0", + "0xda3d454c", + "0x5c778605", + "0x5ec88c79", + "0x528a174c", + "0x4e79238f", + "0x5fc7e71e", + "0x47ef3b3b", + "0x4ef4c3e1", + "0x41c728b9", + "0xeabe7d91", + "0x51dff989", + "0x24008a62", + "0x1ededc91", + "0xd02f7351", + "0x6d35bf91", + "0xbdcdc258", + "0x6a56947e" + ] + ], + [ + "0xFaC00Dc856F454BB674c8588d4CC16Edef9dc28b", + 1, + [ + "0xa7604b41", + "0x70bf66f0", + "0x86df31ee", + "0xadcd5fb9", + "0xd09c54ba", + "0x7858524d", + "0xededbae6", + "0x655f0725", + "0xe85a2960", + "0xbf32442d" + ] + ], + [ + "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", + 1, + [ + "0xf519fc30", + "0x2b5d790c", + "0x317b0b77", + "0x9bf34cbb", + "0x522c656b", + "0x17db2163", + "0xbb857450", + "0x607ef6c1", + "0x51a485e4", + "0x5f5af1aa", + "0x55ee1fe1", + "0x9460c8b5", + "0x2a6a6065", + "0xd24febad", + "0x9cfdd9e6", + "0x2ec04124", + "0x4e0853db", + "0x6662c7c9", + "0x919a3736", + "0x4ef233fc", + "0x24aaa220", + "0x7938146f", + "0x12348e96", + "0x5cc4fdeb", + "0x9159b177", + "0xd6ad5c39", + "0x8b3113f6", + "0xa89766dd", + "0x35439240", + "0x9bd8f6e8", + "0x186db48f", + "0xd136af44", + "0xfd51a3ad", + "0x4964f48c", + "0xb88d846b", + "0x530e784f", + "0xc32094c7", + "0x42adb211" + ] + ], + ["0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", 0, ["0xfe40768f"]], + ["0x7F00af2f30a55e79311392C98fBBfA629D19b3A5", 1, ["0x5544ed9c"]] + ] +} diff --git a/vips/vip-617/utils/cut-params-bsctestnet.json b/vips/vip-617/utils/cut-params-bsctestnet.json new file mode 100644 index 000000000..8baf3b07a --- /dev/null +++ b/vips/vip-617/utils/cut-params-bsctestnet.json @@ -0,0 +1,127 @@ +{ + "cutParams": [ + [ + "0xE160Afd62cAE8FCB16F6b702B325883dd80358d4", + 1, + [ + "0xa76b3fda", + "0x89c13be0", + "0x929fe9a1", + "0xd0d13036", + "0xd585c3c6", + "0xc2998238", + "0xf9682732", + "0xede4edd0", + "0xb0772d0b", + "0xabfceffc", + "0x23617585", + "0xafd3783b", + "0x19ef3e8b", + "0xd686e9ee", + "0x7b86e42c", + "0x63e0d634", + "0xf02fdf97", + "0x007e3dd2", + "0x3d98a1e5", + "0x0ef332ca", + "0xc488847b", + "0xa78dc775", + "0x8e8f294b", + "0x3093c11e", + "0xd137f36e", + "0xcab4f84c", + "0x0686dab6", + "0xddbf54fd", + "0xd463654c", + "0x4d99c776", + "0xc5b4db55" + ] + ], + [ + "0xDAfA77ED8b2CdF4dBE2D1aB27770eDE6A4a54463", + 1, + [ + "0xead1a8a0", + "0xda3d454c", + "0x5c778605", + "0x5ec88c79", + "0x528a174c", + "0x4e79238f", + "0x5fc7e71e", + "0x47ef3b3b", + "0x4ef4c3e1", + "0x41c728b9", + "0xeabe7d91", + "0x51dff989", + "0x24008a62", + "0x1ededc91", + "0xd02f7351", + "0x6d35bf91", + "0xbdcdc258", + "0x6a56947e" + ] + ], + [ + "0x977515f4043111ba5e44C09D3Af071ba5B9B34a1", + 1, + [ + "0xa7604b41", + "0xe85a2960", + "0x70bf66f0", + "0x86df31ee", + "0xadcd5fb9", + "0xd09c54ba", + "0x7858524d", + "0xbf32442d", + "0xededbae6", + "0x655f0725" + ] + ], + [ + "0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", + 1, + [ + "0xf519fc30", + "0x2b5d790c", + "0x317b0b77", + "0x9bf34cbb", + "0x522c656b", + "0x17db2163", + "0xbb857450", + "0x607ef6c1", + "0x51a485e4", + "0x5f5af1aa", + "0x55ee1fe1", + "0x9460c8b5", + "0x2a6a6065", + "0xd24febad", + "0x9cfdd9e6", + "0x2ec04124", + "0x4e0853db", + "0x6662c7c9", + "0x919a3736", + "0x4ef233fc", + "0x24aaa220", + "0x7938146f", + "0x12348e96", + "0x5cc4fdeb", + "0x9159b177", + "0xd6ad5c39", + "0x8b3113f6", + "0xa89766dd", + "0x35439240", + "0x9bd8f6e8", + "0x186db48f", + "0xd136af44", + "0xfd51a3ad", + "0x4964f48c", + "0xb88d846b", + "0x530e784f", + "0xc32094c7", + "0x42adb211" + ] + ], + ["0x694ee0149bE810F68aEbf3D7969a79D760769B18", 1, ["0x5544ed9c"]], + ["0x38DC0fcEC79675c41f3e461797A7dd99EF3baC6E", 0, ["0xfe40768f"]] + ] +}