diff --git a/simulations/vip-600/abi/ILComptroller.json b/simulations/vip-600/abi/ILComptroller.json new file mode 100644 index 000000000..d1801efd8 --- /dev/null +++ b/simulations/vip-600/abi/ILComptroller.json @@ -0,0 +1,2121 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "poolRegistry_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum Action", + "name": "action", + "type": "uint8" + } + ], + "name": "ActionPaused", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowActionNotPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "BorrowCapExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowCapIsNotZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedLessThanOrEqualTo", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "CollateralExceedsThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "CollateralFactorIsNotZero", + "type": "error" + }, + { + "inputs": [], + "name": "ComptrollerMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "DelegationStatusUnchanged", + "type": "error" + }, + { + "inputs": [], + "name": "EnterMarketActionNotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "ExitMarketActionNotPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "collateralToSeize", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "availableCollateral", + "type": "uint256" + } + ], + "name": "InsufficientCollateral", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientLiquidity", + "type": "error" + }, + { + "inputs": [], + "name": "InsufficientShortfall", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidCollateralFactor", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidLiquidationThreshold", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateActionNotPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "MarketNotCollateral", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopsLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requiredLoops", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitExceeded", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expectedGreaterThan", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "MinimalCollateralViolated", + "type": "error" + }, + { + "inputs": [], + "name": "MintActionNotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "NonzeroBorrowBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PriceError", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemActionNotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "RepayActionNotPaused", + "type": "error" + }, + { + "inputs": [], + "name": "SeizeActionNotPaused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "SnapshotError", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "cap", + "type": "uint256" + } + ], + "name": "SupplyCapExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "SupplyCapIsNotZero", + "type": "error" + }, + { + "inputs": [], + "name": "TooMuchRepay", + "type": "error" + }, + { + "inputs": [], + "name": "TransferActionNotPaused", + "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": "address", + "name": "expectedSender", + "type": "address" + }, + { + "internalType": "address", + "name": "actualSender", + "type": "address" + } + ], + "name": "UnexpectedSender", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "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": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "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": false, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketSupported", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketUnlisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldMaxLoopsLimit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newmaxLoopsLimit", + "type": "uint256" + } + ], + "name": "MaxLoopsLimitUpdated", + "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": "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": false, + "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": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "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": "uint256", + "name": "oldMinLiquidatableCollateral", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "NewMinLiquidatableCollateral", + "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": "address", + "name": "rewardsDistributor", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "rewardToken", + "type": "address" + } + ], + "name": "NewRewardsDistributor", + "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": 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" + }, + { + "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": "", + "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": "contract RewardsDistributor", + "name": "_rewardsDistributor", + "type": "address" + } + ], + "name": "addRewardsDistributor", + "outputs": [], + "stateMutability": "nonpayable", + "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": "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": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "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": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "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": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "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": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidity", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getRewardDistributors", + "outputs": [ + { + "internalType": "contract RewardsDistributor[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getRewardsByMarket", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "rewardToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplySpeed", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowSpeed", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.RewardSpeeds[]", + "name": "rewardSpeeds", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "healAccount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "loopLimit", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "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": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "contract VToken", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "internalType": "struct ComptrollerStorage.LiquidationOrder[]", + "name": "orders", + "type": "tuple[]" + } + ], + "name": "liquidateAccount", + "outputs": [], + "stateMutability": "nonpayable", + "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": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokensToSeize", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationIncentiveMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minLiquidatableCollateral", + "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": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "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": "poolRegistry", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "preBorrowHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "preLiquidateHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "preMintHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "preRedeemHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preRepayHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "seizerContract", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + } + ], + "name": "preSeizeHook", + "outputs": [], + "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": "preTransferHook", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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": "renounceOwnership", + "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": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "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": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "marketsList", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actionsList", + "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": [], + "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": [], + "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": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "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": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newMinLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "setMinLiquidatableCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "setPrimeToken", + "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": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "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": [ + { + "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": "account", + "type": "address" + } + ], + "name": "updatePrices", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-600/abi/ILPoolRegistry.json b/simulations/vip-600/abi/ILPoolRegistry.json new file mode 100644 index 000000000..b637988ae --- /dev/null +++ b/simulations/vip-600/abi/ILPoolRegistry.json @@ -0,0 +1,680 @@ +[ + { + "inputs": [], + "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" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "MarketAdded", + "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": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "oldMetadata", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "newMetadata", + "type": "tuple" + } + ], + "name": "PoolMetadataUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldName", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newName", + "type": "string" + } + ], + "name": "PoolNameSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "pool", + "type": "tuple" + } + ], + "name": "PoolRegistered", + "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": [ + { + "components": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "collateralFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "initialSupply", + "type": "uint256" + }, + { + "internalType": "address", + "name": "vTokenReceiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistry.AddMarketInput", + "name": "input", + "type": "tuple" + } + ], + "name": "addMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "contract Comptroller", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "closeFactor", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentive", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minLiquidatableCollateral", + "type": "uint256" + } + ], + "name": "addPool", + "outputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllPools", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolByComptroller", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "creator", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "blockPosted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "timestampPosted", + "type": "uint256" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPool", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPoolsSupportedByAsset", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getVTokenForAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getVenusPoolMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "metadata", + "outputs": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "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": "comptroller", + "type": "address" + }, + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "setPoolName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "components": [ + { + "internalType": "string", + "name": "category", + "type": "string" + }, + { + "internalType": "string", + "name": "logoURL", + "type": "string" + }, + { + "internalType": "string", + "name": "description", + "type": "string" + } + ], + "internalType": "struct PoolRegistryInterface.VenusPoolMetaData", + "name": "metadata_", + "type": "tuple" + } + ], + "name": "updatePoolMetadata", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-600/abi/ILVToken.json b/simulations/vip-600/abi/ILVToken.json new file mode 100644 index 000000000..c039d2ef1 --- /dev/null +++ b/simulations/vip-600/abi/ILVToken.json @@ -0,0 +1,2105 @@ +[ + { + "inputs": [ + { + "internalType": "bool", + "name": "timeBased_", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "blocksPerYear_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxBorrowRateMantissa_", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "actualAddAmount", + "type": "uint256" + } + ], + "name": "AddReservesFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "DelegateNotApproved", + "type": "error" + }, + { + "inputs": [], + "name": "ForceLiquidateBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "HealBorrowUnauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidBlocksPerYear", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidTimeBasedConfiguration", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "LiquidateAccrueCollateralInterestFailed", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsUintMax", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCloseAmountIsZero", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateCollateralFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "LiquidateSeizeLiquidatorIsBorrower", + "type": "error" + }, + { + "inputs": [], + "name": "MintFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "ProtocolSeizeShareTooBig", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RedeemTransferOutNotPossible", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashNotAvailable", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesCashValidation", + "type": "error" + }, + { + "inputs": [], + "name": "ReduceReservesFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "RepayBorrowFreshnessCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetInterestRateModelFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorBoundsCheck", + "type": "error" + }, + { + "inputs": [], + "name": "SetReserveFactorFreshCheck", + "type": "error" + }, + { + "inputs": [], + "name": "TransferNotAllowed", + "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": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cashPrior", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "interestAccumulated", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtOld", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "badDebtNew", + "type": "uint256" + } + ], + "name": "BadDebtRecovered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldInternalCash", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newInternalCash", + "type": "uint256" + } + ], + "name": "CashSynced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "HealBorrow", + "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": true, + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Mint", + "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": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract ComptrollerInterface", + "name": "newComptroller", + "type": "address" + } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": true, + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldProtocolSeizeShareMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa", + "type": "uint256" + } + ], + "name": "NewProtocolSeizeShare", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldProtocolShareReserve", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newProtocolShareReserve", + "type": "address" + } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReduceReservesBlockOrTimestampDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReduceReservesBlockOrTimestampDelta", + "type": "uint256" + } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldReserveFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfall", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfall", + "type": "address" + } + ], + "name": "NewShortfallContract", + "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": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "ProtocolSeize", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBalance", + "type": "uint256" + } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "accountBorrows", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalBorrows", + "type": "uint256" + } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "benefactor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "protocolShareReserve", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTotalReserves", + "type": "uint256" + } + ], + "name": "SpreadReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "SweepToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "NO_ERROR", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "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": "accrualBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "addAmount", + "type": "uint256" + } + ], + "name": "addReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "badDebt", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "recoveredAmount_", + "type": "uint256" + } + ], + "name": "badDebtRecovered", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "blocksOrSecondsPerYear", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [ + { + "internalType": "contract ComptrollerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "bool", + "name": "skipLiquidityCheck", + "type": "bool" + } + ], + "name": "forceLiquidateBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vTokenBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowBalance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "exchangeRate", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumberOrTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "healBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "underlying_", + "type": "address" + }, + { + "internalType": "contract ComptrollerInterface", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract InterestRateModel", + "name": "interestRateModel_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "initialExchangeRateMantissa_", + "type": "uint256" + }, + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "uint8", + "name": "decimals_", + "type": "uint8" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "shortfall", + "type": "address" + }, + { + "internalType": "address payable", + "name": "protocolShareReserve", + "type": "address" + } + ], + "internalType": "struct VTokenInterface.RiskManagementInit", + "name": "riskManagement", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "reserveFactorMantissa_", + "type": "uint256" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [ + { + "internalType": "contract InterestRateModel", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "internalCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isTimeBased", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + }, + { + "internalType": "contract VTokenInterface", + "name": "vTokenCollateral", + "type": "address" + } + ], + "name": "liquidateBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "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": "protocolSeizeShareMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [ + { + "internalType": "address payable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeem", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + } + ], + "name": "redeemUnderlyingBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "reduceAmount", + "type": "uint256" + } + ], + "name": "reduceReserves", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrow", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowBehalf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract InterestRateModel", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "setInterestRateModel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newProtocolSeizeShareMantissa_", + "type": "uint256" + } + ], + "name": "setProtocolSeizeShare", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "protocolShareReserve_", + "type": "address" + } + ], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_newReduceReservesBlockOrTimestampDelta", + "type": "uint256" + } + ], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newReserveFactorMantissa", + "type": "uint256" + } + ], + "name": "setReserveFactor", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfall_", + "type": "address" + } + ], + "name": "setShortfallContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "token", + "type": "address" + } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "syncCash", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-600/abi/VBep20Delegate.json b/simulations/vip-600/abi/VBep20Delegate.json new file mode 100644 index 000000000..a3e02c234 --- /dev/null +++ b/simulations/vip-600/abi/VBep20Delegate.json @@ -0,0 +1,902 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "FlashLoanAlreadyActive", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "fee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" } + ], + "name": "FlashLoanFeeTooHigh", + "type": "error" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "fee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" } + ], + "name": "FlashLoanProtocolShareTooHigh", + "type": "error" + }, + { "inputs": [], "name": "InsufficientCash", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "actualAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "requiredTotalFee", "type": "uint256" } + ], + "name": "InsufficientRepayment", + "type": "error" + }, + { "inputs": [], "name": "InvalidComptroller", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "cashPrior", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "interestAccumulated", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "borrowIndex", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "borrower", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "borrowAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "accountBorrows", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldInternalCash", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newInternalCash", "type": "uint256" } + ], + "name": "CashSynced", + "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": false, "internalType": "uint256", "name": "oldFlashLoanFeeMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newFlashLoanFeeMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "oldFlashLoanProtocolShare", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newFlashLoanProtocolShare", "type": "uint256" } + ], + "name": "FlashLoanFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "bool", "name": "previousStatus", "type": "bool" }, + { "indexed": false, "internalType": "bool", "name": "newStatus", "type": "bool" } + ], + "name": "FlashLoanStatusChanged", + "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": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "minter", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "mintAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "mintTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "payer", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "mintAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "mintTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAccessControlAddress", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlAddress", "type": "address" } + ], + "name": "NewAccessControlManager", + "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": "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": "contract InterestRateModelV8", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModelV8", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "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": true, "internalType": "address", "name": "oldProtocolShareReserve", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newProtocolShareReserve", "type": "address" } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldReduceReservesBlockDelta", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newReduceReservesBlockDelta", "type": "uint256" } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldReserveFactorMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newReserveFactorMantissa", "type": "uint256" } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "redeemer", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "redeemAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "redeemTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "redeemer", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "feeAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "redeemTokens", "type": "uint256" } + ], + "name": "RedeemFee", + "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": "repayAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "accountBorrows", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "benefactor", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "addAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newTotalReserves", "type": "uint256" } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "protocolShareReserve", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "reduceAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newTotalReserves", "type": "uint256" } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "recipient", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "TokenSwept", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalFee", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "protocolFee", "type": "uint256" } + ], + "name": "TransferInUnderlyingFlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "TransferOutUnderlyingFlashLoan", + "type": "event" + }, + { + "inputs": [], + "name": "_acceptAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "addAmount", "type": "uint256" }], + "name": "_addReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes", "name": "data", "type": "bytes" }], + "name": "_becomeImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "reduceAmount_", "type": "uint256" }], + "name": "_reduceReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "_resignImplementation", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "contract ComptrollerInterface", "name": "newComptroller", "type": "address" }], + "name": "_setComptroller", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract InterestRateModelV8", "name": "newInterestRateModel_", "type": "address" }], + "name": "_setInterestRateModel", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address payable", "name": "newPendingAdmin", "type": "address" }], + "name": "_setPendingAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "newReserveFactorMantissa_", "type": "uint256" }], + "name": "_setReserveFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "balanceOfUnderlying", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "borrowAmount", "type": "uint256" }], + "name": "borrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "borrowBalanceCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "borrowBalanceStored", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "borrowAmount", "type": "uint256" } + ], + "name": "borrowBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }], + "name": "calculateFlashLoanFee", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [{ "internalType": "contract ComptrollerInterface", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanAmount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "borrowAmount", "type": "uint256" } + ], + "name": "flashLoanDebtPosition", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanFeeMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanProtocolShareMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "getAccountSnapshot", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "underlying_", "type": "address" }, + { "internalType": "contract ComptrollerInterface", "name": "comptroller_", "type": "address" }, + { "internalType": "contract InterestRateModelV8", "name": "interestRateModel_", "type": "address" }, + { "internalType": "uint256", "name": "initialExchangeRateMantissa_", "type": "uint256" }, + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "uint8", "name": "decimals_", "type": "uint8" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract ComptrollerInterface", "name": "comptroller_", "type": "address" }, + { "internalType": "contract InterestRateModelV8", "name": "interestRateModel_", "type": "address" }, + { "internalType": "uint256", "name": "initialExchangeRateMantissa_", "type": "uint256" }, + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "uint8", "name": "decimals_", "type": "uint8" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [{ "internalType": "contract InterestRateModelV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "internalCash", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isFlashLoanEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "repayAmount", "type": "uint256" }, + { "internalType": "contract VTokenInterface", "name": "vTokenCollateral", "type": "address" } + ], + "name": "liquidateBorrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "mintAmount", "type": "uint256" }], + "name": "mint", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "uint256", "name": "mintAmount", "type": "uint256" } + ], + "name": "mintBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "redeemTokens", "type": "uint256" }], + "name": "redeem", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "redeemer", "type": "address" }, + { "internalType": "uint256", "name": "redeemTokens", "type": "uint256" } + ], + "name": "redeemBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "redeemAmount", "type": "uint256" }], + "name": "redeemUnderlying", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "redeemer", "type": "address" }, + { "internalType": "uint256", "name": "redeemAmount", "type": "uint256" } + ], + "name": "redeemUnderlyingBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "repayAmount", "type": "uint256" }], + "name": "repayBorrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "repayAmount", "type": "uint256" } + ], + "name": "repayBorrowBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "liquidator", "type": "address" }, + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "seizeTokens", "type": "uint256" } + ], + "name": "seize", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newAccessControlManagerAddress", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bool", "name": "enabled", "type": "bool" }], + "name": "setFlashLoanEnabled", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "flashLoanFeeMantissa_", "type": "uint256" }, + { "internalType": "uint256", "name": "flashLoanProtocolShare_", "type": "uint256" } + ], + "name": "setFlashLoanFeeMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address payable", "name": "protcolShareReserve_", "type": "address" }], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "newReduceReservesBlockDelta_", "type": "uint256" }], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "transferAmount", "type": "uint256" }], + "name": "sweepTokenAndSync", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "src", "type": "address" }, + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "from", "type": "address" }, + { "internalType": "uint256", "name": "repaymentAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "totalFee", "type": "uint256" }, + { "internalType": "uint256", "name": "protocolFee", "type": "uint256" } + ], + "name": "transferInUnderlyingFlashLoan", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferOutUnderlyingFlashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-600/abi/vtokenBeacon.json b/simulations/vip-600/abi/vtokenBeacon.json new file mode 100644 index 000000000..fe7f3e52f --- /dev/null +++ b/simulations/vip-600/abi/vtokenBeacon.json @@ -0,0 +1,51 @@ +[ + { + "inputs": [{ "internalType": "address", "name": "implementation_", "type": "address" }], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": "implementation", "type": "address" }], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "implementation", + "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": "address", "name": "newImplementation", "type": "address" }], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-600/arbitrumone.ts b/simulations/vip-600/arbitrumone.ts new file mode 100644 index 000000000..a97dc3db0 --- /dev/null +++ b/simulations/vip-600/arbitrumone.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + ARBITRUMONE_CORE_COMPTROLLER, + ARBITRUMONE_CORE_VTOKENS, + ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION, + ARBITRUMONE_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/arbitrumone"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 443758428; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(ARBITRUMONE_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(ARBITRUMONE_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(ARBITRUMONE_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of ARBITRUMONE_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/basemainnet.ts b/simulations/vip-600/basemainnet.ts new file mode 100644 index 000000000..f1df4303f --- /dev/null +++ b/simulations/vip-600/basemainnet.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + BASEMAINNET_CORE_COMPTROLLER, + BASEMAINNET_CORE_VTOKENS, + BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION, + BASEMAINNET_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/basemainnet"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 43608484; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(BASEMAINNET_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(BASEMAINNET_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(BASEMAINNET_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of BASEMAINNET_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/bscmainnet-2.ts b/simulations/vip-600/bscmainnet-2.ts new file mode 100644 index 000000000..d456f9fda --- /dev/null +++ b/simulations/vip-600/bscmainnet-2.ts @@ -0,0 +1,9 @@ +import { forking, testVip } from "src/vip-framework"; + +import vip601 from "../../vips/vip-600/bscmainnet-2"; + +const BLOCK_NUMBER = 87684581; + +forking(BLOCK_NUMBER, async () => { + testVip("VIP-601 Grant syncCash permissions (all networks)", await vip601()); +}); diff --git a/simulations/vip-600/bscmainnet-3.ts b/simulations/vip-600/bscmainnet-3.ts new file mode 100644 index 000000000..9a1457d91 --- /dev/null +++ b/simulations/vip-600/bscmainnet-3.ts @@ -0,0 +1,9 @@ +import { forking, testVip } from "src/vip-framework"; + +import vip602 from "../../vips/vip-600/bscmainnet-3"; + +const BLOCK_NUMBER = 87684581; + +forking(BLOCK_NUMBER, async () => { + testVip("VIP-602 Upgrade VToken beacon and syncCash (all networks)", await vip602()); +}); diff --git a/simulations/vip-600/bscmainnet.ts b/simulations/vip-600/bscmainnet.ts new file mode 100644 index 000000000..5e04dbe6d --- /dev/null +++ b/simulations/vip-600/bscmainnet.ts @@ -0,0 +1,171 @@ +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { ethers } from "hardhat"; +import { forking, testVip } from "src/vip-framework"; + +import vip600 from "../../vips/vip-600/bscmainnet"; +import VBEP20_DELEGATE_ABI from "./abi/VBep20Delegate.json"; + +const BLOCK_NUMBER = 87684581; + +const NEW_VBEP20_DELEGATE_IMPL = "0xb25b57599BA969c4829699F7E4Fc4076D14745E1"; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +// All 43 VBep20Delegator proxy addresses +const MARKET_ADDRESSES = [ + "0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8", // vUSDC + "0xfD5840Cd36d94D7229439859C0112a4185BC0255", // vUSDT + "0x95c78222B3D6e262426483D42CfA53685A67Ab9D", // vBUSD + "0x2fF3d0F6990a40261c66E1ff2017aCBc282EB6d0", // vSXP + "0x151B1e2635A717bcDc836ECd6FbB62B674FE3E1D", // vXVS + "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B", // vBTC + "0xf508fCD89b8bd15579dc79A6827cB4686A3592c8", // vETH + "0x57A5297F2cB2c0AaC9D554660acd6D385Ab50c6B", // vLTC + "0xB248a295732e0225acd3337607cc01068e3b9c10", // vXRP + "0x5F0388EBc2B94FA8E123F404b79cCF5f40b29176", // vBCH + "0x1610bc33319e9398de5f57B33a5b184c806aD217", // vDOT + "0x650b940a1033B8A1b1873f78730FcFC73ec11f1f", // vLINK + "0x334b3eCB4DCa3593BCCC3c7EBD1A1C1d1780FBF1", // vDAI + "0xf91d58b5aE142DAcC749f58A49FCBac340Cb0343", // vFIL + "0x972207A639CC1B374B893cc33Fa251b55CEB7c07", // vBETH + "0x9A0AF7FDb2065Ce470D72664DE73cAE409dA28Ec", // vADA + "0xec3422Ef92B2fb59e84c8B02Ba73F1fE84Ed8D71", // vDOGE + "0x5c9476FcD6a4F9a3654139721c949c2233bBbBc8", // vMATIC + "0x86aC3974e2BD0d60825230fa6F355fF11409df5c", // vCAKE + "0x26DA28954763B92139ED49283625ceCAf52C6f94", // vAAVE + "0x08CEB3F4a7ed3500cA0982bcd0FC7816688084c3", // vTUSDOLD + "0x61eDcFe8Dd6bA3c891CB9bEc2dc7657B3B422E93", // vTRXOLD + "0xC5D3466aA484B040eE977073fcF337f2c00071c1", // vTRX + "0x6CFdEc747f37DAf3b87a35a1D9c8AD3063A1A8A0", // vWBETH + "0xBf762cd5991cA1DCdDaC9ae5C638F5B5Dc3Bee6E", // vTUSD + "0x27FF564707786720C71A2e5c1490A63266683612", // vUNI + "0xC4eF4229FEc74Ccfe17B2bdeF7715fAC740BA0ba", // vFDUSD + "0x4d41a36D04D97785bcEA57b057C412b278e6Edcc", // vTWT + "0xf841cb62c19fCd4fF5CD0AaB5939f3140BaaC3Ea", // vSolvBTC + "0x86e06EAfa6A1eA631Eab51DE500E3D474933739f", // vTHE + "0xBf515bA4D1b52FFdCeaBF20d31D705Ce789F2cEC", // vSOL + "0x689E0daB47Ab16bcae87Ec18491692BF621Dc6Ab", // vlisUSD + "0x9e4E5fed5Ac5B9F732d0D850A615206330Bf1866", // vPT-sUSDE-26JUN2025 + "0x699658323d58eE25c69F1a29d476946ab011bD18", // vsUSDe + "0x74ca6930108F775CC667894EEa33843e691680d7", // vUSDe + "0x0C1DA220D301155b87318B90692Da8dc43B67340", // vUSD1 + "0xd804dE60aFD05EE6B89aab5D152258fD461B07D5", // vxSolvBTC + "0xCC1dB43a06d97f736C7B045AedD03C6707c09BDF", // vasBNB + "0x6bCa74586218dB34cdB402295796b79663d816e9", // vWBNB + "0x89c910Eb8c90df818b4649b508Ba22130Dc73Adc", // vslisBNB + "0x3d5E269787d562b74aCC55F18Bd26C5D09Fa245E", // vU + "0x6d3BD68E90B42615cb5abF4B8DE92b154ADc435e", // vPT-clisBNB-25JUN2026 + "0x92e6Ea74a1A3047DabF4186405a21c7D63a0612A", // vXAUM +]; + +const MARKET_NAMES = [ + "vUSDC", + "vUSDT", + "vBUSD", + "vSXP", + "vXVS", + "vBTC", + "vETH", + "vLTC", + "vXRP", + "vBCH", + "vDOT", + "vLINK", + "vDAI", + "vFIL", + "vBETH", + "vADA", + "vDOGE", + "vMATIC", + "vCAKE", + "vAAVE", + "vTUSDOLD", + "vTRXOLD", + "vTRX", + "vWBETH", + "vTUSD", + "vUNI", + "vFDUSD", + "vTWT", + "vSolvBTC", + "vTHE", + "vSOL", + "vlisUSD", + "vPT-sUSDE-26JUN2025", + "vsUSDe", + "vUSDe", + "vUSD1", + "vxSolvBTC", + "vasBNB", + "vWBNB", + "vslisBNB", + "vU", + "vPT-clisBNB-25JUN2026", + "vXAUM", +]; + +interface MarketSnapshot { + totalBorrows: BigNumber; + totalReserves: BigNumber; + totalSupply: BigNumber; + exchangeRate: BigNumber; +} + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const preVipSnapshots: Map = new Map(); + + before(async () => { + // Capture pre-VIP state for all markets + for (let i = 0; i < MARKET_ADDRESSES.length; i++) { + const vToken = new ethers.Contract(MARKET_ADDRESSES[i], VBEP20_DELEGATE_ABI, provider); + const [totalBorrows, totalReserves, totalSupply, exchangeRate] = await Promise.all([ + vToken.totalBorrows(), + vToken.totalReserves(), + vToken.totalSupply(), + vToken.exchangeRateStored(), + ]); + preVipSnapshots.set(MARKET_ADDRESSES[i], { totalBorrows, totalReserves, totalSupply, exchangeRate }); + } + }); + + testVip("VIP-600 Upgrade VBep20Delegate for Core Pool", await vip600()); + + describe("Post-VIP behavior", async () => { + for (let i = 0; i < MARKET_ADDRESSES.length; i++) { + const marketAddress = MARKET_ADDRESSES[i]; + const marketName = MARKET_NAMES[i]; + + describe(`${marketName} (${marketAddress})`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(marketAddress, VBEP20_DELEGATE_ABI, provider); + }); + + it("should have the new implementation", async () => { + expect(await vToken.implementation()).to.equal(NEW_VBEP20_DELEGATE_IMPL); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(marketAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should preserve totalSupply", async () => { + const snapshot = preVipSnapshots.get(marketAddress)!; + expect(await vToken.totalSupply()).to.equal(snapshot.totalSupply); + }); + + it("should allow accrueInterest to succeed", async () => { + // accrueInterest should work correctly with synced internalCash + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/ethereum.ts b/simulations/vip-600/ethereum.ts new file mode 100644 index 000000000..0f745bf6a --- /dev/null +++ b/simulations/vip-600/ethereum.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + ETHEREUM_CORE_COMPTROLLER, + ETHEREUM_CORE_VTOKENS, + ETHEREUM_NEW_VTOKEN_IMPLEMENTATION, + ETHEREUM_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/ethereum"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 24698424; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(ETHEREUM_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(ETHEREUM_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(ETHEREUM_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(ETHEREUM_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(ETHEREUM_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of ETHEREUM_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/opbnbmainnet.ts b/simulations/vip-600/opbnbmainnet.ts new file mode 100644 index 000000000..19faddb19 --- /dev/null +++ b/simulations/vip-600/opbnbmainnet.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + OPBNBMAINNET_CORE_COMPTROLLER, + OPBNBMAINNET_CORE_VTOKENS, + OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION, + OPBNBMAINNET_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/opbnbmainnet"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 123557813; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(OPBNBMAINNET_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(OPBNBMAINNET_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(OPBNBMAINNET_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of OPBNBMAINNET_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/opmainnet.ts b/simulations/vip-600/opmainnet.ts new file mode 100644 index 000000000..7a110f500 --- /dev/null +++ b/simulations/vip-600/opmainnet.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + OPMAINNET_CORE_COMPTROLLER, + OPMAINNET_CORE_VTOKENS, + OPMAINNET_NEW_VTOKEN_IMPLEMENTATION, + OPMAINNET_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/opmainnet"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 149203740; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(OPMAINNET_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(OPMAINNET_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(OPMAINNET_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(OPMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(OPMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of OPMAINNET_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/unichainmainnet.ts b/simulations/vip-600/unichainmainnet.ts new file mode 100644 index 000000000..bbd1b691b --- /dev/null +++ b/simulations/vip-600/unichainmainnet.ts @@ -0,0 +1,79 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + UNICHAINMAINNET_CORE_COMPTROLLER, + UNICHAINMAINNET_CORE_VTOKENS, + UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION, + UNICHAINMAINNET_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/unichainmainnet"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 43258056; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(UNICHAINMAINNET_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(UNICHAINMAINNET_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(UNICHAINMAINNET_CORE_VTOKENS.length).to.equal( + allMarkets.length, + "CORE_VTOKENS does not cover all markets", + ); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of UNICHAINMAINNET_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/simulations/vip-600/zksyncmainnet.ts b/simulations/vip-600/zksyncmainnet.ts new file mode 100644 index 000000000..7cc01c4b9 --- /dev/null +++ b/simulations/vip-600/zksyncmainnet.ts @@ -0,0 +1,76 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testForkedNetworkVipCommands } from "src/vip-framework"; + +import { + ZKSYNCMAINNET_CORE_COMPTROLLER, + ZKSYNCMAINNET_CORE_VTOKENS, + ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION, + ZKSYNCMAINNET_VTOKEN_BEACON, +} from "../../vips/vip-600/addresses/zksyncmainnet"; +import vip601 from "../../vips/vip-600/bscmainnet-2"; +import vip602 from "../../vips/vip-600/bscmainnet-3"; +import COMPTROLLER_ABI from "./abi/ILComptroller.json"; +import VTOKEN_ABI from "./abi/ILVToken.json"; +import VTOKEN_BEACON_ABI from "./abi/vtokenBeacon.json"; + +const BLOCK_NUMBER = 69170974; + +const ERC20_ABI = ["function balanceOf(address) view returns (uint256)"]; + +forking(BLOCK_NUMBER, async () => { + const provider = ethers.provider; + const vTokenBeacon = new ethers.Contract(ZKSYNCMAINNET_VTOKEN_BEACON, VTOKEN_BEACON_ABI, provider); + + describe("Pre-VIP behaviour", () => { + it("CORE_VTOKENS should cover all on-chain markets", async () => { + const comptroller = new ethers.Contract(ZKSYNCMAINNET_CORE_COMPTROLLER, COMPTROLLER_ABI, provider); + const allMarkets: string[] = await comptroller.getAllMarkets(); + expect(ZKSYNCMAINNET_CORE_VTOKENS.length).to.equal(allMarkets.length, "CORE_VTOKENS does not cover all markets"); + }); + + it("VToken beacon should not point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.not.equal(ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + }); + + testForkedNetworkVipCommands("VIP-601 Grant syncCash permissions", await vip601()); + + testForkedNetworkVipCommands("VIP-602 Upgrade VToken beacon and syncCash", await vip602(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [VTOKEN_BEACON_ABI], ["Upgraded"], [1]); + }, + }); + + describe("Post-VIP behaviour", () => { + it("VToken beacon should point to new implementation", async () => { + const currentImplementation = await vTokenBeacon.implementation(); + expect(currentImplementation).to.equal(ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION); + }); + + for (const vTokenAddress of ZKSYNCMAINNET_CORE_VTOKENS) { + describe(`VToken ${vTokenAddress}`, () => { + let vToken: Contract; + + before(async () => { + vToken = new ethers.Contract(vTokenAddress, VTOKEN_ABI, provider); + }); + + it("should have internalCash equal to underlying token balance", async () => { + const internalCash = await vToken.internalCash(); + const underlyingAddress = await vToken.underlying(); + const underlyingToken = new ethers.Contract(underlyingAddress, ERC20_ABI, provider); + const underlyingBalance = await underlyingToken.balanceOf(vTokenAddress); + expect(internalCash).to.equal(underlyingBalance); + }); + + it("should allow accrueInterest to succeed", async () => { + await expect(vToken.callStatic.accrueInterest()).to.not.be.reverted; + }); + }); + } + }); +}); diff --git a/vips/vip-600/addresses/arbitrumone.ts b/vips/vip-600/addresses/arbitrumone.ts new file mode 100644 index 000000000..183705ec6 --- /dev/null +++ b/vips/vip-600/addresses/arbitrumone.ts @@ -0,0 +1,18 @@ +import { LzChainId } from "src/types"; + +export const ARBITRUMONE_ACM = "0xD9dD18EB0cf10CbA837677f28A8F9Bda4bc2b157"; +export const ARBITRUMONE_NORMAL_TIMELOCK = "0x4b94589Cc23F618687790036726f744D602c4017"; +export const ARBITRUMONE_CORE_COMPTROLLER = "0x317c1A5739F39046E20b08ac9BeEa3f10fD43326"; +export const ARBITRUMONE_VTOKEN_BEACON = "0xE9381D8CA7006c12Ae9eB97890575E705996fa66"; +export const ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION = "0x1986Fb53535953711265d5fD329cd7A690411669"; +export const ARBITRUMONE_DST_CHAIN_ID = LzChainId.arbitrumone; + +export const ARBITRUMONE_CORE_VTOKENS = [ + "0xada57840b372d4c28623e87fc175de8490792811", // vWBTC_Core + "0x68a34332983f4bf866768dd6d6e638b02ef5e1f0", // vWETH_Core + "0x7d8609f8da70ff9027e9bc5229af4f6727662707", // vUSDC_Core + "0xb9f9117d4200dc296f9acd1e8be1937df834a2fd", // vUSDT_Core + "0xaeb0fed69354f34831fe1d16475d9a83ddacada6", // vARB_Core + "0x9bb8cec9c0d46f53b4f2173bb2a0221f66c353cc", // vgmWETH-USDC_Core + "0x4f3a73f318c5ea67a86eaace24309f29f89900df", // vgmBTC-USDC_Core +]; diff --git a/vips/vip-600/addresses/basemainnet.ts b/vips/vip-600/addresses/basemainnet.ts new file mode 100644 index 000000000..055b06a9b --- /dev/null +++ b/vips/vip-600/addresses/basemainnet.ts @@ -0,0 +1,16 @@ +import { LzChainId } from "src/types"; + +export const BASEMAINNET_ACM = "0x9E6CeEfDC6183e4D0DF8092A9B90cDF659687daB"; +export const BASEMAINNET_NORMAL_TIMELOCK = "0x21c12f2946a1a66cBFf7eb997022a37167eCf517"; +export const BASEMAINNET_CORE_COMPTROLLER = "0x0C7973F9598AA62f9e03B94E92C967fD5437426C"; +export const BASEMAINNET_VTOKEN_BEACON = "0x87a6476510368c4Bfb70d04A3B0e5a881eC7f0d1"; +export const BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION = "0x107bA74c87e75b6cc291510D3A85D0c8EAa73e82"; +export const BASEMAINNET_DST_CHAIN_ID = LzChainId.basemainnet; + +export const BASEMAINNET_CORE_VTOKENS = [ + "0x7bBd1005bB24Ec84705b04e1f2DfcCad533b6D72", // vcbBTC_Core + "0xEB8A79bD44cF4500943bf94a2b4434c95C008599", // vWETH_Core + "0x3cb752d175740043Ec463673094e06ACDa2F9a2e", // vUSDC_Core + "0x75201D81B3B0b9D17b179118837Be37f64fc4930", // vwsuperOETHb_Core + "0x133d3BCD77158D125B75A17Cb517fFD4B4BE64C5", // vwstETH_Core +]; diff --git a/vips/vip-600/addresses/ethereum.ts b/vips/vip-600/addresses/ethereum.ts new file mode 100644 index 000000000..214f229ec --- /dev/null +++ b/vips/vip-600/addresses/ethereum.ts @@ -0,0 +1,34 @@ +import { LzChainId } from "src/types"; + +export const ETHEREUM_ACM = "0x230058da2D23eb8836EC5DB7037ef7250c56E25E"; +export const ETHEREUM_NORMAL_TIMELOCK = "0xd969E79406c35E80750aAae061D402Aab9325714"; +export const ETHEREUM_CORE_COMPTROLLER = "0x687a01ecF6d3907658f7A7c714749fAC32336D1B"; +export const ETHEREUM_VTOKEN_BEACON = "0xfc08aADC7a1A93857f6296C3fb78aBA1d286533a"; +export const ETHEREUM_NEW_VTOKEN_IMPLEMENTATION = "0x33bE30B31f07c8a2bfb705FBcE55E983c47ba864"; +export const ETHEREUM_DST_CHAIN_ID = LzChainId.ethereum; + +export const ETHEREUM_CORE_VTOKENS = [ + "0x8716554364f20bca783cb2baa744d39361fd1d8d", // vWBTC_Core + "0x7c8ff7d2a1372433726f879bd945ffb250b94c65", // vWETH_Core + "0x17c07e0c232f2f80dfdbd7a95b942d893a4c5acb", // vUSDC_Core + "0x8c3e3821259b82ffb32b2450a95d2dcbf161c24e", // vUSDT_Core + "0x672208c10aaaa2f9a6719f449c4c8227bc0bc202", // vcrvUSD_Core + "0xd8add9b41d4e1cd64edad8722ab0ba8d35536657", // vDAI_Core + "0x13eb80fdbe5c5f4a7039728e258a6f05fb3b912b", // vTUSD_Core + "0x4fafbdc4f2a9876bd1764827b26fb8dc4fd1db95", // vFRAX_Core, Paused + "0x17142a05fe678e9584fa1d88efac1bf181bf7abe", // vsFRAX_Core + "0x256addbe0a387c98f487e44b85c29eb983413c5e", // vEIGEN_Core + "0x325ceb02fe1c2ff816a83a5770ea0e88e2faecf2", // veBTC_Core + "0x25c20e6e110a1ce3febacc8b7e48368c7b2f0c91", // vLBTC_Core + "0x0c6b19287999f1e31a5c0a44393b24b62d2c0468", // vUSDS_Core + "0xe36ae842dbbd7ae372eba02c8239cd431cc063d6", // vsUSDS_Core + "0x0ec5488e4f8f319213a14cab188e01fb8517faa8", // vBAL_Core + "0xf87c0a64dc3a8622d6c63265fa29137788163879", // vyvUSDC-1_Core, Paused + "0x475d0c68a8cd275c15d1f01f4f291804e445f677", // vyvUSDT-1_Core, Paused + "0x520d67226bc904ac122dce66ed2f8f61aa1ed764", // vyvUSDS-1_Core, Paused + "0xba3916302cba4abcb51a01e706fc6051aaf272a0", // vyvWETH-1_Core, Paused + "0xc42e4bfb996ed35235bda505430cbe404eb49f77", // vweETHs_Core + "0xa836ce315b7a6bb19397ee996551659b1d92298e", // vsUSDe_Core + "0xa0ee2baa024cc3aa1bc9395522d07b7970ca75b3", // vUSDe_Core + "0x5e35c312862d53fd566737892adcf010cb4928f7", // vtBTC_Core +]; diff --git a/vips/vip-600/addresses/opbnbmainnet.ts b/vips/vip-600/addresses/opbnbmainnet.ts new file mode 100644 index 000000000..7eaf8071f --- /dev/null +++ b/vips/vip-600/addresses/opbnbmainnet.ts @@ -0,0 +1,16 @@ +import { LzChainId } from "src/types"; + +export const OPBNBMAINNET_ACM = "0xA60Deae5344F1152426cA440fb6552eA0e3005D6"; +export const OPBNBMAINNET_NORMAL_TIMELOCK = "0x10f504e939b912569Dca611851fDAC9E3Ef86819"; +export const OPBNBMAINNET_CORE_COMPTROLLER = "0xD6e3E2A1d8d95caE355D15b3b9f8E5c2511874dd"; +export const OPBNBMAINNET_VTOKEN_BEACON = "0xfeD1d3a13597c5aBc893Af41ED5cb17e64c847c7"; +export const OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION = "0x7AA7EB7553DE5f221C06595f3b4021363279e9Fe"; +export const OPBNBMAINNET_DST_CHAIN_ID = LzChainId.opbnbmainnet; + +export const OPBNBMAINNET_CORE_VTOKENS = [ + "0xed827b80bd838192ea95002c01b5c6da8354219a", // vBTCB_Core + "0x509e81ef638d489936fa85bc58f52df01190d26c", // vETH_Core + "0xb7a01ba126830692238521a1aa7e7a7509410b8e", // vUSDT_Core + "0x53d11cb8a0e5320cd7229c3acc80d1a0707f2672", // vWBNB_Core + "0x13b492b8a03d072bab5c54ac91dba5b830a50917", // vFDUSD_Core +]; diff --git a/vips/vip-600/addresses/opmainnet.ts b/vips/vip-600/addresses/opmainnet.ts new file mode 100644 index 000000000..b29baf02c --- /dev/null +++ b/vips/vip-600/addresses/opmainnet.ts @@ -0,0 +1,16 @@ +import { LzChainId } from "src/types"; + +export const OPMAINNET_ACM = "0xD71b1F33f6B0259683f11174EE4Ddc2bb9cE4eD6"; +export const OPMAINNET_NORMAL_TIMELOCK = "0x0C6f1E6B4fDa846f63A0d5a8a73EB811E0e0C04b"; +export const OPMAINNET_CORE_COMPTROLLER = "0x5593FF68bE84C966821eEf5F0a988C285D5B7CeC"; +export const OPMAINNET_VTOKEN_BEACON = "0xd550Bdfa9402e215De0BabCb99F7294BE0268367"; +export const OPMAINNET_NEW_VTOKEN_IMPLEMENTATION = "0xBEB9eE824a0096c0FB606b070c028cB55b6f21e7"; +export const OPMAINNET_DST_CHAIN_ID = LzChainId.opmainnet; + +export const OPMAINNET_CORE_VTOKENS = [ + "0x9EfdCfC2373f81D3DF24647B1c46e15268884c46", // vWBTC_Core + "0x66d5AE25731Ce99D46770745385e662C8e0B4025", // vWETH_Core + "0x37ac9731B0B02df54975cd0c7240e0977a051721", // vUSDT_Core + "0x6b846E3418455804C1920fA4CC7a31A51C659A2D", // vOP_Core + "0x1C9406ee95B7af55F005996947b19F91B6D55b15", // vUSDC_Core +]; diff --git a/vips/vip-600/addresses/unichainmainnet.ts b/vips/vip-600/addresses/unichainmainnet.ts new file mode 100644 index 000000000..d57439b1f --- /dev/null +++ b/vips/vip-600/addresses/unichainmainnet.ts @@ -0,0 +1,18 @@ +import { LzChainId } from "src/types"; + +export const UNICHAINMAINNET_ACM = "0x1f12014c497a9d905155eB9BfDD9FaC6885e61d0"; +export const UNICHAINMAINNET_NORMAL_TIMELOCK = "0x918532A78d22419Da4091930d472bDdf532BE89a"; +export const UNICHAINMAINNET_CORE_COMPTROLLER = "0xe22af1e6b78318e1Fe1053Edbd7209b8Fc62c4Fe"; +export const UNICHAINMAINNET_VTOKEN_BEACON = "0x42c1Efb9Dd9424c5ac8e6EcEa4eb03940c4a15Fc"; +export const UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION = "0x256E61f4056EC9eaB8c56E3aFa217a12c33b8893"; +export const UNICHAINMAINNET_DST_CHAIN_ID = LzChainId.unichainmainnet; + +export const UNICHAINMAINNET_CORE_VTOKENS = [ + "0xc219bc179c7cdb37eacb03f993f9fdc2495e3374", // vWETH_Core + "0xb953f92b9f759d97d2f2dec10a8a3cf75fce3a95", // vUSDC_Core + "0x67716d6bf76170af816f5735e14c4d44d0b05ed2", // vUNI_Core + "0x0170398083eb0d0387709523bafca6426146c218", // vweETH_Core + "0xbec19bef402c697a7be315d3e59e5f65b89fa1bb", // vwstETH_Core + "0x68e2a6f7257fac2f5a557b9e83e1fe6d5b408ce5", // vWBTC_Core + "0xda7ce7ba016d266645712e2e4ebc6cc75ea8e4cd", // vUSD₮0_Core +]; diff --git a/vips/vip-600/addresses/zksyncmainnet.ts b/vips/vip-600/addresses/zksyncmainnet.ts new file mode 100644 index 000000000..9b423d83a --- /dev/null +++ b/vips/vip-600/addresses/zksyncmainnet.ts @@ -0,0 +1,20 @@ +import { LzChainId } from "src/types"; + +export const ZKSYNCMAINNET_ACM = "0x526159A92A82afE5327d37Ef446b68FD9a5cA914"; +export const ZKSYNCMAINNET_NORMAL_TIMELOCK = "0x093565Bc20AA326F4209eBaF3a26089272627613"; +export const ZKSYNCMAINNET_CORE_COMPTROLLER = "0xddE4D098D9995B659724ae6d5E3FB9681Ac941B1"; +export const ZKSYNCMAINNET_VTOKEN_BEACON = "0x53523537aa330640B80400EB8B309fF5896E7eb5"; +export const ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION = "0x3e9cf1eBe018610585D0B519A9956C950E079591"; +export const ZKSYNCMAINNET_DST_CHAIN_ID = LzChainId.zksyncmainnet; + +export const ZKSYNCMAINNET_CORE_VTOKENS = [ + "0xaf8fd83cfcbe963211faaf1847f0f217f80b4719", // vWBTC_Core + "0x1fa916c27c7c2c4602124a14c77dbb40a5ff1be8", // vWETH_Core + "0x1af23bd57c62a99c59ad48236553d0dd11e49d2d", // vUSDC.e_Core + "0x69cda960e3b20dfd480866fffd377ebe40bd0a46", // vUSDT_Core + "0x697a70779c1a03ba2bd28b7627a902bff831b616", // vZK_Core + "0x84064c058f2efea4ab648bb6bd7e40f83ffde39a", // vUSDC_Core + "0x183de3c349fcf546aae925e1c7f364ea6fb4033c", // vwUSDM_Core, Paused + "0x03cad66259f7f34ee075f8b62d133563d249eda4", // vwstETH_Core + "0xceb7da150d16ace58f090754fef2775c23c8b631", // vzkETH_Core, Paused +]; diff --git a/vips/vip-600/bscmainnet-2.ts b/vips/vip-600/bscmainnet-2.ts new file mode 100644 index 000000000..a50dd0448 --- /dev/null +++ b/vips/vip-600/bscmainnet-2.ts @@ -0,0 +1,163 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +import { + ARBITRUMONE_ACM, + ARBITRUMONE_CORE_VTOKENS, + ARBITRUMONE_DST_CHAIN_ID, + ARBITRUMONE_NORMAL_TIMELOCK, +} from "./addresses/arbitrumone"; +import { + BASEMAINNET_ACM, + BASEMAINNET_CORE_VTOKENS, + BASEMAINNET_DST_CHAIN_ID, + BASEMAINNET_NORMAL_TIMELOCK, +} from "./addresses/basemainnet"; +import { + ETHEREUM_ACM, + ETHEREUM_CORE_VTOKENS, + ETHEREUM_DST_CHAIN_ID, + ETHEREUM_NORMAL_TIMELOCK, +} from "./addresses/ethereum"; +import { + OPBNBMAINNET_ACM, + OPBNBMAINNET_CORE_VTOKENS, + OPBNBMAINNET_DST_CHAIN_ID, + OPBNBMAINNET_NORMAL_TIMELOCK, +} from "./addresses/opbnbmainnet"; +import { + OPMAINNET_ACM, + OPMAINNET_CORE_VTOKENS, + OPMAINNET_DST_CHAIN_ID, + OPMAINNET_NORMAL_TIMELOCK, +} from "./addresses/opmainnet"; +import { + UNICHAINMAINNET_ACM, + UNICHAINMAINNET_CORE_VTOKENS, + UNICHAINMAINNET_DST_CHAIN_ID, + UNICHAINMAINNET_NORMAL_TIMELOCK, +} from "./addresses/unichainmainnet"; +import { + ZKSYNCMAINNET_ACM, + ZKSYNCMAINNET_CORE_VTOKENS, + ZKSYNCMAINNET_DST_CHAIN_ID, + ZKSYNCMAINNET_NORMAL_TIMELOCK, +} from "./addresses/zksyncmainnet"; + +interface NetworkConfig { + name: string; + acm: string; + normalTimelock: string; + dstChainId: number; + coreVTokens: string[]; +} + +const NETWORKS: NetworkConfig[] = [ + { + name: "Ethereum", + acm: ETHEREUM_ACM, + normalTimelock: ETHEREUM_NORMAL_TIMELOCK, + dstChainId: ETHEREUM_DST_CHAIN_ID, + coreVTokens: ETHEREUM_CORE_VTOKENS, + }, + { + name: "Arbitrum", + acm: ARBITRUMONE_ACM, + normalTimelock: ARBITRUMONE_NORMAL_TIMELOCK, + dstChainId: ARBITRUMONE_DST_CHAIN_ID, + coreVTokens: ARBITRUMONE_CORE_VTOKENS, + }, + { + name: "Optimism", + acm: OPMAINNET_ACM, + normalTimelock: OPMAINNET_NORMAL_TIMELOCK, + dstChainId: OPMAINNET_DST_CHAIN_ID, + coreVTokens: OPMAINNET_CORE_VTOKENS, + }, + { + name: "Base", + acm: BASEMAINNET_ACM, + normalTimelock: BASEMAINNET_NORMAL_TIMELOCK, + dstChainId: BASEMAINNET_DST_CHAIN_ID, + coreVTokens: BASEMAINNET_CORE_VTOKENS, + }, + { + name: "opBNB", + acm: OPBNBMAINNET_ACM, + normalTimelock: OPBNBMAINNET_NORMAL_TIMELOCK, + dstChainId: OPBNBMAINNET_DST_CHAIN_ID, + coreVTokens: OPBNBMAINNET_CORE_VTOKENS, + }, + { + name: "Unichain", + acm: UNICHAINMAINNET_ACM, + normalTimelock: UNICHAINMAINNET_NORMAL_TIMELOCK, + dstChainId: UNICHAINMAINNET_DST_CHAIN_ID, + coreVTokens: UNICHAINMAINNET_CORE_VTOKENS, + }, + { + name: "ZkSync", + acm: ZKSYNCMAINNET_ACM, + normalTimelock: ZKSYNCMAINNET_NORMAL_TIMELOCK, + dstChainId: ZKSYNCMAINNET_DST_CHAIN_ID, + coreVTokens: ZKSYNCMAINNET_CORE_VTOKENS, + }, +]; + +export const vip601 = () => { + const meta = { + version: "v2", + title: "VIP-601 [Non-BNB Chain] VToken Inflation Attack Patch and Pause Borrowing Across All Markets (part2)", + description: `This VIP upgrades all VToken market implementations across the seven non-BNB Chain Venus Isolated Pool deployments to patch the donation (exchange rate inflation) attack vulnerability identified following the THE token incident on BNB Chain (March 15, 2026). The companion BNB Chain fix is covered in a separate VIP. + +The root cause is that _getCashPrior() previously returned IERC20(underlying).balanceOf(address(this)), which allowed any party to artificially inflate the reported cash — and therefore the exchange rate — by transferring tokens directly to a VToken contract without minting shares. + +The fix replaces this with an internalCash storage variable that is only updated by _doTransferIn, _doTransferOut, and badDebtRecovered(). A one-time syncCash() function, gated by the AccessControlManager (ACM), initializes internalCash to the real underlying balance after the upgrade. syncCash() remains callable post-migration for future reconciliation (e.g., airdrops or direct transfers). + +A secondary measure, pausing borrowing across all affected markets, was deployed to limit exposure while this patch is prepared. Supply, repay, and withdraw functions were not affected by that pause and continue to operate normally. If this VIP passes, borrowing will be restored across all previously paused non-BNB-chain VToken markets. + +#### Changes + +**1. Grant syncCash() permission to the Normal Timelock for each VToken on all non-BNB Chain Isolated Pool deployments** + +Networks: Arbitrum One, Base Mainnet, Ethereum Mainnet, opBNB Mainnet, OP Mainnet, Unichain Mainnet, zkSync Mainnet + +- **Function**: AccessControlManager.giveCallPermission(vToken, "syncCash()", normalTimelock) +- **Effect**: Authorizes the Normal Timelock to call syncCash() on each VToken market, which is required before the implementation upgrade and cash initialization in VIP-602 + +#### Summary + +If approved, this VIP will: +- Grant syncCash() call permissions to the Normal Timelock for all VToken markets on Arbitrum One, Base Mainnet, Ethereum Mainnet, opBNB Mainnet, OP Mainnet, Unichain Mainnet, and zkSync Mainnet +- Enable the subsequent VIP-602 to upgrade the VToken beacon and initialize internalCash via syncCash() on all affected markets + +#### References + +- GitHub PR (Isolated Pools patch): [https://github.com/VenusProtocol/isolated-pools/pull/551](https://github.com/VenusProtocol/isolated-pools/pull/551) +- Allez Labs Post-Mortem: [https://community.venus.io/t/the-market-incident-post-mortem/5712](https://community.venus.io/t/the-market-incident-post-mortem/5712) + +**Voting options** +- For - I agree that Venus Protocol should proceed with this proposal +- Against - I do not think that Venus Protocol should proceed with this proposal +- Abstain - I am indifferent to whether Venus Protocol proceeds or not`, + 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( + NETWORKS.flatMap(({ acm, normalTimelock, dstChainId, coreVTokens }) => + // Grant syncCash() permission to the Normal Timelock for each VToken + coreVTokens.map(vToken => ({ + target: acm, + signature: "giveCallPermission(address,string,address)", + params: [vToken, "syncCash()", normalTimelock], + dstChainId, + })), + ), + meta, + ProposalType.REGULAR, + ); +}; + +export default vip601; diff --git a/vips/vip-600/bscmainnet-3.ts b/vips/vip-600/bscmainnet-3.ts new file mode 100644 index 000000000..3fab6965f --- /dev/null +++ b/vips/vip-600/bscmainnet-3.ts @@ -0,0 +1,195 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +import { + ARBITRUMONE_CORE_VTOKENS, + ARBITRUMONE_DST_CHAIN_ID, + ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION, + ARBITRUMONE_VTOKEN_BEACON, +} from "./addresses/arbitrumone"; +import { + BASEMAINNET_CORE_VTOKENS, + BASEMAINNET_DST_CHAIN_ID, + BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION, + BASEMAINNET_VTOKEN_BEACON, +} from "./addresses/basemainnet"; +import { + ETHEREUM_CORE_VTOKENS, + ETHEREUM_DST_CHAIN_ID, + ETHEREUM_NEW_VTOKEN_IMPLEMENTATION, + ETHEREUM_VTOKEN_BEACON, +} from "./addresses/ethereum"; +import { + OPBNBMAINNET_CORE_VTOKENS, + OPBNBMAINNET_DST_CHAIN_ID, + OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION, + OPBNBMAINNET_VTOKEN_BEACON, +} from "./addresses/opbnbmainnet"; +import { + OPMAINNET_CORE_VTOKENS, + OPMAINNET_DST_CHAIN_ID, + OPMAINNET_NEW_VTOKEN_IMPLEMENTATION, + OPMAINNET_VTOKEN_BEACON, +} from "./addresses/opmainnet"; +import { + UNICHAINMAINNET_CORE_VTOKENS, + UNICHAINMAINNET_DST_CHAIN_ID, + UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION, + UNICHAINMAINNET_VTOKEN_BEACON, +} from "./addresses/unichainmainnet"; +import { + ZKSYNCMAINNET_CORE_VTOKENS, + ZKSYNCMAINNET_DST_CHAIN_ID, + ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION, + ZKSYNCMAINNET_VTOKEN_BEACON, +} from "./addresses/zksyncmainnet"; + +interface NetworkConfig { + name: string; + vTokenBeacon: string; + newImplementation: string; + dstChainId: number; + coreVTokens: string[]; +} + +const NETWORKS: NetworkConfig[] = [ + { + name: "Ethereum", + vTokenBeacon: ETHEREUM_VTOKEN_BEACON, + newImplementation: ETHEREUM_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: ETHEREUM_DST_CHAIN_ID, + coreVTokens: ETHEREUM_CORE_VTOKENS, + }, + { + name: "Arbitrum", + vTokenBeacon: ARBITRUMONE_VTOKEN_BEACON, + newImplementation: ARBITRUMONE_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: ARBITRUMONE_DST_CHAIN_ID, + coreVTokens: ARBITRUMONE_CORE_VTOKENS, + }, + { + name: "Optimism", + vTokenBeacon: OPMAINNET_VTOKEN_BEACON, + newImplementation: OPMAINNET_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: OPMAINNET_DST_CHAIN_ID, + coreVTokens: OPMAINNET_CORE_VTOKENS, + }, + { + name: "Base", + vTokenBeacon: BASEMAINNET_VTOKEN_BEACON, + newImplementation: BASEMAINNET_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: BASEMAINNET_DST_CHAIN_ID, + coreVTokens: BASEMAINNET_CORE_VTOKENS, + }, + { + name: "opBNB", + vTokenBeacon: OPBNBMAINNET_VTOKEN_BEACON, + newImplementation: OPBNBMAINNET_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: OPBNBMAINNET_DST_CHAIN_ID, + coreVTokens: OPBNBMAINNET_CORE_VTOKENS, + }, + { + name: "Unichain", + vTokenBeacon: UNICHAINMAINNET_VTOKEN_BEACON, + newImplementation: UNICHAINMAINNET_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: UNICHAINMAINNET_DST_CHAIN_ID, + coreVTokens: UNICHAINMAINNET_CORE_VTOKENS, + }, + { + name: "ZkSync", + vTokenBeacon: ZKSYNCMAINNET_VTOKEN_BEACON, + newImplementation: ZKSYNCMAINNET_NEW_VTOKEN_IMPLEMENTATION, + dstChainId: ZKSYNCMAINNET_DST_CHAIN_ID, + coreVTokens: ZKSYNCMAINNET_CORE_VTOKENS, + }, +]; + +export const vip602 = () => { + const meta = { + version: "v2", + title: "VIP-602 [Non-BNB Chain] VToken Inflation Attack Patch and Pause Borrowing Across All Markets (part3)", + description: `This VIP upgrades all VToken market implementations across the seven non-BNB Chain Venus Isolated Pool deployments to patch the donation (exchange rate inflation) attack vulnerability identified following the THE token incident on BNB Chain (March 15, 2026). The companion BNB Chain fix is covered in a separate VIP (VIP-600). + +The root cause is that _getCashPrior() previously returned IERC20(underlying).balanceOf(address(this)), which allowed any party to artificially inflate the reported cash — and therefore the exchange rate — by transferring tokens directly to a VToken contract without minting shares. + +The fix replaces this with an internalCash storage variable that is only updated by _doTransferIn, _doTransferOut, and badDebtRecovered(). A one-time syncCash() function, gated by the AccessControlManager (ACM), initializes internalCash to the real underlying balance after the upgrade. syncCash() remains callable post-migration for future reconciliation (e.g., airdrops or direct transfers). + +A secondary measure, pausing borrowing across all affected markets, was deployed to limit exposure while this patch is prepared. Supply, repay, and withdraw functions were not affected by that pause and continue to operate normally. If this VIP passes, borrowing will be restored across all previously paused non-BNB-chain VToken markets. + +#### Changes + +**1. Upgrade VToken implementation on all non-BNB Chain Isolated Pool deployments** + +Networks: Arbitrum One, Base Mainnet, Ethereum Mainnet, opBNB Mainnet, OP Mainnet, Unichain Mainnet, zkSync Mainnet + +- **Beacon upgrade**: VTokenBeacon.upgradeTo(newVTokenImpl) per network +- **Effect**: All VToken proxies on each network begin using the new implementation, which tracks internalCash instead of calling balanceOf(address(this)) in _getCashPrior() + +**2. Contract changes in the new VToken implementation** + +- VTokenStorage: adds uint256 public internalCash (storage gap reduced from 48 to 47) +- _getCashPrior(): returns internalCash instead of IERC20(underlying).balanceOf(address(this)) +- _doTransferIn(): increments internalCash by the actual amount received (balance delta, handles fee-on-transfer tokens) +- _doTransferOut(): decrements internalCash before transfer +- badDebtRecovered(uint256 recoveredAmount_): increments internalCash to keep cash accounting correct during bad debt recovery via Shortfall auctions +- syncCash(): ACM-gated, nonReentrant; sets internalCash = IERC20(underlying).balanceOf(address(this)); emits CashSynced(uint256 oldCash, uint256 newCash) +- VTokenInterface: adds CashSynced event and syncCash() signature + +**3. Initialize internalCash via syncCash() on all markets across all seven networks** + +- **Function**: syncCash() +- **Caller**: ACM-authorized governance timelock +- **Per market per network**: one call per VToken market +- **Effect**: Sets internalCash to the current real underlying balance, bootstrapping the internal accounting post-upgrade + +**4. Unpause borrowing across all affected markets** + +- Reverses the precautionary borrow pause applied in the preceding VIP +- Supply, repay, and withdraw were never affected +- Applies per market per network across all seven chains + +#### Summary + +If approved, this VIP will: +- Upgrade all non-BNB Chain VToken implementations to replace balanceOf-based cash reporting with the internalCash variable, making exchange rate calculations immune to direct token donations +- Call syncCash() on every market post-upgrade to initialize internalCash to the real underlying balance +- Restore borrowing across all previously paused VToken markets on Arbitrum One, Base Mainnet, Ethereum Mainnet, opBNB Mainnet, OP Mainnet, Unichain Mainnet, and zkSync Mainnet +- Ensure badDebtRecovered() correctly updates internalCash during Shortfall auction settlements to prevent exchange rate drift + +#### References + +- GitHub PR (Isolated Pools patch): [https://github.com/VenusProtocol/isolated-pools/pull/551](https://github.com/VenusProtocol/isolated-pools/pull/551) +- Allez Labs Post-Mortem: [https://community.venus.io/t/the-market-incident-post-mortem/5712](https://community.venus.io/t/the-market-incident-post-mortem/5712) + +**Voting options** +- For - I agree that Venus Protocol should proceed with this proposal +- Against - I do not think that Venus Protocol should proceed with this proposal +- Abstain - I am indifferent to whether Venus Protocol proceeds or not`, + 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( + NETWORKS.flatMap(({ vTokenBeacon, newImplementation, dstChainId, coreVTokens }) => [ + // Upgrade the beacon to the new implementation + { + target: vTokenBeacon, + signature: "upgradeTo(address)", + params: [newImplementation], + dstChainId, + }, + // Call syncCash on each VToken to initialize internalCash + ...coreVTokens.map(vToken => ({ + target: vToken, + signature: "syncCash()", + params: [], + dstChainId, + })), + ]), + meta, + ProposalType.REGULAR, + ); +}; + +export default vip602; diff --git a/vips/vip-600/bscmainnet.ts b/vips/vip-600/bscmainnet.ts new file mode 100644 index 000000000..b6f4238cc --- /dev/null +++ b/vips/vip-600/bscmainnet.ts @@ -0,0 +1,166 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const NEW_VBEP20_DELEGATE_IMPL = "0xb25b57599BA969c4829699F7E4Fc4076D14745E1"; + +// VBep20Delegator proxy addresses (43 markets, excludes vBNB) +const vUSDC = "0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8"; +const vUSDT = "0xfD5840Cd36d94D7229439859C0112a4185BC0255"; +const vBUSD = "0x95c78222B3D6e262426483D42CfA53685A67Ab9D"; +const vSXP = "0x2fF3d0F6990a40261c66E1ff2017aCBc282EB6d0"; +const vXVS = "0x151B1e2635A717bcDc836ECd6FbB62B674FE3E1D"; +const vBTC = "0x882C173bC7Ff3b7786CA16dfeD3DFFfb9Ee7847B"; +const vETH = "0xf508fCD89b8bd15579dc79A6827cB4686A3592c8"; +const vLTC = "0x57A5297F2cB2c0AaC9D554660acd6D385Ab50c6B"; +const vXRP = "0xB248a295732e0225acd3337607cc01068e3b9c10"; +const vBCH = "0x5F0388EBc2B94FA8E123F404b79cCF5f40b29176"; +const vDOT = "0x1610bc33319e9398de5f57B33a5b184c806aD217"; +const vLINK = "0x650b940a1033B8A1b1873f78730FcFC73ec11f1f"; +const vDAI = "0x334b3eCB4DCa3593BCCC3c7EBD1A1C1d1780FBF1"; +const vFIL = "0xf91d58b5aE142DAcC749f58A49FCBac340Cb0343"; +const vBETH = "0x972207A639CC1B374B893cc33Fa251b55CEB7c07"; +const vADA = "0x9A0AF7FDb2065Ce470D72664DE73cAE409dA28Ec"; +const vDOGE = "0xec3422Ef92B2fb59e84c8B02Ba73F1fE84Ed8D71"; +const vMATIC = "0x5c9476FcD6a4F9a3654139721c949c2233bBbBc8"; +const vCAKE = "0x86aC3974e2BD0d60825230fa6F355fF11409df5c"; +const vAAVE = "0x26DA28954763B92139ED49283625ceCAf52C6f94"; +const vTUSDOLD = "0x08CEB3F4a7ed3500cA0982bcd0FC7816688084c3"; +const vTRXOLD = "0x61eDcFe8Dd6bA3c891CB9bEc2dc7657B3B422E93"; +const vTRX = "0xC5D3466aA484B040eE977073fcF337f2c00071c1"; +const vWBETH = "0x6CFdEc747f37DAf3b87a35a1D9c8AD3063A1A8A0"; +const vTUSD = "0xBf762cd5991cA1DCdDaC9ae5C638F5B5Dc3Bee6E"; +const vUNI = "0x27FF564707786720C71A2e5c1490A63266683612"; +const vFDUSD = "0xC4eF4229FEc74Ccfe17B2bdeF7715fAC740BA0ba"; +const vTWT = "0x4d41a36D04D97785bcEA57b057C412b278e6Edcc"; +const vSolvBTC = "0xf841cb62c19fCd4fF5CD0AaB5939f3140BaaC3Ea"; +const vTHE = "0x86e06EAfa6A1eA631Eab51DE500E3D474933739f"; +const vSOL = "0xBf515bA4D1b52FFdCeaBF20d31D705Ce789F2cEC"; +const vlisUSD = "0x689E0daB47Ab16bcae87Ec18491692BF621Dc6Ab"; +const vPT_sUSDE_26JUN2025 = "0x9e4E5fed5Ac5B9F732d0D850A615206330Bf1866"; +const vsUSDe = "0x699658323d58eE25c69F1a29d476946ab011bD18"; +const vUSDe = "0x74ca6930108F775CC667894EEa33843e691680d7"; +const vUSD1 = "0x0C1DA220D301155b87318B90692Da8dc43B67340"; +const vxSolvBTC = "0xd804dE60aFD05EE6B89aab5D152258fD461B07D5"; +const vasBNB = "0xCC1dB43a06d97f736C7B045AedD03C6707c09BDF"; +const vWBNB = "0x6bCa74586218dB34cdB402295796b79663d816e9"; +const vslisBNB = "0x89c910Eb8c90df818b4649b508Ba22130Dc73Adc"; +const vU = "0x3d5E269787d562b74aCC55F18Bd26C5D09Fa245E"; +const vPT_clisBNB_25JUN2026 = "0x6d3BD68E90B42615cb5abF4B8DE92b154ADc435e"; +const vXAUM = "0x92e6Ea74a1A3047DabF4186405a21c7D63a0612A"; + +// Markets and their excess token amounts to sweep before syncing +interface MarketConfig { + vToken: string; + name: string; + excessAmount: string; +} + +const MARKETS: MarketConfig[] = [ + { vToken: vUSDC, name: "vUSDC", excessAmount: "0" }, + { vToken: vUSDT, name: "vUSDT", excessAmount: "0" }, + { vToken: vBUSD, name: "vBUSD", excessAmount: "0" }, + { vToken: vSXP, name: "vSXP", excessAmount: "0" }, + { vToken: vXVS, name: "vXVS", excessAmount: "0" }, + { vToken: vBTC, name: "vBTC", excessAmount: "0" }, + { vToken: vETH, name: "vETH", excessAmount: "0" }, + { vToken: vLTC, name: "vLTC", excessAmount: "0" }, + { vToken: vXRP, name: "vXRP", excessAmount: "0" }, + { vToken: vBCH, name: "vBCH", excessAmount: "0" }, + { vToken: vDOT, name: "vDOT", excessAmount: "0" }, + { vToken: vLINK, name: "vLINK", excessAmount: "0" }, + { vToken: vDAI, name: "vDAI", excessAmount: "0" }, + { vToken: vFIL, name: "vFIL", excessAmount: "0" }, + { vToken: vBETH, name: "vBETH", excessAmount: "0" }, + { vToken: vADA, name: "vADA", excessAmount: "0" }, + { vToken: vDOGE, name: "vDOGE", excessAmount: "0" }, + { vToken: vMATIC, name: "vMATIC", excessAmount: "0" }, + { vToken: vCAKE, name: "vCAKE", excessAmount: "0" }, + { vToken: vAAVE, name: "vAAVE", excessAmount: "0" }, + { vToken: vTUSDOLD, name: "vTUSDOLD", excessAmount: "0" }, + { vToken: vTRXOLD, name: "vTRXOLD", excessAmount: "0" }, + { vToken: vTRX, name: "vTRX", excessAmount: "0" }, + { vToken: vWBETH, name: "vWBETH", excessAmount: "0" }, + { vToken: vTUSD, name: "vTUSD", excessAmount: "0" }, + { vToken: vUNI, name: "vUNI", excessAmount: "0" }, + { vToken: vFDUSD, name: "vFDUSD", excessAmount: "0" }, + { vToken: vTWT, name: "vTWT", excessAmount: "0" }, + { vToken: vSolvBTC, name: "vSolvBTC", excessAmount: "0" }, + { vToken: vTHE, name: "vTHE", excessAmount: "0" }, + { vToken: vSOL, name: "vSOL", excessAmount: "0" }, + { vToken: vlisUSD, name: "vlisUSD", excessAmount: "0" }, + { vToken: vPT_sUSDE_26JUN2025, name: "vPT-sUSDE-26JUN2025", excessAmount: "0" }, + { vToken: vsUSDe, name: "vsUSDe", excessAmount: "0" }, + { vToken: vUSDe, name: "vUSDe", excessAmount: "0" }, + { vToken: vUSD1, name: "vUSD1", excessAmount: "0" }, + { vToken: vxSolvBTC, name: "vxSolvBTC", excessAmount: "0" }, + { vToken: vasBNB, name: "vasBNB", excessAmount: "0" }, + { vToken: vWBNB, name: "vWBNB", excessAmount: "0" }, + { vToken: vslisBNB, name: "vslisBNB", excessAmount: "0" }, + { vToken: vU, name: "vU", excessAmount: "0" }, + { vToken: vPT_clisBNB_25JUN2026, name: "vPT-clisBNB-25JUN2026", excessAmount: "0" }, + { vToken: vXAUM, name: "vXAUM", excessAmount: "0" }, +]; + +export const vip600 = () => { + const meta = { + version: "v2", + title: "VIP-600 [BNB Chain] VToken Inflation Attack Patch (part1)", + description: `This VIP upgrades the VBep20Delegate implementation across all 43 BNB Chain core pool VBep20 markets to patch the donation attack vulnerability identified in the THE market incident. The root cause is in getCashPrior() within VBep20.sol, which previously returned IERC20(underlying).balanceOf(address(this)) — an actual on-chain balance that any external actor can inflate by transferring tokens directly to the vToken contract address. The inflated cash distorts the exchange rate formula ((getCashPrior() + totalBorrows - totalReserves) / totalSupply), enabling exchange rate manipulation and first-depositor attacks. + +The fix replaces balance-based cash accounting with an internalCash storage variable that is only updated through protocol-controlled operations (doTransferIn and doTransferOut). Direct token donations can no longer affect getCashPrior() or the exchange rate. A new admin-gated sweepTokenAndSync() function is called atomically in the same VIP to initialise internalCash after each market's implementation upgrade, and to recover any excess donated tokens to the Timelock. + +The 43 affected markets are all VBep20Delegator core pool proxies on BSC mainnet. vBNB is excluded as it is a native BNB market and not subject to this vulnerability. + +#### Changes + +1. **Upgrade VBep20Delegate implementation for all 43 core pool markets** + - Function: proxy._setImplementation(newImpl, false, "0x") + - Points each VBep20Delegator proxy to the new VBep20Delegate implementation containing internal cash tracking + - Markets covered include major stablecoins (vUSDC, vUSDT, vBUSD, vFDUSD, vTUSD, vDAI, vUSDe, vsUSDe, vUSD1), blue-chip assets (vBTC, vETH, vBNB-variants), DeFi tokens (vXVS, vCAKE, vAAVE, vUNI, vLINK), LST/LRT products (vWBETH, vasBNB, vslisBNB, vSolvBTC, vxSolvBTC), and others including vTHE. +2. **Call sweepTokenAndSync(excessAmount) on each upgraded market** + - Function: proxy.sweepTokenAndSync(uint256 transferAmount) + - Must be executed atomically in the same VIP as the implementation upgrade + - Pass 0 for markets with no excess tokens; pass the excess amount for markets with prior donations (e.g. vTHE) to transfer excess to the Timelock before syncing + - Initialises internalCash to match balanceOf(address(this)) post-upgrade + +#### Summary + +If approved, this VIP will: +- Upgrade the VBep20Delegate implementation for all 43 BNB Chain core pool VBep20 markets to use internal cash tracking +- Close the donation attack vector by making getCashPrior() immune to direct token transfers +- Initialise internalCash on all upgraded markets via sweepTokenAndSync() in the same transaction +- Recover any excess donated tokens (including from the vTHE exploit) to the Timelock + +#### References + +- GitHub PR (Core Pool): [https://github.com/VenusProtocol/venus-protocol/pull/664](https://github.com/VenusProtocol/venus-protocol/pull/664) +- Allez Labs Post-Mortem: [https://community.venus.io/t/the-market-incident-post-mortem/5712](https://community.venus.io/t/the-market-incident-post-mortem/5712) + +**Voting options** +- For - I agree that Venus Protocol should proceed with this proposal +- Against - I do not think that Venus Protocol should proceed with this proposal +- Abstain - I am indifferent to whether Venus Protocol proceeds or not`, + 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( + MARKETS.flatMap(({ vToken, excessAmount }) => [ + { + target: vToken, + signature: "_setImplementation(address,bool,bytes)", + params: [NEW_VBEP20_DELEGATE_IMPL, false, "0x"], + }, + { + target: vToken, + signature: "sweepTokenAndSync(uint256)", + params: [excessAmount], + }, + ]), + meta, + ProposalType.REGULAR, + ); +}; + +export default vip600;