From a78b5e74c14f64e0500ef8599c70f929706782b9 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Fri, 10 Jul 2026 14:53:06 +0530 Subject: [PATCH 1/9] feat: add testnet VIP upgrading FRV vault to consent impl --- simulations/vip-999/abi/ERC20.json | 231 ++ simulations/vip-999/abi/FaucetToken.json | 289 +++ .../vip-999/abi/InstitutionalLoanVault.json | 2150 +++++++++++++++++ .../abi/InstitutionalVaultController.json | 1220 ++++++++++ simulations/vip-999/bsctestnet.ts | 241 ++ vips/vip-999/bsctestnet.ts | 54 + 6 files changed, 4185 insertions(+) create mode 100644 simulations/vip-999/abi/ERC20.json create mode 100644 simulations/vip-999/abi/FaucetToken.json create mode 100644 simulations/vip-999/abi/InstitutionalLoanVault.json create mode 100644 simulations/vip-999/abi/InstitutionalVaultController.json create mode 100644 simulations/vip-999/bsctestnet.ts create mode 100644 vips/vip-999/bsctestnet.ts diff --git a/simulations/vip-999/abi/ERC20.json b/simulations/vip-999/abi/ERC20.json new file mode 100644 index 000000000..02d30dd88 --- /dev/null +++ b/simulations/vip-999/abi/ERC20.json @@ -0,0 +1,231 @@ +[ + { "inputs": [], "payable": false, "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": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "value", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "_decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "_symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }], + "name": "burn", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "subtractedValue", "type": "uint256" } + ], + "name": "decreaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "getOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "addedValue", "type": "uint256" } + ], + "name": "increaseAllowance", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }], + "name": "mint", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "recipient", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-999/abi/FaucetToken.json b/simulations/vip-999/abi/FaucetToken.json new file mode 100644 index 000000000..28715d783 --- /dev/null +++ b/simulations/vip-999/abi/FaucetToken.json @@ -0,0 +1,289 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_initialAmount", + "type": "uint256" + }, + { + "internalType": "string", + "name": "_tokenName", + "type": "string" + }, + { + "internalType": "uint8", + "name": "_decimalUnits", + "type": "uint8" + }, + { + "internalType": "string", + "name": "_tokenSymbol", + "type": "string" + } + ], + "payable": false, + "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" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "allocateTo", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "_spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-999/abi/InstitutionalLoanVault.json b/simulations/vip-999/abi/InstitutionalLoanVault.json new file mode 100644 index 000000000..6c611b288 --- /dev/null +++ b/simulations/vip-999/abi/InstitutionalLoanVault.json @@ -0,0 +1,2150 @@ +[ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "BPS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANTISSA_ONE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "YEAR", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allowance", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + }, + { + "name": "spender", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approve", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "asset", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "account", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "calculateSeizeAmount", + "inputs": [ + { + "name": "repayAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "liquidationType", + "type": "uint8", + "internalType": "enum LiquidationType" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "cancelVault", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "claimRaisedFunds", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "closeVault", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "completePause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "config", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct VaultConfig", + "components": [ + { + "name": "supplyAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "fixedAPY", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "reserveFactor", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minSupplierDeposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "openDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "lockDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "settlementWindow", + "type": "uint40", + "internalType": "uint40" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToAssets", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "convertToShares", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decimals", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "uint8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "decreaseAllowance", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "subtractedValue", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "deposit", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositCollateral", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "depositWithConsent", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + }, + { + "name": "consentHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getCollateralValueUSD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getDebtValueUSD", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getHypotheticalVaultLiquidity", + "inputs": [ + { + "name": "withdrawAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "additionalDebt", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "liquidity", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "shortfall", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "getVaultLiquidity", + "inputs": [], + "outputs": [ + { + "name": "liquidity", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "shortfall", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "increaseAllowance", + "inputs": [ + { + "name": "spender", + "type": "address", + "internalType": "address" + }, + { + "name": "addedValue", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "config_", + "type": "tuple", + "internalType": "struct VaultConfig", + "components": [ + { + "name": "supplyAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "fixedAPY", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "reserveFactor", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minSupplierDeposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "openDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "lockDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "settlementWindow", + "type": "uint40", + "internalType": "uint40" + } + ] + }, + { + "name": "instConfig_", + "type": "tuple", + "internalType": "struct InstitutionalConfig", + "components": [ + { + "name": "collateralAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "idealCollateralAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "marginRate", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "institutionOperator", + "type": "address", + "internalType": "address" + }, + { + "name": "positionTokenId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "riskConfig_", + "type": "tuple", + "internalType": "struct RiskConfig", + "components": [ + { + "name": "liquidationThreshold", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "liquidationIncentive", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "latePenaltyRate", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "positionToken_", + "type": "address", + "internalType": "contract IInstitutionPositionToken" + }, + { + "name": "name_", + "type": "string", + "internalType": "string" + }, + { + "name": "symbol_", + "type": "string", + "internalType": "string" + }, + { + "name": "institutionName_", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "institutionName", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "institutionalConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct InstitutionalConfig", + "components": [ + { + "name": "collateralAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "idealCollateralAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "marginRate", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "institutionOperator", + "type": "address", + "internalType": "address" + }, + { + "name": "positionTokenId", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "institutionalRuntime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct InstitutionalRuntime", + "components": [ + { + "name": "totalCollateralDeposited", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minimumCollateralRequired", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "confiscatedMarginRemaining", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "institutionDefaulted", + "type": "bool", + "internalType": "bool" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "liquidate", + "inputs": [ + { + "name": "repayAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "actualRepay", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "liquidateOverdueVault", + "inputs": [ + { + "name": "repayAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "actualRepay", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "maxDeposit", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxMint", + "inputs": [ + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxRedeem", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "maxWithdraw", + "inputs": [ + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "mint", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "mintWithConsent", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + }, + { + "name": "consentHash", + "type": "bytes32", + "internalType": "bytes32" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "openVault", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "outstandingDebt", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "partialPause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "pauseLevel", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum PauseLevel" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "positionToken", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IInstitutionPositionToken" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "previewDeposit", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "previewMint", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "previewRedeem", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "previewWithdraw", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "redeem", + "inputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "repay", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "repayBadDebt", + "inputs": [ + { + "name": "repayAmount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "riskConfig", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct RiskConfig", + "components": [ + { + "name": "liquidationThreshold", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "liquidationIncentive", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "latePenaltyRate", + "type": "uint256", + "internalType": "uint256" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "runtime", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple", + "internalType": "struct VaultRuntime", + "components": [ + { + "name": "state", + "type": "uint8", + "internalType": "enum VaultState" + }, + { + "name": "openStartTime", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "openEndTime", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "lockStartTime", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "lockEndTime", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "settlementDeadline", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "totalRaised", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "totalDebt", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "settlementAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "fundsWithdrawn", + "type": "bool", + "internalType": "bool" + }, + { + "name": "protocolShareSettled", + "type": "bool", + "internalType": "bool" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "setInstitutionName", + "inputs": [ + { + "name": "newName", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLatePenaltyRate", + "inputs": [ + { + "name": "newRate", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLiquidationIncentive", + "inputs": [ + { + "name": "newLI", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLiquidationThreshold", + "inputs": [ + { + "name": "newLT", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "state", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint8", + "internalType": "enum VaultState" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "sweep", + "inputs": [ + { + "name": "token", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "symbol", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "totalAssets", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "totalSupply", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "transfer", + "inputs": [ + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferFrom", + "inputs": [ + { + "name": "from", + "type": "address", + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "unpause", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "updateVaultState", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "vaultController", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "withdraw", + "inputs": [ + { + "name": "assets", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "receiver", + "type": "address", + "internalType": "address" + }, + { + "name": "owner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "shares", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "withdrawCollateral", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "event", + "name": "Approval", + "inputs": [ + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "spender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralDeposited", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "totalCollateral", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "CollateralWithdrawn", + "inputs": [ + { + "name": "positionHolder", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "remaining", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ConsentRecorded", + "inputs": [ + { + "name": "supplier", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "receiver", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "consentHash", + "type": "bytes32", + "indexed": true, + "internalType": "bytes32" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Deposit", + "inputs": [ + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "assets", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "shares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "InstitutionNameUpdated", + "inputs": [ + { + "name": "oldName", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "newName", + "type": "string", + "indexed": false, + "internalType": "string" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LatePenaltyRateUpdated", + "inputs": [ + { + "name": "oldRate", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newRate", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationExecuted", + "inputs": [ + { + "name": "liquidator", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "repayAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "collateralSeized", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationIncentiveUpdated", + "inputs": [ + { + "name": "oldLI", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newLI", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationThresholdUpdated", + "inputs": [ + { + "name": "oldLT", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "newLT", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MarginCompensationClaimed", + "inputs": [ + { + "name": "receiver", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "MarginConfiscated", + "inputs": [ + { + "name": "marginAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OverdueLiquidationExecuted", + "inputs": [ + { + "name": "settler", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "repayAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "collateralSeized", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PSRNotificationFailed", + "inputs": [ + { + "name": "psr", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "reason", + "type": "bytes", + "indexed": false, + "internalType": "bytes" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "PauseLevelSet", + "inputs": [ + { + "name": "oldLevel", + "type": "uint8", + "indexed": false, + "internalType": "enum PauseLevel" + }, + { + "name": "newLevel", + "type": "uint8", + "indexed": false, + "internalType": "enum PauseLevel" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "RaisedFundsClaimed", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Repaid", + "inputs": [ + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "remainingDebt", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "SettlementConfirmed", + "inputs": [ + { + "name": "settlementAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "protocolFee", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "surplus", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ShortfallDetected", + "inputs": [ + { + "name": "totalOwed", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "available", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "StateTransition", + "inputs": [ + { + "name": "from", + "type": "uint8", + "indexed": true, + "internalType": "enum VaultState" + }, + { + "name": "to", + "type": "uint8", + "indexed": true, + "internalType": "enum VaultState" + }, + { + "name": "timestamp", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TokensSwept", + "inputs": [ + { + "name": "token", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "recipient", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "amount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Transfer", + "inputs": [ + { + "name": "from", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "to", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "value", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultCancelled", + "inputs": [ + { + "name": "recipient", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "collateralAmount", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultClosed", + "inputs": [ + { + "name": "state", + "type": "uint8", + "indexed": false, + "internalType": "enum VaultState" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultFailed", + "inputs": [ + { + "name": "totalRaised", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "minBorrowCap", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultLiquidated", + "inputs": [ + { + "name": "available", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultLocked", + "inputs": [ + { + "name": "totalRaised", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "lockEndTime", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultOpened", + "inputs": [ + { + "name": "openEndTime", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Withdraw", + "inputs": [ + { + "name": "sender", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "receiver", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "owner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "assets", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + }, + { + "name": "shares", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "AlreadyWithdrawn", + "inputs": [] + }, + { + "type": "error", + "name": "BelowMinimumDepositAmount", + "inputs": [] + }, + { + "type": "error", + "name": "ClaimWouldBreachLT", + "inputs": [] + }, + { + "type": "error", + "name": "CompletelyPaused", + "inputs": [] + }, + { + "type": "error", + "name": "ExceedsCloseFactor", + "inputs": [] + }, + { + "type": "error", + "name": "ExceedsMaxCap", + "inputs": [] + }, + { + "type": "error", + "name": "InsufficientCollateral", + "inputs": [] + }, + { + "type": "error", + "name": "InsufficientCollateralForSeize", + "inputs": [ + { + "name": "seizeAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "availableCollateral", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "type": "error", + "name": "InsufficientRepayment", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidConsentHash", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidOraclePrice", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidState", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidStateForOverdueLiquidation", + "inputs": [] + }, + { + "type": "error", + "name": "NoOutstandingDebt", + "inputs": [] + }, + { + "type": "error", + "name": "NotBadDebt", + "inputs": [] + }, + { + "type": "error", + "name": "NotLiquidatable", + "inputs": [] + }, + { + "type": "error", + "name": "NotPositionHolder", + "inputs": [] + }, + { + "type": "error", + "name": "NothingToSweep", + "inputs": [] + }, + { + "type": "error", + "name": "PartiallyPaused", + "inputs": [] + }, + { + "type": "error", + "name": "SameStateTransition", + "inputs": [] + }, + { + "type": "error", + "name": "Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "WithdrawExceedsCollateral", + "inputs": [] + }, + { + "type": "error", + "name": "WithdrawalWouldBreachLT", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroRepayAmount", + "inputs": [] + } +] diff --git a/simulations/vip-999/abi/InstitutionalVaultController.json b/simulations/vip-999/abi/InstitutionalVaultController.json new file mode 100644 index 000000000..dbcbd51fe --- /dev/null +++ b/simulations/vip-999/abi/InstitutionalVaultController.json @@ -0,0 +1,1220 @@ +[ + { + "type": "constructor", + "inputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "MANTISSA_ONE", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MANTISSA_ONE_AND_HALF", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "MAX_APY_BPS", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "acceptOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "acceptPositionTokenOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "accessControlManager", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IAccessControlManagerV8" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allVaults", + "inputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "allVaultsLength", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "approvePositionTransfer", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "recipient", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "cancelVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "closeVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "completePauseVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "comptroller", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "createVault", + "inputs": [ + { + "name": "_vaultConfig", + "type": "tuple", + "internalType": "struct VaultConfig", + "components": [ + { + "name": "supplyAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "fixedAPY", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "reserveFactor", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "maxBorrowCap", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "minSupplierDeposit", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "openDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "lockDuration", + "type": "uint40", + "internalType": "uint40" + }, + { + "name": "settlementWindow", + "type": "uint40", + "internalType": "uint40" + } + ] + }, + { + "name": "_instConfig", + "type": "tuple", + "internalType": "struct InstitutionalConfig", + "components": [ + { + "name": "collateralAsset", + "type": "address", + "internalType": "contract IERC20" + }, + { + "name": "idealCollateralAmount", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "marginRate", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "institutionOperator", + "type": "address", + "internalType": "address" + }, + { + "name": "positionTokenId", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "_riskConfig", + "type": "tuple", + "internalType": "struct RiskConfig", + "components": [ + { + "name": "liquidationThreshold", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "liquidationIncentive", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "latePenaltyRate", + "type": "uint256", + "internalType": "uint256" + } + ] + }, + { + "name": "_name", + "type": "string", + "internalType": "string" + }, + { + "name": "_symbol", + "type": "string", + "internalType": "string" + }, + { + "name": "_institutionName", + "type": "string", + "internalType": "string" + } + ], + "outputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "getAggregatedVaultStates", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "tuple[]", + "internalType": "struct VaultStateInfo[]", + "components": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "state", + "type": "uint8", + "internalType": "enum VaultState" + }, + { + "name": "institutionOperator", + "type": "address", + "internalType": "address" + }, + { + "name": "totalRaised", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "outstandingDebt", + "type": "uint256", + "internalType": "uint256" + }, + { + "name": "institutionName", + "type": "string", + "internalType": "string" + } + ] + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "initialize", + "inputs": [ + { + "name": "vaultImplementation_", + "type": "address", + "internalType": "address" + }, + { + "name": "oracle_", + "type": "address", + "internalType": "address" + }, + { + "name": "protocolShareReserve_", + "type": "address", + "internalType": "address" + }, + { + "name": "comptroller_", + "type": "address", + "internalType": "address" + }, + { + "name": "treasury_", + "type": "address", + "internalType": "address" + }, + { + "name": "positionToken_", + "type": "address", + "internalType": "address" + }, + { + "name": "acm_", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "institutionNameOverride", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "string", + "internalType": "string" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "institutionNonce", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "uint256", + "internalType": "uint256" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "isRegistered", + "inputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "bool", + "internalType": "bool" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "liquidationAdapter", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "openVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "oracle", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "owner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "partialPauseVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "pendingOwner", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "positionToken", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "contract IInstitutionPositionToken" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "predictVaultAddress", + "inputs": [ + { + "name": "institution", + "type": "address", + "internalType": "address" + } + ], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "protocolShareReserve", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "renounceOwnership", + "inputs": [], + "outputs": [], + "stateMutability": "pure" + }, + { + "type": "function", + "name": "revokePositionTransfer", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setAccessControlManager", + "inputs": [ + { + "name": "accessControlManager_", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setComptroller", + "inputs": [ + { + "name": "comptroller_", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setInstitutionName", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "newName", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setInstitutionNameOverride", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "newName", + "type": "string", + "internalType": "string" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLatePenaltyRate", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "newRate", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLiquidationAdapter", + "inputs": [ + { + "name": "adapter", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLiquidationIncentive", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "newLI", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setLiquidationThreshold", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "newLT", + "type": "uint256", + "internalType": "uint256" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setOracle", + "inputs": [ + { + "name": "oracle_", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setProtocolShareReserve", + "inputs": [ + { + "name": "psr", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setTreasury", + "inputs": [ + { + "name": "treasury_", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "setVaultImplementation", + "inputs": [ + { + "name": "impl", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "sweep", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + }, + { + "name": "token", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "transferOwnership", + "inputs": [ + { + "name": "newOwner", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "treasury", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "function", + "name": "unpauseVault", + "inputs": [ + { + "name": "vault", + "type": "address", + "internalType": "address" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "type": "function", + "name": "vaultImplementation", + "inputs": [], + "outputs": [ + { + "name": "", + "type": "address", + "internalType": "address" + } + ], + "stateMutability": "view" + }, + { + "type": "event", + "name": "ComptrollerUpdated", + "inputs": [ + { + "name": "oldComptroller", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newComptroller", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "Initialized", + "inputs": [ + { + "name": "version", + "type": "uint8", + "indexed": false, + "internalType": "uint8" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "InstitutionNameOverrideUpdated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "oldName", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "newName", + "type": "string", + "indexed": false, + "internalType": "string" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "InstitutionNameUpdated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "oldName", + "type": "string", + "indexed": false, + "internalType": "string" + }, + { + "name": "newName", + "type": "string", + "indexed": false, + "internalType": "string" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LatePenaltyRateUpdated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newRate", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationAdapterUpdated", + "inputs": [ + { + "name": "oldAdapter", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newAdapter", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationIncentiveUpdated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newLI", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "LiquidationThresholdUpdated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newLT", + "type": "uint256", + "indexed": false, + "internalType": "uint256" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "NewAccessControlManager", + "inputs": [ + { + "name": "oldAccessControlManager", + "type": "address", + "indexed": false, + "internalType": "address" + }, + { + "name": "newAccessControlManager", + "type": "address", + "indexed": false, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OracleUpdated", + "inputs": [ + { + "name": "oldOracle", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOracle", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferStarted", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "OwnershipTransferred", + "inputs": [ + { + "name": "previousOwner", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newOwner", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "ProtocolShareReserveUpdated", + "inputs": [ + { + "name": "oldPSR", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newPSR", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "TreasuryUpdated", + "inputs": [ + { + "name": "oldTreasury", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newTreasury", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultCreated", + "inputs": [ + { + "name": "vault", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "institution", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "event", + "name": "VaultImplementationUpdated", + "inputs": [ + { + "name": "oldImpl", + "type": "address", + "indexed": true, + "internalType": "address" + }, + { + "name": "newImpl", + "type": "address", + "indexed": true, + "internalType": "address" + } + ], + "anonymous": false + }, + { + "type": "error", + "name": "InstitutionNameUnchanged", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidAddress", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidConfig", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidLatePenaltyRate", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidLiquidationIncentive", + "inputs": [] + }, + { + "type": "error", + "name": "InvalidLiquidationThreshold", + "inputs": [] + }, + { + "type": "error", + "name": "OwnershipCannotBeRenounced", + "inputs": [] + }, + { + "type": "error", + "name": "Unauthorized", + "inputs": [ + { + "name": "sender", + "type": "address", + "internalType": "address" + }, + { + "name": "calledContract", + "type": "address", + "internalType": "address" + }, + { + "name": "methodSignature", + "type": "string", + "internalType": "string" + } + ] + }, + { + "type": "error", + "name": "VaultNotRegistered", + "inputs": [] + } +] diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-999/bsctestnet.ts new file mode 100644 index 000000000..791ca300f --- /dev/null +++ b/simulations/vip-999/bsctestnet.ts @@ -0,0 +1,241 @@ +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { initMainnetUser } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import vip999, { + FIXED_RATE_VAULT_CONTROLLER, + NEW_VAULT_IMPLEMENTATION, + OLD_VAULT_IMPLEMENTATION, +} from "../../vips/vip-999/bsctestnet"; +import ERC20_ABI from "./abi/ERC20.json"; +import FAUCET_TOKEN_ABI from "./abi/FaucetToken.json"; +import VAULT_ABI from "./abi/InstitutionalLoanVault.json"; +import CONTROLLER_ABI from "./abi/InstitutionalVaultController.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; + +const FORK_BLOCK = 118272500; + +forking(FORK_BLOCK, async () => { + let controller: Contract; + let timelock: any; + let vaultsBefore: BigNumber; + + before(async () => { + controller = await ethers.getContractAt(CONTROLLER_ABI, FIXED_RATE_VAULT_CONTROLLER); + timelock = await initMainnetUser(bsctestnet.NORMAL_TIMELOCK, parseUnits("40")); + vaultsBefore = await controller.allVaultsLength(); + }); + + describe("Pre-VIP behavior", () => { + it("controller still clones the old vault implementation", async () => { + expect(await controller.vaultImplementation()).to.equal(OLD_VAULT_IMPLEMENTATION); + }); + + it("the new implementation is deployed (has code)", async () => { + expect(await ethers.provider.getCode(NEW_VAULT_IMPLEMENTATION)).to.not.equal("0x"); + }); + }); + + testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999()); + + describe("Post-VIP behavior", () => { + it("controller now clones the new vault implementation", async () => { + expect(await controller.vaultImplementation()).to.equal(NEW_VAULT_IMPLEMENTATION); + }); + }); + + describe("New vault: deposit/mint with consent + normal flow", () => { + const BTCB = "0xA808e341e8e723DC6BA0Bb5204Bafc2330d7B8e4"; + const USDT = "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c"; + const BTCB_WHALE = "0x2Ce1d0ffD7E869D9DF33e28552b12DdDed326706"; + + // IVaultTypes.VaultState + const VaultState = { + WaitingForMargin: 0, + MarginDeposited: 1, + Fundraising: 2, + Lock: 4, + PendingSettlement: 5, + Matured: 7, + }; + + const idealCollateralAmount = parseUnits("21.92", 18); + const marginRate = parseUnits("0.005", 18); // 0.5% + const marginAmount = idealCollateralAmount.mul(marginRate).div(parseUnits("1", 18)); + const openDuration = 7 * 24 * 60 * 60; + const lockDuration = 30 * 24 * 60 * 60; + + const vaultConfig = [ + USDT, // supplyAsset + 600, // fixedAPY = 6% + parseUnits("0.3", 18), // reserveFactor = 30% + parseUnits("10", 6), // minBorrowCap = 10 USDT + parseUnits("1000000", 6), // maxBorrowCap = 1M USDT + 0, // minSupplierDeposit + openDuration, + lockDuration, + 3 * 24 * 60 * 60, // settlementWindow = 3 days + ]; + const riskConfig = [parseUnits("0.9", 18), parseUnits("1.1", 18), parseUnits("1.1", 18)]; + const VAULT_SHARE_NAME = "FRV Consent Test"; + const VAULT_SHARE_SYMBOL = "FRV-consent-test"; + const INSTITUTION_NAME = "ConsentTest"; + + // 4 lenders * 100k deposit = 400k < 1M cap. + const depositAmount = parseUnits("100000", 6); + const lenderFunding = parseUnits("200000", 6); + const consentHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Venus FRV disclaimer v1")); + + let vault: Contract; + let btcb: Contract; + let usdt: Contract; + let institution: any; + let institutionAddress: string; + let deployer: any; + let lenderA: any; + let lenderB: any; + let lenderC: any; + let lenderD: any; + + before(async () => { + btcb = await ethers.getContractAt(ERC20_ABI, BTCB); + usdt = await ethers.getContractAt(FAUCET_TOKEN_ABI, USDT); + + // Institution + lenders are Hardhat signers (pre-funded with gas). + [deployer, institution, lenderA, lenderB, lenderC, lenderD] = await ethers.getSigners(); + institutionAddress = await institution.getAddress(); + + // Create a fresh vault; it is cloned from the just-installed consent-enabled implementation. + const instConfig = [BTCB, idealCollateralAmount, marginRate, institutionAddress, 0]; + await controller + .connect(timelock) + .createVault(vaultConfig, instConfig, riskConfig, VAULT_SHARE_NAME, VAULT_SHARE_SYMBOL, INSTITUTION_NAME); + const vaultAddress = await controller.allVaults(vaultsBefore); + vault = await ethers.getContractAt(VAULT_ABI, vaultAddress); + + // Fund the institution with BTCB collateral and the lenders + institution with USDT. + const whale = await initMainnetUser(BTCB_WHALE, parseUnits("40")); + await btcb.connect(whale).transfer(institutionAddress, idealCollateralAmount); + + for (const lender of [lenderA, lenderB, lenderC, lenderD]) { + await usdt.connect(deployer).allocateTo(await lender.getAddress(), lenderFunding); + } + await usdt.connect(deployer).allocateTo(institutionAddress, parseUnits("50000", 6)); + }); + + it("a new vault backed by the new implementation was registered", async () => { + expect(await controller.allVaultsLength()).to.equal(vaultsBefore.add(1)); + expect(await controller.isRegistered(vault.address)).to.equal(true); + expect(await vault.institutionName()).to.equal(INSTITUTION_NAME); + }); + + it("institution deposits margin and controller opens the vault (-> Fundraising)", async () => { + expect(await vault.state()).to.equal(VaultState.WaitingForMargin); + await btcb.connect(institution).approve(vault.address, idealCollateralAmount); + await vault.connect(institution).depositCollateral(marginAmount); + expect(await vault.state()).to.equal(VaultState.MarginDeposited); + + await controller.connect(timelock).openVault(vault.address); + expect(await vault.state()).to.equal(VaultState.Fundraising); + + // Top up to the full ideal collateral before fundraising deposits. + await vault.connect(institution).depositCollateral(idealCollateralAmount.sub(marginAmount)); + expect(await btcb.balanceOf(vault.address)).to.equal(idealCollateralAmount); + }); + + it("normal deposit(assets, receiver) mints shares", async () => { + const receiver = await lenderA.getAddress(); + await usdt.connect(lenderA).approve(vault.address, lenderFunding); + await vault.connect(lenderA).deposit(depositAmount, receiver); + expect(await vault.balanceOf(receiver)).to.be.gt(0); + }); + + it("normal mint(shares, receiver) pulls assets", async () => { + const receiver = await lenderB.getAddress(); + const shares = await vault.previewDeposit(depositAmount); + await usdt.connect(lenderB).approve(vault.address, lenderFunding); + await vault.connect(lenderB).mint(shares, receiver); + expect(await vault.balanceOf(receiver)).to.equal(shares); + }); + + it("depositWithConsent records the consent hash and mints shares", async () => { + const receiver = await lenderC.getAddress(); + await usdt.connect(lenderC).approve(vault.address, lenderFunding); + await expect(vault.connect(lenderC).depositWithConsent(depositAmount, receiver, consentHash)) + .to.emit(vault, "ConsentRecorded") + .withArgs(receiver, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.be.gt(0); + }); + + it("mintWithConsent records the consent hash and pulls assets", async () => { + const receiver = await lenderD.getAddress(); + const shares = await vault.previewDeposit(depositAmount); + await usdt.connect(lenderD).approve(vault.address, lenderFunding); + await expect(vault.connect(lenderD).mintWithConsent(shares, receiver, consentHash)) + .to.emit(vault, "ConsentRecorded") + .withArgs(receiver, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.equal(shares); + }); + + it("depositWithConsent / mintWithConsent revert on a zero consent hash", async () => { + const zero = ethers.constants.HashZero; + const receiver = await lenderA.getAddress(); + await expect( + vault.connect(lenderA).depositWithConsent(depositAmount, receiver, zero), + ).to.be.revertedWithCustomError(vault, "InvalidConsentHash"); + await expect( + vault.connect(lenderA).mintWithConsent(await vault.previewDeposit(depositAmount), receiver, zero), + ).to.be.revertedWithCustomError(vault, "InvalidConsentHash"); + }); + + it("normal flow completes: lock -> claim -> repay -> matured -> redeem -> withdraw collateral", async () => { + // Lock the vault once the open window elapses. + await ethers.provider.send("evm_increaseTime", [openDuration + 1]); + await ethers.provider.send("evm_mine", []); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.Lock); + + // Institution claims the raised funds. + const raised = await usdt.balanceOf(vault.address); + const instUsdtBefore = await usdt.balanceOf(institutionAddress); + await vault.connect(institution).claimRaisedFunds(); + expect(await usdt.balanceOf(institutionAddress)).to.equal(instUsdtBefore.add(raised)); + + // After the lock period the vault expects settlement; institution repays in full. + await ethers.provider.send("evm_increaseTime", [lockDuration + 1]); + await ethers.provider.send("evm_mine", []); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.PendingSettlement); + + const owed = await vault.outstandingDebt(); + await usdt.connect(institution).approve(vault.address, owed); + await vault.connect(institution).repay(owed); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.Matured); + expect(await vault.outstandingDebt()).to.equal(0); + + // A lender redeems principal + net interest. + const receiver = await lenderA.getAddress(); + const shares = await vault.balanceOf(receiver); + const expectedAssets = await vault.previewRedeem(shares); + expect(expectedAssets).to.be.gt(depositAmount); + const usdtBefore = await usdt.balanceOf(receiver); + await vault.connect(lenderA).redeem(shares, receiver, receiver); + expect(await usdt.balanceOf(receiver)).to.equal(usdtBefore.add(expectedAssets)); + expect(await vault.balanceOf(receiver)).to.equal(0); + + // Institution withdraws its collateral. + const collateral = await btcb.balanceOf(vault.address); + expect(collateral).to.equal(idealCollateralAmount); + const instBtcbBefore = await btcb.balanceOf(institutionAddress); + await vault.connect(institution).withdrawCollateral(collateral); + expect(await btcb.balanceOf(institutionAddress)).to.equal(instBtcbBefore.add(collateral)); + expect(await btcb.balanceOf(vault.address)).to.equal(0); + }); + }); +}); diff --git a/vips/vip-999/bsctestnet.ts b/vips/vip-999/bsctestnet.ts new file mode 100644 index 000000000..17fa85226 --- /dev/null +++ b/vips/vip-999/bsctestnet.ts @@ -0,0 +1,54 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const FIXED_RATE_VAULT_CONTROLLER = "0xf77dED2A00F94e33C392126238360D4642c16Ba2"; +export const OLD_VAULT_IMPLEMENTATION = "0x97421799419Eb782628e73e7220d8E0A207469a3"; + +// Adds depositWithConsent / mintWithConsent (deployed at testnet block 118271685). +export const NEW_VAULT_IMPLEMENTATION = "0x44B13FEDE6b4866C60E1ac78Ac9B065406510433"; + +export const vip999 = () => { + const meta = { + version: "v2", + title: "VIP-999 [BNB Chain Testnet] Upgrade Institutional Fixed Rate Vault implementation (consent recording)", + description: `#### Summary + +If passed, this VIP points the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. + +#### Description + +The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RATE_VAULT_CONTROLLER}) to clone new vaults is upgraded from ${OLD_VAULT_IMPLEMENTATION} to ${NEW_VAULT_IMPLEMENTATION}. The new implementation adds two supplier entrypoints: + +- \`depositWithConsent(uint256 assets, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`deposit\` that emits \`ConsentRecorded(supplier, receiver, consentHash)\`. +- \`mintWithConsent(uint256 shares, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`mint\` that emits the same event. + +Both revert with \`InvalidConsentHash\` if \`consentHash\` is zero. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. + +#### Actions + +- Point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. + +#### Voting options + +- **For** — Execute the proposal +- **Against** — Do not execute the proposal +- **Abstain** — Indifferent to execution`, + forDescription: "I agree that Venus Protocol should proceed with this proposal", + againstDescription: "I do not think that Venus Protocol should proceed with this proposal", + abstainDescription: "I am indifferent to whether Venus Protocol proceeds or not", + }; + + return makeProposal( + [ + { + target: FIXED_RATE_VAULT_CONTROLLER, + signature: "setVaultImplementation(address)", + params: [NEW_VAULT_IMPLEMENTATION], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip999; From c6f30c4798c330e2068c87aefc5d1c688741f85d Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Fri, 10 Jul 2026 15:14:02 +0530 Subject: [PATCH 2/9] fix: update new vault address --- .../vip-999/abi/InstitutionalLoanVault.json | 5 ---- simulations/vip-999/bsctestnet.ts | 23 +++++++++++++------ vips/vip-999/bsctestnet.ts | 4 ++-- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/simulations/vip-999/abi/InstitutionalLoanVault.json b/simulations/vip-999/abi/InstitutionalLoanVault.json index 6c611b288..a01910c17 100644 --- a/simulations/vip-999/abi/InstitutionalLoanVault.json +++ b/simulations/vip-999/abi/InstitutionalLoanVault.json @@ -2072,11 +2072,6 @@ "name": "InsufficientRepayment", "inputs": [] }, - { - "type": "error", - "name": "InvalidConsentHash", - "inputs": [] - }, { "type": "error", "name": "InvalidOraclePrice", diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-999/bsctestnet.ts index 791ca300f..b56c1e08f 100644 --- a/simulations/vip-999/bsctestnet.ts +++ b/simulations/vip-999/bsctestnet.ts @@ -18,7 +18,7 @@ import CONTROLLER_ABI from "./abi/InstitutionalVaultController.json"; const { bsctestnet } = NETWORK_ADDRESSES; -const FORK_BLOCK = 118272500; +const FORK_BLOCK = 118291763; forking(FORK_BLOCK, async () => { let controller: Contract; @@ -182,15 +182,24 @@ forking(FORK_BLOCK, async () => { expect(await vault.balanceOf(receiver)).to.equal(shares); }); - it("depositWithConsent / mintWithConsent revert on a zero consent hash", async () => { + it("depositWithConsent / mintWithConsent accept a zero consent hash without emitting", async () => { const zero = ethers.constants.HashZero; const receiver = await lenderA.getAddress(); + const smallDeposit = parseUnits("10000", 6); + + // A zero hash skips consent recording: no event, no revert, deposit/mint still happens. + const beforeDeposit = await vault.balanceOf(receiver); + await expect(vault.connect(lenderA).depositWithConsent(smallDeposit, receiver, zero)).to.not.emit( + vault, + "ConsentRecorded", + ); + const afterDeposit = await vault.balanceOf(receiver); + expect(afterDeposit).to.be.gt(beforeDeposit); + await expect( - vault.connect(lenderA).depositWithConsent(depositAmount, receiver, zero), - ).to.be.revertedWithCustomError(vault, "InvalidConsentHash"); - await expect( - vault.connect(lenderA).mintWithConsent(await vault.previewDeposit(depositAmount), receiver, zero), - ).to.be.revertedWithCustomError(vault, "InvalidConsentHash"); + vault.connect(lenderA).mintWithConsent(await vault.previewDeposit(smallDeposit), receiver, zero), + ).to.not.emit(vault, "ConsentRecorded"); + expect(await vault.balanceOf(receiver)).to.be.gt(afterDeposit); }); it("normal flow completes: lock -> claim -> repay -> matured -> redeem -> withdraw collateral", async () => { diff --git a/vips/vip-999/bsctestnet.ts b/vips/vip-999/bsctestnet.ts index 17fa85226..db2ebbfd0 100644 --- a/vips/vip-999/bsctestnet.ts +++ b/vips/vip-999/bsctestnet.ts @@ -4,8 +4,8 @@ import { makeProposal } from "src/utils"; export const FIXED_RATE_VAULT_CONTROLLER = "0xf77dED2A00F94e33C392126238360D4642c16Ba2"; export const OLD_VAULT_IMPLEMENTATION = "0x97421799419Eb782628e73e7220d8E0A207469a3"; -// Adds depositWithConsent / mintWithConsent (deployed at testnet block 118271685). -export const NEW_VAULT_IMPLEMENTATION = "0x44B13FEDE6b4866C60E1ac78Ac9B065406510433"; +// Adds depositWithConsent / mintWithConsent. +export const NEW_VAULT_IMPLEMENTATION = "0xB677627eB4B9D8bfB793966e266C899E7FD484C5"; export const vip999 = () => { const meta = { From 78b2cd0ac02dd5aea8f6d056110b60c055f5d5f8 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Fri, 10 Jul 2026 16:43:21 +0530 Subject: [PATCH 3/9] feat: add mainnet VIP + sim for FRV consent vault upgrade --- simulations/vip-999/abi/ResilientOracle.json | 655 +++++++++++++++++++ simulations/vip-999/bscmainnet.ts | 261 ++++++++ simulations/vip-999/bsctestnet.ts | 13 +- vips/vip-999/bscmainnet.ts | 54 ++ vips/vip-999/bsctestnet.ts | 2 +- 5 files changed, 982 insertions(+), 3 deletions(-) create mode 100644 simulations/vip-999/abi/ResilientOracle.json create mode 100644 simulations/vip-999/bscmainnet.ts create mode 100644 vips/vip-999/bscmainnet.ts diff --git a/simulations/vip-999/abi/ResilientOracle.json b/simulations/vip-999/abi/ResilientOracle.json new file mode 100644 index 000000000..927d27526 --- /dev/null +++ b/simulations/vip-999/abi/ResilientOracle.json @@ -0,0 +1,655 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "nativeMarketAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "vaiAddress", + "type": "address" + }, + { + "internalType": "contract BoundValidatorInterface", + "name": "_boundValidator", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "calledContract", + "type": "address" + }, + { + "internalType": "string", + "name": "methodSignature", + "type": "string" + } + ], + "name": "Unauthorized", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": 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": "INVALID_PRICE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "NATIVE_TOKEN_ADDR", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "boundValidator", + "outputs": [ + { + "internalType": "contract BoundValidatorInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "enableOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "getOracle", + "outputs": [ + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "bool", + "name": "enabled", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "getTokenConfig", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + }, + { + "internalType": "bool", + "name": "cachingEnabled", + "type": "bool" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getUnderlyingPrice", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "nativeMarket", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "paused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address", + "name": "oracle", + "type": "address" + }, + { + "internalType": "enum ResilientOracle.OracleRole", + "name": "role", + "type": "uint8" + } + ], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + }, + { + "internalType": "bool", + "name": "cachingEnabled", + "type": "bool" + } + ], + "internalType": "struct ResilientOracle.TokenConfig", + "name": "tokenConfig", + "type": "tuple" + } + ], + "name": "setTokenConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "address[3]", + "name": "oracles", + "type": "address[3]" + }, + { + "internalType": "bool[3]", + "name": "enableFlagsForOracles", + "type": "bool[3]" + }, + { + "internalType": "bool", + "name": "cachingEnabled", + "type": "bool" + } + ], + "internalType": "struct ResilientOracle.TokenConfig[]", + "name": "tokenConfigs_", + "type": "tuple[]" + } + ], + "name": "setTokenConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "unpause", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "asset", + "type": "address" + } + ], + "name": "updateAssetPrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updatePrice", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vai", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-999/bscmainnet.ts b/simulations/vip-999/bscmainnet.ts new file mode 100644 index 000000000..f0ca34bcb --- /dev/null +++ b/simulations/vip-999/bscmainnet.ts @@ -0,0 +1,261 @@ +import { expect } from "chai"; +import { BigNumber, Contract } from "ethers"; +import { parseUnits } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { initMainnetUser, pinResilientOraclePriceViaRedstone } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import vip999, { + FIXED_RATE_VAULT_CONTROLLER, + NEW_VAULT_IMPLEMENTATION, + OLD_VAULT_IMPLEMENTATION, +} from "../../vips/vip-999/bscmainnet"; +import ERC20_ABI from "./abi/ERC20.json"; +import VAULT_ABI from "./abi/InstitutionalLoanVault.json"; +import CONTROLLER_ABI from "./abi/InstitutionalVaultController.json"; +import ORACLE_ABI from "./abi/ResilientOracle.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +const FORK_BLOCK = 109158500; + +const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; +const USDT = "0x55d398326f99059fF775485246999027B3197955"; +const WHALE = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; + +forking(FORK_BLOCK, async () => { + let controller: Contract; + let timelock: any; + let vaultsBefore: BigNumber; + + before(async () => { + controller = await ethers.getContractAt(CONTROLLER_ABI, FIXED_RATE_VAULT_CONTROLLER); + timelock = await initMainnetUser(bscmainnet.NORMAL_TIMELOCK, parseUnits("40")); + vaultsBefore = await controller.allVaultsLength(); + + const resilientOracle = await ethers.getContractAt(ORACLE_ABI, bscmainnet.RESILIENT_ORACLE); + await pinResilientOraclePriceViaRedstone(resilientOracle, BTCB); + await pinResilientOraclePriceViaRedstone(resilientOracle, USDT); + }); + + describe("Pre-VIP behavior", () => { + it("controller still clones the old vault implementation", async () => { + expect(await controller.vaultImplementation()).to.equal(OLD_VAULT_IMPLEMENTATION); + }); + + it("consent entrypoints are absent from the old implementation but present in the new one", async () => { + const iface = new ethers.utils.Interface(VAULT_ABI); + const selectors = [iface.getSighash("depositWithConsent"), iface.getSighash("mintWithConsent")].map(s => + s.slice(2), + ); + const oldCode = await ethers.provider.getCode(OLD_VAULT_IMPLEMENTATION); + const newCode = await ethers.provider.getCode(NEW_VAULT_IMPLEMENTATION); + for (const selector of selectors) { + expect(oldCode, "old impl should not expose the consent entrypoints").to.not.include(selector); + expect(newCode, "new impl should expose the consent entrypoints").to.include(selector); + } + }); + }); + + testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999()); + + describe("Post-VIP behavior", () => { + it("controller now clones the new vault implementation", async () => { + expect(await controller.vaultImplementation()).to.equal(NEW_VAULT_IMPLEMENTATION); + }); + }); + + describe("New vault: deposit/mint with consent + normal flow", () => { + // IVaultTypes.VaultState + const VaultState = { + WaitingForMargin: 0, + MarginDeposited: 1, + Fundraising: 2, + Lock: 4, + PendingSettlement: 5, + Matured: 7, + }; + + const idealCollateralAmount = parseUnits("21.92", 18); + const marginRate = parseUnits("0.005", 18); // 0.5% + const marginAmount = idealCollateralAmount.mul(marginRate).div(parseUnits("1", 18)); + const openDuration = 7 * 24 * 60 * 60; + const lockDuration = 30 * 24 * 60 * 60; + + const vaultConfig = [ + USDT, // supplyAsset + 600, // fixedAPY = 6% + parseUnits("0.3", 18), // reserveFactor = 30% + parseUnits("10", 18), // minBorrowCap = 10 USDT + parseUnits("1000000", 18), // maxBorrowCap = 1M USDT + 0, // minSupplierDeposit + openDuration, + lockDuration, + 3 * 24 * 60 * 60, // settlementWindow = 3 days + ]; + const riskConfig = [parseUnits("0.9", 18), parseUnits("1.1", 18), parseUnits("1.1", 18)]; + const VAULT_SHARE_NAME = "FRV Consent Test"; + const VAULT_SHARE_SYMBOL = "FRV-consent-test"; + const INSTITUTION_NAME = "ConsentTest"; + + // 4 lenders * 100k deposit = 400k < 1M cap. + const depositAmount = parseUnits("100000", 18); + const lenderFunding = parseUnits("200000", 18); + const consentHash = ethers.utils.keccak256(ethers.utils.toUtf8Bytes("Venus FRV disclaimer v1")); + + let vault: Contract; + let btcb: Contract; + let usdt: Contract; + let institution: any; + let institutionAddress: string; + let lenderA: any; + let lenderB: any; + let lenderC: any; + let lenderD: any; + + before(async () => { + btcb = await ethers.getContractAt(ERC20_ABI, BTCB); + usdt = await ethers.getContractAt(ERC20_ABI, USDT); + + // Institution + lenders are Hardhat signers (pre-funded with gas). + [, institution, lenderA, lenderB, lenderC, lenderD] = await ethers.getSigners(); + institutionAddress = await institution.getAddress(); + + // Create a fresh vault; it is cloned from the just-installed consent-enabled implementation. + const instConfig = [BTCB, idealCollateralAmount, marginRate, institutionAddress, 0]; + await controller + .connect(timelock) + .createVault(vaultConfig, instConfig, riskConfig, VAULT_SHARE_NAME, VAULT_SHARE_SYMBOL, INSTITUTION_NAME); + const vaultAddress = await controller.allVaults(vaultsBefore); + vault = await ethers.getContractAt(VAULT_ABI, vaultAddress); + + // Fund the institution with BTCB collateral and the lenders + institution with USDT (from the whale). + const whale = await initMainnetUser(WHALE, parseUnits("40")); + await btcb.connect(whale).transfer(institutionAddress, idealCollateralAmount); + for (const lender of [lenderA, lenderB, lenderC, lenderD]) { + await usdt.connect(whale).transfer(await lender.getAddress(), lenderFunding); + } + await usdt.connect(whale).transfer(institutionAddress, parseUnits("50000", 18)); + }); + + it("a new vault backed by the new implementation was registered", async () => { + expect(await controller.allVaultsLength()).to.equal(vaultsBefore.add(1)); + expect(await controller.isRegistered(vault.address)).to.equal(true); + expect(await vault.institutionName()).to.equal(INSTITUTION_NAME); + }); + + it("institution deposits margin and controller opens the vault (-> Fundraising)", async () => { + expect(await vault.state()).to.equal(VaultState.WaitingForMargin); + await btcb.connect(institution).approve(vault.address, idealCollateralAmount); + await vault.connect(institution).depositCollateral(marginAmount); + expect(await vault.state()).to.equal(VaultState.MarginDeposited); + + await controller.connect(timelock).openVault(vault.address); + expect(await vault.state()).to.equal(VaultState.Fundraising); + + // Top up to the full ideal collateral before fundraising deposits. + await vault.connect(institution).depositCollateral(idealCollateralAmount.sub(marginAmount)); + expect(await btcb.balanceOf(vault.address)).to.equal(idealCollateralAmount); + }); + + it("normal deposit(assets, receiver) mints shares", async () => { + const receiver = await lenderA.getAddress(); + await usdt.connect(lenderA).approve(vault.address, lenderFunding); + await vault.connect(lenderA).deposit(depositAmount, receiver); + expect(await vault.balanceOf(receiver)).to.be.gt(0); + }); + + it("normal mint(shares, receiver) pulls assets", async () => { + const receiver = await lenderB.getAddress(); + const shares = await vault.previewDeposit(depositAmount); + await usdt.connect(lenderB).approve(vault.address, lenderFunding); + await vault.connect(lenderB).mint(shares, receiver); + expect(await vault.balanceOf(receiver)).to.equal(shares); + }); + + it("depositWithConsent records the consent hash and mints shares", async () => { + const receiver = await lenderC.getAddress(); + await usdt.connect(lenderC).approve(vault.address, lenderFunding); + await expect(vault.connect(lenderC).depositWithConsent(depositAmount, receiver, consentHash)) + .to.emit(vault, "ConsentRecorded") + .withArgs(receiver, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.be.gt(0); + }); + + it("mintWithConsent records the consent hash and pulls assets", async () => { + const receiver = await lenderD.getAddress(); + const shares = await vault.previewDeposit(depositAmount); + await usdt.connect(lenderD).approve(vault.address, lenderFunding); + await expect(vault.connect(lenderD).mintWithConsent(shares, receiver, consentHash)) + .to.emit(vault, "ConsentRecorded") + .withArgs(receiver, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.equal(shares); + }); + + it("depositWithConsent / mintWithConsent accept a zero consent hash without emitting", async () => { + const zero = ethers.constants.HashZero; + const receiver = await lenderA.getAddress(); + const smallDeposit = parseUnits("10000", 18); + + // A zero hash skips consent recording: no event, no revert, deposit/mint still happens. + const beforeDeposit = await vault.balanceOf(receiver); + await expect(vault.connect(lenderA).depositWithConsent(smallDeposit, receiver, zero)).to.not.emit( + vault, + "ConsentRecorded", + ); + const afterDeposit = await vault.balanceOf(receiver); + expect(afterDeposit).to.be.gt(beforeDeposit); + + await expect( + vault.connect(lenderA).mintWithConsent(await vault.previewDeposit(smallDeposit), receiver, zero), + ).to.not.emit(vault, "ConsentRecorded"); + expect(await vault.balanceOf(receiver)).to.be.gt(afterDeposit); + }); + + it("normal flow completes: lock -> claim -> repay -> matured -> redeem -> withdraw collateral", async () => { + // Lock the vault once the open window elapses. + await ethers.provider.send("evm_increaseTime", [openDuration + 1]); + await ethers.provider.send("evm_mine", []); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.Lock); + + // Institution claims the raised funds. + const raised = await usdt.balanceOf(vault.address); + const instUsdtBefore = await usdt.balanceOf(institutionAddress); + await vault.connect(institution).claimRaisedFunds(); + expect(await usdt.balanceOf(institutionAddress)).to.equal(instUsdtBefore.add(raised)); + + // After the lock period the vault expects settlement; institution repays in full. + await ethers.provider.send("evm_increaseTime", [lockDuration + 1]); + await ethers.provider.send("evm_mine", []); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.PendingSettlement); + + const owed = await vault.outstandingDebt(); + await usdt.connect(institution).approve(vault.address, owed); + await vault.connect(institution).repay(owed); + await vault.updateVaultState(); + expect(await vault.state()).to.equal(VaultState.Matured); + expect(await vault.outstandingDebt()).to.equal(0); + + // A lender redeems principal + net interest. + const receiver = await lenderA.getAddress(); + const shares = await vault.balanceOf(receiver); + const expectedAssets = await vault.previewRedeem(shares); + expect(expectedAssets).to.be.gt(depositAmount); + const usdtBefore = await usdt.balanceOf(receiver); + await vault.connect(lenderA).redeem(shares, receiver, receiver); + expect(await usdt.balanceOf(receiver)).to.equal(usdtBefore.add(expectedAssets)); + expect(await vault.balanceOf(receiver)).to.equal(0); + + // Institution withdraws its collateral. + const collateral = await btcb.balanceOf(vault.address); + expect(collateral).to.equal(idealCollateralAmount); + const instBtcbBefore = await btcb.balanceOf(institutionAddress); + await vault.connect(institution).withdrawCollateral(collateral); + expect(await btcb.balanceOf(institutionAddress)).to.equal(instBtcbBefore.add(collateral)); + expect(await btcb.balanceOf(vault.address)).to.equal(0); + }); + }); +}); diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-999/bsctestnet.ts index b56c1e08f..c8f2e5d69 100644 --- a/simulations/vip-999/bsctestnet.ts +++ b/simulations/vip-999/bsctestnet.ts @@ -36,8 +36,17 @@ forking(FORK_BLOCK, async () => { expect(await controller.vaultImplementation()).to.equal(OLD_VAULT_IMPLEMENTATION); }); - it("the new implementation is deployed (has code)", async () => { - expect(await ethers.provider.getCode(NEW_VAULT_IMPLEMENTATION)).to.not.equal("0x"); + it("consent entrypoints are absent from the old implementation but present in the new one", async () => { + const iface = new ethers.utils.Interface(VAULT_ABI); + const selectors = [iface.getSighash("depositWithConsent"), iface.getSighash("mintWithConsent")].map(s => + s.slice(2), + ); + const oldCode = await ethers.provider.getCode(OLD_VAULT_IMPLEMENTATION); + const newCode = await ethers.provider.getCode(NEW_VAULT_IMPLEMENTATION); + for (const selector of selectors) { + expect(oldCode, "old impl should not expose the consent entrypoints").to.not.include(selector); + expect(newCode, "new impl should expose the consent entrypoints").to.include(selector); + } }); }); diff --git a/vips/vip-999/bscmainnet.ts b/vips/vip-999/bscmainnet.ts new file mode 100644 index 000000000..1567f7ed6 --- /dev/null +++ b/vips/vip-999/bscmainnet.ts @@ -0,0 +1,54 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const FIXED_RATE_VAULT_CONTROLLER = "0x6D9e91cB766259af42619c14c994E694E57e6E85"; +export const OLD_VAULT_IMPLEMENTATION = "0xC25b2B657D24380eDd1a1Cff5296385541e85204"; + +// Adds depositWithConsent / mintWithConsent. +export const NEW_VAULT_IMPLEMENTATION = "0xe87A1eFCED88bBddf8CCF78EfB3bCF62cFdd5bdC"; + +export const vip999 = () => { + const meta = { + version: "v2", + title: "VIP-999 [BNB Chain] Upgrade Institutional Fixed Rate Vault implementation (consent recording)", + description: `#### Summary + +If passed, this VIP points the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. + +#### Description + +The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RATE_VAULT_CONTROLLER}) to clone new vaults is upgraded from ${OLD_VAULT_IMPLEMENTATION} to ${NEW_VAULT_IMPLEMENTATION}. The new implementation adds two supplier entrypoints: + +- \`depositWithConsent(uint256 assets, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`deposit\` that emits \`ConsentRecorded(supplier, receiver, consentHash)\`. +- \`mintWithConsent(uint256 shares, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`mint\` that emits the same event. + +The consent hash is optional: passing \`bytes32(0)\` skips the event and deposits/mints as usual. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. + +#### Actions + +- Point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. + +#### Voting options + +- **For** — Execute the proposal +- **Against** — Do not execute the proposal +- **Abstain** — Indifferent to execution`, + forDescription: "I agree that Venus Protocol should proceed with this proposal", + againstDescription: "I do not think that Venus Protocol should proceed with this proposal", + abstainDescription: "I am indifferent to whether Venus Protocol proceeds or not", + }; + + return makeProposal( + [ + { + target: FIXED_RATE_VAULT_CONTROLLER, + signature: "setVaultImplementation(address)", + params: [NEW_VAULT_IMPLEMENTATION], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip999; diff --git a/vips/vip-999/bsctestnet.ts b/vips/vip-999/bsctestnet.ts index db2ebbfd0..1f0e007d3 100644 --- a/vips/vip-999/bsctestnet.ts +++ b/vips/vip-999/bsctestnet.ts @@ -22,7 +22,7 @@ The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RA - \`depositWithConsent(uint256 assets, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`deposit\` that emits \`ConsentRecorded(supplier, receiver, consentHash)\`. - \`mintWithConsent(uint256 shares, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`mint\` that emits the same event. -Both revert with \`InvalidConsentHash\` if \`consentHash\` is zero. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. +The consent hash is optional: passing \`bytes32(0)\` skips the event and deposits/mints as usual. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. #### Actions From 4ea910994062664e514b7f1cf623b3f42881fe1c Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Fri, 10 Jul 2026 17:27:23 +0530 Subject: [PATCH 4/9] test: add event emit check --- simulations/vip-999/bscmainnet.ts | 8 ++++++-- simulations/vip-999/bsctestnet.ts | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/simulations/vip-999/bscmainnet.ts b/simulations/vip-999/bscmainnet.ts index f0ca34bcb..edd2dc607 100644 --- a/simulations/vip-999/bscmainnet.ts +++ b/simulations/vip-999/bscmainnet.ts @@ -3,7 +3,7 @@ import { BigNumber, Contract } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { NETWORK_ADDRESSES } from "src/networkAddresses"; -import { initMainnetUser, pinResilientOraclePriceViaRedstone } from "src/utils"; +import { expectEvents, initMainnetUser, pinResilientOraclePriceViaRedstone } from "src/utils"; import { forking, testVip } from "src/vip-framework"; import vip999, { @@ -58,7 +58,11 @@ forking(FORK_BLOCK, async () => { }); }); - testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999()); + testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [CONTROLLER_ABI], ["VaultImplementationUpdated"], [1]); + }, + }); describe("Post-VIP behavior", () => { it("controller now clones the new vault implementation", async () => { diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-999/bsctestnet.ts index c8f2e5d69..69f4ad466 100644 --- a/simulations/vip-999/bsctestnet.ts +++ b/simulations/vip-999/bsctestnet.ts @@ -3,7 +3,7 @@ import { BigNumber, Contract } from "ethers"; import { parseUnits } from "ethers/lib/utils"; import { ethers } from "hardhat"; import { NETWORK_ADDRESSES } from "src/networkAddresses"; -import { initMainnetUser } from "src/utils"; +import { expectEvents, initMainnetUser } from "src/utils"; import { forking, testVip } from "src/vip-framework"; import vip999, { @@ -50,7 +50,11 @@ forking(FORK_BLOCK, async () => { }); }); - testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999()); + testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999(), { + callbackAfterExecution: async txResponse => { + await expectEvents(txResponse, [CONTROLLER_ABI], ["VaultImplementationUpdated"], [1]); + }, + }); describe("Post-VIP behavior", () => { it("controller now clones the new vault implementation", async () => { From 64950dc4a974c280a022b9c826c4977d6211bbc9 Mon Sep 17 00:00:00 2001 From: GitGuru7 Date: Fri, 10 Jul 2026 22:27:53 +0530 Subject: [PATCH 5/9] fix: assert consent event supplier differs from receiver --- simulations/vip-999/bscmainnet.ts | 23 ++++++++++++++--------- simulations/vip-999/bsctestnet.ts | 23 ++++++++++++++--------- 2 files changed, 28 insertions(+), 18 deletions(-) diff --git a/simulations/vip-999/bscmainnet.ts b/simulations/vip-999/bscmainnet.ts index edd2dc607..18cf6abab 100644 --- a/simulations/vip-999/bscmainnet.ts +++ b/simulations/vip-999/bscmainnet.ts @@ -117,13 +117,14 @@ forking(FORK_BLOCK, async () => { let lenderB: any; let lenderC: any; let lenderD: any; + let otherReceiver: any; before(async () => { btcb = await ethers.getContractAt(ERC20_ABI, BTCB); usdt = await ethers.getContractAt(ERC20_ABI, USDT); // Institution + lenders are Hardhat signers (pre-funded with gas). - [, institution, lenderA, lenderB, lenderC, lenderD] = await ethers.getSigners(); + [, institution, lenderA, lenderB, lenderC, lenderD, otherReceiver] = await ethers.getSigners(); institutionAddress = await institution.getAddress(); // Create a fresh vault; it is cloned from the just-installed consent-enabled implementation. @@ -178,23 +179,27 @@ forking(FORK_BLOCK, async () => { expect(await vault.balanceOf(receiver)).to.equal(shares); }); - it("depositWithConsent records the consent hash and mints shares", async () => { - const receiver = await lenderC.getAddress(); + it("depositWithConsent records the consent hash with supplier as sender, not receiver", async () => { + const supplier = await lenderC.getAddress(); + const receiver = await otherReceiver.getAddress(); + const before = await vault.balanceOf(receiver); await usdt.connect(lenderC).approve(vault.address, lenderFunding); await expect(vault.connect(lenderC).depositWithConsent(depositAmount, receiver, consentHash)) .to.emit(vault, "ConsentRecorded") - .withArgs(receiver, receiver, consentHash); - expect(await vault.balanceOf(receiver)).to.be.gt(0); + .withArgs(supplier, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.be.gt(before); }); - it("mintWithConsent records the consent hash and pulls assets", async () => { - const receiver = await lenderD.getAddress(); + it("mintWithConsent records the consent hash with supplier as sender, not receiver", async () => { + const supplier = await lenderD.getAddress(); + const receiver = await otherReceiver.getAddress(); const shares = await vault.previewDeposit(depositAmount); + const before = await vault.balanceOf(receiver); await usdt.connect(lenderD).approve(vault.address, lenderFunding); await expect(vault.connect(lenderD).mintWithConsent(shares, receiver, consentHash)) .to.emit(vault, "ConsentRecorded") - .withArgs(receiver, receiver, consentHash); - expect(await vault.balanceOf(receiver)).to.equal(shares); + .withArgs(supplier, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.equal(before.add(shares)); }); it("depositWithConsent / mintWithConsent accept a zero consent hash without emitting", async () => { diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-999/bsctestnet.ts index 69f4ad466..d6c8a1b91 100644 --- a/simulations/vip-999/bsctestnet.ts +++ b/simulations/vip-999/bsctestnet.ts @@ -114,13 +114,14 @@ forking(FORK_BLOCK, async () => { let lenderB: any; let lenderC: any; let lenderD: any; + let otherReceiver: any; before(async () => { btcb = await ethers.getContractAt(ERC20_ABI, BTCB); usdt = await ethers.getContractAt(FAUCET_TOKEN_ABI, USDT); // Institution + lenders are Hardhat signers (pre-funded with gas). - [deployer, institution, lenderA, lenderB, lenderC, lenderD] = await ethers.getSigners(); + [deployer, institution, lenderA, lenderB, lenderC, lenderD, otherReceiver] = await ethers.getSigners(); institutionAddress = await institution.getAddress(); // Create a fresh vault; it is cloned from the just-installed consent-enabled implementation. @@ -176,23 +177,27 @@ forking(FORK_BLOCK, async () => { expect(await vault.balanceOf(receiver)).to.equal(shares); }); - it("depositWithConsent records the consent hash and mints shares", async () => { - const receiver = await lenderC.getAddress(); + it("depositWithConsent records the consent hash with supplier as sender, not receiver", async () => { + const supplier = await lenderC.getAddress(); + const receiver = await otherReceiver.getAddress(); + const before = await vault.balanceOf(receiver); await usdt.connect(lenderC).approve(vault.address, lenderFunding); await expect(vault.connect(lenderC).depositWithConsent(depositAmount, receiver, consentHash)) .to.emit(vault, "ConsentRecorded") - .withArgs(receiver, receiver, consentHash); - expect(await vault.balanceOf(receiver)).to.be.gt(0); + .withArgs(supplier, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.be.gt(before); }); - it("mintWithConsent records the consent hash and pulls assets", async () => { - const receiver = await lenderD.getAddress(); + it("mintWithConsent records the consent hash with supplier as sender, not receiver", async () => { + const supplier = await lenderD.getAddress(); + const receiver = await otherReceiver.getAddress(); const shares = await vault.previewDeposit(depositAmount); + const before = await vault.balanceOf(receiver); await usdt.connect(lenderD).approve(vault.address, lenderFunding); await expect(vault.connect(lenderD).mintWithConsent(shares, receiver, consentHash)) .to.emit(vault, "ConsentRecorded") - .withArgs(receiver, receiver, consentHash); - expect(await vault.balanceOf(receiver)).to.equal(shares); + .withArgs(supplier, receiver, consentHash); + expect(await vault.balanceOf(receiver)).to.equal(before.add(shares)); }); it("depositWithConsent / mintWithConsent accept a zero consent hash without emitting", async () => { From 7e32cce7c2699599a76ee693a289502e4bd26773 Mon Sep 17 00:00:00 2001 From: fred-venus Date: Tue, 14 Jul 2026 17:04:15 +0800 Subject: [PATCH 6/9] feat: merge VIP-664 DAI market fix into the FRV consent VIP for joint execution Fold PR #737 (VDB-24: disable DeviationSentinel monitoring for DAI, resume vDAI borrowing, reset EBrake snapshots) into the mainnet VIP so both changes execute in a single proposal. - vips/vip-999/bscmainnet.ts: commands 1-5 = DAI fix (sentinel disable first, unpause BORROW, three EBrake snapshot resets), command 6 = FRV setVaultImplementation. No cap restore: EBrake never snapshotted vDAI caps (marketStates(vDAI) = (0,0,false,false) on-chain), live caps intact. - simulations/vip-999/bscmainnet.ts: fork block 109660000 (both pre-states verified on-chain: FRV controller on old impl, vDAI BORROW paused, sentinel monitoring on, EBrake snapshots empty); merged pre/post suites and event expectations; DAI behavioral borrow proof runs after the FRV lifecycle with Chainlink-pinned prices. 31 passing on bscmainnet fork. - ABIs: add Comptroller/DeviationSentinel/EBrake/VToken; ResilientOracle replaced by its superset from PR #737. Testnet VIP and sim unchanged (DAI fix is mainnet-only); 16 passing. Co-Authored-By: Claude Fable 5 --- simulations/vip-999/abi/Comptroller.json | 4145 +++++++++++++++++ .../vip-999/abi/DeviationSentinel.json | 589 +++ simulations/vip-999/abi/EBrake.json | 66 + simulations/vip-999/abi/ResilientOracle.json | 499 +- simulations/vip-999/abi/VToken.json | 870 ++++ simulations/vip-999/bscmainnet.ts | 157 +- vips/vip-999/bscmainnet.ts | 97 +- 7 files changed, 5998 insertions(+), 425 deletions(-) create mode 100644 simulations/vip-999/abi/Comptroller.json create mode 100644 simulations/vip-999/abi/DeviationSentinel.json create mode 100644 simulations/vip-999/abi/EBrake.json create mode 100644 simulations/vip-999/abi/VToken.json diff --git a/simulations/vip-999/abi/Comptroller.json b/simulations/vip-999/abi/Comptroller.json new file mode 100644 index 000000000..5ca3a7000 --- /dev/null +++ b/simulations/vip-999/abi/Comptroller.json @@ -0,0 +1,4145 @@ +[ + { + "inputs": [], + "name": "AlreadyInSelectedPool", + "type": "error" + }, + { + "inputs": [], + "name": "ArrayLengthMismatch", + "type": "error" + }, + { + "inputs": [], + "name": "BorrowNotAllowedInPool", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyPoolLabel", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "InactivePool", + "type": "error" + }, + { + "inputs": [], + "name": "IncompatibleBorrowedAssets", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidOperationForCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "enum WeightFunction", + "name": "strategy", + "type": "uint8" + } + ], + "name": "InvalidWeightingStrategy", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "errorCode", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "shortfall", + "type": "uint256" + } + ], + "name": "LiquidityCheckFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketAlreadyListed", + "type": "error" + }, + { + "inputs": [], + "name": "MarketConfigNotFound", + "type": "error" + }, + { + "inputs": [], + "name": "MarketNotListedInCorePool", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "PoolDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketNotFound", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "enum Action", + "name": "action", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bool", + "name": "pauseState", + "type": "bool" + } + ], + "name": "ActionPausedMarket", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "ActionProtocolPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "BorrowAllowedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "approver", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "DelegateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "venusSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "DistributedVAIVaultVenus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "error", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "info", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "detail", + "type": "uint256" + } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledForUserUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "IsForcedLiquidationEnabledUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketEntered", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "MarketExited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketListed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketUnlisted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "NewAccessControl", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newBorrowCap", + "type": "uint256" + } + ], + "name": "NewBorrowCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldCloseFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCloseFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldCollateralFactorMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + } + ], + "name": "NewCollateralFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldComptrollerLens", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newComptrollerLens", + "type": "address" + } + ], + "name": "NewComptrollerLens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationIncentiveMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationIncentive", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "oldLiquidationThresholdMantissa", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "NewLiquidationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldLiquidatorContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newLiquidatorContract", + "type": "address" + } + ], + "name": "NewLiquidatorContract", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldPauseGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "NewPauseGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "oldPriceOracle", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract ResilientOracleInterface", + "name": "newPriceOracle", + "type": "address" + } + ], + "name": "NewPriceOracle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract IPrime", + "name": "oldPrimeToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract IPrime", + "name": "newPrimeToken", + "type": "address" + } + ], + "name": "NewPrimeToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSupplyCap", + "type": "uint256" + } + ], + "name": "NewSupplyCap", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + } + ], + "name": "NewTreasuryAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldTreasuryGuardian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + } + ], + "name": "NewTreasuryGuardian", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldTreasuryPercent", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "NewTreasuryPercent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "oldVAIController", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract VAIControllerInterface", + "name": "newVAIController", + "type": "address" + } + ], + "name": "NewVAIController", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVAIMintRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "NewVAIMintRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "releaseInterval_", + "type": "uint256" + } + ], + "name": "NewVAIVaultInfo", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "oldVenusVAIVaultRate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newVenusVAIVaultRate", + "type": "uint256" + } + ], + "name": "NewVenusVAIVaultRate", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVS", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVS", + "type": "address" + } + ], + "name": "NewXVSToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldXVSVToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newXVSVToken", + "type": "address" + } + ], + "name": "NewXVSVToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolActiveStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "PoolCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "oldStatus", + "type": "bool" + }, + { + "indexed": false, + "internalType": "bool", + "name": "newStatus", + "type": "bool" + } + ], + "name": "PoolFallbackStatusUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "string", + "name": "oldLabel", + "type": "string" + }, + { + "indexed": false, + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "PoolLabelUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "PoolMarketInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "PoolMarketRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "previousPoolId", + "type": "uint96" + }, + { + "indexed": true, + "internalType": "uint96", + "name": "newPoolId", + "type": "uint96" + } + ], + "name": "PoolSelected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "VenusSeized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "VenusSupplySpeedUpdated", + "type": "event" + }, + { + "stateMutability": "nonpayable", + "type": "fallback" + }, + { + "inputs": [ + { + "internalType": "contract Unitroller", + "name": "unitroller", + "type": "address" + } + ], + "name": "_become", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "_grantXVS", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAccessControlAddress", + "type": "address" + } + ], + "name": "_setAccessControl", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "_setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "_setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "comptrollerLens_", + "type": "address" + } + ], + "name": "_setComptrollerLens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "_setForcedLiquidationForUser", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newLiquidatorContract_", + "type": "address" + } + ], + "name": "_setLiquidatorContract", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "_setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newPauseGuardian", + "type": "address" + } + ], + "name": "_setPauseGuardian", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "_setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "_setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "state", + "type": "bool" + } + ], + "name": "_setProtocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newTreasuryGuardian", + "type": "address" + }, + { + "internalType": "address", + "name": "newTreasuryAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newTreasuryPercent", + "type": "uint256" + } + ], + "name": "_setTreasuryData", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "vaiController_", + "type": "address" + } + ], + "name": "_setVAIController", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newVAIMintRate", + "type": "uint256" + } + ], + "name": "_setVAIMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vault_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "releaseStartBlock_", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minReleaseAmount_", + "type": "uint256" + } + ], + "name": "_setVAIVaultInfo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "_setVenusSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "venusVAIVaultRate_", + "type": "uint256" + } + ], + "name": "_setVenusVAIVaultRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvs_", + "type": "address" + } + ], + "name": "_setXVSToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "xvsVToken_", + "type": "address" + } + ], + "name": "_setXVSVToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "_supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "accountAssets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + }, + { + "internalType": "enum Action", + "name": "action", + "type": "uint8" + } + ], + "name": "actionPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96[]", + "name": "poolIds", + "type": "uint96[]" + }, + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "addPoolMarkets", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "allMarkets", + "outputs": [ + { + "internalType": "contract VToken", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "approvedDelegates", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowCapGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "borrowCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "borrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "checkMembership", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "collateral", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "borrowers", + "type": "bool" + }, + { + "internalType": "bool", + "name": "suppliers", + "type": "bool" + } + ], + "name": "claimVenus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimVenusAsCollateral", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactorMantissa", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptrollerLens", + "outputs": [ + { + "internalType": "contract ComptrollerLensInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "corePoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + } + ], + "name": "createPool", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut_", + "type": "tuple[]" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "enterMarkets", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "enterPool", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenAddress", + "type": "address" + } + ], + "name": "exitMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "uint96", + "name": "functionSelectorPosition", + "type": "uint96" + } + ], + "internalType": "struct ComptrollerV13Storage.FacetAddressAndPosition", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "facet", + "type": "address" + } + ], + "name": "facetPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct Diamond.Facet[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAllMarkets", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAssetsIn", + "outputs": [ + { + "internalType": "contract VToken[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getBorrowingPower", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getEffectiveLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "enum WeightFunction", + "name": "weightingStrategy", + "type": "uint8" + } + ], + "name": "getEffectiveLtvFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenModify", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowAmount", + "type": "uint256" + } + ], + "name": "getHypotheticalAccountLiquidity", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getLiquidationThreshold", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "getPoolMarketIndex", + "outputs": [ + { + "internalType": "PoolMarketId", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + } + ], + "name": "getPoolVTokens", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getXVSVTokenAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint96", + "name": "targetPoolId", + "type": "uint96" + } + ], + "name": "hasValidPoolBorrows", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isComptroller", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabled", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "isForcedLiquidationEnabledForUser", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "isMarketListed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lastPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "liquidateBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "liquidateBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateCalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + } + ], + "name": "liquidateVAICalculateSeizeTokens", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidatorContract", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "markets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxAssets", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "minReleaseAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "mintAmount", + "type": "uint256" + } + ], + "name": "mintAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "mintVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "minter", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualMintAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "mintTokens", + "type": "uint256" + } + ], + "name": "mintVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "mintedVAIs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pauseGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingComptrollerImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "poolMarkets", + "outputs": [ + { + "internalType": "bool", + "name": "isListed", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "collateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "isVenus", + "type": "bool" + }, + { + "internalType": "uint256", + "name": "liquidationThresholdMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "liquidationIncentiveMantissa", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "marketPoolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isBorrowAllowed", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "name": "pools", + "outputs": [ + { + "internalType": "string", + "name": "label", + "type": "string" + }, + { + "internalType": "bool", + "name": "isActive", + "type": "bool" + }, + { + "internalType": "bool", + "name": "allowCorePoolFallback", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prime", + "outputs": [ + { + "internalType": "contract IPrime", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "redeemer", + "type": "address" + }, + { + "internalType": "uint256", + "name": "redeemAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "redeemTokens", + "type": "uint256" + } + ], + "name": "redeemVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "releaseStartBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "removePoolMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "repayAmount", + "type": "uint256" + } + ], + "name": "repayBorrowAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "payer", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "actualRepayAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "borrowerIndex", + "type": "uint256" + } + ], + "name": "repayBorrowVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "repayVAIGuardianPaused", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "holders", + "type": "address[]" + }, + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "seizeVenus", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenCollateral", + "type": "address" + }, + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seizeVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "markets_", + "type": "address[]" + }, + { + "internalType": "enum Action[]", + "name": "actions_", + "type": "uint8[]" + }, + { + "internalType": "bool", + "name": "paused_", + "type": "bool" + } + ], + "name": "setActionsPaused", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "allowFallback", + "type": "bool" + } + ], + "name": "setAllowCorePoolFallback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "newCloseFactorMantissa", + "type": "uint256" + } + ], + "name": "setCloseFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newCollateralFactorMantissa", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newLiquidationThresholdMantissa", + "type": "uint256" + } + ], + "name": "setCollateralFactor", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vTokenBorrowed", + "type": "address" + }, + { + "internalType": "bool", + "name": "enable", + "type": "bool" + } + ], + "name": "setForcedLiquidation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "bool", + "name": "borrowAllowed", + "type": "bool" + } + ], + "name": "setIsBorrowAllowed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "uint256", + "name": "newLiquidationIncentiveMantissa", + "type": "uint256" + } + ], + "name": "setLiquidationIncentive", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newBorrowCaps", + "type": "uint256[]" + } + ], + "name": "setMarketBorrowCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "newSupplyCaps", + "type": "uint256[]" + } + ], + "name": "setMarketSupplyCaps", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "setMintedVAIOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "active", + "type": "bool" + } + ], + "name": "setPoolActive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "poolId", + "type": "uint96" + }, + { + "internalType": "string", + "name": "newLabel", + "type": "string" + } + ], + "name": "setPoolLabel", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract ResilientOracleInterface", + "name": "newOracle", + "type": "address" + } + ], + "name": "setPriceOracle", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IPrime", + "name": "_prime", + "type": "address" + } + ], + "name": "setPrimeToken", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "supplyCaps", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + } + ], + "name": "supportMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferAllowed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "transferTokens", + "type": "uint256" + } + ], + "name": "transferVerify", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryGuardian", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "treasuryPercent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "market", + "type": "address" + } + ], + "name": "unlistMarket", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "delegate", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "updateDelegate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "userPoolId", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiController", + "outputs": [ + { + "internalType": "contract VAIControllerInterface", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiMintRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vaiVaultAddress", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusInitialIndex", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "venusSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "venusVAIVaultRate", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-999/abi/DeviationSentinel.json b/simulations/vip-999/abi/DeviationSentinel.json new file mode 100644 index 000000000..c12ea017a --- /dev/null +++ b/simulations/vip-999/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-999/abi/EBrake.json b/simulations/vip-999/abi/EBrake.json new file mode 100644 index 000000000..7cd40dcde --- /dev/null +++ b/simulations/vip-999/abi/EBrake.json @@ -0,0 +1,66 @@ +[ + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "market", "type": "address" }], + "name": "BorrowCapSnapshotReset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "market", "type": "address" }], + "name": "CFSnapshotReset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "market", "type": "address" }], + "name": "SupplyCapSnapshotReset", + "type": "event" + }, + { + "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": "", "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": [{ "internalType": "address", "name": "market", "type": "address" }], + "name": "resetBorrowCapSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "market", "type": "address" }], + "name": "resetCFSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "market", "type": "address" }], + "name": "resetSupplyCapSnapshot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-999/abi/ResilientOracle.json b/simulations/vip-999/abi/ResilientOracle.json index 927d27526..373eb14e9 100644 --- a/simulations/vip-999/abi/ResilientOracle.json +++ b/simulations/vip-999/abi/ResilientOracle.json @@ -1,42 +1,18 @@ [ { "inputs": [ - { - "internalType": "address", - "name": "nativeMarketAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "vaiAddress", - "type": "address" - }, - { - "internalType": "contract BoundValidatorInterface", - "name": "_boundValidator", - "type": "address" - } + { "internalType": "address", "name": "nativeMarketAddress", "type": "address" }, + { "internalType": "address", "name": "vaiAddress", "type": "address" }, + { "internalType": "contract BoundValidatorInterface", "name": "_boundValidator", "type": "address" } ], "stateMutability": "nonpayable", "type": "constructor" }, { "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "calledContract", - "type": "address" - }, - { - "internalType": "string", - "name": "methodSignature", - "type": "string" - } + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "calledContract", "type": "address" }, + { "internalType": "string", "name": "methodSignature", "type": "string" } ], "name": "Unauthorized", "type": "error" @@ -44,31 +20,23 @@ { "anonymous": false, "inputs": [ - { - "indexed": false, - "internalType": "uint8", - "name": "version", - "type": "uint8" - } + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "bool", "name": "enabled", "type": "bool" } ], + "name": "CachedEnabled", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], "name": "Initialized", "type": "event" }, { "anonymous": false, "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "oldAccessControlManager", - "type": "address" - }, - { - "indexed": false, - "internalType": "address", - "name": "newAccessControlManager", - "type": "address" - } + { "indexed": false, "internalType": "address", "name": "oldAccessControlManager", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlManager", "type": "address" } ], "name": "NewAccessControlManager", "type": "event" @@ -76,24 +44,9 @@ { "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" - } + { "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" @@ -101,24 +54,9 @@ { "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" - } + { "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" @@ -126,18 +64,8 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } ], "name": "OwnershipTransferStarted", "type": "event" @@ -145,155 +73,76 @@ { "anonymous": false, "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } + { "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" - } - ], + "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" - } + { "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" - } - ], + "inputs": [{ "indexed": false, "internalType": "address", "name": "account", "type": "address" }], "name": "Unpaused", "type": "event" }, { "inputs": [], - "name": "INVALID_PRICE", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "name": "CACHE_SLOT", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "NATIVE_TOKEN_ADDR", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "name": "INVALID_PRICE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", + "name": "NATIVE_TOKEN_ADDR", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "accessControlManager", - "outputs": [ - { - "internalType": "contract IAccessControlManagerV8", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "boundValidator", - "outputs": [ - { - "internalType": "contract BoundValidatorInterface", - "name": "", - "type": "address" - } - ], + "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" - } + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" }, + { "internalType": "bool", "name": "enable", "type": "bool" } ], "name": "enableOracle", "outputs": [], @@ -302,84 +151,34 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - } + { "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" - } + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "bool", "name": "enabled", "type": "bool" } ], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], "name": "getPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], "name": "getTokenConfig", "outputs": [ { "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" - }, - { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" - }, - { - "internalType": "bool", - "name": "cachingEnabled", - "type": "bool" - } + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } ], "internalType": "struct ResilientOracle.TokenConfig", "name": "", @@ -390,32 +189,14 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], "name": "getUnderlyingPrice", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], "stateMutability": "view", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], "name": "initialize", "outputs": [], "stateMutability": "nonpayable", @@ -424,77 +205,35 @@ { "inputs": [], "name": "nativeMarket", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, - { - "inputs": [], - "name": "pause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, + { "inputs": [], "name": "pause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { "inputs": [], "name": "paused", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], "stateMutability": "view", "type": "function" }, { "inputs": [], "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "accessControlManager_", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], "name": "setAccessControlManager", "outputs": [], "stateMutability": "nonpayable", @@ -502,21 +241,9 @@ }, { "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address", - "name": "oracle", - "type": "address" - }, - { - "internalType": "enum ResilientOracle.OracleRole", - "name": "role", - "type": "uint8" - } + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address", "name": "oracle", "type": "address" }, + { "internalType": "enum ResilientOracle.OracleRole", "name": "role", "type": "uint8" } ], "name": "setOracle", "outputs": [], @@ -527,26 +254,10 @@ "inputs": [ { "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" - }, - { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" - }, - { - "internalType": "bool", - "name": "cachingEnabled", - "type": "bool" - } + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } ], "internalType": "struct ResilientOracle.TokenConfig", "name": "tokenConfig", @@ -562,26 +273,10 @@ "inputs": [ { "components": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - }, - { - "internalType": "address[3]", - "name": "oracles", - "type": "address[3]" - }, - { - "internalType": "bool[3]", - "name": "enableFlagsForOracles", - "type": "bool[3]" - }, - { - "internalType": "bool", - "name": "cachingEnabled", - "type": "bool" - } + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "address[3]", "name": "oracles", "type": "address[3]" }, + { "internalType": "bool[3]", "name": "enableFlagsForOracles", "type": "bool[3]" }, + { "internalType": "bool", "name": "cachingEnabled", "type": "bool" } ], "internalType": "struct ResilientOracle.TokenConfig[]", "name": "tokenConfigs_", @@ -594,46 +289,22 @@ "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], "name": "transferOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { "inputs": [], "name": "unpause", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [], - "name": "unpause", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "asset", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "asset", "type": "address" }], "name": "updateAssetPrice", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, { - "inputs": [ - { - "internalType": "address", - "name": "vToken", - "type": "address" - } - ], + "inputs": [{ "internalType": "address", "name": "vToken", "type": "address" }], "name": "updatePrice", "outputs": [], "stateMutability": "nonpayable", @@ -642,13 +313,7 @@ { "inputs": [], "name": "vai", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], "stateMutability": "view", "type": "function" } diff --git a/simulations/vip-999/abi/VToken.json b/simulations/vip-999/abi/VToken.json new file mode 100644 index 000000000..68f428c6c --- /dev/null +++ b/simulations/vip-999/abi/VToken.json @@ -0,0 +1,870 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "FlashLoanAlreadyActive", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "fee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" } + ], + "name": "FlashLoanFeeTooHigh", + "type": "error" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "fee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" } + ], + "name": "FlashLoanProtocolShareTooHigh", + "type": "error" + }, + { "inputs": [], "name": "InsufficientCash", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "actualAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "requiredTotalFee", "type": "uint256" } + ], + "name": "InsufficientRepayment", + "type": "error" + }, + { "inputs": [], "name": "InvalidComptroller", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "cashPrior", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "interestAccumulated", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "borrowIndex", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "AccrueInterest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "spender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "borrower", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "borrowAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "accountBorrows", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "Borrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "error", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "info", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "detail", "type": "uint256" } + ], + "name": "Failure", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldFlashLoanFeeMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newFlashLoanFeeMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "oldFlashLoanProtocolShare", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newFlashLoanProtocolShare", "type": "uint256" } + ], + "name": "FlashLoanFeeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "bool", "name": "previousStatus", "type": "bool" }, + { "indexed": false, "internalType": "bool", "name": "newStatus", "type": "bool" } + ], + "name": "FlashLoanStatusChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "liquidator", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "borrower", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "repayAmount", "type": "uint256" }, + { "indexed": false, "internalType": "address", "name": "vTokenCollateral", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "seizeTokens", "type": "uint256" } + ], + "name": "LiquidateBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "minter", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "mintAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "mintTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "Mint", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "payer", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "mintAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "mintTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "MintBehalf", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAccessControlAddress", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlAddress", "type": "address" } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAdmin", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "NewAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract ComptrollerInterface", + "name": "oldComptroller", + "type": "address" + }, + { "indexed": false, "internalType": "contract ComptrollerInterface", "name": "newComptroller", "type": "address" } + ], + "name": "NewComptroller", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "contract InterestRateModelV8", + "name": "oldInterestRateModel", + "type": "address" + }, + { + "indexed": false, + "internalType": "contract InterestRateModelV8", + "name": "newInterestRateModel", + "type": "address" + } + ], + "name": "NewMarketInterestRateModel", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldPendingAdmin", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newPendingAdmin", "type": "address" } + ], + "name": "NewPendingAdmin", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldProtocolShareReserve", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newProtocolShareReserve", "type": "address" } + ], + "name": "NewProtocolShareReserve", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldReduceReservesBlockDelta", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newReduceReservesBlockDelta", "type": "uint256" } + ], + "name": "NewReduceReservesBlockDelta", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldReserveFactorMantissa", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newReserveFactorMantissa", "type": "uint256" } + ], + "name": "NewReserveFactor", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "redeemer", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "redeemAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "redeemTokens", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalSupply", "type": "uint256" } + ], + "name": "Redeem", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "redeemer", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "feeAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "redeemTokens", "type": "uint256" } + ], + "name": "RedeemFee", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "payer", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "borrower", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "repayAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "accountBorrows", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalBorrows", "type": "uint256" } + ], + "name": "RepayBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "benefactor", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "addAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newTotalReserves", "type": "uint256" } + ], + "name": "ReservesAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "protocolShareReserve", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "reduceAmount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newTotalReserves", "type": "uint256" } + ], + "name": "ReservesReduced", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "totalFee", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "protocolFee", "type": "uint256" } + ], + "name": "TransferInUnderlyingFlashLoan", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "TransferOutUnderlyingFlashLoan", + "type": "event" + }, + { + "inputs": [], + "name": "_acceptAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "addAmount", "type": "uint256" }], + "name": "_addReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes", "name": "data", "type": "bytes" }], + "name": "_becomeImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "reduceAmount_", "type": "uint256" }], + "name": "_reduceReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { "inputs": [], "name": "_resignImplementation", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "contract ComptrollerInterface", "name": "newComptroller", "type": "address" }], + "name": "_setComptroller", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract InterestRateModelV8", "name": "newInterestRateModel_", "type": "address" }], + "name": "_setInterestRateModel", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address payable", "name": "newPendingAdmin", "type": "address" }], + "name": "_setPendingAdmin", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "newReserveFactorMantissa_", "type": "uint256" }], + "name": "_setReserveFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrualBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "accrueInterest", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "admin", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "spender", "type": "address" } + ], + "name": "allowance", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "spender", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "approve", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "balanceOfUnderlying", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "borrowAmount", "type": "uint256" }], + "name": "borrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "borrowBalanceCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "borrowBalanceStored", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "borrowAmount", "type": "uint256" } + ], + "name": "borrowBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "borrowIndex", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "amount", "type": "uint256" }], + "name": "calculateFlashLoanFee", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [{ "internalType": "contract ComptrollerInterface", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [{ "internalType": "uint8", "name": "", "type": "uint8" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanAmount", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "borrowAmount", "type": "uint256" } + ], + "name": "flashLoanDebtPosition", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanFeeMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "flashLoanProtocolShareMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "account", "type": "address" }], + "name": "getAccountSnapshot", + "outputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "underlying_", "type": "address" }, + { "internalType": "contract ComptrollerInterface", "name": "comptroller_", "type": "address" }, + { "internalType": "contract InterestRateModelV8", "name": "interestRateModel_", "type": "address" }, + { "internalType": "uint256", "name": "initialExchangeRateMantissa_", "type": "uint256" }, + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "uint8", "name": "decimals_", "type": "uint8" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract ComptrollerInterface", "name": "comptroller_", "type": "address" }, + { "internalType": "contract InterestRateModelV8", "name": "interestRateModel_", "type": "address" }, + { "internalType": "uint256", "name": "initialExchangeRateMantissa_", "type": "uint256" }, + { "internalType": "string", "name": "name_", "type": "string" }, + { "internalType": "string", "name": "symbol_", "type": "string" }, + { "internalType": "uint8", "name": "decimals_", "type": "uint8" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "interestRateModel", + "outputs": [{ "internalType": "contract InterestRateModelV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isFlashLoanEnabled", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isVToken", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "repayAmount", "type": "uint256" }, + { "internalType": "contract VTokenInterface", "name": "vTokenCollateral", "type": "address" } + ], + "name": "liquidateBorrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "mintAmount", "type": "uint256" }], + "name": "mint", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "receiver", "type": "address" }, + { "internalType": "uint256", "name": "mintAmount", "type": "uint256" } + ], + "name": "mintBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingAdmin", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [{ "internalType": "address payable", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "redeemTokens", "type": "uint256" }], + "name": "redeem", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "redeemer", "type": "address" }, + { "internalType": "uint256", "name": "redeemTokens", "type": "uint256" } + ], + "name": "redeemBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "redeemAmount", "type": "uint256" }], + "name": "redeemUnderlying", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "redeemer", "type": "address" }, + { "internalType": "uint256", "name": "redeemAmount", "type": "uint256" } + ], + "name": "redeemUnderlyingBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockDelta", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "reduceReservesBlockNumber", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "repayAmount", "type": "uint256" }], + "name": "repayBorrow", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "repayAmount", "type": "uint256" } + ], + "name": "repayBorrowBehalf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "reserveFactorMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "liquidator", "type": "address" }, + { "internalType": "address", "name": "borrower", "type": "address" }, + { "internalType": "uint256", "name": "seizeTokens", "type": "uint256" } + ], + "name": "seize", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newAccessControlManagerAddress", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bool", "name": "enabled", "type": "bool" }], + "name": "setFlashLoanEnabled", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "flashLoanFeeMantissa_", "type": "uint256" }, + { "internalType": "uint256", "name": "flashLoanProtocolShare_", "type": "uint256" } + ], + "name": "setFlashLoanFeeMantissa", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address payable", "name": "protcolShareReserve_", "type": "address" }], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "newReduceReservesBlockDelta_", "type": "uint256" }], + "name": "setReduceReservesBlockDelta", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrows", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "src", "type": "address" }, + { "internalType": "address", "name": "dst", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "from", "type": "address" }, + { "internalType": "uint256", "name": "repaymentAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "totalFee", "type": "uint256" }, + { "internalType": "uint256", "name": "protocolFee", "type": "uint256" } + ], + "name": "transferInUnderlyingFlashLoan", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address payable", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "transferOutUnderlyingFlashLoan", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "underlying", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-999/bscmainnet.ts b/simulations/vip-999/bscmainnet.ts index 18cf6abab..05d955d4f 100644 --- a/simulations/vip-999/bscmainnet.ts +++ b/simulations/vip-999/bscmainnet.ts @@ -7,38 +7,86 @@ import { expectEvents, initMainnetUser, pinResilientOraclePriceViaRedstone } fro import { forking, testVip } from "src/vip-framework"; import vip999, { + BORROW, + DAI, + DEVIATION_SENTINEL, + EBRAKE, FIXED_RATE_VAULT_CONTROLLER, NEW_VAULT_IMPLEMENTATION, OLD_VAULT_IMPLEMENTATION, + vDAI, } from "../../vips/vip-999/bscmainnet"; +import COMPTROLLER_ABI from "./abi/Comptroller.json"; +import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; +import EBRAKE_ABI from "./abi/EBrake.json"; import ERC20_ABI from "./abi/ERC20.json"; import VAULT_ABI from "./abi/InstitutionalLoanVault.json"; import CONTROLLER_ABI from "./abi/InstitutionalVaultController.json"; import ORACLE_ABI from "./abi/ResilientOracle.json"; +import VTOKEN_ABI from "./abi/VToken.json"; const { bscmainnet } = NETWORK_ADDRESSES; -const FORK_BLOCK = 109158500; +// Block shortly before the proposal — vDAI borrowing is paused, the sentinel still monitors DAI, +// the EBrake snapshots for vDAI are empty (the weekend incident only paused borrowing), and the +// FRV controller still clones the old (pre-consent) vault implementation. +const FORK_BLOCK = 109660000; const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; const USDT = "0x55d398326f99059fF775485246999027B3197955"; const WHALE = "0xF977814e90dA44bFA03b6295A0616a897441aceC"; +// A trusted keeper on the DeviationSentinel (verified on-chain) — used to call handleDeviation. +const GUARDIAN = "0x1C2CAc6ec528c20800B2fe734820D87b581eAA6B"; +// Collateral market used to prove borrowing DAI works again (vUSDT has a non-zero collateral factor). +const vUSDT = "0xfD5840Cd36d94D7229439859C0112a4185BC0255"; +// Core Pool id for the CF snapshot read on EBrake. +const CORE_POOL_ID = 0; + forking(FORK_BLOCK, async () => { + const comptroller = new ethers.Contract(bscmainnet.UNITROLLER, COMPTROLLER_ABI, ethers.provider); + const deviationSentinel = new ethers.Contract(DEVIATION_SENTINEL, DEVIATION_SENTINEL_ABI, ethers.provider); + const ebrake = new ethers.Contract(EBRAKE, EBRAKE_ABI, ethers.provider); + let controller: Contract; + let resilientOracle: Contract; let timelock: any; let vaultsBefore: BigNumber; + // DAI and USDT prices captured at the fork block (before the governance lifecycle warps time and + // makes the RedStone pivot feed stale) so the behavioral DAI borrow can pin them via the Chainlink feed. + let daiPrice: BigNumber; + let usdtPrice: BigNumber; + before(async () => { controller = await ethers.getContractAt(CONTROLLER_ABI, FIXED_RATE_VAULT_CONTROLLER); timelock = await initMainnetUser(bscmainnet.NORMAL_TIMELOCK, parseUnits("40")); vaultsBefore = await controller.allVaultsLength(); - const resilientOracle = await ethers.getContractAt(ORACLE_ABI, bscmainnet.RESILIENT_ORACLE); + resilientOracle = await ethers.getContractAt(ORACLE_ABI, bscmainnet.RESILIENT_ORACLE); + daiPrice = await resilientOracle.getPrice(DAI); + usdtPrice = await resilientOracle.getPrice(USDT); + await pinResilientOraclePriceViaRedstone(resilientOracle, BTCB); await pinResilientOraclePriceViaRedstone(resilientOracle, USDT); }); + // Repoint an asset to the Chainlink feed as the sole ResilientOracle source and pin an exact price. + const pinPriceViaChainlink = async (asset: string, price: BigNumber) => { + await resilientOracle.connect(timelock).setTokenConfig({ + asset, + oracles: [bscmainnet.CHAINLINK_ORACLE, ethers.constants.AddressZero, ethers.constants.AddressZero], + enableFlagsForOracles: [true, false, false], + cachingEnabled: false, + }); + const chainlinkOracle = new ethers.Contract( + bscmainnet.CHAINLINK_ORACLE, + ["function setDirectPrice(address,uint256)"], + timelock, + ); + await chainlinkOracle.setDirectPrice(asset, price); + }; + describe("Pre-VIP behavior", () => { it("controller still clones the old vault implementation", async () => { expect(await controller.vaultImplementation()).to.equal(OLD_VAULT_IMPLEMENTATION); @@ -56,10 +104,49 @@ forking(FORK_BLOCK, async () => { expect(newCode, "new impl should expose the consent entrypoints").to.include(selector); } }); + + it("borrowing is paused on the vDAI market", async () => { + expect(await comptroller.actionPaused(vDAI, BORROW)).to.equal(true); + }); + + it("vDAI collateral factor is 0", async () => { + const market = await comptroller.markets(vDAI); + expect(market.collateralFactorMantissa).to.equal(0); + }); + + it("DeviationSentinel monitors DAI (enabled, deviation 10%)", async () => { + const config = await deviationSentinel.tokenConfigs(DAI); + expect(config.enabled).to.equal(true); + expect(config.deviation).to.equal(10); + }); + + it("EBrake holds no collateral-factor snapshot for vDAI", async () => { + const [cf, lt] = await ebrake.getMarketCFSnapshot(vDAI, CORE_POOL_ID); + expect(cf).to.equal(0); + expect(lt).to.equal(0); + }); + + it("EBrake holds no cap snapshots for vDAI", async () => { + const state = await ebrake.marketStates(vDAI); + expect(state.borrowCapSnapshotted).to.equal(false); + expect(state.supplyCapSnapshotted).to.equal(false); + }); }); - testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999(), { + testVip("VIP-999 Fix DAI market + upgrade Institutional Fixed Rate Vault implementation", await vip999(), { callbackAfterExecution: async txResponse => { + // Monitoring toggled off for DAI on the DeviationSentinel. + await expectEvents(txResponse, [DEVIATION_SENTINEL_ABI], ["TokenMonitoringStatusChanged"], [1]); + // Borrow action unpaused on the Core Pool Comptroller for vDAI. + await expectEvents(txResponse, [COMPTROLLER_ABI], ["ActionPausedMarket"], [1]); + // Three EBrake snapshots reset for vDAI. + await expectEvents( + txResponse, + [EBRAKE_ABI], + ["CFSnapshotReset", "BorrowCapSnapshotReset", "SupplyCapSnapshotReset"], + [1, 1, 1], + ); + // FRV clone source upgraded on the controller. await expectEvents(txResponse, [CONTROLLER_ABI], ["VaultImplementationUpdated"], [1]); }, }); @@ -68,6 +155,30 @@ forking(FORK_BLOCK, async () => { it("controller now clones the new vault implementation", async () => { expect(await controller.vaultImplementation()).to.equal(NEW_VAULT_IMPLEMENTATION); }); + + it("borrowing is resumed on the vDAI market", async () => { + expect(await comptroller.actionPaused(vDAI, BORROW)).to.equal(false); + }); + + it("vDAI collateral factor is unchanged (0)", async () => { + const market = await comptroller.markets(vDAI); + expect(market.collateralFactorMantissa).to.equal(0); + }); + + it("DeviationSentinel no longer monitors DAI (deviation config preserved)", async () => { + const config = await deviationSentinel.tokenConfigs(DAI); + expect(config.enabled).to.equal(false); + expect(config.deviation).to.equal(10); + }); + + it("EBrake snapshots for vDAI remain empty", async () => { + const [cf, lt] = await ebrake.getMarketCFSnapshot(vDAI, CORE_POOL_ID); + expect(cf).to.equal(0); + expect(lt).to.equal(0); + const state = await ebrake.marketStates(vDAI); + expect(state.borrowCapSnapshotted).to.equal(false); + expect(state.supplyCapSnapshotted).to.equal(false); + }); }); describe("New vault: deposit/mint with consent + normal flow", () => { @@ -267,4 +378,44 @@ forking(FORK_BLOCK, async () => { expect(await btcb.balanceOf(vault.address)).to.equal(0); }); }); + + describe("Post-VIP behavioral proof: DAI market", () => { + it("a user with collateral can borrow DAI, and the sentinel can no longer act on vDAI", async () => { + const dai = new ethers.Contract(DAI, ERC20_ABI, ethers.provider); + const usdt = new ethers.Contract(USDT, ERC20_ABI, ethers.provider); + const vUsdt = new ethers.Contract(vUSDT, VTOKEN_ABI, ethers.provider); + const vDai = new ethers.Contract(vDAI, VTOKEN_ABI, ethers.provider); + + // The mined governance lifecycle and the FRV vault lifecycle advance time, staling DAI/USDT's + // RedStone pivot feed (its internal guard cannot be widened). Repoint both to the Chainlink feed + // as the single source and pin the price captured at the fork block, so the borrow path prices + // don't revert. + await pinPriceViaChainlink(DAI, daiPrice); + await pinPriceViaChainlink(USDT, usdtPrice); + + const user = await initMainnetUser("0x000000000000000000000000000000000000dEaD", parseUnits("10")); + const whale = await initMainnetUser(WHALE, parseUnits("10")); + + // Fund the user with USDT collateral and supply it. + const collateral = parseUnits("1000", 18); + await usdt.connect(whale).transfer(user.address, collateral); + await usdt.connect(user).approve(vUSDT, collateral); + await vUsdt.connect(user).mint(collateral); + await comptroller.connect(user).enterMarkets([vUSDT]); + + // Borrow a small amount of DAI — previously reverted on the borrow-paused guard. + const borrowAmount = parseUnits("100", 18); + const daiBefore = await dai.balanceOf(user.address); + await expect(vDai.connect(user).borrow(borrowAmount)).to.not.be.reverted; + expect(await dai.balanceOf(user.address)).to.equal(daiBefore.add(borrowAmount)); + expect(await vDai.callStatic.borrowBalanceCurrent(user.address)).to.be.gte(borrowAmount); + + // With monitoring disabled, a trusted keeper can no longer act on the vDAI market. + const keeper = await initMainnetUser(GUARDIAN, parseUnits("10")); + await expect(deviationSentinel.connect(keeper).handleDeviation(vDAI)).to.be.revertedWithCustomError( + deviationSentinel, + "TokenMonitoringDisabled", + ); + }); + }); }); diff --git a/vips/vip-999/bscmainnet.ts b/vips/vip-999/bscmainnet.ts index 1567f7ed6..e261a732e 100644 --- a/vips/vip-999/bscmainnet.ts +++ b/vips/vip-999/bscmainnet.ts @@ -1,6 +1,23 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { ProposalType } from "src/types"; import { makeProposal } from "src/utils"; +const { bscmainnet } = NETWORK_ADDRESSES; + +// ── DAI market fix (VDB-24) ──────────────────────────────────────────────── +// Core Pool market and its underlying +export const vDAI = "0x334b3eCB4DCa3593BCCC3c7EBD1A1C1d1780FBF1"; +export const DAI = "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3"; + +// DeviationSentinel proxy (deployed in VIP-590, EBrake-integrated impl since VIP-610) +export const DEVIATION_SENTINEL = "0x6599C15cc8407046CD91E5c0F8B7f765fF914870"; +// Emergency Brake (EBrakeV2) — holds the pre-incident CF/cap snapshots (VIP-610) +export const EBRAKE = "0x35eBaBB99c7Fb7ba0C90bCc26e5d55Cdf89C23Ec"; + +// Comptroller Action enum: BORROW +export const BORROW = 2; + +// ── Institutional Fixed Rate Vault implementation upgrade (VPD-1596) ─────── export const FIXED_RATE_VAULT_CONTROLLER = "0x6D9e91cB766259af42619c14c994E694E57e6E85"; export const OLD_VAULT_IMPLEMENTATION = "0xC25b2B657D24380eDd1a1Cff5296385541e85204"; @@ -10,12 +27,38 @@ export const NEW_VAULT_IMPLEMENTATION = "0xe87A1eFCED88bBddf8CCF78EfB3bCF62cFdd5 export const vip999 = () => { const meta = { version: "v2", - title: "VIP-999 [BNB Chain] Upgrade Institutional Fixed Rate Vault implementation (consent recording)", + title: + "VIP-999 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing) and upgrade Institutional Fixed Rate Vault implementation", description: `#### Summary -If passed, this VIP points the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. +If passed, this VIP will (1) stop the DeviationSentinel from monitoring DAI, resume borrowing on the vDAI market and clear the related Emergency Brake snapshots, and (2) point the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. + +#### Part 1 — Fix the DAI market + +DAI has thin, volatile DEX liquidity on BNB Chain. Because the DEX price of DAI is chronically noisy relative to the ResilientOracle price, the DeviationSentinel has repeatedly tripped false positives on the DAI market — most recently over the weekend, pausing borrowing on the vDAI market. As reliably configuring a deviation threshold for such a shallow pool is not practical, the risk team has decided to stop monitoring DAI with the DeviationSentinel. + +**1. Disable DeviationSentinel monitoring for DAI** -#### Description +- **Contract**: DeviationSentinel (${DEVIATION_SENTINEL}) +- **Function**: setTokenMonitoringEnabled(address,bool) +- **Parameters**: token = DAI (${DAI}), enabled = false +- **Effect**: handleDeviation can no longer act on the vDAI market (it reverts TokenMonitoringDisabled). The stored deviation threshold for DAI is left unchanged. This is ordered first so the market cannot be re-tripped around execution. + +**2. Resume borrowing on vDAI** + +- **Contract**: Core Pool Comptroller (${bscmainnet.UNITROLLER}) +- **Function**: setActionsPaused(address[],uint8[],bool) +- **Parameters**: markets = [vDAI], actions = [BORROW (2)], paused = false +- **Effect**: Users can borrow DAI again. The collateral factor of vDAI is **not** changed by this VIP: its pre-incident collateral factor was already 0 (which is why the EBrake collateral-factor snapshot for vDAI is empty — the sentinel only paused borrowing, it never lowered a non-zero collateral factor), so there is no collateral factor to restore. Likewise the borrow and supply caps were never reduced by EBrake (both cap snapshots are empty and the live caps are intact), so there are no caps to restore. + +**3. Reset the DAI snapshots on EBrake** + +- **Contract**: EBrake (${EBRAKE}) +- **Functions**: resetCFSnapshot(address), resetBorrowCapSnapshot(address), resetSupplyCapSnapshot(address) +- **Parameters**: market = vDAI +- **Effect**: Clears any stored collateral-factor / borrow-cap / supply-cap snapshot for the vDAI market so EBrake tracks no residual state for DAI after monitoring is disabled. + +#### Part 2 — Upgrade the Institutional Fixed Rate Vault implementation (consent recording) The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RATE_VAULT_CONTROLLER}) to clone new vaults is upgraded from ${OLD_VAULT_IMPLEMENTATION} to ${NEW_VAULT_IMPLEMENTATION}. The new implementation adds two supplier entrypoints: @@ -24,9 +67,9 @@ The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RA The consent hash is optional: passing \`bytes32(0)\` skips the event and deposits/mints as usual. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. -#### Actions +- **Action**: point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. -- Point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. +No new AccessControlManager permissions are required — the Normal Timelock already holds all of the roles used by this proposal. #### Voting options @@ -40,6 +83,50 @@ The consent hash is optional: passing \`bytes32(0)\` skips the event and deposit return makeProposal( [ + // ──────────────────────────────────────────────────────────────────────── + // Part 1.1 — Disable DeviationSentinel monitoring for DAI (ordered first so + // the vDAI market cannot be re-tripped around execution). + // ──────────────────────────────────────────────────────────────────────── + { + target: DEVIATION_SENTINEL, + signature: "setTokenMonitoringEnabled(address,bool)", + params: [DAI, false], + }, + + // ──────────────────────────────────────────────────────────────────────── + // Part 1.2 — Resume borrowing on the vDAI market. No collateral-factor or + // cap commands: the pre-incident collateral factor was already 0 and the + // caps were never reduced (all EBrake snapshots for vDAI are empty). + // ──────────────────────────────────────────────────────────────────────── + { + target: bscmainnet.UNITROLLER, + signature: "setActionsPaused(address[],uint8[],bool)", + params: [[vDAI], [BORROW], false], + }, + + // ──────────────────────────────────────────────────────────────────────── + // Part 1.3 — Reset the EBrake snapshots for vDAI (clean, pre-incident slate). + // ──────────────────────────────────────────────────────────────────────── + { + target: EBRAKE, + signature: "resetCFSnapshot(address)", + params: [vDAI], + }, + { + target: EBRAKE, + signature: "resetBorrowCapSnapshot(address)", + params: [vDAI], + }, + { + target: EBRAKE, + signature: "resetSupplyCapSnapshot(address)", + params: [vDAI], + }, + + // ──────────────────────────────────────────────────────────────────────── + // Part 2 — Point the FRV controller at the consent-enabled vault + // implementation. Only affects vaults cloned from now on. + // ──────────────────────────────────────────────────────────────────────── { target: FIXED_RATE_VAULT_CONTROLLER, signature: "setVaultImplementation(address)", From 113dbb57a6ef3a4b69ba9342c4e4a6fdffcd6a8d Mon Sep 17 00:00:00 2001 From: fred-venus Date: Tue, 14 Jul 2026 17:48:28 +0800 Subject: [PATCH 7/9] chore: prepare VIP-644 for proposal Renumber vip-999 placeholder to VIP-644 (on-chain proposalCount 642; 643 reserved for the preceding proposal). Mainnet simulation re-run: 31 passing. Co-Authored-By: Claude Fable 5 --- simulations/{vip-999 => vip-644}/abi/Comptroller.json | 0 simulations/{vip-999 => vip-644}/abi/DeviationSentinel.json | 0 simulations/{vip-999 => vip-644}/abi/EBrake.json | 0 simulations/{vip-999 => vip-644}/abi/ERC20.json | 0 simulations/{vip-999 => vip-644}/abi/FaucetToken.json | 0 .../{vip-999 => vip-644}/abi/InstitutionalLoanVault.json | 0 .../abi/InstitutionalVaultController.json | 0 simulations/{vip-999 => vip-644}/abi/ResilientOracle.json | 0 simulations/{vip-999 => vip-644}/abi/VToken.json | 0 simulations/{vip-999 => vip-644}/bscmainnet.ts | 6 +++--- simulations/{vip-999 => vip-644}/bsctestnet.ts | 6 +++--- vips/{vip-999 => vip-644}/bscmainnet.ts | 6 +++--- vips/{vip-999 => vip-644}/bsctestnet.ts | 6 +++--- 13 files changed, 12 insertions(+), 12 deletions(-) rename simulations/{vip-999 => vip-644}/abi/Comptroller.json (100%) rename simulations/{vip-999 => vip-644}/abi/DeviationSentinel.json (100%) rename simulations/{vip-999 => vip-644}/abi/EBrake.json (100%) rename simulations/{vip-999 => vip-644}/abi/ERC20.json (100%) rename simulations/{vip-999 => vip-644}/abi/FaucetToken.json (100%) rename simulations/{vip-999 => vip-644}/abi/InstitutionalLoanVault.json (100%) rename simulations/{vip-999 => vip-644}/abi/InstitutionalVaultController.json (100%) rename simulations/{vip-999 => vip-644}/abi/ResilientOracle.json (100%) rename simulations/{vip-999 => vip-644}/abi/VToken.json (100%) rename simulations/{vip-999 => vip-644}/bscmainnet.ts (99%) rename simulations/{vip-999 => vip-644}/bsctestnet.ts (98%) rename vips/{vip-999 => vip-644}/bscmainnet.ts (98%) rename vips/{vip-999 => vip-644}/bsctestnet.ts (95%) diff --git a/simulations/vip-999/abi/Comptroller.json b/simulations/vip-644/abi/Comptroller.json similarity index 100% rename from simulations/vip-999/abi/Comptroller.json rename to simulations/vip-644/abi/Comptroller.json diff --git a/simulations/vip-999/abi/DeviationSentinel.json b/simulations/vip-644/abi/DeviationSentinel.json similarity index 100% rename from simulations/vip-999/abi/DeviationSentinel.json rename to simulations/vip-644/abi/DeviationSentinel.json diff --git a/simulations/vip-999/abi/EBrake.json b/simulations/vip-644/abi/EBrake.json similarity index 100% rename from simulations/vip-999/abi/EBrake.json rename to simulations/vip-644/abi/EBrake.json diff --git a/simulations/vip-999/abi/ERC20.json b/simulations/vip-644/abi/ERC20.json similarity index 100% rename from simulations/vip-999/abi/ERC20.json rename to simulations/vip-644/abi/ERC20.json diff --git a/simulations/vip-999/abi/FaucetToken.json b/simulations/vip-644/abi/FaucetToken.json similarity index 100% rename from simulations/vip-999/abi/FaucetToken.json rename to simulations/vip-644/abi/FaucetToken.json diff --git a/simulations/vip-999/abi/InstitutionalLoanVault.json b/simulations/vip-644/abi/InstitutionalLoanVault.json similarity index 100% rename from simulations/vip-999/abi/InstitutionalLoanVault.json rename to simulations/vip-644/abi/InstitutionalLoanVault.json diff --git a/simulations/vip-999/abi/InstitutionalVaultController.json b/simulations/vip-644/abi/InstitutionalVaultController.json similarity index 100% rename from simulations/vip-999/abi/InstitutionalVaultController.json rename to simulations/vip-644/abi/InstitutionalVaultController.json diff --git a/simulations/vip-999/abi/ResilientOracle.json b/simulations/vip-644/abi/ResilientOracle.json similarity index 100% rename from simulations/vip-999/abi/ResilientOracle.json rename to simulations/vip-644/abi/ResilientOracle.json diff --git a/simulations/vip-999/abi/VToken.json b/simulations/vip-644/abi/VToken.json similarity index 100% rename from simulations/vip-999/abi/VToken.json rename to simulations/vip-644/abi/VToken.json diff --git a/simulations/vip-999/bscmainnet.ts b/simulations/vip-644/bscmainnet.ts similarity index 99% rename from simulations/vip-999/bscmainnet.ts rename to simulations/vip-644/bscmainnet.ts index 05d955d4f..5f603264a 100644 --- a/simulations/vip-999/bscmainnet.ts +++ b/simulations/vip-644/bscmainnet.ts @@ -6,7 +6,7 @@ import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { expectEvents, initMainnetUser, pinResilientOraclePriceViaRedstone } from "src/utils"; import { forking, testVip } from "src/vip-framework"; -import vip999, { +import vip644, { BORROW, DAI, DEVIATION_SENTINEL, @@ -15,7 +15,7 @@ import vip999, { NEW_VAULT_IMPLEMENTATION, OLD_VAULT_IMPLEMENTATION, vDAI, -} from "../../vips/vip-999/bscmainnet"; +} from "../../vips/vip-644/bscmainnet"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; import EBRAKE_ABI from "./abi/EBrake.json"; @@ -133,7 +133,7 @@ forking(FORK_BLOCK, async () => { }); }); - testVip("VIP-999 Fix DAI market + upgrade Institutional Fixed Rate Vault implementation", await vip999(), { + testVip("VIP-644 Fix DAI market + upgrade Institutional Fixed Rate Vault implementation", await vip644(), { callbackAfterExecution: async txResponse => { // Monitoring toggled off for DAI on the DeviationSentinel. await expectEvents(txResponse, [DEVIATION_SENTINEL_ABI], ["TokenMonitoringStatusChanged"], [1]); diff --git a/simulations/vip-999/bsctestnet.ts b/simulations/vip-644/bsctestnet.ts similarity index 98% rename from simulations/vip-999/bsctestnet.ts rename to simulations/vip-644/bsctestnet.ts index d6c8a1b91..d6f89351a 100644 --- a/simulations/vip-999/bsctestnet.ts +++ b/simulations/vip-644/bsctestnet.ts @@ -6,11 +6,11 @@ import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { expectEvents, initMainnetUser } from "src/utils"; import { forking, testVip } from "src/vip-framework"; -import vip999, { +import vip644, { FIXED_RATE_VAULT_CONTROLLER, NEW_VAULT_IMPLEMENTATION, OLD_VAULT_IMPLEMENTATION, -} from "../../vips/vip-999/bsctestnet"; +} from "../../vips/vip-644/bsctestnet"; import ERC20_ABI from "./abi/ERC20.json"; import FAUCET_TOKEN_ABI from "./abi/FaucetToken.json"; import VAULT_ABI from "./abi/InstitutionalLoanVault.json"; @@ -50,7 +50,7 @@ forking(FORK_BLOCK, async () => { }); }); - testVip("VIP-999 Upgrade Institutional Fixed Rate Vault implementation", await vip999(), { + testVip("VIP-644 Upgrade Institutional Fixed Rate Vault implementation", await vip644(), { callbackAfterExecution: async txResponse => { await expectEvents(txResponse, [CONTROLLER_ABI], ["VaultImplementationUpdated"], [1]); }, diff --git a/vips/vip-999/bscmainnet.ts b/vips/vip-644/bscmainnet.ts similarity index 98% rename from vips/vip-999/bscmainnet.ts rename to vips/vip-644/bscmainnet.ts index e261a732e..81e8d59dd 100644 --- a/vips/vip-999/bscmainnet.ts +++ b/vips/vip-644/bscmainnet.ts @@ -24,11 +24,11 @@ export const OLD_VAULT_IMPLEMENTATION = "0xC25b2B657D24380eDd1a1Cff5296385541e85 // Adds depositWithConsent / mintWithConsent. export const NEW_VAULT_IMPLEMENTATION = "0xe87A1eFCED88bBddf8CCF78EfB3bCF62cFdd5bdC"; -export const vip999 = () => { +export const vip644 = () => { const meta = { version: "v2", title: - "VIP-999 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing) and upgrade Institutional Fixed Rate Vault implementation", + "VIP-644 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing) and upgrade Institutional Fixed Rate Vault implementation", description: `#### Summary If passed, this VIP will (1) stop the DeviationSentinel from monitoring DAI, resume borrowing on the vDAI market and clear the related Emergency Brake snapshots, and (2) point the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. @@ -138,4 +138,4 @@ No new AccessControlManager permissions are required — the Normal Timelock alr ); }; -export default vip999; +export default vip644; diff --git a/vips/vip-999/bsctestnet.ts b/vips/vip-644/bsctestnet.ts similarity index 95% rename from vips/vip-999/bsctestnet.ts rename to vips/vip-644/bsctestnet.ts index 1f0e007d3..df99e99fa 100644 --- a/vips/vip-999/bsctestnet.ts +++ b/vips/vip-644/bsctestnet.ts @@ -7,10 +7,10 @@ export const OLD_VAULT_IMPLEMENTATION = "0x97421799419Eb782628e73e7220d8E0A20746 // Adds depositWithConsent / mintWithConsent. export const NEW_VAULT_IMPLEMENTATION = "0xB677627eB4B9D8bfB793966e266C899E7FD484C5"; -export const vip999 = () => { +export const vip644 = () => { const meta = { version: "v2", - title: "VIP-999 [BNB Chain Testnet] Upgrade Institutional Fixed Rate Vault implementation (consent recording)", + title: "VIP-644 [BNB Chain Testnet] Upgrade Institutional Fixed Rate Vault implementation (consent recording)", description: `#### Summary If passed, this VIP points the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. @@ -51,4 +51,4 @@ The consent hash is optional: passing \`bytes32(0)\` skips the event and deposit ); }; -export default vip999; +export default vip644; From f3165a37881b21ac1bb921c142ba12c7ef7d9f22 Mon Sep 17 00:00:00 2001 From: fred-venus Date: Wed, 15 Jul 2026 10:42:33 +0800 Subject: [PATCH 8/9] feat: pay Allez Labs 105,000 USDC for Q3 2026 via vUSDC redemption Treasury liquid USDC (~86K) does not cover the payment, so vUSDC is redeemed through the TokenRedeemer (VIP-594 flow): withdraw 3.96M vUSDC to the redeemer, redeemUnderlyingAndTransfer exactly 105,000 USDC to Allez Labs, remainder vUSDC returned to the treasury. Co-Authored-By: Claude Fable 5 --- simulations/vip-644/bscmainnet.ts | 42 ++++++++++++++++++++++++ vips/vip-644/bscmainnet.ts | 54 +++++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/simulations/vip-644/bscmainnet.ts b/simulations/vip-644/bscmainnet.ts index 5f603264a..8809550e8 100644 --- a/simulations/vip-644/bscmainnet.ts +++ b/simulations/vip-644/bscmainnet.ts @@ -7,6 +7,8 @@ import { expectEvents, initMainnetUser, pinResilientOraclePriceViaRedstone } fro import { forking, testVip } from "src/vip-framework"; import vip644, { + ALLEZ_LABS, + ALLEZ_LABS_USDC_AMOUNT, BORROW, DAI, DEVIATION_SENTINEL, @@ -14,7 +16,11 @@ import vip644, { FIXED_RATE_VAULT_CONTROLLER, NEW_VAULT_IMPLEMENTATION, OLD_VAULT_IMPLEMENTATION, + TOKEN_REDEEMER, + USDC, + VUSDC_WITHDRAW_AMOUNT, vDAI, + vUSDC, } from "../../vips/vip-644/bscmainnet"; import COMPTROLLER_ABI from "./abi/Comptroller.json"; import DEVIATION_SENTINEL_ABI from "./abi/DeviationSentinel.json"; @@ -53,6 +59,12 @@ forking(FORK_BLOCK, async () => { let timelock: any; let vaultsBefore: BigNumber; + let usdc: Contract; + let vUsdc: Contract; + let allezUsdcBefore: BigNumber; + let treasuryUsdcBefore: BigNumber; + let treasuryVUsdcBefore: BigNumber; + // DAI and USDT prices captured at the fork block (before the governance lifecycle warps time and // makes the RedStone pivot feed stale) so the behavioral DAI borrow can pin them via the Chainlink feed. let daiPrice: BigNumber; @@ -67,6 +79,12 @@ forking(FORK_BLOCK, async () => { daiPrice = await resilientOracle.getPrice(DAI); usdtPrice = await resilientOracle.getPrice(USDT); + usdc = await ethers.getContractAt(ERC20_ABI, USDC); + vUsdc = await ethers.getContractAt(ERC20_ABI, vUSDC); + allezUsdcBefore = await usdc.balanceOf(ALLEZ_LABS); + treasuryUsdcBefore = await usdc.balanceOf(bscmainnet.VTREASURY); + treasuryVUsdcBefore = await vUsdc.balanceOf(bscmainnet.VTREASURY); + await pinResilientOraclePriceViaRedstone(resilientOracle, BTCB); await pinResilientOraclePriceViaRedstone(resilientOracle, USDT); }); @@ -181,6 +199,30 @@ forking(FORK_BLOCK, async () => { }); }); + describe("Post-VIP behavior: Allez Labs Q3 2026 payment", () => { + it("Allez Labs received exactly 105,000 USDC", async () => { + expect(await usdc.balanceOf(ALLEZ_LABS)).to.equal(allezUsdcBefore.add(ALLEZ_LABS_USDC_AMOUNT)); + }); + + it("treasury liquid USDC is untouched", async () => { + expect(await usdc.balanceOf(bscmainnet.VTREASURY)).to.equal(treasuryUsdcBefore); + }); + + it("treasury vUSDC decreased by at most the withdrawn amount (remainder returned)", async () => { + const treasuryVUsdcAfter = await vUsdc.balanceOf(bscmainnet.VTREASURY); + const consumed = treasuryVUsdcBefore.sub(treasuryVUsdcAfter); + // The redeemer consumes only what 105,000 USDC requires at the execution-time + // exchange rate and returns the rest; the 3.96M withdrawal carries ~0.13% headroom. + expect(consumed).to.be.lte(VUSDC_WITHDRAW_AMOUNT); + expect(consumed).to.be.gte(VUSDC_WITHDRAW_AMOUNT.mul(99).div(100)); + }); + + it("the Token Redeemer retains no vUSDC or USDC", async () => { + expect(await vUsdc.balanceOf(TOKEN_REDEEMER)).to.equal(0); + expect(await usdc.balanceOf(TOKEN_REDEEMER)).to.equal(0); + }); + }); + describe("New vault: deposit/mint with consent + normal flow", () => { // IVaultTypes.VaultState const VaultState = { diff --git a/vips/vip-644/bscmainnet.ts b/vips/vip-644/bscmainnet.ts index 81e8d59dd..faa12d35b 100644 --- a/vips/vip-644/bscmainnet.ts +++ b/vips/vip-644/bscmainnet.ts @@ -1,3 +1,4 @@ +import { parseUnits } from "ethers/lib/utils"; import { NETWORK_ADDRESSES } from "src/networkAddresses"; import { ProposalType } from "src/types"; import { makeProposal } from "src/utils"; @@ -24,14 +25,30 @@ export const OLD_VAULT_IMPLEMENTATION = "0xC25b2B657D24380eDd1a1Cff5296385541e85 // Adds depositWithConsent / mintWithConsent. export const NEW_VAULT_IMPLEMENTATION = "0xe87A1eFCED88bBddf8CCF78EfB3bCF62cFdd5bdC"; +// ── Allez Labs Q3 2026 payment (risk management services) ───────────────── +export const USDC = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"; +export const vUSDC = "0xecA88125a5ADbe82614ffC12D0DB554E2e2867C8"; // vUSDC Core Pool +export const TOKEN_REDEEMER = "0xC53ffda840B51068C64b2E052a5715043f634bcd"; +export const ALLEZ_LABS = "0x1757564C8C9a2c3cbE12620ea21B97d6E149F98e"; + +export const ALLEZ_LABS_USDC_AMOUNT = parseUnits("105000", 18); + +// The treasury's liquid USDC (~86K) does not cover the payment, so the USDC is sourced +// by redeeming treasury vUSDC via the TokenRedeemer (same flow as VIP-594). ~3.96M vUSDC +// is withdrawn against a need of ~3,954,894 vUSDC at the authoring exchange rate +// (~0.02655 USDC per vUSDC); the rate only increases through interest accrual, so this +// amount always covers 105,000 USDC at execution time and the unused vUSDC remainder is +// returned to the treasury by the redeemer. +export const VUSDC_WITHDRAW_AMOUNT = parseUnits("3960000", 8); + export const vip644 = () => { const meta = { version: "v2", title: - "VIP-644 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing) and upgrade Institutional Fixed Rate Vault implementation", + "VIP-644 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing), upgrade Institutional Fixed Rate Vault implementation and pay Allez Labs Q3 2026 fees", description: `#### Summary -If passed, this VIP will (1) stop the DeviationSentinel from monitoring DAI, resume borrowing on the vDAI market and clear the related Emergency Brake snapshots, and (2) point the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow. +If passed, this VIP will (1) stop the DeviationSentinel from monitoring DAI, resume borrowing on the vDAI market and clear the related Emergency Brake snapshots, (2) point the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow, and (3) transfer 105,000 USDC from the Venus Treasury to Allez Labs for Q3 2026 risk management services, sourced by redeeming treasury vUSDC. #### Part 1 — Fix the DAI market @@ -69,6 +86,23 @@ The consent hash is optional: passing \`bytes32(0)\` skips the event and deposit - **Action**: point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. +#### Part 3 — Allez Labs Q3 2026 Risk Services Payment + +Allez Labs provides risk management services to Venus Protocol. Per the contract terms, fees are paid quarterly in advance. This is the payment covering Q3 2026 (26 July 2026 – 25 October 2026), following the Q2 2026 payment executed in [VIP-612](https://app.venus.io/#/governance/proposal/612?chainId=56). + +**Transfer Details** + +- Amount: 105,000 USDC (at $35,000/month × 3 months) +- Source: Venus Treasury (${bscmainnet.VTREASURY}), by redeeming treasury-held vUSDC +- Destination: Allez Labs (${ALLEZ_LABS}) + +**Technical implementation.** The treasury's liquid USDC balance does not cover the payment, so this VIP uses the Token Redeemer (${TOKEN_REDEEMER}) to convert treasury vUSDC into USDC — the same flow as [VIP-594](https://app.venus.io/#/governance/proposal/594?chainId=56): + +1. Withdraw 3,960,000 vUSDC (~105K USDC worth) from the Venus Treasury to the Token Redeemer. +2. Call \`redeemUnderlyingAndTransfer\`: redeems exactly 105,000 USDC and sends it to Allez Labs; the unused vUSDC remainder is returned to the Venus Treasury. + +The vUSDC exchange rate (~0.02655 USDC per vUSDC at authoring) only increases over time via interest accrual, so 3,960,000 vUSDC always covers 105,000 USDC at execution time, and the amount received by Allez Labs is exact and deterministic. + No new AccessControlManager permissions are required — the Normal Timelock already holds all of the roles used by this proposal. #### Voting options @@ -132,6 +166,22 @@ No new AccessControlManager permissions are required — the Normal Timelock alr signature: "setVaultImplementation(address)", params: [NEW_VAULT_IMPLEMENTATION], }, + + // ──────────────────────────────────────────────────────────────────────── + // Part 3 — Allez Labs Q3 2026 payment: withdraw vUSDC from the treasury to + // the Token Redeemer, redeem exactly 105,000 USDC to Allez Labs, and + // return the unused vUSDC remainder to the treasury (VIP-594 flow). + // ──────────────────────────────────────────────────────────────────────── + { + target: bscmainnet.VTREASURY, + signature: "withdrawTreasuryBEP20(address,uint256,address)", + params: [vUSDC, VUSDC_WITHDRAW_AMOUNT, TOKEN_REDEEMER], + }, + { + target: TOKEN_REDEEMER, + signature: "redeemUnderlyingAndTransfer(address,address,uint256,address)", + params: [vUSDC, ALLEZ_LABS, ALLEZ_LABS_USDC_AMOUNT, bscmainnet.VTREASURY], + }, ], meta, ProposalType.REGULAR, From ec6ea9f0068774e90832c88af95cf67030d9bddc Mon Sep 17 00:00:00 2001 From: fred-venus Date: Wed, 15 Jul 2026 11:56:48 +0800 Subject: [PATCH 9/9] chore: prepare VIP-644 for proposal Title and description from the voting Notion doc, with Part 3 / Actions corrected to describe the actual vUSDC-redemption payment commands. Co-Authored-By: Claude Fable 5 --- vips/vip-644/bscmainnet.ts | 63 +++++++++----------------------------- 1 file changed, 14 insertions(+), 49 deletions(-) diff --git a/vips/vip-644/bscmainnet.ts b/vips/vip-644/bscmainnet.ts index faa12d35b..4fdfb31b1 100644 --- a/vips/vip-644/bscmainnet.ts +++ b/vips/vip-644/bscmainnet.ts @@ -44,64 +44,29 @@ export const VUSDC_WITHDRAW_AMOUNT = parseUnits("3960000", 8); export const vip644 = () => { const meta = { version: "v2", - title: - "VIP-644 [BNB Chain] Fix DAI market (disable DeviationSentinel monitoring, resume borrowing), upgrade Institutional Fixed Rate Vault implementation and pay Allez Labs Q3 2026 fees", + title: "VIP-644 [BNB Chain] Fix DAI Market, Upgrade Institutional Fixed Rate Vault, and Pay Allez Labs Q3", description: `#### Summary -If passed, this VIP will (1) stop the DeviationSentinel from monitoring DAI, resume borrowing on the vDAI market and clear the related Emergency Brake snapshots, (2) point the Institutional Fixed Rate Vault controller at a new vault clone-source implementation that adds on-chain disclaimer-consent recording to the supplier deposit/mint flow, and (3) transfer 105,000 USDC from the Venus Treasury to Allez Labs for Q3 2026 risk management services, sourced by redeeming treasury vUSDC. +This VIP (1) stops DeviationSentinel monitoring of DAI, resumes vDAI borrowing and clears the related Emergency Brake snapshots, (2) upgrades the Institutional Fixed Rate Vault to an implementation that adds optional on-chain disclaimer-consent recording to the deposit/mint flow, and (3) transfers 105,000 USDC from the Venus Treasury to Allez Labs for Q3 2026 risk-management services, sourced by redeeming Treasury-held vUSDC. -#### Part 1 — Fix the DAI market +#### Description -DAI has thin, volatile DEX liquidity on BNB Chain. Because the DEX price of DAI is chronically noisy relative to the ResilientOracle price, the DeviationSentinel has repeatedly tripped false positives on the DAI market — most recently over the weekend, pausing borrowing on the vDAI market. As reliably configuring a deviation threshold for such a shallow pool is not practical, the risk team has decided to stop monitoring DAI with the DeviationSentinel. +**Part 1 — DAI market.** DAI's thin, volatile DEX liquidity makes its price noisy against the ResilientOracle, repeatedly tripping DeviationSentinel false positives on vDAI (most recently last weekend). Monitoring is disabled and borrowing resumed; no collateral factor or cap is restored because EBrake never reduced any (vDAI's collateral factor was already 0). -**1. Disable DeviationSentinel monitoring for DAI** +**Part 2 — Fixed Rate Vault.** A new implementation adds depositWithConsent / mintWithConsent — ERC-4626 wrappers that emit ConsentRecorded (a zero hash skips it). Plain deposit/mint and existing vaults are unaffected; only vaults created after execution use it. -- **Contract**: DeviationSentinel (${DEVIATION_SENTINEL}) -- **Function**: setTokenMonitoringEnabled(address,bool) -- **Parameters**: token = DAI (${DAI}), enabled = false -- **Effect**: handleDeviation can no longer act on the vDAI market (it reverts TokenMonitoringDisabled). The stored deviation threshold for DAI is left unchanged. This is ordered first so the market cannot be re-tripped around execution. +**Part 3 — Allez Labs Q3 payment.** Allez Labs provides risk-management services to Venus, billed quarterly in advance. This pays the Q3 2026 fee of 105,000 USDC ($35,000/month × 3, covering 26 July 2026 – 25 October 2026) — the same amount as the Q2 payment ([VIP-612](https://app.venus.io/#/governance/proposal/612?chainId=56)), paid in USDC. Because the Treasury's liquid USDC does not cover the amount, the USDC is sourced by redeeming Treasury-held vUSDC through the Token Redeemer, the same flow as [VIP-594](https://app.venus.io/#/governance/proposal/594?chainId=56): the redemption pays Allez Labs exactly 105,000 USDC and returns the unused vUSDC remainder to the Treasury. The vUSDC exchange rate only increases over time via interest accrual, so the withdrawn 3,960,000 vUSDC always covers the payment at execution time. -**2. Resume borrowing on vDAI** +#### Actions -- **Contract**: Core Pool Comptroller (${bscmainnet.UNITROLLER}) -- **Function**: setActionsPaused(address[],uint8[],bool) -- **Parameters**: markets = [vDAI], actions = [BORROW (2)], paused = false -- **Effect**: Users can borrow DAI again. The collateral factor of vDAI is **not** changed by this VIP: its pre-incident collateral factor was already 0 (which is why the EBrake collateral-factor snapshot for vDAI is empty — the sentinel only paused borrowing, it never lowered a non-zero collateral factor), so there is no collateral factor to restore. Likewise the borrow and supply caps were never reduced by EBrake (both cap snapshots are empty and the live caps are intact), so there are no caps to restore. +This VIP performs 8 actions on BNB Chain: -**3. Reset the DAI snapshots on EBrake** - -- **Contract**: EBrake (${EBRAKE}) -- **Functions**: resetCFSnapshot(address), resetBorrowCapSnapshot(address), resetSupplyCapSnapshot(address) -- **Parameters**: market = vDAI -- **Effect**: Clears any stored collateral-factor / borrow-cap / supply-cap snapshot for the vDAI market so EBrake tracks no residual state for DAI after monitoring is disabled. - -#### Part 2 — Upgrade the Institutional Fixed Rate Vault implementation (consent recording) - -The \`InstitutionalLoanVault\` implementation used by the controller (${FIXED_RATE_VAULT_CONTROLLER}) to clone new vaults is upgraded from ${OLD_VAULT_IMPLEMENTATION} to ${NEW_VAULT_IMPLEMENTATION}. The new implementation adds two supplier entrypoints: - -- \`depositWithConsent(uint256 assets, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`deposit\` that emits \`ConsentRecorded(supplier, receiver, consentHash)\`. -- \`mintWithConsent(uint256 shares, address receiver, bytes32 consentHash)\` — a thin wrapper over ERC-4626 \`mint\` that emits the same event. - -The consent hash is optional: passing \`bytes32(0)\` skips the event and deposits/mints as usual. The plain \`deposit\`/\`mint\` entrypoints are unchanged. Existing vaults are immutable clones and are not modified; the change applies to vaults created from now on. - -- **Action**: point the controller at the new vault implementation via \`setVaultImplementation(${NEW_VAULT_IMPLEMENTATION})\`. - -#### Part 3 — Allez Labs Q3 2026 Risk Services Payment - -Allez Labs provides risk management services to Venus Protocol. Per the contract terms, fees are paid quarterly in advance. This is the payment covering Q3 2026 (26 July 2026 – 25 October 2026), following the Q2 2026 payment executed in [VIP-612](https://app.venus.io/#/governance/proposal/612?chainId=56). - -**Transfer Details** - -- Amount: 105,000 USDC (at $35,000/month × 3 months) -- Source: Venus Treasury (${bscmainnet.VTREASURY}), by redeeming treasury-held vUSDC -- Destination: Allez Labs (${ALLEZ_LABS}) - -**Technical implementation.** The treasury's liquid USDC balance does not cover the payment, so this VIP uses the Token Redeemer (${TOKEN_REDEEMER}) to convert treasury vUSDC into USDC — the same flow as [VIP-594](https://app.venus.io/#/governance/proposal/594?chainId=56): - -1. Withdraw 3,960,000 vUSDC (~105K USDC worth) from the Venus Treasury to the Token Redeemer. -2. Call \`redeemUnderlyingAndTransfer\`: redeems exactly 105,000 USDC and sends it to Allez Labs; the unused vUSDC remainder is returned to the Venus Treasury. - -The vUSDC exchange rate (~0.02655 USDC per vUSDC at authoring) only increases over time via interest accrual, so 3,960,000 vUSDC always covers 105,000 USDC at execution time, and the amount received by Allez Labs is exact and deterministic. +1. **Disable DeviationSentinel monitoring for DAI** — setTokenMonitoringEnabled(DAI, false) on DeviationSentinel (${DEVIATION_SENTINEL}), ordered first so vDAI cannot be re-tripped around execution. +2. **Resume borrowing on vDAI** — setActionsPaused([vDAI], [BORROW], false) on the Core Pool Comptroller (${bscmainnet.UNITROLLER}). +3. **Clear the vDAI Emergency Brake snapshots** — resetCFSnapshot, resetBorrowCapSnapshot and resetSupplyCapSnapshot(vDAI) on EBrake (${EBRAKE}). +4. **Upgrade the Fixed Rate Vault implementation** — setVaultImplementation(${NEW_VAULT_IMPLEMENTATION}) on the controller (${FIXED_RATE_VAULT_CONTROLLER}), replacing ${OLD_VAULT_IMPLEMENTATION}; only vaults cloned after execution use it. +5. **Withdraw vUSDC for the Allez Labs payment** — withdrawTreasuryBEP20(vUSDC, 3,960,000, TOKEN_REDEEMER) on the Venus Treasury (${bscmainnet.VTREASURY}), moving 3,960,000 vUSDC (${vUSDC}) to the Token Redeemer (${TOKEN_REDEEMER}). +6. **Pay Allez Labs for Q3 2026** — redeemUnderlyingAndTransfer on the Token Redeemer, redeeming exactly 105,000 USDC (${USDC}) to Allez Labs (${ALLEZ_LABS}) and returning the unused vUSDC remainder to the Venus Treasury. No new AccessControlManager permissions are required — the Normal Timelock already holds all of the roles used by this proposal.