From aba4f1078e07745e88c1c1314e59b5b7b744e20b Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Mon, 8 Jun 2026 20:13:26 +0530 Subject: [PATCH 01/10] feat: scaffold for adding new markets on BSC Chain --- .../vip-669/abi/AccessControlManager.json | 23 + simulations/vip-669/abi/AtlasOracle.json | 568 +++ simulations/vip-669/abi/Comptroller.json | 4145 +++++++++++++++++ simulations/vip-669/abi/ERC20.json | 134 + simulations/vip-669/abi/ResilientOracle.json | 320 ++ simulations/vip-669/abi/VToken.json | 870 ++++ simulations/vip-669/abi/VTreasury.json | 83 + simulations/vip-669/bscmainnet.ts | 158 + simulations/vip-669/bsctestnet.ts | 158 + vips/vip-669/bscmainnet.ts | 296 ++ vips/vip-669/bsctestnet.ts | 292 ++ 11 files changed, 7047 insertions(+) create mode 100644 simulations/vip-669/abi/AccessControlManager.json create mode 100644 simulations/vip-669/abi/AtlasOracle.json create mode 100644 simulations/vip-669/abi/Comptroller.json create mode 100644 simulations/vip-669/abi/ERC20.json create mode 100644 simulations/vip-669/abi/ResilientOracle.json create mode 100644 simulations/vip-669/abi/VToken.json create mode 100644 simulations/vip-669/abi/VTreasury.json create mode 100644 simulations/vip-669/bscmainnet.ts create mode 100644 simulations/vip-669/bsctestnet.ts create mode 100644 vips/vip-669/bscmainnet.ts create mode 100644 vips/vip-669/bsctestnet.ts diff --git a/simulations/vip-669/abi/AccessControlManager.json b/simulations/vip-669/abi/AccessControlManager.json new file mode 100644 index 000000000..6fe053ac3 --- /dev/null +++ b/simulations/vip-669/abi/AccessControlManager.json @@ -0,0 +1,23 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "account", "type": "address" }, + { "internalType": "address", "name": "contractAddress", "type": "address" }, + { "internalType": "string", "name": "functionSig", "type": "string" } + ], + "name": "hasPermission", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "account", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "contractAddress", "type": "address" }, + { "indexed": false, "internalType": "string", "name": "functionSig", "type": "string" } + ], + "name": "PermissionGranted", + "type": "event" + } +] diff --git a/simulations/vip-669/abi/AtlasOracle.json b/simulations/vip-669/abi/AtlasOracle.json new file mode 100644 index 000000000..6f0d082e6 --- /dev/null +++ b/simulations/vip-669/abi/AtlasOracle.json @@ -0,0 +1,568 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "previousPriceMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newPriceMantissa", + "type": "uint256" + } + ], + "name": "PricePosted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "inputs": [], + "name": "BNB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "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": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "prices", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "setDirectPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "internalType": "struct ChainlinkOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VBep20Interface", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "underlyingPriceMantissa", + "type": "uint256" + } + ], + "name": "setUnderlyingPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "feed", + "type": "address" + }, + { + "internalType": "uint256", + "name": "maxStalePeriod", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBnb", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] \ No newline at end of file diff --git a/simulations/vip-669/abi/Comptroller.json b/simulations/vip-669/abi/Comptroller.json new file mode 100644 index 000000000..5ca3a7000 --- /dev/null +++ b/simulations/vip-669/abi/Comptroller.json @@ -0,0 +1,4145 @@ +[ + { + "inputs": [], + "name": "AlreadyInSelectedPool", + "type": "error" + }, + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowNotAllowedInPool", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPoolLabel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "InactivePool", + "type": "error" + }, + { + "inputs": [], + "name": "IncompatibleBorrowedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOperationForCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WeightFunction", + "name": "strategy", + "type": "uint8" + } + ], + "name": "InvalidWeightingStrategy", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "name": "LiquidityCheckFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketConfigNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotListedInCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "PoolDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketNotFound", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "ActionProtocolPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "BorrowAllowedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "approver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "DelegateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledForUserUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketUnlisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldComptrollerLens", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newComptrollerLens", + "type": "address" + } + ], + "name": "NewComptrollerLens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationThresholdMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldLiquidatorContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newLiquidatorContract", + "type": "address" + } + ], + "name": "NewLiquidatorContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "oldVAIController", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "newVAIController", + "type": "address" + } + ], + "name": "NewVAIController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVAIMintRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "NewVAIMintRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseInterval_", + "type": "uint256" + } + ], + "name": "NewVAIVaultInfo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIVaultRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIVaultRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIVaultRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVS", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVS", + "type": "address" + } + ], + "name": "NewXVSToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVSVToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVSVToken", + "type": "address" + } + ], + "name": "NewXVSVToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolActiveStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolFallbackStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldLabel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "PoolLabelUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "PoolMarketInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "previousPoolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "uint96", + "name": "newPoolId", + "type": "uint96" + } + ], + "name": "PoolSelected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusSeized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusSupplySpeedUpdated", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "_grantXVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "_setAccessControl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "_setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptrollerLens_", + "type": "address" + } + ], + "name": "_setComptrollerLens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidationForUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newLiquidatorContract_", + "type": "address" + } + ], + "name": "_setLiquidatorContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "_setPauseGuardian", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "_setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "_setProtocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "vaiController_", + "type": "address" + } + ], + "name": "_setVAIController", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "_setVAIMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minReleaseAmount_", + "type": "uint256" + } + ], + "name": "_setVAIVaultInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "_setVenusSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "venusVAIVaultRate_", + "type": "uint256" + } + ], + "name": "_setVenusVAIVaultRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvs_", + "type": "address" + } + ], + "name": "_setXVSToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvsVToken_", + "type": "address" + } + ], + "name": "_setXVSVToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96[]", + "name": "poolIds", + "type": "uint96[]" + }, + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "addPoolMarkets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "collateral", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenusAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "corePoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "enterPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getBorrowingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getEffectiveLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "enum WeightFunction", + "name": "weightingStrategy", + "type": "uint8" + } + ], + "name": "getEffectiveLtvFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getPoolMarketIndex", + "outputs": [ + { + "internalType": "PoolMarketId", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "getPoolVTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSVTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint96", + "name": "targetPoolId", + "type": "uint96" + } + ], + "name": "hasValidPoolBorrows", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabledForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateVAICalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "poolMarkets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "allowCorePoolFallback", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "removePoolMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "seizeVenus", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "allowFallback", + "type": "bool" + } + ], + "name": "setAllowCorePoolFallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "borrowAllowed", + "type": "bool" + } + ], + "name": "setIsBorrowAllowed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMintedVAIOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "name": "setPoolActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "setPoolLabel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "unlistMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-669/abi/ERC20.json b/simulations/vip-669/abi/ERC20.json new file mode 100644 index 000000000..3a509c9c4 --- /dev/null +++ b/simulations/vip-669/abi/ERC20.json @@ -0,0 +1,134 @@ +[ + { + "inputs": [ + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "uint8", "name": "decimals_", "type": "uint8" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Approval", + "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": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "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": "account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "subtractedValue", "type": "uint256" } + ], + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }], + "name": "faucet", + "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": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-669/abi/ResilientOracle.json b/simulations/vip-669/abi/ResilientOracle.json new file mode 100644 index 000000000..373eb14e9 --- /dev/null +++ b/simulations/vip-669/abi/ResilientOracle.json @@ -0,0 +1,320 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "nativeMarketAddress", "type": "address" }, + { "internalType": "address", "name": "vaiAddress", "type": "address" }, + { "internalType": "contract BoundValidatorInterface", "name": "_boundValidator", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "calledContract", "type": "address" }, + { "internalType": "string", "name": "methodSignature", "type": "string" } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "name": "CachedEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAccessControlManager", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlManager", "type": "address" } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "role", "type": "uint256" }, + { "indexed": true, "internalType": "bool", "name": "enable", "type": "bool" } + ], + "name": "OracleEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "oracle", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "role", "type": "uint256" } + ], + "name": "OracleSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "address", "name": "account", "type": "address" }], + "name": "Paused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "mainOracle", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "pivotOracle", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "fallbackOracle", "type": "address" } + ], + "name": "TokenConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "address", "name": "account", "type": "address" }], + "name": "Unpaused", + "type": "event" + }, + { + "inputs": [], + "name": "CACHE_SLOT", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INVALID_PRICE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boundValidator", + "outputs": [{ "internalType": "contract BoundValidatorInterface", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" }, + { "internalType": "bool", "name": "enable", "type": "bool" } + ], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" } + ], + "name": "getOracle", + "outputs": [ + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "bool", "name": "enabled", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "getPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "getTokenConfig", + "outputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], + "name": "getUnderlyingPrice", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "pause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "paused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "unpause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], + "name": "updateAssetPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-669/abi/VToken.json b/simulations/vip-669/abi/VToken.json new file mode 100644 index 000000000..68f428c6c --- /dev/null +++ b/simulations/vip-669/abi/VToken.json @@ -0,0 +1,870 @@ +[ + { "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": "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": "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": "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": [], + "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-669/abi/VTreasury.json b/simulations/vip-669/abi/VTreasury.json new file mode 100644 index 000000000..df5a655ee --- /dev/null +++ b/simulations/vip-669/abi/VTreasury.json @@ -0,0 +1,83 @@ +[ + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "tokenAddress", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "withdrawAmount", "type": "uint256" }, + { "indexed": false, "internalType": "address", "name": "withdrawAddress", "type": "address" } + ], + "name": "WithdrawTreasuryBEP20", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "withdrawAmount", "type": "uint256" }, + { "indexed": false, "internalType": "address", "name": "withdrawAddress", "type": "address" } + ], + "name": "WithdrawTreasuryBNB", + "type": "event" + }, + { "payable": true, "stateMutability": "payable", "type": "fallback" }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" }, + { "internalType": "uint256", "name": "withdrawAmount", "type": "uint256" }, + { "internalType": "address", "name": "withdrawAddress", "type": "address" } + ], + "name": "withdrawTreasuryBEP20", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "uint256", "name": "withdrawAmount", "type": "uint256" }, + { "internalType": "address payable", "name": "withdrawAddress", "type": "address" } + ], + "name": "withdrawTreasuryBNB", + "outputs": [], + "payable": true, + "stateMutability": "payable", + "type": "function" + } +] diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts new file mode 100644 index 000000000..20332370e --- /dev/null +++ b/simulations/vip-669/bscmainnet.ts @@ -0,0 +1,158 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; +import { checkRiskParameters } from "src/vip-framework/checks/checkRiskParameters"; +import { checkVToken } from "src/vip-framework/checks/checkVToken"; +import { checkInterestRate } from "src/vip-framework/checks/interestRateModel"; + +import { + ATLAS_ORACLE, + MARKETS, + PROTOCOL_SHARE_RESERVE, + REDUCE_RESERVES_BLOCK_DELTA, + convertAmountToVTokens, + vTokensRemaining, + vip669, +} from "../../vips/vip-669/bscmainnet"; +import ATLAS_ORACLE_ABI from "./abi/AtlasOracle.json"; +import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; +import VTOKEN_ABI from "./abi/VToken.json"; +import VTREASURY_ABI from "./abi/VTreasury.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +// TODO(pre-deployment): set the fork block to one after the markets are deployed. +const FORK_BLOCK = 83432607; + +forking(FORK_BLOCK, async () => { + const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); + const resilientOracle = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider); + const atlasOracle = new ethers.Contract(ATLAS_ORACLE, ATLAS_ORACLE_ABI, ethers.provider); + + describe("Pre-VIP behavior", async () => { + for (const m of MARKETS) { + it(`check ${m.vToken.symbol} market not listed`, async () => { + const market = await comptroller.markets(m.vToken.address); + expect(market.isListed).to.equal(false); + }); + } + }); + + testVip("VIP-669", await vip669(), { + callbackAfterExecution: async txResponse => { + await expectEvents( + txResponse, + [COMPTROLLER_ABI, VTOKEN_ABI, VTREASURY_ABI], + [ + "MarketListed", + "NewSupplyCap", + "NewBorrowCap", + "BorrowAllowedUpdated", + "NewAccessControlManager", + "NewProtocolShareReserve", + "NewReduceReservesBlockDelta", + "NewReserveFactor", + "NewCollateralFactor", + "NewLiquidationThreshold", + "NewLiquidationIncentive", + ], + // 2 markets listed in this VIP + [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + ); + }, + }); + + describe("Post-VIP behavior", async () => { + for (const m of MARKETS) { + describe(`${m.vToken.symbol} market`, async () => { + const vToken = new ethers.Contract(m.vToken.address, VTOKEN_ABI, ethers.provider); + const underlying = new ethers.Contract(m.vToken.underlying.address, ERC20_ABI, ethers.provider); + + it("check new IRM", async () => { + expect(await vToken.interestRateModel()).to.equal(m.rateModel); + }); + + checkInterestRate(m.rateModel, m.vToken.symbol, { + base: m.interestRateModel.baseRatePerYear, + multiplier: m.interestRateModel.multiplierPerYear, + jump: m.interestRateModel.jumpMultiplierPerYear, + kink: m.interestRateModel.kink, + }); + + checkVToken(m.vToken.address, { + name: m.vToken.name, + symbol: m.vToken.symbol, + decimals: m.vToken.decimals, + underlying: m.vToken.underlying.address, + exchangeRate: m.vToken.exchangeRate, + comptroller: m.vToken.comptroller, + }); + + checkRiskParameters(m.vToken.address, m.vToken, m.riskParameters); + + it("returns the configured price from the oracle", async () => { + const price = await resilientOracle.getUnderlyingPrice(m.vToken.address); + expect(price).to.equal(m.oracle.price); + }); + + it("configures the ResilientOracle to use the Atlas Oracle", async () => { + const config = await resilientOracle.getTokenConfig(m.vToken.underlying.address); + expect(config.oracles[0]).to.equal(m.oracle.address); + expect(config.enableFlagsForOracles[0]).to.equal(true); + }); + + it("configures the Atlas Oracle feed for the underlying", async () => { + const config = await atlasOracle.tokenConfigs(m.vToken.underlying.address); + expect(config.feed).to.equal(m.oracle.feed); + expect(config.maxStalePeriod).to.equal(m.oracle.maxStalePeriod); + }); + + it("market has correct owner", async () => { + expect(await vToken.admin()).to.equal(bscmainnet.NORMAL_TIMELOCK); + }); + + it("market has correct ACM", async () => { + expect(await vToken.accessControlManager()).to.equal(bscmainnet.ACCESS_CONTROL_MANAGER); + }); + + it("market has correct protocol share reserve", async () => { + expect(await vToken.protocolShareReserve()).to.equal(PROTOCOL_SHARE_RESERVE); + }); + + it("market has correct total supply", async () => { + const supply = await vToken.totalSupply(); + expect(supply).to.equal(convertAmountToVTokens(m.initialSupply.amount, m.vToken.exchangeRate)); + }); + + it("market has correct reduce reserves block delta", async () => { + expect(await vToken.reduceReservesBlockDelta()).to.equal(REDUCE_RESERVES_BLOCK_DELTA); + }); + + it("market has balance of underlying", async () => { + expect(await underlying.balanceOf(m.vToken.address)).to.equal(m.initialSupply.amount); + }); + + it("should not leave any vTokens in the timelock", async () => { + expect(await vToken.balanceOf(bscmainnet.NORMAL_TIMELOCK)).to.equal(0); + }); + + it("should burn vTokens", async () => { + expect(await vToken.balanceOf(ethers.constants.AddressZero)).to.equal(m.initialSupply.vTokensToBurn); + }); + + it("should send remaining vTokens to vTokenReceiver", async () => { + expect(await vToken.balanceOf(m.initialSupply.vTokenReceiver)).to.equal(vTokensRemaining(m)); + }); + + it("should allow borrowing on the market", async () => { + const market = await comptroller.markets(m.vToken.address); + expect(market.isBorrowAllowed).to.equal(true); + }); + }); + } + }); +}); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts new file mode 100644 index 000000000..61e05f932 --- /dev/null +++ b/simulations/vip-669/bsctestnet.ts @@ -0,0 +1,158 @@ +import { expect } from "chai"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; +import { checkRiskParameters } from "src/vip-framework/checks/checkRiskParameters"; +import { checkVToken } from "src/vip-framework/checks/checkVToken"; +import { checkInterestRate } from "src/vip-framework/checks/interestRateModel"; + +import { + ATLAS_ORACLE, + ATLAS_ORACLE_PERMISSIONS, + MARKETS, + PROTOCOL_SHARE_RESERVE, + REDUCE_RESERVES_BLOCK_DELTA, + TIMELOCKS, + convertAmountToVTokens, + vTokensRemaining, + vip669, +} from "../../vips/vip-669/bsctestnet"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; +import VTOKEN_ABI from "./abi/VToken.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; + +// Block after the T4B/N4B markets and the Atlas oracle were deployed on testnet. +const FORK_BLOCK = 112188900; + +forking(FORK_BLOCK, async () => { + const comptroller = new ethers.Contract(bsctestnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); + const resilientOracle = new ethers.Contract(bsctestnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider); + const acm = new ethers.Contract(bsctestnet.ACCESS_CONTROL_MANAGER, ACM_ABI, ethers.provider); + + describe("Pre-VIP behavior", async () => { + for (const m of MARKETS) { + it(`check ${m.vToken.symbol} market not listed`, async () => { + const market = await comptroller.markets(m.vToken.address); + expect(market.isListed).to.equal(false); + }); + } + }); + + testVip("VIP-669 Testnet", await vip669(), { + callbackAfterExecution: async txResponse => { + await expectEvents( + txResponse, + [COMPTROLLER_ABI, VTOKEN_ABI, ACM_ABI], + [ + "PermissionGranted", + "MarketListed", + "NewSupplyCap", + "NewBorrowCap", + "BorrowAllowedUpdated", + "NewAccessControlManager", + "NewProtocolShareReserve", + "NewReduceReservesBlockDelta", + "NewReserveFactor", + "NewCollateralFactor", + "NewLiquidationThreshold", + "NewLiquidationIncentive", + ], + // 6 permission grants (2 functions x 3 timelocks); the rest are 2 markets each + [6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + ); + }, + }); + + describe("Post-VIP behavior", async () => { + for (const m of MARKETS) { + describe(`${m.vToken.symbol} market`, async () => { + const vToken = new ethers.Contract(m.vToken.address, VTOKEN_ABI, ethers.provider); + const underlying = new ethers.Contract(m.vToken.underlying.address, ERC20_ABI, ethers.provider); + + it("check new IRM", async () => { + expect(await vToken.interestRateModel()).to.equal(m.rateModel); + }); + + checkInterestRate(m.rateModel, m.vToken.symbol, { + base: m.interestRateModel.baseRatePerYear, + multiplier: m.interestRateModel.multiplierPerYear, + jump: m.interestRateModel.jumpMultiplierPerYear, + kink: m.interestRateModel.kink, + }); + + checkVToken(m.vToken.address, { + name: m.vToken.name, + symbol: m.vToken.symbol, + decimals: m.vToken.decimals, + underlying: m.vToken.underlying.address, + exchangeRate: m.vToken.exchangeRate, + comptroller: m.vToken.comptroller, + }); + + checkRiskParameters(m.vToken.address, m.vToken, m.riskParameters); + + it("returns the configured price from the oracle", async () => { + const price = await resilientOracle.getUnderlyingPrice(m.vToken.address); + expect(price).to.equal(m.oracle.directPrice); + }); + + it("market has correct owner", async () => { + expect(await vToken.admin()).to.equal(bsctestnet.NORMAL_TIMELOCK); + }); + + it("market has correct ACM", async () => { + expect(await vToken.accessControlManager()).to.equal(bsctestnet.ACCESS_CONTROL_MANAGER); + }); + + it("market has correct protocol share reserve", async () => { + expect(await vToken.protocolShareReserve()).to.equal(PROTOCOL_SHARE_RESERVE); + }); + + it("market has correct total supply", async () => { + const supply = await vToken.totalSupply(); + expect(supply).to.equal(convertAmountToVTokens(m.initialSupply.amount, m.vToken.exchangeRate)); + }); + + it("market has correct reduce reserves block delta", async () => { + expect(await vToken.reduceReservesBlockDelta()).to.equal(REDUCE_RESERVES_BLOCK_DELTA); + }); + + it("market has balance of underlying", async () => { + expect(await underlying.balanceOf(m.vToken.address)).to.equal(m.initialSupply.amount); + }); + + it("should burn vTokens", async () => { + expect(await vToken.balanceOf(ethers.constants.AddressZero)).to.equal(m.initialSupply.vTokensToBurn); + }); + + it("should send remaining vTokens to vTokenReceiver", async () => { + expect(await vToken.balanceOf(m.initialSupply.vTokenReceiver)).to.equal(vTokensRemaining(m)); + }); + + it("should not leave any vTokens in the timelock", async () => { + expect(await vToken.balanceOf(bsctestnet.NORMAL_TIMELOCK)).to.equal(0); + }); + + it("should allow borrowing on the market", async () => { + const market = await comptroller.markets(m.vToken.address); + expect(market.isBorrowAllowed).to.equal(true); + }); + }); + } + }); + + describe("Atlas Oracle permissions", async () => { + for (const signature of ATLAS_ORACLE_PERMISSIONS) { + for (const timelock of TIMELOCKS) { + it(`grants "${signature}" on the Atlas Oracle to ${timelock}`, async () => { + expect(await acm.hasPermission(timelock, ATLAS_ORACLE, signature)).to.equal(true); + }); + } + } + }); +}); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts new file mode 100644 index 000000000..38efcbf9a --- /dev/null +++ b/vips/vip-669/bscmainnet.ts @@ -0,0 +1,296 @@ +import { BigNumber } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +export const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; +export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; +export const CORE_POOL_ID = 0; + +export const { RESILIENT_ORACLE } = NETWORK_ADDRESSES.bscmainnet; +export const ATLAS_ORACLE = "0x9E6928Ec418948ceb9f1cd9872fD312b13D841D0"; +export const ATLAS_MAX_STALE_PERIOD = 86700; // ~24h + +export type MarketSpec = { + vToken: { + address: string; + name: string; + symbol: string; + underlying: { address: string; symbol: string; decimals: number }; + decimals: number; + exchangeRate: BigNumber; + comptroller: string; + isLegacyPool: boolean; + }; + rateModel: string; + interestRateModel: { + model: "jump"; + baseRatePerYear: string; + multiplierPerYear: string; + jumpMultiplierPerYear: string; + kink: string; + }; + oracle: { + address: string; + feed: string; + maxStalePeriod: number; + price: BigNumber; + }; + riskParameters: { + collateralFactor: BigNumber; + liquidationThreshold: BigNumber; + liquidationIncentive: BigNumber; + reserveFactor: BigNumber; + supplyCap: BigNumber; + borrowCap: BigNumber; + }; + initialSupply: { + amount: BigNumber; + vTokenReceiver: string; + vTokensToBurn: BigNumber; + }; +}; + +// Market 1 — T4B +export const MARKET_1: MarketSpec = { + vToken: { + address: "0x1111111111111111111111111111111111111111", // TODO vToken (not deployed on mainnet yet) + name: "Venus T4B", + symbol: "vT4B", + underlying: { + address: "0x1111111111111111111111111111111111111112", // TODO underlying (not deployed on mainnet yet) + symbol: "T4B", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bscmainnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0x1111111111111111111111111111111111111113", // TODO rate model (not deployed on mainnet yet) + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + feed: "0x1111111111111111111111111111111111111115", // TODO Atlas feed (configured later) + maxStalePeriod: ATLAS_MAX_STALE_PERIOD, + price: parseUnits("400", 18), // TODO placeholder, update with the real feed price + }, + riskParameters: { + collateralFactor: parseUnits("0.6", 18), + liquidationThreshold: parseUnits("0.7", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("236", 18), + borrowCap: parseUnits("236", 18), + }, + initialSupply: { + amount: parseUnits("0.26", 18), + vTokenReceiver: bscmainnet.VTREASURY, + vTokensToBurn: parseUnits("0.026", 8), + }, +}; + +// Market 2 — N4B +export const MARKET_2: MarketSpec = { + vToken: { + address: "0x2222222222222222222222222222222222222221", // TODO vToken (not deployed on mainnet yet) + name: "Venus N4B", + symbol: "vN4B", + underlying: { + address: "0x2222222222222222222222222222222222222222", // TODO underlying (not deployed on mainnet yet) + symbol: "N4B", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bscmainnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0x2222222222222222222222222222222222222223", // TODO rate model (not deployed on mainnet yet) + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + feed: "0x2222222222222222222222222222222222222225", // TODO Atlas feed (configured later) + maxStalePeriod: ATLAS_MAX_STALE_PERIOD, + price: parseUnits("200", 18), // TODO placeholder, update with the real feed price + }, + riskParameters: { + collateralFactor: parseUnits("0.6", 18), + liquidationThreshold: parseUnits("0.7", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("450", 18), + borrowCap: parseUnits("450", 18), + }, + initialSupply: { + amount: parseUnits("0.5", 18), + vTokenReceiver: bscmainnet.VTREASURY, + vTokensToBurn: parseUnits("0.05", 8), + }, +}; + +export const MARKETS: MarketSpec[] = [MARKET_1, MARKET_2]; + +export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { + const EXP_SCALE = parseUnits("1", 18); + return amount.mul(EXP_SCALE).div(exchangeRate); +}; + +export const vTokensMinted = (m: MarketSpec) => convertAmountToVTokens(m.initialSupply.amount, m.vToken.exchangeRate); + +export const vTokensRemaining = (m: MarketSpec) => vTokensMinted(m).sub(m.initialSupply.vTokensToBurn); + +export const vip669 = () => { + const meta = { + version: "v2", + title: "VIP-669 [BNB Chain] List new markets in the Venus Core Pool", + description: `#### Summary + +If passed, this VIP will list two new markets in the Venus Core Pool on BNB Chain. + +The assets, risk parameters and oracle configuration will be detailed ahead of execution. + +#### Description + +For each new market this VIP will: + +- Configure the asset to use the Atlas Oracle in the ResilientOracle +- Add the market to the Core Pool Comptroller +- Set the supply cap, borrow cap, collateral factor, liquidation threshold, liquidation incentive and reserve factor +- Set the AccessControlManager, ProtocolShareReserve and reduce-reserves block delta on the vToken +- Provide bootstrap liquidity (minting an initial supply and sending the resulting vTokens to the VTreasury)`, + 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(m => [ + // Oracle configuration — single source: the Atlas Oracle (feed configured later). + { + target: m.oracle.address, + signature: "setTokenConfig((address,address,uint256))", + params: [[m.vToken.underlying.address, m.oracle.feed, m.oracle.maxStalePeriod]], + }, + { + target: RESILIENT_ORACLE, + signature: "setTokenConfig((address,address[3],bool[3],bool))", + params: [ + [ + m.vToken.underlying.address, + [m.oracle.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + [true, false, false], + false, + ], + ], + }, + + // Add market + { + target: m.vToken.comptroller, + signature: "_supportMarket(address)", + params: [m.vToken.address], + }, + { + target: m.vToken.comptroller, + signature: "_setMarketSupplyCaps(address[],uint256[])", + params: [[m.vToken.address], [m.riskParameters.supplyCap]], + }, + { + target: m.vToken.comptroller, + signature: "_setMarketBorrowCaps(address[],uint256[])", + params: [[m.vToken.address], [m.riskParameters.borrowCap]], + }, + // Enable borrowing for the market. + { + target: m.vToken.comptroller, + signature: "setIsBorrowAllowed(uint96,address,bool)", + params: [CORE_POOL_ID, m.vToken.address, true], + }, + { + target: m.vToken.address, + signature: "setAccessControlManager(address)", + params: [bscmainnet.ACCESS_CONTROL_MANAGER], + }, + { + target: m.vToken.address, + signature: "setProtocolShareReserve(address)", + params: [PROTOCOL_SHARE_RESERVE], + }, + { + target: m.vToken.address, + signature: "setReduceReservesBlockDelta(uint256)", + params: [REDUCE_RESERVES_BLOCK_DELTA], + }, + { + target: m.vToken.address, + signature: "_setReserveFactor(uint256)", + params: [m.riskParameters.reserveFactor], + }, + { + target: m.vToken.comptroller, + signature: "setCollateralFactor(address,uint256,uint256)", + params: [m.vToken.address, m.riskParameters.collateralFactor, m.riskParameters.liquidationThreshold], + }, + { + target: m.vToken.comptroller, + signature: "setLiquidationIncentive(address,uint256)", + params: [m.vToken.address, m.riskParameters.liquidationIncentive], + }, + + // Initial liquidity: pull underlying from the Treasury, mint, burn a slice, and send the remainder to the receiver. + { + target: bscmainnet.VTREASURY, + signature: "withdrawTreasuryBEP20(address,uint256,address)", + params: [m.vToken.underlying.address, m.initialSupply.amount, bscmainnet.NORMAL_TIMELOCK], + }, + { + target: m.vToken.underlying.address, + signature: "approve(address,uint256)", + params: [m.vToken.address, m.initialSupply.amount], + }, + { + target: m.vToken.address, + signature: "mint(uint256)", + params: [m.initialSupply.amount], + }, + { + target: m.vToken.underlying.address, + signature: "approve(address,uint256)", + params: [m.vToken.address, 0], + }, + // Burn a slice of vTokens. + { + target: m.vToken.address, + signature: "transfer(address,uint256)", + params: [ethers.constants.AddressZero, m.initialSupply.vTokensToBurn], + }, + // Transfer remaining vTokens to the receiver (VTreasury). + { + target: m.vToken.address, + signature: "transfer(address,uint256)", + params: [m.initialSupply.vTokenReceiver, vTokensRemaining(m)], + }, + ]), + meta, + ProposalType.REGULAR, + ); +}; + +export default vip669; diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts new file mode 100644 index 000000000..1e641e400 --- /dev/null +++ b/vips/vip-669/bsctestnet.ts @@ -0,0 +1,292 @@ +import { BigNumber } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { bsctestnet } = NETWORK_ADDRESSES; +export const { RESILIENT_ORACLE } = NETWORK_ADDRESSES.bsctestnet; +export const ATLAS_ORACLE = "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5"; + +export const PROTOCOL_SHARE_RESERVE = "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3"; +export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; +export const CORE_POOL_ID = 0; + +// ACM permissions to grant on the newly deployed Atlas Oracle, to every governance timelock. +export const ATLAS_ORACLE_PERMISSIONS = ["setDirectPrice(address,uint256)", "setTokenConfig(TokenConfig)"]; +export const TIMELOCKS = [bsctestnet.NORMAL_TIMELOCK, bsctestnet.FAST_TRACK_TIMELOCK, bsctestnet.CRITICAL_TIMELOCK]; + +export type MarketSpec = { + vToken: { + address: string; + name: string; + symbol: string; + underlying: { address: string; symbol: string; decimals: number }; + decimals: number; + exchangeRate: BigNumber; + comptroller: string; + isLegacyPool: boolean; + }; + rateModel: string; + interestRateModel: { + model: "jump"; + baseRatePerYear: string; + multiplierPerYear: string; + jumpMultiplierPerYear: string; + kink: string; + }; + oracle: { + address: string; + // Testnet uses a direct mocked price. + directPrice: BigNumber; + }; + riskParameters: { + collateralFactor: BigNumber; + liquidationThreshold: BigNumber; + liquidationIncentive: BigNumber; + reserveFactor: BigNumber; + supplyCap: BigNumber; + borrowCap: BigNumber; + }; + initialSupply: { + amount: BigNumber; + vTokenReceiver: string; + vTokensToBurn: BigNumber; + }; +}; + +// Market 1 — T4B +export const MARKET_1: MarketSpec = { + vToken: { + address: "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", + name: "Venus T4B", + symbol: "vT4B", + underlying: { + address: "0xc79Cb7efEBd121DC4B39eA141C214606595D665A", // MockT4B + symbol: "T4B", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bsctestnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + directPrice: parseUnits("400", 18), // $400 + }, + riskParameters: { + collateralFactor: parseUnits("0.6", 18), + liquidationThreshold: parseUnits("0.7", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("236", 18), + borrowCap: parseUnits("236", 18), + }, + initialSupply: { + amount: parseUnits("0.26", 18), + vTokenReceiver: bsctestnet.VTREASURY, + vTokensToBurn: parseUnits("0.026", 8), + }, +}; + +// Market 2 — N4B +export const MARKET_2: MarketSpec = { + vToken: { + address: "0x7397B6bcFA9332Cc8791c886F339B4D114651719", + name: "Venus N4B", + symbol: "vN4B", + underlying: { + address: "0x16691f500541ca35bd63DD878B6D78728C9518AE", // MockN4B + symbol: "N4B", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bsctestnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + directPrice: parseUnits("200", 18), // $200 + }, + riskParameters: { + collateralFactor: parseUnits("0.6", 18), + liquidationThreshold: parseUnits("0.7", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("450", 18), + borrowCap: parseUnits("450", 18), + }, + initialSupply: { + amount: parseUnits("0.5", 18), + vTokenReceiver: bsctestnet.VTREASURY, + vTokensToBurn: parseUnits("0.05", 8), + }, +}; + +export const MARKETS: MarketSpec[] = [MARKET_1, MARKET_2]; + +export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { + const EXP_SCALE = parseUnits("1", 18); + return amount.mul(EXP_SCALE).div(exchangeRate); +}; + +export const vTokensRemaining = (m: MarketSpec) => + convertAmountToVTokens(m.initialSupply.amount, m.vToken.exchangeRate).sub(m.initialSupply.vTokensToBurn); + +export const vip669 = () => { + const meta = { + version: "v2", + title: "VIP-669 [BNB Chain Testnet] List new markets in the Venus Core Pool", + description: `#### Summary + +If passed, this VIP will list two new markets in the Venus Core Pool on BNB Chain testnet. + +The assets, risk parameters and oracle configuration will be detailed ahead of execution.`, + 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( + [ + // Grant every governance timelock permission to configure the newly deployed Atlas Oracle. + ...ATLAS_ORACLE_PERMISSIONS.flatMap(signature => + TIMELOCKS.map(timelock => ({ + target: bsctestnet.ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [ATLAS_ORACLE, signature, timelock], + })), + ), + ...MARKETS.flatMap(m => [ + // Oracle configuration — set a direct mocked price on the Atlas Oracle, then route the ResilientOracle to it. + { + target: m.oracle.address, + signature: "setDirectPrice(address,uint256)", + params: [m.vToken.underlying.address, m.oracle.directPrice], + }, + { + target: RESILIENT_ORACLE, + signature: "setTokenConfig((address,address[3],bool[3],bool))", + params: [ + [ + m.vToken.underlying.address, + [m.oracle.address, ethers.constants.AddressZero, ethers.constants.AddressZero], + [true, false, false], + false, + ], + ], + }, + + // Add market + { + target: m.vToken.comptroller, + signature: "_supportMarket(address)", + params: [m.vToken.address], + }, + { + target: m.vToken.comptroller, + signature: "_setMarketSupplyCaps(address[],uint256[])", + params: [[m.vToken.address], [m.riskParameters.supplyCap]], + }, + { + target: m.vToken.comptroller, + signature: "_setMarketBorrowCaps(address[],uint256[])", + params: [[m.vToken.address], [m.riskParameters.borrowCap]], + }, + // Enable borrowing for the market + { + target: m.vToken.comptroller, + signature: "setIsBorrowAllowed(uint96,address,bool)", + params: [CORE_POOL_ID, m.vToken.address, true], + }, + { + target: m.vToken.address, + signature: "setAccessControlManager(address)", + params: [bsctestnet.ACCESS_CONTROL_MANAGER], + }, + { + target: m.vToken.address, + signature: "setProtocolShareReserve(address)", + params: [PROTOCOL_SHARE_RESERVE], + }, + { + target: m.vToken.address, + signature: "setReduceReservesBlockDelta(uint256)", + params: [REDUCE_RESERVES_BLOCK_DELTA], + }, + { + target: m.vToken.address, + signature: "_setReserveFactor(uint256)", + params: [m.riskParameters.reserveFactor], + }, + { + target: m.vToken.comptroller, + signature: "setCollateralFactor(address,uint256,uint256)", + params: [m.vToken.address, m.riskParameters.collateralFactor, m.riskParameters.liquidationThreshold], + }, + { + target: m.vToken.comptroller, + signature: "setLiquidationIncentive(address,uint256)", + params: [m.vToken.address, m.riskParameters.liquidationIncentive], + }, + + // Initial liquidity: faucet the mock underlying, mint, burn a slice, send the rest to the receiver. + { + target: m.vToken.underlying.address, + signature: "faucet(uint256)", + params: [m.initialSupply.amount], + }, + { + target: m.vToken.underlying.address, + signature: "approve(address,uint256)", + params: [m.vToken.address, m.initialSupply.amount], + }, + { + target: m.vToken.address, + signature: "mint(uint256)", + params: [m.initialSupply.amount], + }, + { + target: m.vToken.underlying.address, + signature: "approve(address,uint256)", + params: [m.vToken.address, 0], + }, + // Burn a slice of vTokens + { + target: m.vToken.address, + signature: "transfer(address,uint256)", + params: [ethers.constants.AddressZero, m.initialSupply.vTokensToBurn], + }, + // Transfer remaining vTokens to the receiver. + { + target: m.vToken.address, + signature: "transfer(address,uint256)", + params: [m.initialSupply.vTokenReceiver, vTokensRemaining(m)], + }, + ]), + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip669; From 82e2b8465829a04d0dd1833921caf9758d8467fb Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 9 Jun 2026 12:07:21 +0530 Subject: [PATCH 02/10] fix: update vip and simulations --- simulations/vip-669/bscmainnet.ts | 3 +-- simulations/vip-669/bsctestnet.ts | 3 +-- vips/vip-669/bscmainnet.ts | 28 ++++++++++++++-------------- vips/vip-669/bsctestnet.ts | 24 ++++++++++++------------ 4 files changed, 28 insertions(+), 30 deletions(-) diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts index 20332370e..1269df641 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-669/bscmainnet.ts @@ -25,8 +25,7 @@ import VTREASURY_ABI from "./abi/VTreasury.json"; const { bscmainnet } = NETWORK_ADDRESSES; -// TODO(pre-deployment): set the fork block to one after the markets are deployed. -const FORK_BLOCK = 83432607; +const FORK_BLOCK = 103175700; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index 61e05f932..20f51ce84 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -26,8 +26,7 @@ import VTOKEN_ABI from "./abi/VToken.json"; const { bsctestnet } = NETWORK_ADDRESSES; -// Block after the T4B/N4B markets and the Atlas oracle were deployed on testnet. -const FORK_BLOCK = 112188900; +const FORK_BLOCK = 112317000; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bsctestnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index 38efcbf9a..c8e9536db 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -55,15 +55,15 @@ export type MarketSpec = { }; }; -// Market 1 — T4B +// Market 1 — TSLAB export const MARKET_1: MarketSpec = { vToken: { - address: "0x1111111111111111111111111111111111111111", // TODO vToken (not deployed on mainnet yet) - name: "Venus T4B", - symbol: "vT4B", + address: "0x97421799419Eb782628e73e7220d8E0A207469a3", + name: "Venus TSLAB", + symbol: "vTSLAB", underlying: { - address: "0x1111111111111111111111111111111111111112", // TODO underlying (not deployed on mainnet yet) - symbol: "T4B", + address: "0x5b1910eaad6450e50f816082aa078c41f10c292f", + symbol: "T4B", // TODO: update to "TSLAB" once the underlying symbol is updated on-chain decimals: 18, }, decimals: 8, @@ -71,7 +71,7 @@ export const MARKET_1: MarketSpec = { comptroller: bscmainnet.UNITROLLER, isLegacyPool: true, }, - rateModel: "0x1111111111111111111111111111111111111113", // TODO rate model (not deployed on mainnet yet) + rateModel: "0xe589E884f69dF3137B43A760C4Ec9E55D944439D", interestRateModel: { model: "jump", baseRatePerYear: "0", @@ -100,15 +100,15 @@ export const MARKET_1: MarketSpec = { }, }; -// Market 2 — N4B +// Market 2 — NVDAB export const MARKET_2: MarketSpec = { vToken: { - address: "0x2222222222222222222222222222222222222221", // TODO vToken (not deployed on mainnet yet) - name: "Venus N4B", - symbol: "vN4B", + address: "0xEb8Ca841cBe1BC4832A10b15c7dAB1081eDaD371", + name: "Venus NVDAB", + symbol: "vNVDAB", underlying: { - address: "0x2222222222222222222222222222222222222222", // TODO underlying (not deployed on mainnet yet) - symbol: "N4B", + address: "0x02fca66c1d1afb4e2a7884261eb00f63598a7436", + symbol: "N4B", // TODO: update to "NVDAB" once the underlying symbol is updated on-chain decimals: 18, }, decimals: 8, @@ -116,7 +116,7 @@ export const MARKET_2: MarketSpec = { comptroller: bscmainnet.UNITROLLER, isLegacyPool: true, }, - rateModel: "0x2222222222222222222222222222222222222223", // TODO rate model (not deployed on mainnet yet) + rateModel: "0xe589E884f69dF3137B43A760C4Ec9E55D944439D", interestRateModel: { model: "jump", baseRatePerYear: "0", diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts index 1e641e400..599e45150 100644 --- a/vips/vip-669/bsctestnet.ts +++ b/vips/vip-669/bsctestnet.ts @@ -56,15 +56,15 @@ export type MarketSpec = { }; }; -// Market 1 — T4B +// Market 1 — TSLAB export const MARKET_1: MarketSpec = { vToken: { - address: "0x4a45FBAf2A736bdF025DEd1D0Af3dF80070EDac0", - name: "Venus T4B", - symbol: "vT4B", + address: "0x3Ed56f6937fc8549f9325405d1e8E650739647Fa", + name: "Venus TSLAB", + symbol: "vTSLAB", underlying: { - address: "0xc79Cb7efEBd121DC4B39eA141C214606595D665A", // MockT4B - symbol: "T4B", + address: "0x10d63B1203E5A0719AbbE927C8BFc87135b2F129", // MockTSLAB + symbol: "TSLAB", decimals: 18, }, decimals: 8, @@ -99,15 +99,15 @@ export const MARKET_1: MarketSpec = { }, }; -// Market 2 — N4B +// Market 2 — NVDAB export const MARKET_2: MarketSpec = { vToken: { - address: "0x7397B6bcFA9332Cc8791c886F339B4D114651719", - name: "Venus N4B", - symbol: "vN4B", + address: "0x9e1ECb2671AfabE9eaAA2e74Cb2318a9b6A2Eb5d", + name: "Venus NVDAB", + symbol: "vNVDAB", underlying: { - address: "0x16691f500541ca35bd63DD878B6D78728C9518AE", // MockN4B - symbol: "N4B", + address: "0x8A7d8589A597619A7842d3BC284b9a5a276FaE56", // MockNVDAB + symbol: "NVDAB", decimals: 18, }, decimals: 8, From e205c6a046d1f82dfe0d2739c5400906101b9b72 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 10:28:21 +0530 Subject: [PATCH 03/10] feat: update price feeds --- simulations/vip-669/abi/AtlasOracle.json | 2 +- simulations/vip-669/bscmainnet.ts | 78 +++++++++++++++++++++--- simulations/vip-669/bsctestnet.ts | 8 +-- vips/vip-669/bscmainnet.ts | 32 ++++++---- vips/vip-669/bsctestnet.ts | 7 ++- 5 files changed, 98 insertions(+), 29 deletions(-) diff --git a/simulations/vip-669/abi/AtlasOracle.json b/simulations/vip-669/abi/AtlasOracle.json index 6f0d082e6..972c40e43 100644 --- a/simulations/vip-669/abi/AtlasOracle.json +++ b/simulations/vip-669/abi/AtlasOracle.json @@ -565,4 +565,4 @@ "stateMutability": "payable", "type": "constructor" } -] \ No newline at end of file +] diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts index 1269df641..3f7ef3a2e 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-669/bscmainnet.ts @@ -1,15 +1,20 @@ +import { setStorageAt } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; +import { BigNumber } from "ethers"; import { ethers } from "hardhat"; import { NETWORK_ADDRESSES } from "src/networkAddresses"; -import { expectEvents } from "src/utils"; +import { expectEvents, initMainnetUser } from "src/utils"; import { forking, testVip } from "src/vip-framework"; import { checkRiskParameters } from "src/vip-framework/checks/checkRiskParameters"; import { checkVToken } from "src/vip-framework/checks/checkVToken"; import { checkInterestRate } from "src/vip-framework/checks/interestRateModel"; import { + ATLAS_MAX_STALE_PERIOD, ATLAS_ORACLE, + BORROW_ACTION, MARKETS, + ONE_YEAR, PROTOCOL_SHARE_RESERVE, REDUCE_RESERVES_BLOCK_DELTA, convertAmountToVTokens, @@ -25,13 +30,48 @@ import VTREASURY_ABI from "./abi/VTreasury.json"; const { bscmainnet } = NETWORK_ADDRESSES; -const FORK_BLOCK = 103175700; +// Block after the TSLAB/NVDAB markets and their Atlas feeds were deployed on mainnet. +const FORK_BLOCK = 104503915; + +// The underlying RWA tokens have zero supply on mainnet, so there is no holder to impersonate. +// Instead we "deal" the bootstrap amount straight into the VTreasury by writing the ERC20 +// balances mapping slot. The slot index is unknown, so we brute-force it: sequential slots +// (covers OZ v4 layouts) plus the OZ v5 ERC20 namespaced storage base. +const OZ_V5_ERC20_BASE = BigNumber.from("0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00"); +let cachedBalancesSlot: BigNumber | undefined; + +const dealTokens = async (token: string, holder: string, amount: BigNumber) => { + const erc20 = new ethers.Contract(token, ERC20_ABI, ethers.provider); + const value = ethers.utils.hexZeroPad(amount.toHexString(), 32); + const bases: BigNumber[] = []; + if (cachedBalancesSlot) bases.push(cachedBalancesSlot); + for (let i = 0; i <= 120; i++) bases.push(BigNumber.from(i)); + bases.push(OZ_V5_ERC20_BASE); + for (const base of bases) { + const index = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [holder, base])); + const prev = await ethers.provider.getStorageAt(token, index); + await setStorageAt(token, index, value); + if ((await erc20.balanceOf(holder)).eq(amount)) { + cachedBalancesSlot = base; + return; + } + await setStorageAt(token, index, prev); // wrong slot — restore and keep searching + } + throw new Error(`Could not locate the ERC20 balances slot for ${token}`); +}; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); const resilientOracle = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider); const atlasOracle = new ethers.Contract(ATLAS_ORACLE, ATLAS_ORACLE_ABI, ethers.provider); + before(async () => { + // Fund the VTreasury with the bootstrap liquidity the VIP withdraws via withdrawTreasuryBEP20. + for (const m of MARKETS) { + await dealTokens(m.vToken.underlying.address, bscmainnet.VTREASURY, m.initialSupply.amount); + } + }); + describe("Pre-VIP behavior", async () => { for (const m of MARKETS) { it(`check ${m.vToken.symbol} market not listed`, async () => { @@ -41,7 +81,7 @@ forking(FORK_BLOCK, async () => { } }); - testVip("VIP-669", await vip669(), { + testVip("VIP-669", await vip669(true), { callbackAfterExecution: async txResponse => { await expectEvents( txResponse, @@ -50,7 +90,7 @@ forking(FORK_BLOCK, async () => { "MarketListed", "NewSupplyCap", "NewBorrowCap", - "BorrowAllowedUpdated", + "ActionPausedMarket", "NewAccessControlManager", "NewProtocolShareReserve", "NewReduceReservesBlockDelta", @@ -107,7 +147,8 @@ forking(FORK_BLOCK, async () => { it("configures the Atlas Oracle feed for the underlying", async () => { const config = await atlasOracle.tokenConfigs(m.vToken.underlying.address); expect(config.feed).to.equal(m.oracle.feed); - expect(config.maxStalePeriod).to.equal(m.oracle.maxStalePeriod); + // Simulations configure a 1-year stale period (see VIP-615 workaround). + expect(config.maxStalePeriod).to.equal(ONE_YEAR); }); it("market has correct owner", async () => { @@ -147,11 +188,32 @@ forking(FORK_BLOCK, async () => { expect(await vToken.balanceOf(m.initialSupply.vTokenReceiver)).to.equal(vTokensRemaining(m)); }); - it("should allow borrowing on the market", async () => { - const market = await comptroller.markets(m.vToken.address); - expect(market.isBorrowAllowed).to.equal(true); + it("should pause borrowing on the market", async () => { + expect(await comptroller.actionPaused(m.vToken.address, BORROW_ACTION)).to.equal(true); }); }); } }); + + // Runs last: the proposal configures ONE_YEAR for simulation purposes; here we roll the Atlas + // stale period back to the production value to confirm it is settable by the Normal Timelock. + // (Must come after the price assertions above — once the real ~1h period is in place, the feed + // is stale relative to the mined governance lifecycle and getUnderlyingPrice would revert.) + describe("Atlas Oracle stale period rollback", () => { + before(async () => { + const timelock = await initMainnetUser(bscmainnet.NORMAL_TIMELOCK, ethers.utils.parseEther("1")); + for (const m of MARKETS) { + await atlasOracle + .connect(timelock) + .setTokenConfig([m.vToken.underlying.address, m.oracle.feed, ATLAS_MAX_STALE_PERIOD]); + } + }); + + for (const m of MARKETS) { + it(`resets the ${m.vToken.symbol} Atlas stale period to the production value`, async () => { + const config = await atlasOracle.tokenConfigs(m.vToken.underlying.address); + expect(config.maxStalePeriod).to.equal(ATLAS_MAX_STALE_PERIOD); + }); + } + }); }); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index 20f51ce84..e251c2bd1 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -10,6 +10,7 @@ import { checkInterestRate } from "src/vip-framework/checks/interestRateModel"; import { ATLAS_ORACLE, ATLAS_ORACLE_PERMISSIONS, + BORROW_ACTION, MARKETS, PROTOCOL_SHARE_RESERVE, REDUCE_RESERVES_BLOCK_DELTA, @@ -52,7 +53,7 @@ forking(FORK_BLOCK, async () => { "MarketListed", "NewSupplyCap", "NewBorrowCap", - "BorrowAllowedUpdated", + "ActionPausedMarket", "NewAccessControlManager", "NewProtocolShareReserve", "NewReduceReservesBlockDelta", @@ -137,9 +138,8 @@ forking(FORK_BLOCK, async () => { expect(await vToken.balanceOf(bsctestnet.NORMAL_TIMELOCK)).to.equal(0); }); - it("should allow borrowing on the market", async () => { - const market = await comptroller.markets(m.vToken.address); - expect(market.isBorrowAllowed).to.equal(true); + it("should pause borrowing on the market", async () => { + expect(await comptroller.actionPaused(m.vToken.address, BORROW_ACTION)).to.equal(true); }); }); } diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index c8e9536db..2fe45a125 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -10,10 +10,14 @@ const { bscmainnet } = NETWORK_ADDRESSES; export const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; export const CORE_POOL_ID = 0; +export const BORROW_ACTION = 2; // Comptroller Action enum: BORROW export const { RESILIENT_ORACLE } = NETWORK_ADDRESSES.bscmainnet; export const ATLAS_ORACLE = "0x9E6928Ec418948ceb9f1cd9872fD312b13D841D0"; -export const ATLAS_MAX_STALE_PERIOD = 86700; // ~24h +export const ATLAS_MAX_STALE_PERIOD = 3800; // ~1h +// Used in simulations only: the governance lifecycle mines ~72h of blocks, which would exceed the +// real stale period and make getUnderlyingPrice revert. See VIP-615 stale-period workaround. +export const ONE_YEAR = 31536000; export type MarketSpec = { vToken: { @@ -62,7 +66,7 @@ export const MARKET_1: MarketSpec = { name: "Venus TSLAB", symbol: "vTSLAB", underlying: { - address: "0x5b1910eaad6450e50f816082aa078c41f10c292f", + address: "0x5b1910eAaD6450E50f816082Aa078C41F10C292f", symbol: "T4B", // TODO: update to "TSLAB" once the underlying symbol is updated on-chain decimals: 18, }, @@ -81,9 +85,9 @@ export const MARKET_1: MarketSpec = { }, oracle: { address: ATLAS_ORACLE, - feed: "0x1111111111111111111111111111111111111115", // TODO Atlas feed (configured later) + feed: "0x63950C265e7CDB4016bA60C288c46291C0148ce2", // Atlas TSLAB/USD feed (id 772) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: parseUnits("400", 18), // TODO placeholder, update with the real feed price + price: BigNumber.from("404989994819567769480"), // feed answer @ FORK_BLOCK (~$405.00) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -107,7 +111,7 @@ export const MARKET_2: MarketSpec = { name: "Venus NVDAB", symbol: "vNVDAB", underlying: { - address: "0x02fca66c1d1afb4e2a7884261eb00f63598a7436", + address: "0x02Fca66C1D1aFB4E2A7884261eB00F63598a7436", symbol: "N4B", // TODO: update to "NVDAB" once the underlying symbol is updated on-chain decimals: 18, }, @@ -126,9 +130,9 @@ export const MARKET_2: MarketSpec = { }, oracle: { address: ATLAS_ORACLE, - feed: "0x2222222222222222222222222222222222222225", // TODO Atlas feed (configured later) + feed: "0x8a44cF4E55adD99EB8bAC5D5DB749C63106d54AA", // Atlas NVDAB/USD feed (id 773) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: parseUnits("200", 18), // TODO placeholder, update with the real feed price + price: BigNumber.from("211086527189540030430"), // feed answer @ FORK_BLOCK (~$211.09) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -156,7 +160,7 @@ export const vTokensMinted = (m: MarketSpec) => convertAmountToVTokens(m.initial export const vTokensRemaining = (m: MarketSpec) => vTokensMinted(m).sub(m.initialSupply.vTokensToBurn); -export const vip669 = () => { +export const vip669 = (simulations = false) => { const meta = { version: "v2", title: "VIP-669 [BNB Chain] List new markets in the Venus Core Pool", @@ -182,11 +186,13 @@ For each new market this VIP will: return makeProposal( MARKETS.flatMap(m => [ - // Oracle configuration — single source: the Atlas Oracle (feed configured later). + // Oracle configuration — single source: the Atlas Oracle. + // In simulations use a 1-year stale period so the mined governance lifecycle doesn't make + // the feed appear stale. { target: m.oracle.address, signature: "setTokenConfig((address,address,uint256))", - params: [[m.vToken.underlying.address, m.oracle.feed, m.oracle.maxStalePeriod]], + params: [[m.vToken.underlying.address, m.oracle.feed, simulations ? ONE_YEAR : m.oracle.maxStalePeriod]], }, { target: RESILIENT_ORACLE, @@ -217,11 +223,11 @@ For each new market this VIP will: signature: "_setMarketBorrowCaps(address[],uint256[])", params: [[m.vToken.address], [m.riskParameters.borrowCap]], }, - // Enable borrowing for the market. + // Pause borrowing for the market at launch. { target: m.vToken.comptroller, - signature: "setIsBorrowAllowed(uint96,address,bool)", - params: [CORE_POOL_ID, m.vToken.address, true], + signature: "setActionsPaused(address[],uint8[],bool)", + params: [[m.vToken.address], [BORROW_ACTION], true], }, { target: m.vToken.address, diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts index 599e45150..5b0ab2e64 100644 --- a/vips/vip-669/bsctestnet.ts +++ b/vips/vip-669/bsctestnet.ts @@ -12,6 +12,7 @@ export const ATLAS_ORACLE = "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5"; export const PROTOCOL_SHARE_RESERVE = "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3"; export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; export const CORE_POOL_ID = 0; +export const BORROW_ACTION = 2; // Comptroller Action enum: BORROW // ACM permissions to grant on the newly deployed Atlas Oracle, to every governance timelock. export const ATLAS_ORACLE_PERMISSIONS = ["setDirectPrice(address,uint256)", "setTokenConfig(TokenConfig)"]; @@ -212,11 +213,11 @@ The assets, risk parameters and oracle configuration will be detailed ahead of e signature: "_setMarketBorrowCaps(address[],uint256[])", params: [[m.vToken.address], [m.riskParameters.borrowCap]], }, - // Enable borrowing for the market + // Pause borrowing for the market at launch { target: m.vToken.comptroller, - signature: "setIsBorrowAllowed(uint96,address,bool)", - params: [CORE_POOL_ID, m.vToken.address, true], + signature: "setActionsPaused(address[],uint8[],bool)", + params: [[m.vToken.address], [BORROW_ACTION], true], }, { target: m.vToken.address, From 67fe379a9bb8a70924fd28d9477f7778a2554306 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 12:37:05 +0530 Subject: [PATCH 04/10] feat: update underlying symbol --- simulations/vip-669/bscmainnet.ts | 2 +- simulations/vip-669/bsctestnet.ts | 2 +- vips/vip-669/bscmainnet.ts | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts index 3f7ef3a2e..153ca4531 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-669/bscmainnet.ts @@ -126,7 +126,7 @@ forking(FORK_BLOCK, async () => { name: m.vToken.name, symbol: m.vToken.symbol, decimals: m.vToken.decimals, - underlying: m.vToken.underlying.address, + underlying: m.vToken.underlying, exchangeRate: m.vToken.exchangeRate, comptroller: m.vToken.comptroller, }); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index e251c2bd1..87d71f24d 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -89,7 +89,7 @@ forking(FORK_BLOCK, async () => { name: m.vToken.name, symbol: m.vToken.symbol, decimals: m.vToken.decimals, - underlying: m.vToken.underlying.address, + underlying: m.vToken.underlying, exchangeRate: m.vToken.exchangeRate, comptroller: m.vToken.comptroller, }); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index 2fe45a125..d3df5bab1 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -67,7 +67,7 @@ export const MARKET_1: MarketSpec = { symbol: "vTSLAB", underlying: { address: "0x5b1910eAaD6450E50f816082Aa078C41F10C292f", - symbol: "T4B", // TODO: update to "TSLAB" once the underlying symbol is updated on-chain + symbol: "TSLAB", decimals: 18, }, decimals: 8, @@ -112,7 +112,7 @@ export const MARKET_2: MarketSpec = { symbol: "vNVDAB", underlying: { address: "0x02Fca66C1D1aFB4E2A7884261eB00F63598a7436", - symbol: "N4B", // TODO: update to "NVDAB" once the underlying symbol is updated on-chain + symbol: "NVDAB", decimals: 18, }, decimals: 8, From cf992b6c868c3c35dfb33f9739b22ddfee21366d Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 13:28:03 +0530 Subject: [PATCH 05/10] fix: remove borrowCap command --- simulations/vip-669/bscmainnet.ts | 3 +-- simulations/vip-669/bsctestnet.ts | 3 +-- vips/vip-669/bscmainnet.ts | 36 ++++++++++++++++++++----------- vips/vip-669/bsctestnet.ts | 10 ++------- 4 files changed, 27 insertions(+), 25 deletions(-) diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts index 153ca4531..a859d2991 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-669/bscmainnet.ts @@ -89,7 +89,6 @@ forking(FORK_BLOCK, async () => { [ "MarketListed", "NewSupplyCap", - "NewBorrowCap", "ActionPausedMarket", "NewAccessControlManager", "NewProtocolShareReserve", @@ -100,7 +99,7 @@ forking(FORK_BLOCK, async () => { "NewLiquidationIncentive", ], // 2 markets listed in this VIP - [2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], ); }, }); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index 87d71f24d..81c8c6aeb 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -52,7 +52,6 @@ forking(FORK_BLOCK, async () => { "PermissionGranted", "MarketListed", "NewSupplyCap", - "NewBorrowCap", "ActionPausedMarket", "NewAccessControlManager", "NewProtocolShareReserve", @@ -63,7 +62,7 @@ forking(FORK_BLOCK, async () => { "NewLiquidationIncentive", ], // 6 permission grants (2 functions x 3 timelocks); the rest are 2 markets each - [6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + [6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], ); }, }); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index d3df5bab1..e78b1ec4d 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -9,7 +9,6 @@ const { bscmainnet } = NETWORK_ADDRESSES; export const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; -export const CORE_POOL_ID = 0; export const BORROW_ACTION = 2; // Comptroller Action enum: BORROW export const { RESILIENT_ORACLE } = NETWORK_ADDRESSES.bscmainnet; @@ -95,7 +94,7 @@ export const MARKET_1: MarketSpec = { liquidationIncentive: parseUnits("1.1", 18), reserveFactor: parseUnits("0.1", 18), supplyCap: parseUnits("236", 18), - borrowCap: parseUnits("236", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch }, initialSupply: { amount: parseUnits("0.26", 18), @@ -140,7 +139,7 @@ export const MARKET_2: MarketSpec = { liquidationIncentive: parseUnits("1.1", 18), reserveFactor: parseUnits("0.1", 18), supplyCap: parseUnits("450", 18), - borrowCap: parseUnits("450", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch }, initialSupply: { amount: parseUnits("0.5", 18), @@ -166,19 +165,35 @@ export const vip669 = (simulations = false) => { title: "VIP-669 [BNB Chain] List new markets in the Venus Core Pool", description: `#### Summary -If passed, this VIP will list two new markets in the Venus Core Pool on BNB Chain. +If passed, this VIP will list two new tokenized-equity markets in the Venus Core Pool on BNB Chain, with borrowing paused at launch: -The assets, risk parameters and oracle configuration will be detailed ahead of execution. +- **Venus TSLAB (vTSLAB)** — backed by TSLAB (Tesla, Inc.) +- **Venus NVDAB (vNVDAB)** — backed by NVDAB (NVIDIA Corp) #### Description For each new market this VIP will: -- Configure the asset to use the Atlas Oracle in the ResilientOracle +- Configure the underlying to use its Atlas Oracle price feed (TSLAB/USD, NVDAB/USD) in the ResilientOracle - Add the market to the Core Pool Comptroller -- Set the supply cap, borrow cap, collateral factor, liquidation threshold, liquidation incentive and reserve factor +- Set the supply cap, collateral factor, liquidation threshold, liquidation incentive and reserve factor - Set the AccessControlManager, ProtocolShareReserve and reduce-reserves block delta on the vToken -- Provide bootstrap liquidity (minting an initial supply and sending the resulting vTokens to the VTreasury)`, +- Provide bootstrap liquidity (minting an initial supply and sending the resulting vTokens to the VTreasury) +- Pause borrowing for the market at launch + +#### Risk parameters + +Both markets share the same interest rate model (base 0%, multiplier 6.67%, jump multiplier 627%, kink 75%) and the following parameters: + +| Parameter | Venus TSLAB | Venus NVDAB | +| --- | --- | --- | +| Collateral factor | 60% | 60% | +| Liquidation threshold | 70% | 70% | +| Liquidation incentive | 10% | 10% | +| Reserve factor | 10% | 10% | +| Supply cap | 236 TSLAB | 450 NVDAB | +| Borrow cap | 0 (borrowing disabled) | 0 (borrowing disabled) | +| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB |`, 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", @@ -218,11 +233,6 @@ For each new market this VIP will: signature: "_setMarketSupplyCaps(address[],uint256[])", params: [[m.vToken.address], [m.riskParameters.supplyCap]], }, - { - target: m.vToken.comptroller, - signature: "_setMarketBorrowCaps(address[],uint256[])", - params: [[m.vToken.address], [m.riskParameters.borrowCap]], - }, // Pause borrowing for the market at launch. { target: m.vToken.comptroller, diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts index 5b0ab2e64..aed108993 100644 --- a/vips/vip-669/bsctestnet.ts +++ b/vips/vip-669/bsctestnet.ts @@ -11,7 +11,6 @@ export const ATLAS_ORACLE = "0x7F00af2f30a55e79311392C98fBBfA629D19b3A5"; export const PROTOCOL_SHARE_RESERVE = "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3"; export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; -export const CORE_POOL_ID = 0; export const BORROW_ACTION = 2; // Comptroller Action enum: BORROW // ACM permissions to grant on the newly deployed Atlas Oracle, to every governance timelock. @@ -91,7 +90,7 @@ export const MARKET_1: MarketSpec = { liquidationIncentive: parseUnits("1.1", 18), reserveFactor: parseUnits("0.1", 18), supplyCap: parseUnits("236", 18), - borrowCap: parseUnits("236", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch }, initialSupply: { amount: parseUnits("0.26", 18), @@ -134,7 +133,7 @@ export const MARKET_2: MarketSpec = { liquidationIncentive: parseUnits("1.1", 18), reserveFactor: parseUnits("0.1", 18), supplyCap: parseUnits("450", 18), - borrowCap: parseUnits("450", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch }, initialSupply: { amount: parseUnits("0.5", 18), @@ -208,11 +207,6 @@ The assets, risk parameters and oracle configuration will be detailed ahead of e signature: "_setMarketSupplyCaps(address[],uint256[])", params: [[m.vToken.address], [m.riskParameters.supplyCap]], }, - { - target: m.vToken.comptroller, - signature: "_setMarketBorrowCaps(address[],uint256[])", - params: [[m.vToken.address], [m.riskParameters.borrowCap]], - }, // Pause borrowing for the market at launch { target: m.vToken.comptroller, From c7bdee6a5cb388b4800ec9d2e86bd1710d8349a4 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 15:49:51 +0530 Subject: [PATCH 06/10] feat: enable protection mode and remove initial supply mock behaviour --- .../vip-669/abi/DeviationBoundedOracle.json | 1374 +++++++++++++++++ simulations/vip-669/bscmainnet.ts | 55 +- simulations/vip-669/bsctestnet.ts | 15 + vips/vip-669/bscmainnet.ts | 30 +- vips/vip-669/bsctestnet.ts | 28 +- 5 files changed, 1457 insertions(+), 45 deletions(-) create mode 100644 simulations/vip-669/abi/DeviationBoundedOracle.json diff --git a/simulations/vip-669/abi/DeviationBoundedOracle.json b/simulations/vip-669/abi/DeviationBoundedOracle.json new file mode 100644 index 000000000..9984f9c99 --- /dev/null +++ b/simulations/vip-669/abi/DeviationBoundedOracle.json @@ -0,0 +1,1374 @@ +[ + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "_resilientOracle", + "type": "address" + }, + { + "internalType": "address", + "name": "nativeMarketAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "lastProtectionTriggeredAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + } + ], + "name": "CooldownNotElapsed", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidArrayLength", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "action", + "type": "uint8" + } + ], + "name": "InvalidKeeperAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "currentSpot", + "type": "uint256" + } + ], + "name": "InvalidMaxPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + }, + { + "internalType": "uint256", + "name": "currentSpot", + "type": "uint256" + } + ], + "name": "InvalidMinPrice", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + } + ], + "name": "InvalidResetThreshold", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "MarketAlreadyInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "MarketNotInitialized", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "price", + "type": "uint256" + } + ], + "name": "PriceExceedsUint128", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentRangeRatio", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + } + ], + "name": "PriceRangeNotConverged", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectedPriceActive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectedPriceInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximum", + "type": "uint256" + } + ], + "name": "ThresholdAboveMaximum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "threshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minimum", + "type": "uint256" + } + ], + "name": "ThresholdBelowMinimum", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "inputs": [], + "name": "VAINotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroPriceNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroValueNotAllowed", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "whitelisted", + "type": "bool" + } + ], + "name": "BoundedPricingWhitelistUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldEnabled", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newEnabled", + "type": "bool" + } + ], + "name": "CachingEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "oldCooldown", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "newCooldown", + "type": "uint64" + } + ], + "name": "CooldownPeriodSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "oldMax", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + } + ], + "name": "MaxPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "oldMin", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + } + ], + "name": "MinPriceUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + } + ], + "name": "ProtectionInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "ProtectionModeExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "spotPrice", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "indexed": false, + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + } + ], + "name": "ProtectionTriggered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldExitThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newExitThreshold", + "type": "uint256" + } + ], + "name": "ResetThresholdSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldThreshold", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newThreshold", + "type": "uint256" + } + ], + "name": "TriggerThresholdSet", + "type": "event" + }, + { + "inputs": [], + "name": "COLLATERAL_PRICE_CACHE_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEBT_PRICE_CACHE_SLOT", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "KEEPER_DEADBAND", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MIN_THRESHOLD", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allAssets", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "assetProtectionConfig", + "outputs": [ + { + "internalType": "uint128", + "name": "minPrice", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "maxPrice", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "currentlyUsingProtectedPrice", + "type": "bool" + }, + { + "internalType": "bool", + "name": "isBoundedPricingEnabled", + "type": "bool" + }, + { + "internalType": "uint64", + "name": "lastProtectionTriggeredAt", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "triggerThreshold", + "type": "uint128" + }, + { + "internalType": "uint128", + "name": "resetThreshold", + "type": "uint128" + }, + { + "internalType": "bool", + "name": "cachingEnabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "canExitProtection", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "assets", + "type": "address[]" + }, + { + "internalType": "uint128[]", + "name": "proposedMins", + "type": "uint128[]" + }, + { + "internalType": "uint128[]", + "name": "proposedMaxs", + "type": "uint128[]" + } + ], + "name": "checkAndGetWindowDrift", + "outputs": [ + { + "internalType": "bool[]", + "name": "needsMinUpdate", + "type": "bool[]" + }, + { + "internalType": "bool[]", + "name": "needsMaxUpdate", + "type": "bool[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "currentlyUsingProtectedPrice", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "exitProtectionMode", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAllBoundedPricingEnabledAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedCollateralPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedCollateralPriceView", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedDebtPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedDebtPriceView", + "outputs": [ + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedPrices", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getBoundedPricesView", + "outputs": [ + { + "internalType": "uint256", + "name": "collateralPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "debtPrice", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInitializedAssets", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "isBoundedPricingEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setAssetBoundedPricingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setCachingEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "newCooldown", + "type": "uint64" + } + ], + "name": "setCooldownPeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTriggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newResetThreshold", + "type": "uint256" + } + ], + "name": "setThresholds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enableBoundedPricing", + "type": "bool" + }, + { + "internalType": "bool", + "name": "enableCaching", + "type": "bool" + } + ], + "internalType": "struct IDeviationBoundedOracle.TokenConfigInput", + "name": "tokenConfig_", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint64", + "name": "cooldownPeriod", + "type": "uint64" + }, + { + "internalType": "uint256", + "name": "triggerThreshold", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resetThreshold", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "enableBoundedPricing", + "type": "bool" + }, + { + "internalType": "bool", + "name": "enableCaching", + "type": "bool" + } + ], + "internalType": "struct IDeviationBoundedOracle.TokenConfigInput[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum IDeviationBoundedOracle.KeeperAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "internalType": "struct IDeviationBoundedOracle.KeeperActionItem[]", + "name": "actions", + "type": "tuple[]" + } + ], + "name": "syncPriceBoundsAndProtections", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMax", + "type": "uint128" + } + ], + "name": "updateMaxPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint128", + "name": "newMin", + "type": "uint128" + } + ], + "name": "updateMinPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateProtectionState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-669/bscmainnet.ts index a859d2991..8fff37a1c 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-669/bscmainnet.ts @@ -1,6 +1,4 @@ -import { setStorageAt } from "@nomicfoundation/hardhat-network-helpers"; import { expect } from "chai"; -import { BigNumber } from "ethers"; import { ethers } from "hardhat"; import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { expectEvents, initMainnetUser } from "src/utils"; @@ -13,6 +11,10 @@ import { ATLAS_MAX_STALE_PERIOD, ATLAS_ORACLE, BORROW_ACTION, + DBO_COOLDOWN_PERIOD, + DBO_RESET_THRESHOLD, + DBO_TRIGGER_THRESHOLD, + DEVIATION_BOUNDED_ORACLE, MARKETS, ONE_YEAR, PROTOCOL_SHARE_RESERVE, @@ -23,6 +25,7 @@ import { } from "../../vips/vip-669/bscmainnet"; import ATLAS_ORACLE_ABI from "./abi/AtlasOracle.json"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import DBO_ABI from "./abi/DeviationBoundedOracle.json"; import ERC20_ABI from "./abi/ERC20.json"; import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; import VTOKEN_ABI from "./abi/VToken.json"; @@ -30,47 +33,14 @@ import VTREASURY_ABI from "./abi/VTreasury.json"; const { bscmainnet } = NETWORK_ADDRESSES; -// Block after the TSLAB/NVDAB markets and their Atlas feeds were deployed on mainnet. -const FORK_BLOCK = 104503915; - -// The underlying RWA tokens have zero supply on mainnet, so there is no holder to impersonate. -// Instead we "deal" the bootstrap amount straight into the VTreasury by writing the ERC20 -// balances mapping slot. The slot index is unknown, so we brute-force it: sequential slots -// (covers OZ v4 layouts) plus the OZ v5 ERC20 namespaced storage base. -const OZ_V5_ERC20_BASE = BigNumber.from("0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00"); -let cachedBalancesSlot: BigNumber | undefined; - -const dealTokens = async (token: string, holder: string, amount: BigNumber) => { - const erc20 = new ethers.Contract(token, ERC20_ABI, ethers.provider); - const value = ethers.utils.hexZeroPad(amount.toHexString(), 32); - const bases: BigNumber[] = []; - if (cachedBalancesSlot) bases.push(cachedBalancesSlot); - for (let i = 0; i <= 120; i++) bases.push(BigNumber.from(i)); - bases.push(OZ_V5_ERC20_BASE); - for (const base of bases) { - const index = ethers.utils.keccak256(ethers.utils.defaultAbiCoder.encode(["address", "uint256"], [holder, base])); - const prev = await ethers.provider.getStorageAt(token, index); - await setStorageAt(token, index, value); - if ((await erc20.balanceOf(holder)).eq(amount)) { - cachedBalancesSlot = base; - return; - } - await setStorageAt(token, index, prev); // wrong slot — restore and keep searching - } - throw new Error(`Could not locate the ERC20 balances slot for ${token}`); -}; +// Block after the TSLAB/NVDAB markets, their Atlas feeds, and the VTreasury bootstrap funding. +const FORK_BLOCK = 104542000; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); const resilientOracle = new ethers.Contract(bscmainnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider); const atlasOracle = new ethers.Contract(ATLAS_ORACLE, ATLAS_ORACLE_ABI, ethers.provider); - - before(async () => { - // Fund the VTreasury with the bootstrap liquidity the VIP withdraws via withdrawTreasuryBEP20. - for (const m of MARKETS) { - await dealTokens(m.vToken.underlying.address, bscmainnet.VTREASURY, m.initialSupply.amount); - } - }); + const dbo = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, DBO_ABI, ethers.provider); describe("Pre-VIP behavior", async () => { for (const m of MARKETS) { @@ -150,6 +120,15 @@ forking(FORK_BLOCK, async () => { expect(config.maxStalePeriod).to.equal(ONE_YEAR); }); + it("enables Oracle Dynamic Protection Mode with a 16.67% trigger", async () => { + const cfg = await dbo.assetProtectionConfig(m.vToken.underlying.address); + expect(cfg.isBoundedPricingEnabled).to.equal(true); + expect(cfg.triggerThreshold).to.equal(DBO_TRIGGER_THRESHOLD); + expect(cfg.resetThreshold).to.equal(DBO_RESET_THRESHOLD); + expect(cfg.cooldownPeriod).to.equal(DBO_COOLDOWN_PERIOD); + expect(cfg.cachingEnabled).to.equal(false); + }); + it("market has correct owner", async () => { expect(await vToken.admin()).to.equal(bscmainnet.NORMAL_TIMELOCK); }); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index 81c8c6aeb..2c13e4061 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -11,6 +11,10 @@ import { ATLAS_ORACLE, ATLAS_ORACLE_PERMISSIONS, BORROW_ACTION, + DBO_COOLDOWN_PERIOD, + DBO_RESET_THRESHOLD, + DBO_TRIGGER_THRESHOLD, + DEVIATION_BOUNDED_ORACLE, MARKETS, PROTOCOL_SHARE_RESERVE, REDUCE_RESERVES_BLOCK_DELTA, @@ -21,6 +25,7 @@ import { } from "../../vips/vip-669/bsctestnet"; import ACM_ABI from "./abi/AccessControlManager.json"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import DBO_ABI from "./abi/DeviationBoundedOracle.json"; import ERC20_ABI from "./abi/ERC20.json"; import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; import VTOKEN_ABI from "./abi/VToken.json"; @@ -33,6 +38,7 @@ forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bsctestnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); const resilientOracle = new ethers.Contract(bsctestnet.RESILIENT_ORACLE, RESILIENT_ORACLE_ABI, ethers.provider); const acm = new ethers.Contract(bsctestnet.ACCESS_CONTROL_MANAGER, ACM_ABI, ethers.provider); + const dbo = new ethers.Contract(DEVIATION_BOUNDED_ORACLE, DBO_ABI, ethers.provider); describe("Pre-VIP behavior", async () => { for (const m of MARKETS) { @@ -100,6 +106,15 @@ forking(FORK_BLOCK, async () => { expect(price).to.equal(m.oracle.directPrice); }); + it("enables Oracle Dynamic Protection Mode with a 16.67% trigger", async () => { + const cfg = await dbo.assetProtectionConfig(m.vToken.underlying.address); + expect(cfg.isBoundedPricingEnabled).to.equal(true); + expect(cfg.triggerThreshold).to.equal(DBO_TRIGGER_THRESHOLD); + expect(cfg.resetThreshold).to.equal(DBO_RESET_THRESHOLD); + expect(cfg.cooldownPeriod).to.equal(DBO_COOLDOWN_PERIOD); + expect(cfg.cachingEnabled).to.equal(false); + }); + it("market has correct owner", async () => { expect(await vToken.admin()).to.equal(bsctestnet.NORMAL_TIMELOCK); }); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index e78b1ec4d..acc28cc2d 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -18,6 +18,12 @@ export const ATLAS_MAX_STALE_PERIOD = 3800; // ~1h // real stale period and make getUnderlyingPrice revert. See VIP-615 stale-period workaround. export const ONE_YEAR = 31536000; +// Oracle Dynamic Protection Mode (DeviationBoundedOracle) +export const DEVIATION_BOUNDED_ORACLE = "0xc79Cb7efEBd121DC4B39eA141C214606595D665A"; +export const DBO_COOLDOWN_PERIOD = 3600; // 1h rolling window +export const DBO_TRIGGER_THRESHOLD = parseUnits("0.1667", 18); // 16.67% — arms protection beyond this deviation +export const DBO_RESET_THRESHOLD = parseUnits("0.05", 18); // 5% + export type MarketSpec = { vToken: { address: string; @@ -86,7 +92,7 @@ export const MARKET_1: MarketSpec = { address: ATLAS_ORACLE, feed: "0x63950C265e7CDB4016bA60C288c46291C0148ce2", // Atlas TSLAB/USD feed (id 772) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("404989994819567769480"), // feed answer @ FORK_BLOCK (~$405.00) + price: BigNumber.from("405127531587687588120"), // feed answer @ FORK_BLOCK (~$405.13) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -131,7 +137,7 @@ export const MARKET_2: MarketSpec = { address: ATLAS_ORACLE, feed: "0x8a44cF4E55adD99EB8bAC5D5DB749C63106d54AA", // Atlas NVDAB/USD feed (id 773) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("211086527189540030430"), // feed answer @ FORK_BLOCK (~$211.09) + price: BigNumber.from("211853899347221359990"), // feed answer @ FORK_BLOCK (~$211.85) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -180,6 +186,7 @@ For each new market this VIP will: - Set the AccessControlManager, ProtocolShareReserve and reduce-reserves block delta on the vToken - Provide bootstrap liquidity (minting an initial supply and sending the resulting vTokens to the VTreasury) - Pause borrowing for the market at launch +- Enable Oracle Dynamic Protection Mode (DeviationBoundedOracle, see VIP-617) for the underlying, with a 16.67% deviation trigger #### Risk parameters @@ -193,7 +200,8 @@ Both markets share the same interest rate model (base 0%, multiplier 6.67%, jump | Reserve factor | 10% | 10% | | Supply cap | 236 TSLAB | 450 NVDAB | | Borrow cap | 0 (borrowing disabled) | 0 (borrowing disabled) | -| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB |`, +| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB | +| Protection trigger | 16.67% | 16.67% |`, 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", @@ -303,6 +311,22 @@ Both markets share the same interest rate model (base 0%, multiplier 6.67%, jump signature: "transfer(address,uint256)", params: [m.initialSupply.vTokenReceiver, vTokensRemaining(m)], }, + + // Enable Oracle Dynamic Protection Mode (DBO) for the underlying with a 16.67% deviation trigger. + { + target: DEVIATION_BOUNDED_ORACLE, + signature: "setTokenConfig((address,uint64,uint256,uint256,bool,bool))", + params: [ + [ + m.vToken.underlying.address, + DBO_COOLDOWN_PERIOD, + DBO_TRIGGER_THRESHOLD, + DBO_RESET_THRESHOLD, + true, // isBoundedPricingEnabled + false, // cachingEnabled + ], + ], + }, ]), meta, ProposalType.REGULAR, diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts index aed108993..9569c3136 100644 --- a/vips/vip-669/bsctestnet.ts +++ b/vips/vip-669/bsctestnet.ts @@ -13,6 +13,12 @@ export const PROTOCOL_SHARE_RESERVE = "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E export const REDUCE_RESERVES_BLOCK_DELTA = "28800"; export const BORROW_ACTION = 2; // Comptroller Action enum: BORROW +// Oracle Dynamic Protection Mode (DeviationBoundedOracle) +export const DEVIATION_BOUNDED_ORACLE = "0xE0dafC97895B3c98d3B96D3f8739AaC73166beB8"; +export const DBO_COOLDOWN_PERIOD = 3600; // 1h rolling window +export const DBO_TRIGGER_THRESHOLD = parseUnits("0.1667", 18); // 16.67% — arms protection beyond this deviation +export const DBO_RESET_THRESHOLD = parseUnits("0.05", 18); // 5% + // ACM permissions to grant on the newly deployed Atlas Oracle, to every governance timelock. export const ATLAS_ORACLE_PERMISSIONS = ["setDirectPrice(address,uint256)", "setTokenConfig(TokenConfig)"]; export const TIMELOCKS = [bsctestnet.NORMAL_TIMELOCK, bsctestnet.FAST_TRACK_TIMELOCK, bsctestnet.CRITICAL_TIMELOCK]; @@ -155,12 +161,10 @@ export const vTokensRemaining = (m: MarketSpec) => export const vip669 = () => { const meta = { version: "v2", - title: "VIP-669 [BNB Chain Testnet] List new markets in the Venus Core Pool", + title: "VIP-669 [BNB Chain Testnet] List vTSLAB and vNVDAB markets in the Venus Core Pool", description: `#### Summary -If passed, this VIP will list two new markets in the Venus Core Pool on BNB Chain testnet. - -The assets, risk parameters and oracle configuration will be detailed ahead of execution.`, +If passed, this VIP will list two new tokenized-equity markets — Venus TSLAB (vTSLAB) and Venus NVDAB (vNVDAB) — in the Venus Core Pool on BNB Chain testnet, with borrowing paused at launch.`, 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", @@ -277,6 +281,22 @@ The assets, risk parameters and oracle configuration will be detailed ahead of e signature: "transfer(address,uint256)", params: [m.initialSupply.vTokenReceiver, vTokensRemaining(m)], }, + + // Enable Oracle Dynamic Protection Mode (DBO) for the underlying with a 16.67% deviation trigger. + { + target: DEVIATION_BOUNDED_ORACLE, + signature: "setTokenConfig((address,uint64,uint256,uint256,bool,bool))", + params: [ + [ + m.vToken.underlying.address, + DBO_COOLDOWN_PERIOD, + DBO_TRIGGER_THRESHOLD, + DBO_RESET_THRESHOLD, + true, // isBoundedPricingEnabled + false, // cachingEnabled + ], + ], + }, ]), ], meta, From 7d2d7fb4ede566d32b483d894588193939d7b7e1 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 18:07:28 +0530 Subject: [PATCH 07/10] feat: add SPCXB market listing commands --- simulations/vip-669/bsctestnet.ts | 6 +-- vips/vip-669/bscmainnet.ts | 86 ++++++++++++++++++++++++------- vips/vip-669/bsctestnet.ts | 57 +++++++++++++++++--- 3 files changed, 120 insertions(+), 29 deletions(-) diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-669/bsctestnet.ts index 2c13e4061..ed2f9aabd 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-669/bsctestnet.ts @@ -32,7 +32,7 @@ import VTOKEN_ABI from "./abi/VToken.json"; const { bsctestnet } = NETWORK_ADDRESSES; -const FORK_BLOCK = 112317000; +const FORK_BLOCK = 113708000; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bsctestnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); @@ -67,8 +67,8 @@ forking(FORK_BLOCK, async () => { "NewLiquidationThreshold", "NewLiquidationIncentive", ], - // 6 permission grants (2 functions x 3 timelocks); the rest are 2 markets each - [6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + // 6 permission grants (2 functions x 3 timelocks); the rest are 3 markets each + [6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3], ); }, }); diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index acc28cc2d..f9b149c98 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -64,8 +64,8 @@ export type MarketSpec = { }; }; -// Market 1 — TSLAB -export const MARKET_1: MarketSpec = { +// Market — TSLAB +export const MARKET_TSLAB: MarketSpec = { vToken: { address: "0x97421799419Eb782628e73e7220d8E0A207469a3", name: "Venus TSLAB", @@ -109,8 +109,8 @@ export const MARKET_1: MarketSpec = { }, }; -// Market 2 — NVDAB -export const MARKET_2: MarketSpec = { +// Market — NVDAB +export const MARKET_NVDAB: MarketSpec = { vToken: { address: "0xEb8Ca841cBe1BC4832A10b15c7dAB1081eDaD371", name: "Venus NVDAB", @@ -154,7 +154,54 @@ export const MARKET_2: MarketSpec = { }, }; -export const MARKETS: MarketSpec[] = [MARKET_1, MARKET_2]; +// Market — SPCXB (Venus SpaceX) +export const MARKET_SPCXB: MarketSpec = { + vToken: { + address: "0xC36dFaCc7a125859C106F29b9F2d874CCF29A55A", + name: "Venus SpaceX", + symbol: "vSPCXB", + underlying: { + address: "0xbe9D156892E55e7154BcD3cB0FEA677F9D3103E1", + symbol: "SPCXB", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bscmainnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0xe589E884f69dF3137B43A760C4Ec9E55D944439D", + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + feed: ethers.constants.AddressZero, // TODO: set Atlas SPCXB/USD feed + maxStalePeriod: ATLAS_MAX_STALE_PERIOD, + price: BigNumber.from("0"), // TODO: feed answer @ FORK_BLOCK once the feed is configured + }, + riskParameters: { + collateralFactor: parseUnits("0.5", 18), + liquidationThreshold: parseUnits("0.65", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("500", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch + }, + initialSupply: { + amount: parseUnits("0.51", 18), + vTokenReceiver: bscmainnet.VTREASURY, + vTokensToBurn: parseUnits("0.051", 8), // 10% of minted vTokens + }, +}; + +// TODO: add MARKET_SPCXB once its Atlas feed is configured +// (and the VTreasury holds the 0.51 SPCXB bootstrap amount). +export const MARKETS: MarketSpec[] = [MARKET_TSLAB, MARKET_NVDAB]; export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { const EXP_SCALE = parseUnits("1", 18); @@ -168,19 +215,20 @@ export const vTokensRemaining = (m: MarketSpec) => vTokensMinted(m).sub(m.initia export const vip669 = (simulations = false) => { const meta = { version: "v2", - title: "VIP-669 [BNB Chain] List new markets in the Venus Core Pool", + title: "VIP-669 [BNB Chain] List vTSLAB and vNVDAB markets in the Venus Core Pool", description: `#### Summary -If passed, this VIP will list two new tokenized-equity markets in the Venus Core Pool on BNB Chain, with borrowing paused at launch: +If passed, this VIP will list three new tokenized-equity markets in the Venus Core Pool on BNB Chain, with borrowing paused at launch: - **Venus TSLAB (vTSLAB)** — backed by TSLAB (Tesla, Inc.) - **Venus NVDAB (vNVDAB)** — backed by NVDAB (NVIDIA Corp) +- **Venus SpaceX (vSPCXB)** — backed by SPCXB (SpaceX) #### Description For each new market this VIP will: -- Configure the underlying to use its Atlas Oracle price feed (TSLAB/USD, NVDAB/USD) in the ResilientOracle +- Configure the underlying to use its Atlas Oracle price feed (TSLAB/USD, NVDAB/USD, SPCXB/USD) in the ResilientOracle - Add the market to the Core Pool Comptroller - Set the supply cap, collateral factor, liquidation threshold, liquidation incentive and reserve factor - Set the AccessControlManager, ProtocolShareReserve and reduce-reserves block delta on the vToken @@ -190,18 +238,18 @@ For each new market this VIP will: #### Risk parameters -Both markets share the same interest rate model (base 0%, multiplier 6.67%, jump multiplier 627%, kink 75%) and the following parameters: +All three markets share the same interest rate model (base 0%, multiplier 6.67%, jump multiplier 627%, kink 75%) and the following parameters: -| Parameter | Venus TSLAB | Venus NVDAB | -| --- | --- | --- | -| Collateral factor | 60% | 60% | -| Liquidation threshold | 70% | 70% | -| Liquidation incentive | 10% | 10% | -| Reserve factor | 10% | 10% | -| Supply cap | 236 TSLAB | 450 NVDAB | -| Borrow cap | 0 (borrowing disabled) | 0 (borrowing disabled) | -| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB | -| Protection trigger | 16.67% | 16.67% |`, +| Parameter | Venus TSLAB | Venus NVDAB | Venus SpaceX | +| --- | --- | --- | --- | +| Collateral factor | 60% | 60% | 50% | +| Liquidation threshold | 70% | 70% | 65% | +| Liquidation incentive | 10% | 10% | 10% | +| Reserve factor | 10% | 10% | 10% | +| Supply cap | 236 TSLAB | 450 NVDAB | 500 SPCXB | +| Borrow cap | 0 (borrowing disabled) | 0 (borrowing disabled) | 0 (borrowing disabled) | +| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB | 0.51 SPCXB | +| Protection trigger | 16.67% | 16.67% | 16.67% |`, 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", diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-669/bsctestnet.ts index 9569c3136..f61ba3597 100644 --- a/vips/vip-669/bsctestnet.ts +++ b/vips/vip-669/bsctestnet.ts @@ -62,8 +62,8 @@ export type MarketSpec = { }; }; -// Market 1 — TSLAB -export const MARKET_1: MarketSpec = { +// Market — TSLAB +export const MARKET_TSLAB: MarketSpec = { vToken: { address: "0x3Ed56f6937fc8549f9325405d1e8E650739647Fa", name: "Venus TSLAB", @@ -105,8 +105,8 @@ export const MARKET_1: MarketSpec = { }, }; -// Market 2 — NVDAB -export const MARKET_2: MarketSpec = { +// Market — NVDAB +export const MARKET_NVDAB: MarketSpec = { vToken: { address: "0x9e1ECb2671AfabE9eaAA2e74Cb2318a9b6A2Eb5d", name: "Venus NVDAB", @@ -148,7 +148,50 @@ export const MARKET_2: MarketSpec = { }, }; -export const MARKETS: MarketSpec[] = [MARKET_1, MARKET_2]; +// Market — SPCXB (Venus SpaceX) +export const MARKET_SPCXB: MarketSpec = { + vToken: { + address: "0x05B2EC5B7437FB188175bf440e3EB36af79fe319", + name: "Venus SpaceX", + symbol: "vSPCXB", + underlying: { + address: "0x6D9e91cB766259af42619c14c994E694E57e6E85", // MockSPCXB + symbol: "SPCXB", + decimals: 18, + }, + decimals: 8, + exchangeRate: parseUnits("1", 28), + comptroller: bsctestnet.UNITROLLER, + isLegacyPool: true, + }, + rateModel: "0x1CcDaf39085bae4e27c3Ba100561b1AD1B5A6b80", + interestRateModel: { + model: "jump", + baseRatePerYear: "0", + multiplierPerYear: "0.0667", + jumpMultiplierPerYear: "6.27", + kink: "0.75", + }, + oracle: { + address: ATLAS_ORACLE, + directPrice: parseUnits("192", 18), // $192 (mocked) + }, + riskParameters: { + collateralFactor: parseUnits("0.5", 18), + liquidationThreshold: parseUnits("0.65", 18), + liquidationIncentive: parseUnits("1.1", 18), + reserveFactor: parseUnits("0.1", 18), + supplyCap: parseUnits("500", 18), + borrowCap: parseUnits("0", 18), // borrowing disabled at launch + }, + initialSupply: { + amount: parseUnits("0.51", 18), + vTokenReceiver: bsctestnet.VTREASURY, + vTokensToBurn: parseUnits("0.051", 8), + }, +}; + +export const MARKETS: MarketSpec[] = [MARKET_TSLAB, MARKET_NVDAB, MARKET_SPCXB]; export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { const EXP_SCALE = parseUnits("1", 18); @@ -161,10 +204,10 @@ export const vTokensRemaining = (m: MarketSpec) => export const vip669 = () => { const meta = { version: "v2", - title: "VIP-669 [BNB Chain Testnet] List vTSLAB and vNVDAB markets in the Venus Core Pool", + title: "VIP-669 [BNB Chain Testnet] List vTSLAB, vNVDAB and vSPCXB markets in the Venus Core Pool", description: `#### Summary -If passed, this VIP will list two new tokenized-equity markets — Venus TSLAB (vTSLAB) and Venus NVDAB (vNVDAB) — in the Venus Core Pool on BNB Chain testnet, with borrowing paused at launch.`, +If passed, this VIP will list three new tokenized-equity markets — Venus TSLAB (vTSLAB), Venus NVDAB (vNVDAB) and Venus SpaceX (vSPCXB) — in the Venus Core Pool on BNB Chain testnet, with borrowing paused at launch.`, 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", From a875c97b33680470b9ce2f4137b74ec02d9df3f8 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Tue, 16 Jun 2026 19:39:59 +0530 Subject: [PATCH 08/10] feat: update SPCXB price feed --- vips/vip-669/bscmainnet.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-669/bscmainnet.ts index f9b149c98..a312b3150 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-669/bscmainnet.ts @@ -180,9 +180,9 @@ export const MARKET_SPCXB: MarketSpec = { }, oracle: { address: ATLAS_ORACLE, - feed: ethers.constants.AddressZero, // TODO: set Atlas SPCXB/USD feed + feed: "0x0072e55bff6fEC200708cE82612569a1C0EB4B24", // Atlas SPCXB/USD feed maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("0"), // TODO: feed answer @ FORK_BLOCK once the feed is configured + price: BigNumber.from("212715918086907586340"), // feed answer (~$212.72); }, riskParameters: { collateralFactor: parseUnits("0.5", 18), @@ -199,8 +199,7 @@ export const MARKET_SPCXB: MarketSpec = { }, }; -// TODO: add MARKET_SPCXB once its Atlas feed is configured -// (and the VTreasury holds the 0.51 SPCXB bootstrap amount). +// TODO: add MARKET_SPCXB once the VTreasury holds the initial supply. export const MARKETS: MarketSpec[] = [MARKET_TSLAB, MARKET_NVDAB]; export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { From a51b458f412d0ac59b0b152c53ea2877cbc85614 Mon Sep 17 00:00:00 2001 From: Venus Fred Date: Wed, 17 Jun 2026 00:00:09 +0800 Subject: [PATCH 09/10] chore: prepare VIP-633 for proposal --- .../abi/AccessControlManager.json | 0 .../{vip-669 => vip-633}/abi/AtlasOracle.json | 0 .../{vip-669 => vip-633}/abi/Comptroller.json | 0 .../abi/DeviationBoundedOracle.json | 0 .../{vip-669 => vip-633}/abi/ERC20.json | 0 .../abi/ResilientOracle.json | 0 .../{vip-669 => vip-633}/abi/VToken.json | 0 .../{vip-669 => vip-633}/abi/VTreasury.json | 0 .../{vip-669 => vip-633}/bscmainnet.ts | 15 ++--- .../{vip-669 => vip-633}/bsctestnet.ts | 2 +- vips/{vip-669 => vip-633}/bscmainnet.ts | 56 ++++++++++++------- vips/{vip-669 => vip-633}/bsctestnet.ts | 0 12 files changed, 46 insertions(+), 27 deletions(-) rename simulations/{vip-669 => vip-633}/abi/AccessControlManager.json (100%) rename simulations/{vip-669 => vip-633}/abi/AtlasOracle.json (100%) rename simulations/{vip-669 => vip-633}/abi/Comptroller.json (100%) rename simulations/{vip-669 => vip-633}/abi/DeviationBoundedOracle.json (100%) rename simulations/{vip-669 => vip-633}/abi/ERC20.json (100%) rename simulations/{vip-669 => vip-633}/abi/ResilientOracle.json (100%) rename simulations/{vip-669 => vip-633}/abi/VToken.json (100%) rename simulations/{vip-669 => vip-633}/abi/VTreasury.json (100%) rename simulations/{vip-669 => vip-633}/bscmainnet.ts (95%) rename simulations/{vip-669 => vip-633}/bsctestnet.ts (99%) rename vips/{vip-669 => vip-633}/bscmainnet.ts (90%) rename vips/{vip-669 => vip-633}/bsctestnet.ts (100%) diff --git a/simulations/vip-669/abi/AccessControlManager.json b/simulations/vip-633/abi/AccessControlManager.json similarity index 100% rename from simulations/vip-669/abi/AccessControlManager.json rename to simulations/vip-633/abi/AccessControlManager.json diff --git a/simulations/vip-669/abi/AtlasOracle.json b/simulations/vip-633/abi/AtlasOracle.json similarity index 100% rename from simulations/vip-669/abi/AtlasOracle.json rename to simulations/vip-633/abi/AtlasOracle.json diff --git a/simulations/vip-669/abi/Comptroller.json b/simulations/vip-633/abi/Comptroller.json similarity index 100% rename from simulations/vip-669/abi/Comptroller.json rename to simulations/vip-633/abi/Comptroller.json diff --git a/simulations/vip-669/abi/DeviationBoundedOracle.json b/simulations/vip-633/abi/DeviationBoundedOracle.json similarity index 100% rename from simulations/vip-669/abi/DeviationBoundedOracle.json rename to simulations/vip-633/abi/DeviationBoundedOracle.json diff --git a/simulations/vip-669/abi/ERC20.json b/simulations/vip-633/abi/ERC20.json similarity index 100% rename from simulations/vip-669/abi/ERC20.json rename to simulations/vip-633/abi/ERC20.json diff --git a/simulations/vip-669/abi/ResilientOracle.json b/simulations/vip-633/abi/ResilientOracle.json similarity index 100% rename from simulations/vip-669/abi/ResilientOracle.json rename to simulations/vip-633/abi/ResilientOracle.json diff --git a/simulations/vip-669/abi/VToken.json b/simulations/vip-633/abi/VToken.json similarity index 100% rename from simulations/vip-669/abi/VToken.json rename to simulations/vip-633/abi/VToken.json diff --git a/simulations/vip-669/abi/VTreasury.json b/simulations/vip-633/abi/VTreasury.json similarity index 100% rename from simulations/vip-669/abi/VTreasury.json rename to simulations/vip-633/abi/VTreasury.json diff --git a/simulations/vip-669/bscmainnet.ts b/simulations/vip-633/bscmainnet.ts similarity index 95% rename from simulations/vip-669/bscmainnet.ts rename to simulations/vip-633/bscmainnet.ts index 8fff37a1c..bf2ac7718 100644 --- a/simulations/vip-669/bscmainnet.ts +++ b/simulations/vip-633/bscmainnet.ts @@ -21,8 +21,8 @@ import { REDUCE_RESERVES_BLOCK_DELTA, convertAmountToVTokens, vTokensRemaining, - vip669, -} from "../../vips/vip-669/bscmainnet"; + vip633, +} from "../../vips/vip-633/bscmainnet"; import ATLAS_ORACLE_ABI from "./abi/AtlasOracle.json"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; import DBO_ABI from "./abi/DeviationBoundedOracle.json"; @@ -33,8 +33,9 @@ import VTREASURY_ABI from "./abi/VTreasury.json"; const { bscmainnet } = NETWORK_ADDRESSES; -// Block after the TSLAB/NVDAB markets, their Atlas feeds, and the VTreasury bootstrap funding. -const FORK_BLOCK = 104542000; +// Block after all three markets (TSLAB/NVDAB/SPCXB) were deployed, their Atlas feeds went live, +// and the VTreasury received the bootstrap funding for each. +const FORK_BLOCK = 104593700; forking(FORK_BLOCK, async () => { const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); @@ -51,7 +52,7 @@ forking(FORK_BLOCK, async () => { } }); - testVip("VIP-669", await vip669(true), { + testVip("VIP-633", await vip633(true), { callbackAfterExecution: async txResponse => { await expectEvents( txResponse, @@ -68,8 +69,8 @@ forking(FORK_BLOCK, async () => { "NewLiquidationThreshold", "NewLiquidationIncentive", ], - // 2 markets listed in this VIP - [2, 2, 2, 2, 2, 2, 2, 2, 2, 2], + // 3 markets listed in this VIP + [3, 3, 3, 3, 3, 3, 3, 3, 3, 3], ); }, }); diff --git a/simulations/vip-669/bsctestnet.ts b/simulations/vip-633/bsctestnet.ts similarity index 99% rename from simulations/vip-669/bsctestnet.ts rename to simulations/vip-633/bsctestnet.ts index ed2f9aabd..78db924ab 100644 --- a/simulations/vip-669/bsctestnet.ts +++ b/simulations/vip-633/bsctestnet.ts @@ -22,7 +22,7 @@ import { convertAmountToVTokens, vTokensRemaining, vip669, -} from "../../vips/vip-669/bsctestnet"; +} from "../../vips/vip-633/bsctestnet"; import ACM_ABI from "./abi/AccessControlManager.json"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; import DBO_ABI from "./abi/DeviationBoundedOracle.json"; diff --git a/vips/vip-669/bscmainnet.ts b/vips/vip-633/bscmainnet.ts similarity index 90% rename from vips/vip-669/bscmainnet.ts rename to vips/vip-633/bscmainnet.ts index a312b3150..9a78d3595 100644 --- a/vips/vip-669/bscmainnet.ts +++ b/vips/vip-633/bscmainnet.ts @@ -92,7 +92,7 @@ export const MARKET_TSLAB: MarketSpec = { address: ATLAS_ORACLE, feed: "0x63950C265e7CDB4016bA60C288c46291C0148ce2", // Atlas TSLAB/USD feed (id 772) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("405127531587687588120"), // feed answer @ FORK_BLOCK (~$405.13) + price: BigNumber.from("405935900574526605890"), // feed answer @ FORK_BLOCK (~$405.94) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -137,7 +137,7 @@ export const MARKET_NVDAB: MarketSpec = { address: ATLAS_ORACLE, feed: "0x8a44cF4E55adD99EB8bAC5D5DB749C63106d54AA", // Atlas NVDAB/USD feed (id 773) maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("211853899347221359990"), // feed answer @ FORK_BLOCK (~$211.85) + price: BigNumber.from("209041550339998554920"), // feed answer @ FORK_BLOCK (~$209.04) }, riskParameters: { collateralFactor: parseUnits("0.6", 18), @@ -182,7 +182,7 @@ export const MARKET_SPCXB: MarketSpec = { address: ATLAS_ORACLE, feed: "0x0072e55bff6fEC200708cE82612569a1C0EB4B24", // Atlas SPCXB/USD feed maxStalePeriod: ATLAS_MAX_STALE_PERIOD, - price: BigNumber.from("212715918086907586340"), // feed answer (~$212.72); + price: BigNumber.from("210591042364299936480"), // feed answer @ FORK_BLOCK (~$210.59) }, riskParameters: { collateralFactor: parseUnits("0.5", 18), @@ -199,8 +199,7 @@ export const MARKET_SPCXB: MarketSpec = { }, }; -// TODO: add MARKET_SPCXB once the VTreasury holds the initial supply. -export const MARKETS: MarketSpec[] = [MARKET_TSLAB, MARKET_NVDAB]; +export const MARKETS: MarketSpec[] = [MARKET_TSLAB, MARKET_NVDAB, MARKET_SPCXB]; export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumber) => { const EXP_SCALE = parseUnits("1", 18); @@ -211,10 +210,10 @@ export const vTokensMinted = (m: MarketSpec) => convertAmountToVTokens(m.initial export const vTokensRemaining = (m: MarketSpec) => vTokensMinted(m).sub(m.initialSupply.vTokensToBurn); -export const vip669 = (simulations = false) => { +export const vip633 = (simulations = false) => { const meta = { version: "v2", - title: "VIP-669 [BNB Chain] List vTSLAB and vNVDAB markets in the Venus Core Pool", + title: "VIP-633 [BNB Chain] List vTSLAB, vNVDAB and vSPCXB markets in the Venus Core Pool", description: `#### Summary If passed, this VIP will list three new tokenized-equity markets in the Venus Core Pool on BNB Chain, with borrowing paused at launch: @@ -237,18 +236,37 @@ For each new market this VIP will: #### Risk parameters -All three markets share the same interest rate model (base 0%, multiplier 6.67%, jump multiplier 627%, kink 75%) and the following parameters: +All three markets share the same interest rate model (base 0%, multiplier 6.67%, jump multiplier 627%, kink 75%). Per-market parameters: -| Parameter | Venus TSLAB | Venus NVDAB | Venus SpaceX | -| --- | --- | --- | --- | -| Collateral factor | 60% | 60% | 50% | -| Liquidation threshold | 70% | 70% | 65% | -| Liquidation incentive | 10% | 10% | 10% | -| Reserve factor | 10% | 10% | 10% | -| Supply cap | 236 TSLAB | 450 NVDAB | 500 SPCXB | -| Borrow cap | 0 (borrowing disabled) | 0 (borrowing disabled) | 0 (borrowing disabled) | -| Bootstrap liquidity | 0.26 TSLAB | 0.5 NVDAB | 0.51 SPCXB | -| Protection trigger | 16.67% | 16.67% | 16.67% |`, +**Venus TSLAB (vTSLAB)** +- Collateral factor: 60% +- Liquidation threshold: 70% +- Liquidation incentive: 10% +- Reserve factor: 10% +- Supply cap: 236 TSLAB +- Borrow cap: 0 (borrowing disabled) +- Bootstrap liquidity: 0.26 TSLAB +- Protection trigger: 16.67% + +**Venus NVDAB (vNVDAB)** +- Collateral factor: 60% +- Liquidation threshold: 70% +- Liquidation incentive: 10% +- Reserve factor: 10% +- Supply cap: 450 NVDAB +- Borrow cap: 0 (borrowing disabled) +- Bootstrap liquidity: 0.5 NVDAB +- Protection trigger: 16.67% + +**Venus SpaceX (vSPCXB)** +- Collateral factor: 50% +- Liquidation threshold: 65% +- Liquidation incentive: 10% +- Reserve factor: 10% +- Supply cap: 500 SPCXB +- Borrow cap: 0 (borrowing disabled) +- Bootstrap liquidity: 0.51 SPCXB +- Protection trigger: 16.67%`, 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", @@ -380,4 +398,4 @@ All three markets share the same interest rate model (base 0%, multiplier 6.67%, ); }; -export default vip669; +export default vip633; diff --git a/vips/vip-669/bsctestnet.ts b/vips/vip-633/bsctestnet.ts similarity index 100% rename from vips/vip-669/bsctestnet.ts rename to vips/vip-633/bsctestnet.ts From a5fb00ae8105c9b962a3f872551b8c71dbb02e26 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Wed, 17 Jun 2026 11:21:27 +0530 Subject: [PATCH 10/10] chore: update vip number --- simulations/vip-633/bsctestnet.ts | 4 ++-- vips/vip-633/bsctestnet.ts | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/simulations/vip-633/bsctestnet.ts b/simulations/vip-633/bsctestnet.ts index 78db924ab..c9e7dccc7 100644 --- a/simulations/vip-633/bsctestnet.ts +++ b/simulations/vip-633/bsctestnet.ts @@ -21,7 +21,7 @@ import { TIMELOCKS, convertAmountToVTokens, vTokensRemaining, - vip669, + vip633, } from "../../vips/vip-633/bsctestnet"; import ACM_ABI from "./abi/AccessControlManager.json"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; @@ -49,7 +49,7 @@ forking(FORK_BLOCK, async () => { } }); - testVip("VIP-669 Testnet", await vip669(), { + testVip("VIP-633 Testnet", await vip633(), { callbackAfterExecution: async txResponse => { await expectEvents( txResponse, diff --git a/vips/vip-633/bsctestnet.ts b/vips/vip-633/bsctestnet.ts index f61ba3597..e6b971e86 100644 --- a/vips/vip-633/bsctestnet.ts +++ b/vips/vip-633/bsctestnet.ts @@ -201,10 +201,10 @@ export const convertAmountToVTokens = (amount: BigNumber, exchangeRate: BigNumbe export const vTokensRemaining = (m: MarketSpec) => convertAmountToVTokens(m.initialSupply.amount, m.vToken.exchangeRate).sub(m.initialSupply.vTokensToBurn); -export const vip669 = () => { +export const vip633 = () => { const meta = { version: "v2", - title: "VIP-669 [BNB Chain Testnet] List vTSLAB, vNVDAB and vSPCXB markets in the Venus Core Pool", + title: "VIP-633 [BNB Chain Testnet] List vTSLAB, vNVDAB and vSPCXB markets in the Venus Core Pool", description: `#### Summary If passed, this VIP will list three new tokenized-equity markets — Venus TSLAB (vTSLAB), Venus NVDAB (vNVDAB) and Venus SpaceX (vSPCXB) — in the Venus Core Pool on BNB Chain testnet, with borrowing paused at launch.`, @@ -347,4 +347,4 @@ If passed, this VIP will list three new tokenized-equity markets — Venus TSLAB ); }; -export default vip669; +export default vip633;