diff --git a/simulations/vip-661/abi/AccessControlManager.json b/simulations/vip-661/abi/AccessControlManager.json new file mode 100644 index 000000000..4a118fcc4 --- /dev/null +++ b/simulations/vip-661/abi/AccessControlManager.json @@ -0,0 +1,360 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToPermit", + "type": "address" + } + ], + "name": "giveCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "hasPermission", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "isAllowedToCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToRevoke", + "type": "address" + } + ], + "name": "revokeCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-661/abi/DeviationSentinel.json b/simulations/vip-661/abi/DeviationSentinel.json new file mode 100644 index 000000000..c12ea017a --- /dev/null +++ b/simulations/vip-661/abi/DeviationSentinel.json @@ -0,0 +1,589 @@ +[ + { + "inputs": [ + { + "internalType": "contract IEBrake", + "name": "eBrake_", + "type": "address" + }, + { + "internalType": "contract ResilientOracleInterface", + "name": "resilientOracle_", + "type": "address" + }, + { + "internalType": "contract OracleInterface", + "name": "sentinelOracle_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ExceedsMaxDeviation", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotConfigured", + "type": "error" + }, + { + "inputs": [], + "name": "TokenMonitoringDisabled", + "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": "UnauthorizedKeeper", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroDeviation", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "BorrowPaused", + "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": "market", + "type": "address" + } + ], + "name": "MarketStateReset", + "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": "market", + "type": "address" + } + ], + "name": "SupplyPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "deviation", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "indexed": false, + "internalType": "struct DeviationSentinel.DeviationConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "TokenConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "TokenMonitoringStatusChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isTrusted", + "type": "bool" + } + ], + "name": "TrustedKeeperUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "EBRAKE", + "outputs": [ + { + "internalType": "contract IEBrake", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_DEVIATION", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RESILIENT_ORACLE", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "SENTINEL_ORACLE", + "outputs": [ + { + "internalType": "contract OracleInterface", + "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": "contract IVToken", + "name": "market", + "type": "address" + } + ], + "name": "checkPriceDeviation", + "outputs": [ + { + "internalType": "bool", + "name": "hasDeviation", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "oraclePrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sentinelPrice", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "deviationPercent", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IVToken", + "name": "market", + "type": "address" + } + ], + "name": "handleDeviation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "marketStates", + "outputs": [ + { + "internalType": "bool", + "name": "borrowPaused", + "type": "bool" + }, + { + "internalType": "bool", + "name": "cfModifiedAndSupplyPaused", + "type": "bool" + } + ], + "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": "contract IVToken", + "name": "market", + "type": "address" + } + ], + "name": "resetMarketState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "deviation", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "internalType": "struct DeviationSentinel.DeviationConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "name": "setTokenMonitoringEnabled", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "keeper", + "type": "address" + }, + { + "internalType": "bool", + "name": "isTrusted", + "type": "bool" + } + ], + "name": "setTrustedKeeper", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "tokenConfigs", + "outputs": [ + { + "internalType": "uint8", + "name": "deviation", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "trustedKeepers", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-661/abi/EBrake.json b/simulations/vip-661/abi/EBrake.json new file mode 100644 index 000000000..c7aedf09d --- /dev/null +++ b/simulations/vip-661/abi/EBrake.json @@ -0,0 +1,683 @@ +[ + { + "inputs": [ + { + "internalType": "contract ICorePoolComptroller", + "name": "corePoolComptroller_", + "type": "address" + }, + { + "internalType": "bool", + "name": "isIsolatedPool_", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "actual", + "type": "uint256" + } + ], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint256", + "name": "currentCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requestedCap", + "type": "uint256" + } + ], + "name": "CapExceedsCurrent", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyArray", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum IComptroller.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "ForbiddenAction", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "MarketNotListed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + } + ], + "name": "SetCollateralFactorFailed", + "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": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "enum IComptroller.Action", + "name": "action", + "type": "uint8" + } + ], + "name": "ActionPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "enum IComptroller.Action[]", + "name": "actions", + "type": "uint8[]" + } + ], + "name": "ActionsPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "BorrowCapsDecreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "CollateralFactorZeroed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "caller", + "type": "address" + } + ], + "name": "FlashLoanPaused", + "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": "market", + "type": "address" + } + ], + "name": "MarketStateReset", + "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": "caller", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "SupplyCapsDecreased", + "type": "event" + }, + { + "inputs": [], + "name": "COMPTROLLER", + "outputs": [ + { + "internalType": "contract ICorePoolComptroller", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "IS_ISOLATED_POOL", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "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": "market", + "type": "address" + }, + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "getMarketCFSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "cf", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "lt", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "marketStates", + "outputs": [ + { + "internalType": "uint256", + "name": "borrowCap", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "supplyCap", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "borrowCapSnapshotted", + "type": "bool" + }, + { + "internalType": "bool", + "name": "supplyCapSnapshotted", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "enum IComptroller.Action[]", + "name": "actions", + "type": "uint8[]" + } + ], + "name": "pauseActions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "pauseBorrow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pauseFlashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "pauseRedeem", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "pauseSupply", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "pauseTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "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": "market", + "type": "address" + } + ], + "name": "resetMarketState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "setCFZero", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "setCFZero", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-661/abi/ERC20.json b/simulations/vip-661/abi/ERC20.json new file mode 100644 index 000000000..3a509c9c4 --- /dev/null +++ b/simulations/vip-661/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-661/abi/ProxyAdmin.json b/simulations/vip-661/abi/ProxyAdmin.json new file mode 100644 index 000000000..b4c51d8df --- /dev/null +++ b/simulations/vip-661/abi/ProxyAdmin.json @@ -0,0 +1,151 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/simulations/vip-661/abi/ResilientOracle.json b/simulations/vip-661/abi/ResilientOracle.json new file mode 100644 index 000000000..04fb2fe79 --- /dev/null +++ b/simulations/vip-661/abi/ResilientOracle.json @@ -0,0 +1,750 @@ +[ + { + "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": "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": "BNB_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "INVALID_PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "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": "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": "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": "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": "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": "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" + } +] diff --git a/simulations/vip-661/abi/comptroller.json b/simulations/vip-661/abi/comptroller.json new file mode 100644 index 000000000..f2cb3ea37 --- /dev/null +++ b/simulations/vip-661/abi/comptroller.json @@ -0,0 +1,3979 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "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": [ + { + "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" + }, + { + "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": [ + { + "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": "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-661/bscmainnet.ts b/simulations/vip-661/bscmainnet.ts new file mode 100644 index 000000000..9a94e4c7a --- /dev/null +++ b/simulations/vip-661/bscmainnet.ts @@ -0,0 +1,229 @@ +import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/signers"; +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents, initMainnetUser } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import vip661, { + ACM, + CORE_POOL_COMPTROLLER, + DEVIATION_SENTINEL, + EBRAKE, + MULTISIG, + NEW_DEVIATION_SENTINEL_IMPL, + PROXY_ADMIN, +} from "../../vips/vip-661/bscmainnet"; +import ACCESS_CONTROL_MANAGER_ABI from "./abi/AccessControlManager.json"; +import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; +import EBRAKE_ABI from "./abi/EBrake.json"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, GUARDIAN } = NETWORK_ADDRESSES.bscmainnet; +const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; + +// Permissions EBrake needs on the Core Pool Comptroller +const EBRAKE_COMPTROLLER_PERMS = [ + "_setActionsPaused(address[],uint8[],bool)", + "setCollateralFactor(address,uint256,uint256)", + "setCollateralFactor(uint96,address,uint256,uint256)", + "_setMarketBorrowCaps(address[],uint256[])", + "_setMarketSupplyCaps(address[],uint256[])", + "setFlashLoanPaused(bool)", + "setIsBorrowAllowed(uint96,address,bool)", + "setWhiteListFlashLoanAccount(address,bool)", +]; + +// Permissions DeviationSentinel will have on EBrake +const SENTINEL_EBRAKE_PERMS = ["pauseBorrow(address)", "pauseSupply(address)", "decreaseCF(address,uint256)"]; + +// Granular snapshot-reset functions governance/guardian can call on EBrake +const RESET_PERMS = ["resetCFSnapshot(address)", "resetBorrowCapSnapshot(address)", "resetSupplyCapSnapshot(address)"]; + +// All EBrake action functions governance/guardian can call directly +// (so a Critical VIP can route through EBrake and get snapshot coverage) +const GOVERNANCE_EBRAKE_PERMS = [ + "pauseBorrow(address)", + "pauseSupply(address)", + "pauseRedeem(address)", + "pauseTransfer(address)", + "pauseFlashLoan()", + "pauseActions(address[],uint8[])", + "setMarketBorrowCaps(address[],uint256[])", + "setMarketSupplyCaps(address[],uint256[])", + "disablePoolBorrow(uint96,address)", + "revokeFlashLoanAccess(address)", + "decreaseCF(address,uint256)", + "decreaseCF(address,uint96,uint256)", +]; + +// Permissions DeviationSentinel had directly on the comptroller in VIP-590 — this VIP revokes them +const SENTINEL_COMPTROLLER_PERMS_TO_REVOKE = [ + "setActionsPaused(address[],uint8[],bool)", + "_setActionsPaused(address[],uint8[],bool)", + "setCollateralFactor(uint96,address,uint256,uint256)", +]; + +forking(91721610, async () => { + let accessControlManager: Contract; + let deviationSentinel: Contract; + let proxyAdmin: Contract; + + // BSC mainnet ACM checks msg.sender (the host contract) against the stored contract address. + // We impersonate the host so isAllowedToCall returns the correct result. + let impersonatedComptroller: SignerWithAddress; + let impersonatedEBrake: SignerWithAddress; + + before(async () => { + accessControlManager = await ethers.getContractAt(ACCESS_CONTROL_MANAGER_ABI, ACM); + deviationSentinel = await ethers.getContractAt(DEVIATION_SENTINEL_ABI, DEVIATION_SENTINEL); + proxyAdmin = await ethers.getContractAt(PROXY_ADMIN_ABI, PROXY_ADMIN); + + impersonatedComptroller = await initMainnetUser(CORE_POOL_COMPTROLLER, ethers.utils.parseEther("1")); + impersonatedEBrake = await initMainnetUser(EBRAKE, ethers.utils.parseEther("1")); + }); + + describe("Pre-VIP behavior", () => { + it("DeviationSentinel proxy implementation should not yet be the new EBrake-integrated one", async () => { + expect(await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL)).to.not.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("EBrake should not yet have any permissions on the Core Pool Comptroller", async () => { + const acm = accessControlManager.connect(impersonatedComptroller); + for (const sig of EBRAKE_COMPTROLLER_PERMS) { + expect(await acm.isAllowedToCall(EBRAKE, sig)).to.equal(false, `unexpected permission: ${sig}`); + } + }); + + it("Guardian and governance timelocks should not yet have granular reset permissions on EBrake", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const account of [GUARDIAN, ...TIMELOCKS]) { + for (const sig of RESET_PERMS) { + expect(await acm.isAllowedToCall(account, sig)).to.equal( + false, + `unexpected permission: ${sig} for ${account}`, + ); + } + } + }); + + it("Guardian and governance timelocks should not yet have new EBrake function permissions", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + // setMarketBorrowCaps/setMarketSupplyCaps share names with comptroller functions that governance + // already has granted at the comptroller address — skip those here to avoid false failures. + const ebrakeUnique = GOVERNANCE_EBRAKE_PERMS.filter( + sig => sig !== "setMarketBorrowCaps(address[],uint256[])" && sig !== "setMarketSupplyCaps(address[],uint256[])", + ); + for (const account of [GUARDIAN, ...TIMELOCKS]) { + for (const sig of ebrakeUnique) { + expect(await acm.isAllowedToCall(account, sig)).to.equal( + false, + `unexpected permission: ${sig} for ${account}`, + ); + } + } + }); + + it("Multisig should not yet have EBrake action permissions", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const sig of GOVERNANCE_EBRAKE_PERMS) { + expect(await acm.isAllowedToCall(MULTISIG, sig)).to.equal(false, `unexpected permission: ${sig} for multisig`); + } + }); + + it("DeviationSentinel should not yet have any permissions on EBrake", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const sig of SENTINEL_EBRAKE_PERMS) { + expect(await acm.isAllowedToCall(DEVIATION_SENTINEL, sig)).to.equal(false, `unexpected permission: ${sig}`); + } + }); + + it("DeviationSentinel should still have direct comptroller permissions from VIP-590", async () => { + const acm = accessControlManager.connect(impersonatedComptroller); + for (const sig of SENTINEL_COMPTROLLER_PERMS_TO_REVOKE) { + expect(await acm.isAllowedToCall(DEVIATION_SENTINEL, sig)).to.equal(true, `expected permission: ${sig}`); + } + }); + }); + + testVip("VIP-661 [BNB Chain] Configure EBrake-integrated DeviationSentinel", await vip661(), { + callbackAfterExecution: async txResponse => { + // RoleGranted breakdown: + // - 8 EBrake on Core Pool Comptroller (6 original + setIsBorrowAllowed + setWhiteListFlashLoanAccount) + // - 12 granular reset functions (3 × 4 accounts: Guardian + 3 timelocks) + // - 3 DeviationSentinel on EBrake (pauseBorrow, pauseSupply, decreaseCF) + // - 48 governance EBrake action functions (12 functions × 4 accounts) + // - 12 EBrake action functions for Venus team multisig (emergency pausing, Phase 0) + // RoleRevoked: 3 (DeviationSentinel direct comptroller perms from VIP-590) + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["RoleGranted"], [83]); + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["RoleRevoked"], [3]); + }, + }); + + describe("Post-VIP behavior", () => { + it("DeviationSentinel proxy should point to the new EBrake-integrated implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL)).to.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("EBrake should have all required permissions on the Core Pool Comptroller", async () => { + const acm = accessControlManager.connect(impersonatedComptroller); + for (const sig of EBRAKE_COMPTROLLER_PERMS) { + expect(await acm.isAllowedToCall(EBRAKE, sig)).to.equal(true, `missing permission: ${sig}`); + } + }); + + it("Guardian and governance timelocks should have granular reset permissions on EBrake", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const account of [GUARDIAN, ...TIMELOCKS]) { + for (const sig of RESET_PERMS) { + expect(await acm.isAllowedToCall(account, sig)).to.equal(true, `missing permission: ${sig} for ${account}`); + } + } + }); + + it("Guardian and governance timelocks should have new EBrake function permissions", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const account of [GUARDIAN, ...TIMELOCKS]) { + for (const sig of GOVERNANCE_EBRAKE_PERMS) { + expect(await acm.isAllowedToCall(account, sig)).to.equal(true, `missing permission: ${sig} for ${account}`); + } + } + }); + + it("Multisig should have all EBrake action permissions for emergency pausing", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const sig of GOVERNANCE_EBRAKE_PERMS) { + expect(await acm.isAllowedToCall(MULTISIG, sig)).to.equal(true, `missing permission: ${sig} for multisig`); + } + }); + + it("DeviationSentinel should have pauseBorrow / pauseSupply / decreaseCF permissions on EBrake", async () => { + const acm = accessControlManager.connect(impersonatedEBrake); + for (const sig of SENTINEL_EBRAKE_PERMS) { + expect(await acm.isAllowedToCall(DEVIATION_SENTINEL, sig)).to.equal(true, `missing permission: ${sig}`); + } + }); + + it("DeviationSentinel should no longer have direct comptroller permissions (revoked)", async () => { + const acm = accessControlManager.connect(impersonatedComptroller); + for (const sig of SENTINEL_COMPTROLLER_PERMS_TO_REVOKE) { + expect(await acm.isAllowedToCall(DEVIATION_SENTINEL, sig)).to.equal(false, `unexpected permission: ${sig}`); + } + }); + + it("EBrake.COMPTROLLER should equal the Core Pool Comptroller", async () => { + const eBrake = await ethers.getContractAt(EBRAKE_ABI, EBRAKE); + expect(await eBrake.COMPTROLLER()).to.equal(CORE_POOL_COMPTROLLER); + }); + + it("EBrake.IS_ISOLATED_POOL should be false (Core Pool Diamond)", async () => { + const eBrake = await ethers.getContractAt(EBRAKE_ABI, EBRAKE); + expect(await eBrake.IS_ISOLATED_POOL()).to.equal(false); + }); + + it("DeviationSentinel.EBRAKE should equal the deployed EBrake address", async () => { + expect(await deviationSentinel.EBRAKE()).to.equal(EBRAKE); + }); + }); +}); diff --git a/simulations/vip-661/bsctestnet-addendum-2.ts b/simulations/vip-661/bsctestnet-addendum-2.ts new file mode 100644 index 000000000..9c0589895 --- /dev/null +++ b/simulations/vip-661/bsctestnet-addendum-2.ts @@ -0,0 +1,93 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents, setMaxStalePeriod } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { + CF, + COMPTROLLER, + EBRAKE, + LT, + VETH_CORE, + vip661TestnetAddendum2, +} from "../../vips/vip-661/bsctestnet-addendum-2"; +import EBRAKE_ABI from "./abi/EBrake.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; +import COMPTROLLER_ABI from "./abi/comptroller.json"; + +const Action = { + MINT: 0, +}; + +const ETH = "0x98f7A83361F7Ac8765CcEBAB1425da6b341958a7"; + +// Fork from block 100233050 — after VIP-661 Addendum 1 was executed on BSC Testnet and all +// guardian(keeper)/timelock permissions were established. A Tenderly web action subsequently re-triggered +// the DeviationSentinel, causing EBrake to zero vETH_Core's CF and pause MINT again. This +// simulation validates that addendum-2 (the three minimal recovery actions) fully restores +// the market from that second incident. +forking(100233050, async () => { + let comptroller: Contract; + let eBrake: Contract; + let resilientOracle: Contract; + let eth: Contract; + + before(async () => { + comptroller = await ethers.getContractAt(COMPTROLLER_ABI, COMPTROLLER); + eBrake = await ethers.getContractAt(EBRAKE_ABI, EBRAKE); + resilientOracle = await ethers.getContractAt( + RESILIENT_ORACLE_ABI, + NETWORK_ADDRESSES["bsctestnet"].RESILIENT_ORACLE, + ); + eth = await ethers.getContractAt(ERC20_ABI, ETH); + + await setMaxStalePeriod(resilientOracle, eth, 7 * 24 * 60 * 60); + }); + + describe("Pre-VIP behavior", () => { + it("vETH_Core should have collateral factor of 0 (tightened by EBrake)", async () => { + const market = await comptroller.markets(VETH_CORE); + expect(market.collateralFactorMantissa).to.equal(0); + }); + + it("vETH_Core mint should be paused (tightened by EBrake)", async () => { + const paused = await comptroller.actionPaused(VETH_CORE, Action.MINT); + expect(paused).to.equal(true); + }); + + it("EBrake should have non-zero snapshot for vETH_Core", async () => { + const snapshot = await eBrake.getMarketCFSnapshot(VETH_CORE, 0); + expect(snapshot.cf).to.equal(CF); + expect(snapshot.lt).to.equal(LT); + }); + }); + + testVip("VIP-661 Addendum 2: Minimal Recovery of vETH_Core", await vip661TestnetAddendum2(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [COMPTROLLER_ABI], ["ActionPausedMarket", "NewCollateralFactor"], [1, 1]); + await expectEvents(txResponse, [EBRAKE_ABI], ["MarketStateReset"], [1]); + }, + }); + + describe("Post-VIP behavior", () => { + it("vETH_Core should have restored collateral factor", async () => { + const market = await comptroller.markets(VETH_CORE); + expect(market.collateralFactorMantissa).to.equal(CF); + expect(market.liquidationThresholdMantissa).to.equal(LT); + }); + + it("vETH_Core mint should be unpaused", async () => { + const paused = await comptroller.actionPaused(VETH_CORE, Action.MINT); + expect(paused).to.equal(false); + }); + + it("EBrake snapshot for vETH_Core should be cleared", async () => { + const snapshot = await eBrake.getMarketCFSnapshot(VETH_CORE, 0); + expect(snapshot.cf).to.equal(0); + expect(snapshot.lt).to.equal(0); + }); + }); +}); diff --git a/simulations/vip-661/bsctestnet-addendum-3.ts b/simulations/vip-661/bsctestnet-addendum-3.ts new file mode 100644 index 000000000..e02198433 --- /dev/null +++ b/simulations/vip-661/bsctestnet-addendum-3.ts @@ -0,0 +1,219 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { + ACM, + DEVIATION_SENTINEL, + EBRAKE, + KEEPER_ADDRESS, + NEW_DEVIATION_SENTINEL_IMPL, + NEW_EBRAKE_IMPL, + PROXY_ADMIN, + vip661TestnetAddendum3, +} from "../../vips/vip-661/bsctestnet-addendum-3"; +import ACCESS_CONTROL_MANAGER_ABI from "./abi/AccessControlManager.json"; +import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; +import EBRAKE_ABI from "./abi/EBrake.json"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK } = NETWORK_ADDRESSES.bsctestnet; +const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; +// All accounts that had resetMarketState and will receive the new granular reset permissions +const RESET_ACCOUNTS = [...TIMELOCKS, KEEPER_ADDRESS]; + +// Granular snapshot-reset functions (replace resetMarketState) +const RESET_PERMS = ["resetCFSnapshot(address)", "resetBorrowCapSnapshot(address)", "resetSupplyCapSnapshot(address)"]; + +// All EBrake action functions governance/timelocks/keeper can call directly +const GOVERNANCE_EBRAKE_PERMS = [ + "pauseBorrow(address)", + "pauseSupply(address)", + "pauseRedeem(address)", + "pauseTransfer(address)", + "pauseFlashLoan()", + "pauseActions(address[],uint8[])", + "setMarketBorrowCaps(address[],uint256[])", + "setMarketSupplyCaps(address[],uint256[])", + "disablePoolBorrow(uint96,address)", + "revokeFlashLoanAccess(address)", + "decreaseCF(address,uint256)", + "decreaseCF(address,uint96,uint256)", +]; + +// New Comptroller permissions EBrake needs for the new surgical controls +const NEW_EBRAKE_COMPTROLLER_PERMS = [ + "setIsBorrowAllowed(uint96,address,bool)", + "setWhiteListFlashLoanAccount(address,bool)", +]; + +forking(100849419, async () => { + let accessControlManager: Contract; + let proxyAdmin: Contract; + let deviationSentinel: Contract; + + before(async () => { + accessControlManager = await ethers.getContractAt(ACCESS_CONTROL_MANAGER_ABI, ACM); + proxyAdmin = new ethers.Contract(PROXY_ADMIN, PROXY_ADMIN_ABI, ethers.provider); + deviationSentinel = await ethers.getContractAt(DEVIATION_SENTINEL_ABI, DEVIATION_SENTINEL); + }); + + describe("Pre-VIP behavior", () => { + it("EBrake proxy should not yet point to the audit-fixed implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(EBRAKE)).to.not.equal(NEW_EBRAKE_IMPL); + }); + + it("DeviationSentinel proxy should not yet point to the new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL)).to.not.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("DeviationSentinel should still have old setCFZero permission on EBrake", async () => { + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "setCFZero(address)")).to.equal(true); + }); + + it("DeviationSentinel should not yet have decreaseCF permission on EBrake", async () => { + expect( + await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "decreaseCF(address,uint256)"), + ).to.equal(false); + }); + + it("Timelocks and keeper should still have resetMarketState permission", async () => { + // Timelocks were granted at address(0) in bsctestnet.ts + for (const account of TIMELOCKS) { + expect( + await accessControlManager.hasPermission(account, ethers.constants.AddressZero, "resetMarketState(address)"), + ).to.equal(true, `expected resetMarketState for ${account}`); + } + // Keeper was granted at EBRAKE specifically in Addendum 1 + expect(await accessControlManager.hasPermission(KEEPER_ADDRESS, EBRAKE, "resetMarketState(address)")).to.equal( + true, + ); + }); + + it("Timelocks and keeper should not yet have granular reset permissions", async () => { + for (const account of RESET_ACCOUNTS) { + for (const sig of RESET_PERMS) { + expect(await accessControlManager.hasPermission(account, ethers.constants.AddressZero, sig)).to.equal( + false, + `unexpected permission: ${sig} for ${account}`, + ); + } + } + }); + + it("EBrake should not yet have new Comptroller permissions", async () => { + for (const sig of NEW_EBRAKE_COMPTROLLER_PERMS) { + expect(await accessControlManager.hasPermission(EBRAKE, ethers.constants.AddressZero, sig)).to.equal( + false, + `unexpected permission: ${sig}`, + ); + } + }); + + it("Timelocks and keeper should not yet have new EBrake-unique function permissions", async () => { + // setMarketBorrowCaps/setMarketSupplyCaps share names with comptroller functions that timelocks + // already have granted at address(0) from prior governance VIPs — skip those here. + const ebrakeUnique = GOVERNANCE_EBRAKE_PERMS.filter( + sig => sig !== "setMarketBorrowCaps(address[],uint256[])" && sig !== "setMarketSupplyCaps(address[],uint256[])", + ); + for (const account of RESET_ACCOUNTS) { + for (const sig of ebrakeUnique) { + expect(await accessControlManager.hasPermission(account, ethers.constants.AddressZero, sig)).to.equal( + false, + `unexpected permission: ${sig} for ${account}`, + ); + } + } + }); + }); + + testVip("VIP-661 Addendum 3: Apply Phase-0 Audit Fixes (EBrake) on BSC Testnet", await vip661TestnetAddendum3(), { + callbackAfterExecution: async txResponse => { + // PermissionRevoked breakdown: + // - 1 setCFZero from DeviationSentinel on EBrake + // - 3 resetMarketState from [3 timelocks] at address(0) (bsctestnet.ts grants) + // - 1 resetMarketState from NormalTimelock at EBRAKE (Addendum 1 grant) + // - 1 resetMarketState from Keeper at EBRAKE (Addendum 1 grant) + // PermissionGranted breakdown: + // - 1 decreaseCF(address,uint256) for DeviationSentinel on EBrake + // - 12 granular reset functions (3 × 4 accounts) + // - 2 new Comptroller permissions for EBrake (setIsBorrowAllowed, setWhiteListFlashLoanAccount) + // - 48 governance EBrake action functions (12 functions × 4 accounts) + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["PermissionGranted"], [63]); + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["PermissionRevoked"], [6]); + }, + }); + + describe("Post-VIP behavior", () => { + it("EBrake proxy should point to the audit-fixed implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(EBRAKE)).to.equal(NEW_EBRAKE_IMPL); + }); + + it("DeviationSentinel proxy should point to the new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL)).to.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("DeviationSentinel should no longer have setCFZero permission on EBrake", async () => { + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "setCFZero(address)")).to.equal( + false, + ); + }); + + it("DeviationSentinel should have decreaseCF permission on EBrake", async () => { + expect( + await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "decreaseCF(address,uint256)"), + ).to.equal(true); + }); + + it("Timelocks and keeper should no longer have resetMarketState permission", async () => { + for (const account of RESET_ACCOUNTS) { + expect( + await accessControlManager.hasPermission(account, ethers.constants.AddressZero, "resetMarketState(address)"), + ).to.equal(false, `unexpected resetMarketState for ${account}`); + } + }); + + it("Timelocks and keeper should have all three granular reset permissions", async () => { + for (const account of RESET_ACCOUNTS) { + for (const sig of RESET_PERMS) { + expect(await accessControlManager.hasPermission(account, ethers.constants.AddressZero, sig)).to.equal( + true, + `missing permission: ${sig} for ${account}`, + ); + } + } + }); + + it("EBrake should have new Comptroller permissions for surgical controls", async () => { + for (const sig of NEW_EBRAKE_COMPTROLLER_PERMS) { + expect(await accessControlManager.hasPermission(EBRAKE, ethers.constants.AddressZero, sig)).to.equal( + true, + `missing permission: ${sig}`, + ); + } + }); + + it("Timelocks and keeper should have all new EBrake function permissions", async () => { + for (const account of RESET_ACCOUNTS) { + for (const sig of GOVERNANCE_EBRAKE_PERMS) { + expect(await accessControlManager.hasPermission(account, ethers.constants.AddressZero, sig)).to.equal( + true, + `missing permission: ${sig} for ${account}`, + ); + } + } + }); + + it("DeviationSentinel.EBRAKE should still equal the deployed EBrake address", async () => { + expect(await deviationSentinel.EBRAKE()).to.equal(EBRAKE); + }); + + it("EBrake.IS_ISOLATED_POOL should be false (Core Pool Diamond)", async () => { + const eBrake = await ethers.getContractAt(EBRAKE_ABI, EBRAKE); + expect(await eBrake.IS_ISOLATED_POOL()).to.equal(false); + }); + }); +}); diff --git a/simulations/vip-661/bsctestnet-addendum.ts b/simulations/vip-661/bsctestnet-addendum.ts new file mode 100644 index 000000000..f1597bfc7 --- /dev/null +++ b/simulations/vip-661/bsctestnet-addendum.ts @@ -0,0 +1,166 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents, setMaxStalePeriod } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { + ACM, + CF, + COMPTROLLER, + EBRAKE, + KEEPER_ADDRESS, + LT, + VETH_CORE, + vip661TestnetAddendum, +} from "../../vips/vip-661/bsctestnet-addendum"; +import ACCESS_CONTROL_MANAGER_ABI from "./abi/AccessControlManager.json"; +import EBRAKE_ABI from "./abi/EBrake.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import RESILIENT_ORACLE_ABI from "./abi/ResilientOracle.json"; +import COMPTROLLER_ABI from "./abi/comptroller.json"; + +const Action = { + MINT: 0, +}; + +const ETH = "0x98f7A83361F7Ac8765CcEBAB1425da6b341958a7"; + +forking(100083240, async () => { + let comptroller: Contract; + let eBrake: Contract; + let accessControlManager: Contract; + let resilientOracle: Contract; + let eth: Contract; + + before(async () => { + comptroller = await ethers.getContractAt(COMPTROLLER_ABI, COMPTROLLER); + eBrake = await ethers.getContractAt(EBRAKE_ABI, EBRAKE); + accessControlManager = await ethers.getContractAt(ACCESS_CONTROL_MANAGER_ABI, ACM); + resilientOracle = await ethers.getContractAt( + RESILIENT_ORACLE_ABI, + NETWORK_ADDRESSES["bsctestnet"].RESILIENT_ORACLE, + ); + eth = await ethers.getContractAt(ERC20_ABI, ETH); + + await setMaxStalePeriod(resilientOracle, eth, 7 * 24 * 60 * 60); + }); + + describe("Pre-VIP behavior", () => { + it("vETH_Core should have collateral factor of 0", async () => { + const market = await comptroller.markets(VETH_CORE); + expect(market.collateralFactorMantissa).to.equal(0); + }); + + it("vETH_Core mint should be paused", async () => { + const paused = await comptroller.actionPaused(VETH_CORE, Action.MINT); + expect(paused).to.equal(true); + }); + + it("EBrake should have non-zero snapshot for vETH_Core", async () => { + const snapshot = await eBrake.getMarketCFSnapshot(VETH_CORE, 0); + expect(snapshot.cf).to.equal(CF); + expect(snapshot.lt).to.equal(LT); + }); + + it("Normal Timelock should not have resetMarketState permission on EBrake", async () => { + expect( + await accessControlManager.hasPermission( + NETWORK_ADDRESSES.bsctestnet.NORMAL_TIMELOCK, + EBRAKE, + "resetMarketState(address)", + ), + ).to.equal(false); + }); + + it("Keeper should not have _setActionsPaused permission on comptrollers", async () => { + expect( + await accessControlManager.hasPermission( + KEEPER_ADDRESS, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(false); + }); + + it("Keeper should not have setCollateralFactor permission on comptrollers", async () => { + expect( + await accessControlManager.hasPermission( + KEEPER_ADDRESS, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(false); + }); + + it("Keeper should not have resetMarketState permission on EBrake", async () => { + expect(await accessControlManager.hasPermission(KEEPER_ADDRESS, EBRAKE, "resetMarketState(address)")).to.equal( + false, + ); + }); + }); + + testVip("VIP-661 Addendum: Recover vETH_Core after EBrake Incident", await vip661TestnetAddendum(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [COMPTROLLER_ABI], ["ActionPausedMarket", "NewCollateralFactor"], [1, 1]); + await expectEvents(txResponse, [EBRAKE_ABI], ["MarketStateReset"], [1]); + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["PermissionGranted"], [4]); + }, + }); + + describe("Post-VIP behavior", () => { + it("vETH_Core should have restored collateral factor", async () => { + const market = await comptroller.markets(VETH_CORE); + expect(market.collateralFactorMantissa).to.equal(CF); + expect(market.liquidationThresholdMantissa).to.equal(LT); + }); + + it("vETH_Core mint should be unpaused", async () => { + const paused = await comptroller.actionPaused(VETH_CORE, Action.MINT); + expect(paused).to.equal(false); + }); + + it("EBrake snapshot for vETH_Core should be cleared", async () => { + const snapshot = await eBrake.getMarketCFSnapshot(VETH_CORE, 0); + expect(snapshot.cf).to.equal(0); + expect(snapshot.lt).to.equal(0); + }); + + it("Normal Timelock should have resetMarketState permission on EBrake", async () => { + expect( + await accessControlManager.hasPermission( + NETWORK_ADDRESSES.bsctestnet.NORMAL_TIMELOCK, + EBRAKE, + "resetMarketState(address)", + ), + ).to.equal(true); + }); + + it("Keeper should have _setActionsPaused permission on comptrollers", async () => { + expect( + await accessControlManager.hasPermission( + KEEPER_ADDRESS, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(true); + }); + + it("Keeper should have setCollateralFactor permission on comptrollers", async () => { + expect( + await accessControlManager.hasPermission( + KEEPER_ADDRESS, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(true); + }); + + it("Keeper should have resetMarketState permission on EBrake", async () => { + expect(await accessControlManager.hasPermission(KEEPER_ADDRESS, EBRAKE, "resetMarketState(address)")).to.equal( + true, + ); + }); + }); +}); diff --git a/simulations/vip-661/bsctestnet.ts b/simulations/vip-661/bsctestnet.ts new file mode 100644 index 000000000..3ee43a310 --- /dev/null +++ b/simulations/vip-661/bsctestnet.ts @@ -0,0 +1,267 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import { NETWORK_ADDRESSES } from "../../src/networkAddresses"; +import { + ACM, + DEVIATION_SENTINEL, + EBRAKE, + NEW_DEVIATION_SENTINEL_IMPL, + PROXY_ADMIN, + vip661Testnet, +} from "../../vips/vip-661/bsctestnet"; +import ACCESS_CONTROL_MANAGER_ABI from "./abi/AccessControlManager.json"; +import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK } = NETWORK_ADDRESSES.bsctestnet; + +forking(99316719, async () => { + let accessControlManager: Contract; + let proxyAdmin: Contract; + let deviationSentinel: Contract; + + before(async () => { + accessControlManager = await ethers.getContractAt(ACCESS_CONTROL_MANAGER_ABI, ACM); + proxyAdmin = new ethers.Contract(PROXY_ADMIN, PROXY_ADMIN_ABI, ethers.provider); + deviationSentinel = await ethers.getContractAt(DEVIATION_SENTINEL_ABI, DEVIATION_SENTINEL); + }); + + describe("Pre-VIP behavior", () => { + it("DeviationSentinel proxy should not point to new implementation", async () => { + const impl = await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL); + expect(impl).to.not.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("EBrake should not have comptroller permissions", async () => { + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setCollateralFactor(uint96,address,uint256,uint256)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setMarketBorrowCaps(address[],uint256[])", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setMarketSupplyCaps(address[],uint256[])", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setMarketBorrowCaps(address[],uint256[])", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setMarketSupplyCaps(address[],uint256[])", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission(EBRAKE, ethers.constants.AddressZero, "setFlashLoanPaused(bool)"), + ).to.equal(false); + }); + + it("Timelocks should not have resetMarketState permission", async () => { + for (const timelock of [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]) { + expect( + await accessControlManager.hasPermission(timelock, ethers.constants.AddressZero, "resetMarketState(address)"), + ).to.equal(false); + } + }); + + it("DeviationSentinel should not have permissions on EBrake", async () => { + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "pauseBorrow(address)")).to.equal( + false, + ); + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "pauseSupply(address)")).to.equal( + false, + ); + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "setCFZero(address)")).to.equal( + false, + ); + }); + + it("DeviationSentinel should have old direct comptroller permissions", async () => { + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setCollateralFactor(uint96,address,uint256,uint256)", + ), + ).to.equal(true); + }); + }); + + testVip("VIP-661 Configure EBrake-integrated DeviationSentinel", await vip661Testnet(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["PermissionGranted"], [14]); + await expectEvents(txResponse, [ACCESS_CONTROL_MANAGER_ABI], ["PermissionRevoked"], [4]); + }, + }); + + describe("Post-VIP behavior", () => { + it("DeviationSentinel proxy should point to new implementation", async () => { + const impl = await proxyAdmin.getProxyImplementation(DEVIATION_SENTINEL); + expect(impl).to.equal(NEW_DEVIATION_SENTINEL_IMPL); + }); + + it("DeviationSentinel should return correct EBrake address", async () => { + expect(await deviationSentinel.EBRAKE()).to.equal(EBRAKE); + }); + + it("EBrake should have comptroller permissions", async () => { + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setCollateralFactor(uint96,address,uint256,uint256)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setMarketBorrowCaps(address[],uint256[])", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "_setMarketSupplyCaps(address[],uint256[])", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setMarketBorrowCaps(address[],uint256[])", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission( + EBRAKE, + ethers.constants.AddressZero, + "setMarketSupplyCaps(address[],uint256[])", + ), + ).to.equal(true); + expect( + await accessControlManager.hasPermission(EBRAKE, ethers.constants.AddressZero, "setFlashLoanPaused(bool)"), + ).to.equal(true); + }); + + it("Timelocks should have resetMarketState permission", async () => { + for (const timelock of [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]) { + expect( + await accessControlManager.hasPermission(timelock, ethers.constants.AddressZero, "resetMarketState(address)"), + ).to.equal(true); + } + }); + + it("DeviationSentinel should have permissions on EBrake", async () => { + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "pauseBorrow(address)")).to.equal( + true, + ); + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "pauseSupply(address)")).to.equal( + true, + ); + expect(await accessControlManager.hasPermission(DEVIATION_SENTINEL, EBRAKE, "setCFZero(address)")).to.equal(true); + }); + + it("DeviationSentinel should no longer have direct comptroller permissions", async () => { + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "_setActionsPaused(address[],uint8[],bool)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setCollateralFactor(address,uint256,uint256)", + ), + ).to.equal(false); + expect( + await accessControlManager.hasPermission( + DEVIATION_SENTINEL, + ethers.constants.AddressZero, + "setCollateralFactor(uint96,address,uint256,uint256)", + ), + ).to.equal(false); + }); + }); +}); diff --git a/vips/vip-661/bscmainnet.ts b/vips/vip-661/bscmainnet.ts new file mode 100644 index 000000000..51835795a --- /dev/null +++ b/vips/vip-661/bscmainnet.ts @@ -0,0 +1,171 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, GUARDIAN } = NETWORK_ADDRESSES.bscmainnet; + +export const EBRAKE = "0x35eBaBB99c7Fb7ba0C90bCc26e5d55Cdf89C23Ec"; +export const NEW_DEVIATION_SENTINEL_IMPL = "0xc86153Ae39fc9B60Ff59E99cA75aAD5Ab9d28a87"; + +// DeviationSentinel proxy (deployed in VIP-590) +export const DEVIATION_SENTINEL = "0x6599C15cc8407046CD91E5c0F8B7f765fF914870"; +// Default Proxy Admin that owns the DeviationSentinel proxy (admin slot read on-chain; +// owner is Normal Timelock 0x939bD8d64c0A9583A7Dcea9933f7b21697ab6396) +export const PROXY_ADMIN = "0x6beb6d2695b67feb73ad4f172e8e2975497187e4"; +// Venus Core Pool Comptroller (Diamond proxy) +export const CORE_POOL_COMPTROLLER = NETWORK_ADDRESSES.bscmainnet.UNITROLLER; +// Access Control Manager +export const ACM = NETWORK_ADDRESSES.bscmainnet.ACCESS_CONTROL_MANAGER; +// Venus team multisig — can call EBrake action functions directly for emergency pausing (Phase 0) +export const MULTISIG = "0xCCa5a587eBDBe80f23c8610F2e53B03158e62948"; + +const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; + +// Comptroller functions EBrake is allowed to call +const EBRAKE_COMPTROLLER_PERMS = [ + "_setActionsPaused(address[],uint8[],bool)", + "setCollateralFactor(uint96,address,uint256,uint256)", + "setCollateralFactor(address,uint256,uint256)", + "_setMarketBorrowCaps(address[],uint256[])", + "_setMarketSupplyCaps(address[],uint256[])", + "setFlashLoanPaused(bool)", + "setIsBorrowAllowed(uint96,address,bool)", // disablePoolBorrow + "setWhiteListFlashLoanAccount(address,bool)", // revokeFlashLoanAccess +]; + +// Granular snapshot-reset functions governance timelocks and Guardian can call on EBrake +const RESET_PERMS = ["resetCFSnapshot(address)", "resetBorrowCapSnapshot(address)", "resetSupplyCapSnapshot(address)"]; + +// EBrake functions DeviationSentinel calls via handleDeviation +const SENTINEL_EBRAKE_PERMS = ["pauseBorrow(address)", "pauseSupply(address)", "decreaseCF(address,uint256)"]; + +// All EBrake action functions governance timelocks and Guardian can call directly. +// Lets a Critical VIP (~1h delay) route through EBrake and get snapshot coverage, +// making recovery via resetXxxSnapshot trivial. Without this, governance would call +// the comptroller directly (no snapshot stored). +const GOVERNANCE_EBRAKE_PERMS = [ + "pauseBorrow(address)", + "pauseSupply(address)", + "pauseRedeem(address)", + "pauseTransfer(address)", + "pauseFlashLoan()", + "pauseActions(address[],uint8[])", + "setMarketBorrowCaps(address[],uint256[])", + "setMarketSupplyCaps(address[],uint256[])", + "disablePoolBorrow(uint96,address)", + "revokeFlashLoanAccess(address)", + "decreaseCF(address,uint256)", + "decreaseCF(address,uint96,uint256)", +]; + +// DeviationSentinel direct comptroller permissions granted in VIP-590 — revoked here +// since the sentinel now routes all emergency actions through EBrake +const SENTINEL_COMPTROLLER_PERMS_TO_REVOKE = [ + "setActionsPaused(address[],uint8[],bool)", + "_setActionsPaused(address[],uint8[],bool)", + "setCollateralFactor(uint96,address,uint256,uint256)", +]; + +const giveCallPermission = (contract: string, sig: string, account: string) => ({ + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [contract, sig, account], +}); + +const revokeCallPermission = (contract: string, sig: string, account: string) => ({ + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [contract, sig, account], +}); + +export const vip661 = () => { + const meta = { + version: "v2", + title: "VIP-661 [BNB Chain] Configure EBrake-integrated DeviationSentinel", + description: `#### Summary + +This VIP wires up the **EBrake** contract on BNB Chain Mainnet and migrates **DeviationSentinel** to route all +emergency actions through it. EBrake is a thin emergency-action router that exposes Comptroller pause / +collateral-factor / cap functions behind ACM permissions, snapshots pre-incident state for safe recovery, and is +called by DeviationSentinel when a price deviation is detected. + +This VIP incorporates Phase-0 Hashdit audit fixes (venus-periphery#62): \`setCFZero\` replaced by +\`decreaseCF(address,uint256)\`, \`resetMarketState\` split into three granular snapshot-reset functions, and two +new surgical controls (\`disablePoolBorrow\`, \`revokeFlashLoanAccess\`) added to EBrake. + +If approved, this VIP will: + +1. Upgrade the DeviationSentinel proxy to the new implementation that routes actions through EBrake +2. Grant EBrake permissions on the Core Pool Comptroller (so EBrake can pause actions, decrease collateral + factors, decrease borrow/supply caps, pause flash loans, disable per-pool borrows, and revoke flash loan access) +3. Grant the Normal, FastTrack and Critical Timelocks (and Guardian) permission to call the three granular + snapshot-reset functions on EBrake (\`resetCFSnapshot\`, \`resetBorrowCapSnapshot\`, \`resetSupplyCapSnapshot\`) +4. Grant DeviationSentinel permission to call \`pauseBorrow\`, \`pauseSupply\` and \`decreaseCF\` on EBrake (the + three functions \`handleDeviation\` invokes) +5. Grant the Normal, FastTrack and Critical Timelocks (and Guardian) permission to call all EBrake action + functions directly, so a Critical VIP can route through EBrake and benefit from its snapshot mechanism +6. Revoke DeviationSentinel's existing direct comptroller permissions (granted in VIP-590), since the sentinel + now goes through EBrake +7. Grant the Venus team multisig (\`${MULTISIG}\`) permission to call all EBrake action functions directly, + enabling the team to pause the protocol in emergency conditions (Phase 0) + +#### Description + +**EBrake** (\`EmergencyBrake/EBrake.sol\`) is the new emergency action router. It holds no detection logic — it +only exposes Comptroller emergency functions behind ACM checks and snapshots the pre-incident state of every +market it touches (collateral factors per pool, borrow/supply caps) so a recovery VIP can restore exact prior +values. Snapshots are first-write-wins and cleared via the three granular reset functions. + +**DeviationSentinel** has been refactored so that \`handleDeviation\` calls EBrake (\`pauseBorrow\`, +\`pauseSupply\`, \`decreaseCF\`) instead of the comptroller directly. This adds an additional safety layer +(snapshot + idempotency live in EBrake) and standardizes emergency action routing across the protocol. + +#### References + +- [VIP Pull Request](https://github.com/VenusProtocol/vips/pull/694) +- [DeviationSentinel Proxy](https://bscscan.com/address/${DEVIATION_SENTINEL}) +- [New DeviationSentinel Implementation](https://bscscan.com/address/${NEW_DEVIATION_SENTINEL_IMPL}) +- [EBrake Contract](https://bscscan.com/address/${EBRAKE}) +- [Venus Team Multisig](https://bscscan.com/address/${MULTISIG})`, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // 1. Upgrade DeviationSentinel proxy to new (EBrake-integrated) implementation + { + target: PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [DEVIATION_SENTINEL, NEW_DEVIATION_SENTINEL_IMPL], + }, + + // 2. Grant EBrake permissions on the Core Pool Comptroller + ...EBRAKE_COMPTROLLER_PERMS.map(sig => giveCallPermission(CORE_POOL_COMPTROLLER, sig, EBRAKE)), + + // 3. Grant granular snapshot-reset permissions to governance timelocks and Guardian + ...[GUARDIAN, ...TIMELOCKS].flatMap(account => RESET_PERMS.map(sig => giveCallPermission(EBRAKE, sig, account))), + + // 4. Grant DeviationSentinel permissions on EBrake (the three functions handleDeviation invokes) + ...SENTINEL_EBRAKE_PERMS.map(sig => giveCallPermission(EBRAKE, sig, DEVIATION_SENTINEL)), + + // 5. Grant governance timelocks and Guardian permissions on all EBrake action functions + ...[GUARDIAN, ...TIMELOCKS].flatMap(account => + GOVERNANCE_EBRAKE_PERMS.map(sig => giveCallPermission(EBRAKE, sig, account)), + ), + + // 6. Revoke DeviationSentinel's old direct comptroller permissions (granted in VIP-590) + ...SENTINEL_COMPTROLLER_PERMS_TO_REVOKE.map(sig => + revokeCallPermission(CORE_POOL_COMPTROLLER, sig, DEVIATION_SENTINEL), + ), + + // 7. Grant Venus team multisig permission on all EBrake action functions (emergency pausing, Phase 0) + ...GOVERNANCE_EBRAKE_PERMS.map(sig => giveCallPermission(EBRAKE, sig, MULTISIG)), + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip661; diff --git a/vips/vip-661/bsctestnet-addendum-2.ts b/vips/vip-661/bsctestnet-addendum-2.ts new file mode 100644 index 000000000..62fac7bf8 --- /dev/null +++ b/vips/vip-661/bsctestnet-addendum-2.ts @@ -0,0 +1,64 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const EBRAKE = "0x957c09e3Ac3d9e689244DC74307c94111FBa8B42"; +export const COMPTROLLER = "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D"; +export const VETH_CORE = "0x162D005F0Fff510E54958Cfc5CF32A3180A84aab"; + +export const CF = "800000000000000000"; +export const LT = "800000000000000000"; + +const Action = { + MINT: 0, +}; + +export const vip661TestnetAddendum2 = () => { + const meta = { + version: "v2", + title: "VIP-661 Addendum 2: Minimal Recovery of vETH_Core after EBrake Incident on BSC Testnet", + description: `#### Summary + +Recover the vETH_Core market on BSC Testnet after EBrake tightened it a second time during DeviationSentinel testing. +VIP-661 Addendum 1 already established all required permissions (Normal Timelock → \`resetMarketState\`, Guardian +convenience grants), so this VIP contains only the three actions that are strictly necessary to restore the market. +This serves as a reference for the minimal governance footprint needed to recover from any future EBrake incident. + +#### Actions + +1. Restore vETH_Core collateral factor to 0.8e18 / 0.8e18 (values stored in EBrake snapshot) +2. Unpause MINT (supply) on vETH_Core +3. Clear EBrake's stored snapshot for vETH_Core via \`resetMarketState\``, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // 1. Restore vETH_Core collateral factor on the comptroller + { + target: COMPTROLLER, + signature: "setCollateralFactor(address,uint256,uint256)", + params: [VETH_CORE, CF, LT], + }, + + // 2. Unpause MINT (supply) on vETH_Core + { + target: COMPTROLLER, + signature: "_setActionsPaused(address[],uint8[],bool)", + params: [[VETH_CORE], [Action.MINT], false], + }, + + // 3. Clear EBrake's stored snapshot for vETH_Core + { + target: EBRAKE, + signature: "resetMarketState(address)", + params: [VETH_CORE], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip661TestnetAddendum2; diff --git a/vips/vip-661/bsctestnet-addendum-3.ts b/vips/vip-661/bsctestnet-addendum-3.ts new file mode 100644 index 000000000..3ed220da1 --- /dev/null +++ b/vips/vip-661/bsctestnet-addendum-3.ts @@ -0,0 +1,134 @@ +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK } = NETWORK_ADDRESSES.bsctestnet; + +export const NEW_EBRAKE_IMPL = "0x9cA0f0C412d2E8a2c4323c04214D811375c17B24"; +export const NEW_DEVIATION_SENTINEL_IMPL = "0x455C09D6BA46e7C9f80f29506DcC8E5F8378832a"; + +export const EBRAKE = "0x957c09e3Ac3d9e689244DC74307c94111FBa8B42"; +export const DEVIATION_SENTINEL = "0x9245d72712548707809D66848e63B8E2B169F3c1"; +export const PROXY_ADMIN = "0x7877ffd62649b6a1557b55d4c20fcbab17344c91"; +export const ACM = "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA"; +// Keeper/Guardian address granted extra testnet convenience permissions in Addendum 1 +export const KEEPER_ADDRESS = "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706"; + +const TIMELOCKS = [NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK]; +// All accounts that received resetMarketState permission (bsctestnet.ts + Addendum 1) +const RESET_ACCOUNTS = [...TIMELOCKS, KEEPER_ADDRESS]; + +// Testnet uses address(0) so grants apply across all comptrollers +const ADDR_ZERO = ethers.constants.AddressZero; + +// Granular snapshot-reset functions (replace resetMarketState) +const RESET_PERMS = ["resetCFSnapshot(address)", "resetBorrowCapSnapshot(address)", "resetSupplyCapSnapshot(address)"]; + +// New Comptroller permissions EBrake needs for the new surgical controls +const NEW_EBRAKE_COMPTROLLER_PERMS = [ + "setIsBorrowAllowed(uint96,address,bool)", + "setWhiteListFlashLoanAccount(address,bool)", +]; + +// All EBrake action functions timelocks and keeper can call directly. +// Lets a Critical VIP (~1h delay) route through EBrake and get snapshot coverage, +// making recovery via resetXxxSnapshot trivial. Without this, governance would call +// the comptroller directly (no snapshot stored). +const GOVERNANCE_EBRAKE_PERMS = [ + "pauseBorrow(address)", + "pauseSupply(address)", + "pauseRedeem(address)", + "pauseTransfer(address)", + "pauseFlashLoan()", + "pauseActions(address[],uint8[])", + "setMarketBorrowCaps(address[],uint256[])", + "setMarketSupplyCaps(address[],uint256[])", + "disablePoolBorrow(uint96,address)", + "revokeFlashLoanAccess(address)", + "decreaseCF(address,uint256)", + "decreaseCF(address,uint96,uint256)", +]; + +const giveCallPermission = (contract: string, sig: string, account: string) => ({ + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [contract, sig, account], +}); + +const revokeCallPermission = (contract: string, sig: string, account: string) => ({ + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [contract, sig, account], +}); + +export const vip661TestnetAddendum3 = () => { + const meta = { + version: "v2", + title: "VIP-661 Addendum 3: Update EBrake permissions on BSC Testnet", + description: `#### Summary + +This VIP updates the EBrake system on BSC Testnet with changes from +[venus-periphery#62](https://github.com/VenusProtocol/venus-periphery/pull/62). + +If approved, this VIP will: + +1. Upgrade EBrake proxy to the new implementation +2. Upgrade DeviationSentinel proxy to the new implementation (calls \`decreaseCF\` instead of \`setCFZero\`) +3. Revoke the old \`setCFZero(address)\` grant from DeviationSentinel on EBrake; grant \`decreaseCF(address,uint256)\` instead +4. Revoke the old \`resetMarketState(address)\` grants from all accounts (timelocks + keeper); replace with three + granular snapshot-reset functions: \`resetCFSnapshot\`, \`resetBorrowCapSnapshot\`, \`resetSupplyCapSnapshot\` +5. Grant EBrake two new Comptroller permissions needed by the new surgical controls: + \`setIsBorrowAllowed(uint96,address,bool)\` and \`setWhiteListFlashLoanAccount(address,bool)\` +6. Grant timelocks and keeper permission to call all EBrake action functions directly, so a Critical VIP + can route through EBrake and benefit from its snapshot mechanism + +#### References + +- [EBrake Contract](https://testnet.bscscan.com/address/${EBRAKE}) +- [DeviationSentinel Proxy](https://testnet.bscscan.com/address/${DEVIATION_SENTINEL}) +- [New EBrake Implementation](https://testnet.bscscan.com/address/${NEW_EBRAKE_IMPL}) +- [New DeviationSentinel Implementation](https://testnet.bscscan.com/address/${NEW_DEVIATION_SENTINEL_IMPL})`, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // 1. Upgrade EBrake proxy to new implementation + { target: PROXY_ADMIN, signature: "upgrade(address,address)", params: [EBRAKE, NEW_EBRAKE_IMPL] }, + + // 2. Upgrade DeviationSentinel proxy to new implementation + { + target: PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [DEVIATION_SENTINEL, NEW_DEVIATION_SENTINEL_IMPL], + }, + + // 3. Swap setCFZero → decreaseCF for DeviationSentinel on EBrake + revokeCallPermission(EBRAKE, "setCFZero(address)", DEVIATION_SENTINEL), + giveCallPermission(EBRAKE, "decreaseCF(address,uint256)", DEVIATION_SENTINEL), + + // 4. Revoke resetMarketState; grant three granular reset functions in its place + // Timelocks were granted at address(0) in bsctestnet.ts. + // NormalTimelock + Keeper were additionally granted at EBRAKE specifically in Addendum 1. + ...TIMELOCKS.map(account => revokeCallPermission(ADDR_ZERO, "resetMarketState(address)", account)), + revokeCallPermission(EBRAKE, "resetMarketState(address)", NORMAL_TIMELOCK), + revokeCallPermission(EBRAKE, "resetMarketState(address)", KEEPER_ADDRESS), + ...RESET_ACCOUNTS.flatMap(account => RESET_PERMS.map(sig => giveCallPermission(ADDR_ZERO, sig, account))), + + // 5. Grant EBrake new Comptroller permissions for the new surgical controls + ...NEW_EBRAKE_COMPTROLLER_PERMS.map(sig => giveCallPermission(ADDR_ZERO, sig, EBRAKE)), + + // 6. Grant timelocks and keeper permission on all EBrake action functions + ...RESET_ACCOUNTS.flatMap(account => + GOVERNANCE_EBRAKE_PERMS.map(sig => giveCallPermission(ADDR_ZERO, sig, account)), + ), + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip661TestnetAddendum3; diff --git a/vips/vip-661/bsctestnet-addendum.ts b/vips/vip-661/bsctestnet-addendum.ts new file mode 100644 index 000000000..c074385ee --- /dev/null +++ b/vips/vip-661/bsctestnet-addendum.ts @@ -0,0 +1,98 @@ +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const EBRAKE = "0x957c09e3Ac3d9e689244DC74307c94111FBa8B42"; +export const COMPTROLLER = "0x94d1820b2D1c7c7452A163983Dc888CEC546b77D"; +export const VETH_CORE = "0x162D005F0Fff510E54958Cfc5CF32A3180A84aab"; +export const KEEPER_ADDRESS = "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706"; // bsctestnet Guardian address +export const ACM = "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA"; + +export const CF = "800000000000000000"; +export const LT = "800000000000000000"; + +const Action = { + MINT: 0, +}; + +export const vip661TestnetAddendum = () => { + const meta = { + version: "v2", + title: "VIP-661 Addendum: Recover vETH_Core after EBrake Incident on BSC Testnet", + description: `#### Summary + +Recover the vETH_Core market on BSC Testnet after EBrake tightened it during DeviationSentinel testing. The price deviation has resolved (5% < 10% threshold), so this VIP restores the market to normal operating state and clears EBrake's stored snapshot. + +This VIP also grants the keeper address permissions on the comptroller for direct pause/CF management on testnet, so future testing iterations don't require a governance VIP. + +#### Actions + +1. Grant Normal Timelock permission to call \`resetMarketState\` on EBrake (required for step 4) +2. Restore vETH_Core collateral factor to 0.8e18 / 0.8e18 (snapshot values from EBrake) +3. Unpause MINT (supply) on vETH_Core +4. Clear EBrake's stored snapshot for vETH_Core via \`resetMarketState\` +5. Grant keeper address permission to call \`_setActionsPaused\` on comptrollers (testnet convenience) +6. Grant keeper address permission to call \`setCollateralFactor\` on comptrollers (testnet convenience)`, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // 1. Grant Normal Timelock permission to call resetMarketState on EBrake + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [EBRAKE, "resetMarketState(address)", NETWORK_ADDRESSES.bsctestnet.NORMAL_TIMELOCK], + }, + + // 2. Restore vETH_Core collateral factor on the comptroller + { + target: COMPTROLLER, + signature: "setCollateralFactor(address,uint256,uint256)", + params: [VETH_CORE, CF, LT], + }, + + // 3. Unpause MINT (supply) on vETH_Core + { + target: COMPTROLLER, + signature: "_setActionsPaused(address[],uint8[],bool)", + params: [[VETH_CORE], [Action.MINT], false], + }, + + // 4. Clear EBrake's stored snapshot for vETH_Core + { + target: EBRAKE, + signature: "resetMarketState(address)", + params: [VETH_CORE], + }, + + // 5. Grant keeper permission to pause/unpause actions on comptrollers (testnet only) + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "_setActionsPaused(address[],uint8[],bool)", KEEPER_ADDRESS], + }, + + // 6. Grant keeper permission to set collateral factor on comptrollers (testnet only) + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setCollateralFactor(address,uint256,uint256)", KEEPER_ADDRESS], + }, + + // 7. Grant keeper permission to reset EBrake market state (testnet convenience — enables repeatable E2E testing) + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [EBRAKE, "resetMarketState(address)", KEEPER_ADDRESS], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip661TestnetAddendum; diff --git a/vips/vip-661/bsctestnet.ts b/vips/vip-661/bsctestnet.ts new file mode 100644 index 000000000..67f9a7808 --- /dev/null +++ b/vips/vip-661/bsctestnet.ts @@ -0,0 +1,172 @@ +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK } = NETWORK_ADDRESSES.bsctestnet; + +// New deployments +export const EBRAKE = "0x957c09e3Ac3d9e689244DC74307c94111FBa8B42"; +export const NEW_DEVIATION_SENTINEL_IMPL = "0xBC7249c0ABb89a374CD2AA2bEEd0820E2E189e03"; + +// Existing testnet addresses +export const DEVIATION_SENTINEL = "0x9245d72712548707809D66848e63B8E2B169F3c1"; +export const PROXY_ADMIN = "0x7877ffd62649b6a1557b55d4c20fcbab17344c91"; +export const ACM = "0x45f8a08F534f34A97187626E05d4b6648Eeaa9AA"; + +export const vip661Testnet = () => { + const meta = { + version: "v2", + title: "VIP-661 Configure EBrake-integrated DeviationSentinel", + description: `#### Summary + +This VIP configures the EBrake-integrated DeviationSentinel system on BSC Testnet by: + +1. Upgrading the DeviationSentinel proxy to the new implementation that routes actions through EBrake +2. Granting EBrake permissions on comptrollers (so EBrake can pause actions and set collateral factors) +3. Granting DeviationSentinel permissions on EBrake (so sentinel can trigger emergency actions via EBrake) +4. Revoking old direct comptroller permissions from DeviationSentinel (sentinel now goes through EBrake) + +#### Description + +**DeviationSentinel** has been refactored to route all emergency actions through the **EBrake** contract instead of calling comptrollers directly. When a price deviation is detected, DeviationSentinel calls EBrake functions (pauseBorrow, pauseSupply, setCFZero), and EBrake in turn calls the appropriate comptroller functions. + +This architecture change adds an additional safety layer and standardizes emergency action routing. + +#### References + +- [DeviationSentinel Proxy](https://testnet.bscscan.com/address/${DEVIATION_SENTINEL}) +- [New Implementation](https://testnet.bscscan.com/address/${NEW_DEVIATION_SENTINEL_IMPL}) +- [EBrake Contract](https://testnet.bscscan.com/address/${EBRAKE})`, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + // ======================================== + // 1. Upgrade DeviationSentinel proxy to new implementation + // ======================================== + { + target: PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [DEVIATION_SENTINEL, NEW_DEVIATION_SENTINEL_IMPL], + }, + + // ======================================== + // 2. Grant EBrake permissions on comptrollers + // ======================================== + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "_setActionsPaused(address[],uint8[],bool)", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setCollateralFactor(uint96,address,uint256,uint256)", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setCollateralFactor(address,uint256,uint256)", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "_setMarketBorrowCaps(address[],uint256[])", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "_setMarketSupplyCaps(address[],uint256[])", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setMarketBorrowCaps(address[],uint256[])", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setMarketSupplyCaps(address[],uint256[])", EBRAKE], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setFlashLoanPaused(bool)", EBRAKE], + }, + + // ======================================== + // 2b. Grant resetMarketState permission to timelocks + // ======================================== + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "resetMarketState(address)", NORMAL_TIMELOCK], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "resetMarketState(address)", FAST_TRACK_TIMELOCK], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "resetMarketState(address)", CRITICAL_TIMELOCK], + }, + + // ======================================== + // 3. Grant DeviationSentinel permissions on EBrake + // ======================================== + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [EBRAKE, "pauseBorrow(address)", DEVIATION_SENTINEL], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [EBRAKE, "pauseSupply(address)", DEVIATION_SENTINEL], + }, + { + target: ACM, + signature: "giveCallPermission(address,string,address)", + params: [EBRAKE, "setCFZero(address)", DEVIATION_SENTINEL], + }, + + // ======================================== + // 4. Revoke old direct comptroller permissions from DeviationSentinel + // ======================================== + { + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setActionsPaused(address[],uint8[],bool)", DEVIATION_SENTINEL], + }, + { + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "_setActionsPaused(address[],uint8[],bool)", DEVIATION_SENTINEL], + }, + { + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [ethers.constants.AddressZero, "setCollateralFactor(address,uint256,uint256)", DEVIATION_SENTINEL], + }, + { + target: ACM, + signature: "revokeCallPermission(address,string,address)", + params: [ + ethers.constants.AddressZero, + "setCollateralFactor(uint96,address,uint256,uint256)", + DEVIATION_SENTINEL, + ], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip661Testnet;