diff --git a/simulations/vip-664/abi/ACMAggregator.json b/simulations/vip-664/abi/ACMAggregator.json new file mode 100644 index 000000000..0974d4ab3 --- /dev/null +++ b/simulations/vip-664/abi/ACMAggregator.json @@ -0,0 +1,118 @@ +[ + { + "inputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "_acm", "type": "address" }], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [], "name": "EmptyPermissions", "type": "error" }, + { "inputs": [], "name": "ZeroAddressNotAllowed", "type": "error" }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "GrantPermissionsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "GrantPermissionsExecuted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "RevokePermissionsAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "RevokePermissionsExecuted", + "type": "event" + }, + { + "inputs": [], + "name": "ACM", + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "contractAddress", "type": "address" }, + { "internalType": "string", "name": "functionSig", "type": "string" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "internalType": "struct ACMCommandsAggregator.Permission[]", + "name": "_permissions", + "type": "tuple[]" + } + ], + "name": "addGrantPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "address", "name": "contractAddress", "type": "address" }, + { "internalType": "string", "name": "functionSig", "type": "string" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "internalType": "struct ACMCommandsAggregator.Permission[]", + "name": "_permissions", + "type": "tuple[]" + } + ], + "name": "addRevokePermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "executeGrantPermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "index", "type": "uint256" }], + "name": "executeRevokePermissions", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "name": "grantPermissions", + "outputs": [ + { "internalType": "address", "name": "contractAddress", "type": "address" }, + { "internalType": "string", "name": "functionSig", "type": "string" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "", "type": "uint256" }, + { "internalType": "uint256", "name": "", "type": "uint256" } + ], + "name": "revokePermissions", + "outputs": [ + { "internalType": "address", "name": "contractAddress", "type": "address" }, + { "internalType": "string", "name": "functionSig", "type": "string" }, + { "internalType": "address", "name": "account", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-664/abi/AccessControlManager.json b/simulations/vip-664/abi/AccessControlManager.json new file mode 100644 index 000000000..4a118fcc4 --- /dev/null +++ b/simulations/vip-664/abi/AccessControlManager.json @@ -0,0 +1,360 @@ +[ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "PermissionRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToPermit", + "type": "address" + } + ], + "name": "giveCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "hasPermission", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + } + ], + "name": "isAllowedToCall", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + }, + { + "internalType": "string", + "name": "functionSig", + "type": "string" + }, + { + "internalType": "address", + "name": "accountToRevoke", + "type": "address" + } + ], + "name": "revokeCallPermission", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-664/abi/InstitutionPositionToken.json b/simulations/vip-664/abi/InstitutionPositionToken.json new file mode 100644 index 000000000..8933a45ce --- /dev/null +++ b/simulations/vip-664/abi/InstitutionPositionToken.json @@ -0,0 +1,267 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "OwnershipCannotBeRenounced", "type": "error" }, + { + "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "TransferNotApproved", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "approved", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "owner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "operator", "type": "address" }, + { "indexed": false, "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "ApprovalForAll", + "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": "vault", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "indexed": true, "internalType": "address", "name": "institution", "type": "address" } + ], + "name": "PositionTokenMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "PositionTransferApproved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "PositionTransferRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "from", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": true, "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "Transfer", + "type": "event" + }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "approve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "approveTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "owner", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "getApproved", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "owner", "type": "address" }, + { "internalType": "address", "name": "operator", "type": "address" } + ], + "name": "isApprovedForAll", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "address", "name": "vault", "type": "address" } + ], + "name": "mint", + "outputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nextTokenId", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "ownerOf", + "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": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "revokeTransferApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "operator", "type": "address" }, + { "internalType": "bool", "name": "approved", "type": "bool" } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes4", "name": "interfaceId", "type": "bytes4" }], + "name": "supportsInterface", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "tokenIdToVault", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "tokenId", "type": "uint256" }], + "name": "tokenURI", + "outputs": [{ "internalType": "string", "name": "", "type": "string" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "transferApproved", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "tokenId", "type": "uint256" } + ], + "name": "transferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "vaultToTokenId", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-664/abi/InstitutionalLoanVault.json b/simulations/vip-664/abi/InstitutionalLoanVault.json new file mode 100644 index 000000000..efe35a44d --- /dev/null +++ b/simulations/vip-664/abi/InstitutionalLoanVault.json @@ -0,0 +1,2001 @@ +[ + { + "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": "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": "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" + } + ], + "outputs": [], + "stateMutability": "nonpayable" + }, + { + "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": "idealCollateralValuation", + "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": "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": "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": "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": "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": "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": "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": "PositionTokenIdNotSet", + "inputs": [] + }, + { + "type": "error", + "name": "SameStateTransition", + "inputs": [] + }, + { + "type": "error", + "name": "Unauthorized", + "inputs": [] + }, + { + "type": "error", + "name": "WithdrawExceedsCollateral", + "inputs": [] + }, + { + "type": "error", + "name": "WithdrawalWouldBreachLT", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroAddress", + "inputs": [] + }, + { + "type": "error", + "name": "ZeroRepayAmount", + "inputs": [] + } +] diff --git a/simulations/vip-664/abi/InstitutionalVaultController.json b/simulations/vip-664/abi/InstitutionalVaultController.json new file mode 100644 index 000000000..0bf203dbb --- /dev/null +++ b/simulations/vip-664/abi/InstitutionalVaultController.json @@ -0,0 +1,505 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { "inputs": [], "name": "InvalidAddress", "type": "error" }, + { "inputs": [], "name": "InvalidConfig", "type": "error" }, + { "inputs": [], "name": "InvalidLatePenaltyRate", "type": "error" }, + { "inputs": [], "name": "InvalidLiquidationIncentive", "type": "error" }, + { "inputs": [], "name": "InvalidLiquidationThreshold", "type": "error" }, + { "inputs": [], "name": "OwnershipCannotBeRenounced", "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": "VaultNotRegistered", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldComptroller", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newComptroller", "type": "address" } + ], + "name": "ComptrollerUpdated", + "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": "vault", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "newRate", "type": "uint256" } + ], + "name": "LatePenaltyRateUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldAdapter", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newAdapter", "type": "address" } + ], + "name": "LiquidationAdapterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "vault", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "newLI", "type": "uint256" } + ], + "name": "LiquidationIncentiveUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "vault", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "newLT", "type": "uint256" } + ], + "name": "LiquidationThresholdUpdated", + "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": "oldOracle", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOracle", "type": "address" } + ], + "name": "OracleUpdated", + "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": "oldPSR", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newPSR", "type": "address" } + ], + "name": "ProtocolShareReserveUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldTreasury", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newTreasury", "type": "address" } + ], + "name": "TreasuryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "vault", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "institution", "type": "address" } + ], + "name": "VaultCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldImpl", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newImpl", "type": "address" } + ], + "name": "VaultImplementationUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "MANTISSA_ONE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MANTISSA_ONE_AND_HALF", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_APY_BPS", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "acceptPositionTokenOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "allVaults", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allVaultsLength", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "approvePositionTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "closeVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "completePauseVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "comptroller", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "contract IERC20", "name": "supplyAsset", "type": "address" }, + { "internalType": "uint256", "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": "uint40", "name": "openDuration", "type": "uint40" }, + { "internalType": "uint40", "name": "lockDuration", "type": "uint40" }, + { "internalType": "uint40", "name": "settlementWindow", "type": "uint40" } + ], + "internalType": "struct VaultConfig", + "name": "_vaultConfig", + "type": "tuple" + }, + { + "components": [ + { "internalType": "contract IERC20", "name": "collateralAsset", "type": "address" }, + { "internalType": "uint256", "name": "idealCollateralAmount", "type": "uint256" }, + { "internalType": "uint256", "name": "marginRate", "type": "uint256" }, + { "internalType": "address", "name": "institutionOperator", "type": "address" }, + { "internalType": "uint256", "name": "positionTokenId", "type": "uint256" } + ], + "internalType": "struct InstitutionalConfig", + "name": "_instConfig", + "type": "tuple" + }, + { + "components": [ + { "internalType": "uint256", "name": "liquidationThreshold", "type": "uint256" }, + { "internalType": "uint256", "name": "liquidationIncentive", "type": "uint256" }, + { "internalType": "uint256", "name": "latePenaltyRate", "type": "uint256" } + ], + "internalType": "struct RiskConfig", + "name": "_riskConfig", + "type": "tuple" + }, + { "internalType": "string", "name": "_name", "type": "string" }, + { "internalType": "string", "name": "_symbol", "type": "string" } + ], + "name": "createVault", + "outputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAggregatedVaultStates", + "outputs": [ + { + "components": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "enum VaultState", "name": "state", "type": "uint8" }, + { "internalType": "address", "name": "institutionOperator", "type": "address" }, + { "internalType": "uint256", "name": "totalRaised", "type": "uint256" }, + { "internalType": "uint256", "name": "outstandingDebt", "type": "uint256" } + ], + "internalType": "struct VaultStateInfo[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "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" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "institutionNonce", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "isRegistered", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "liquidationAdapter", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "openVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "oracle", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "partialPauseVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "positionToken", + "outputs": [{ "internalType": "contract IInstitutionPositionToken", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "institution", "type": "address" }], + "name": "predictVaultAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolShareReserve", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "revokePositionTransfer", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "comptroller_", "type": "address" }], + "name": "setComptroller", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "uint256", "name": "newRate", "type": "uint256" } + ], + "name": "setLatePenaltyRate", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "adapter", "type": "address" }], + "name": "setLiquidationAdapter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "uint256", "name": "newLI", "type": "uint256" } + ], + "name": "setLiquidationIncentive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "uint256", "name": "newLT", "type": "uint256" } + ], + "name": "setLiquidationThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "oracle_", "type": "address" }], + "name": "setOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "psr", "type": "address" }], + "name": "setProtocolShareReserve", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "treasury_", "type": "address" }], + "name": "setTreasury", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "impl", "type": "address" }], + "name": "setVaultImplementation", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "vault", "type": "address" }, + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "sweep", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "treasury", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "vault", "type": "address" }], + "name": "unpauseVault", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vaultImplementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-664/abi/LiquidationAdapter.json b/simulations/vip-664/abi/LiquidationAdapter.json new file mode 100644 index 000000000..c90cf602b --- /dev/null +++ b/simulations/vip-664/abi/LiquidationAdapter.json @@ -0,0 +1,37 @@ +[ + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "protocolLiquidationShare", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "closeFactor", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-664/bsctestnet.ts b/simulations/vip-664/bsctestnet.ts new file mode 100644 index 000000000..9eb5d5841 --- /dev/null +++ b/simulations/vip-664/bsctestnet.ts @@ -0,0 +1,273 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { parseEther } from "ethers/lib/utils"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { expectEvents } from "src/utils"; +import { forking, testVip } from "src/vip-framework"; + +import vip664, { + ACM_AGGREGATOR, + ACM_AGGREGATOR_INDEX, + ADAPTER_FUNCTIONS, + ADAPTER_GUARDIAN_FUNCTIONS, + CONTROLLER_FUNCTIONS, + CONTROLLER_GUARDIAN_FUNCTIONS, + DEFAULT_ADMIN_ROLE, + EXPECTED_PERMISSION_GRANTED_EVENTS, + INSTITUTIONAL_VAULT_CONTROLLER, + INSTITUTION_POSITION_TOKEN, + LIQUIDATION_ADAPTER, + PERMISSIONS, +} from "../../vips/vip-664/bsctestnet"; +import ACM_AGGREGATOR_ABI from "./abi/ACMAggregator.json"; +import ACCESS_CONTROL_MANAGER_ABI from "./abi/AccessControlManager.json"; +import INSTITUTION_POSITION_TOKEN_ABI from "./abi/InstitutionPositionToken.json"; +import INSTITUTIONAL_VAULT_CONTROLLER_ABI from "./abi/InstitutionalVaultController.json"; +import LIQUIDATION_ADAPTER_ABI from "./abi/LiquidationAdapter.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, GUARDIAN, ACCESS_CONTROL_MANAGER } = bsctestnet; + +const FORK_BLOCK = 102151520; + +forking(FORK_BLOCK, async () => { + let accessControlManager: Contract; + let controller: Contract; + let liquidationAdapter: Contract; + let positionToken: Contract; + let acmAggregator: Contract; + + before(async () => { + accessControlManager = new ethers.Contract(ACCESS_CONTROL_MANAGER, ACCESS_CONTROL_MANAGER_ABI, ethers.provider); + controller = new ethers.Contract( + INSTITUTIONAL_VAULT_CONTROLLER, + INSTITUTIONAL_VAULT_CONTROLLER_ABI, + ethers.provider, + ); + liquidationAdapter = new ethers.Contract(LIQUIDATION_ADAPTER, LIQUIDATION_ADAPTER_ABI, ethers.provider); + positionToken = new ethers.Contract(INSTITUTION_POSITION_TOKEN, INSTITUTION_POSITION_TOKEN_ABI, ethers.provider); + acmAggregator = new ethers.Contract(ACM_AGGREGATOR, ACM_AGGREGATOR_ABI, ethers.provider); + }); + + // ────────────────────────────────────────────────────────────────────── + // Pre-VIP: verify deployments + // ────────────────────────────────────────────────────────────────────── + // These checks confirm that all three contracts are deployed and that the + // ownership transfer initiation (transferOwnership in the deploy script) has + // been executed before the VIP runs. + describe("Pre-VIP: verify deployments", () => { + it("InstitutionalVaultController proxy should be deployed", async () => { + const code = await ethers.provider.getCode(INSTITUTIONAL_VAULT_CONTROLLER); + expect(code).to.not.equal("0x"); + }); + + it("LiquidationAdapter proxy should be deployed", async () => { + const code = await ethers.provider.getCode(LIQUIDATION_ADAPTER); + expect(code).to.not.equal("0x"); + }); + + it("InstitutionPositionToken should be deployed", async () => { + const code = await ethers.provider.getCode(INSTITUTION_POSITION_TOKEN); + expect(code).to.not.equal("0x"); + }); + + it("InstitutionPositionToken pending owner should be the controller proxy (transferOwnership was called in deploy script)", async () => { + const pendingOwner = await positionToken.pendingOwner(); + expect(pendingOwner).to.equal(INSTITUTIONAL_VAULT_CONTROLLER); + }); + + it("NORMAL_TIMELOCK should not yet have setLiquidationAdapter permission on controller", async () => { + const allowed = await accessControlManager.hasPermission( + NORMAL_TIMELOCK, + INSTITUTIONAL_VAULT_CONTROLLER, + "setLiquidationAdapter(address)", + ); + expect(allowed).to.be.false; + }); + + it("NORMAL_TIMELOCK should not yet have acceptPositionTokenOwnership permission on controller", async () => { + const allowed = await accessControlManager.hasPermission( + NORMAL_TIMELOCK, + INSTITUTIONAL_VAULT_CONTROLLER, + "acceptPositionTokenOwnership()", + ); + expect(allowed).to.be.false; + }); + + it("controller pendingOwner should be NORMAL_TIMELOCK (transferOwnership was called in deploy script)", async () => { + const pendingOwner = await controller.pendingOwner(); + expect(pendingOwner).to.equal(NORMAL_TIMELOCK); + }); + + it("liquidationAdapter pendingOwner should be NORMAL_TIMELOCK (transferOwnership was called in deploy script)", async () => { + const pendingOwner = await liquidationAdapter.pendingOwner(); + expect(pendingOwner).to.equal(NORMAL_TIMELOCK); + }); + + it("liquidationAdapter protocolLiquidationShare should be 0.5e18", async () => { + const share = await liquidationAdapter.protocolLiquidationShare(); + expect(share).to.equal(parseEther("0.5")); + }); + + it("liquidationAdapter closeFactor should be 0.5e18", async () => { + const factor = await liquidationAdapter.closeFactor(); + expect(factor).to.equal(parseEther("0.5")); + }); + + it("controller liquidationAdapter should be address(0) before VIP", async () => { + const adapter = await controller.liquidationAdapter(); + expect(adapter).to.equal(ethers.constants.AddressZero); + }); + + it("ACM Aggregator stored permissions should match PERMISSIONS array", async () => { + for (let i = 0; i < PERMISSIONS.length; i++) { + const stored = await acmAggregator.grantPermissions(ACM_AGGREGATOR_INDEX, i); + expect(stored.contractAddress.toLowerCase()).to.equal( + PERMISSIONS[i][0].toLowerCase(), + `Permission ${i} contractAddress mismatch`, + ); + expect(stored.functionSig).to.equal(PERMISSIONS[i][1], `Permission ${i} functionSig mismatch`); + expect(stored.account.toLowerCase()).to.equal( + PERMISSIONS[i][2].toLowerCase(), + `Permission ${i} account mismatch`, + ); + } + }); + }); + + // ────────────────────────────────────────────────────────────────────── + // VIP execution + // ────────────────────────────────────────────────────────────────────── + testVip("VIP-664 [BNB Chain Testnet] Configure Institutional Fixed Rate Vault System", await vip664(), { + callbackAfterExecution: async txResponse => { + await expectEvents( + txResponse, + [ACCESS_CONTROL_MANAGER_ABI], + ["PermissionGranted", "RoleGranted", "RoleRevoked"], + [EXPECTED_PERMISSION_GRANTED_EVENTS, EXPECTED_PERMISSION_GRANTED_EVENTS + 1, 1], + ); + await expectEvents(txResponse, [ACM_AGGREGATOR_ABI], ["GrantPermissionsExecuted"], [1]); + }, + }); + + // ────────────────────────────────────────────────────────────────────── + // Post-VIP: ACM permission and system wiring checks + // ────────────────────────────────────────────────────────────────────── + + describe("Post-VIP: verify setup", () => { + describe("InstitutionalVaultController — NORMAL_TIMELOCK permissions", () => { + for (const funcSig of CONTROLLER_FUNCTIONS) { + it(`NORMAL_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission( + NORMAL_TIMELOCK, + INSTITUTIONAL_VAULT_CONTROLLER, + funcSig, + ); + expect(allowed).to.be.true; + }); + } + }); + + describe("InstitutionalVaultController — FAST_TRACK_TIMELOCK permissions", () => { + for (const funcSig of CONTROLLER_FUNCTIONS) { + it(`FAST_TRACK_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission( + FAST_TRACK_TIMELOCK, + INSTITUTIONAL_VAULT_CONTROLLER, + funcSig, + ); + expect(allowed).to.be.true; + }); + } + }); + + describe("InstitutionalVaultController — CRITICAL_TIMELOCK permissions", () => { + for (const funcSig of CONTROLLER_FUNCTIONS) { + it(`CRITICAL_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission( + CRITICAL_TIMELOCK, + INSTITUTIONAL_VAULT_CONTROLLER, + funcSig, + ); + expect(allowed).to.be.true; + }); + } + }); + + describe("InstitutionalVaultController — GUARDIAN permissions", () => { + for (const funcSig of CONTROLLER_GUARDIAN_FUNCTIONS) { + it(`GUARDIAN should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission(GUARDIAN, INSTITUTIONAL_VAULT_CONTROLLER, funcSig); + expect(allowed).to.be.true; + }); + } + }); + + describe("LiquidationAdapter — NORMAL_TIMELOCK permissions", () => { + for (const funcSig of ADAPTER_FUNCTIONS) { + it(`NORMAL_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission(NORMAL_TIMELOCK, LIQUIDATION_ADAPTER, funcSig); + expect(allowed).to.be.true; + }); + } + }); + + describe("LiquidationAdapter — CRITICAL_TIMELOCK permissions", () => { + for (const funcSig of ADAPTER_FUNCTIONS) { + it(`CRITICAL_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission(CRITICAL_TIMELOCK, LIQUIDATION_ADAPTER, funcSig); + expect(allowed).to.be.true; + }); + } + }); + + describe("LiquidationAdapter — FAST_TRACK_TIMELOCK permissions", () => { + for (const funcSig of ADAPTER_FUNCTIONS) { + it(`FAST_TRACK_TIMELOCK should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission(FAST_TRACK_TIMELOCK, LIQUIDATION_ADAPTER, funcSig); + expect(allowed).to.be.true; + }); + } + }); + + describe("LiquidationAdapter — GUARDIAN permissions", () => { + for (const funcSig of ADAPTER_GUARDIAN_FUNCTIONS) { + it(`GUARDIAN should have permission: ${funcSig}`, async () => { + const allowed = await accessControlManager.hasPermission(GUARDIAN, LIQUIDATION_ADAPTER, funcSig); + expect(allowed).to.be.true; + }); + } + }); + + describe("Ownership acceptance", () => { + it("controller owner should be NORMAL_TIMELOCK", async () => { + const owner = await controller.owner(); + expect(owner).to.equal(NORMAL_TIMELOCK); + }); + + it("liquidationAdapter owner should be NORMAL_TIMELOCK", async () => { + const owner = await liquidationAdapter.owner(); + expect(owner).to.equal(NORMAL_TIMELOCK); + }); + }); + + describe("ACM Aggregator cleanup", () => { + it("DEFAULT_ADMIN_ROLE should be revoked from ACM Aggregator", async () => { + expect(await accessControlManager.hasRole(DEFAULT_ADMIN_ROLE, ACM_AGGREGATOR)).to.be.false; + }); + }); + + describe("System wiring", () => { + it("controller liquidationAdapter should be set to the adapter proxy", async () => { + const adapter = await controller.liquidationAdapter(); + expect(adapter).to.equal(LIQUIDATION_ADAPTER); + }); + + it("InstitutionPositionToken owner should be the controller proxy (ownership accepted)", async () => { + const owner = await positionToken.owner(); + expect(owner).to.equal(INSTITUTIONAL_VAULT_CONTROLLER); + }); + }); + }); +}); diff --git a/vips/vip-664/addGrantPermissions.ts b/vips/vip-664/addGrantPermissions.ts new file mode 100644 index 000000000..d18cae838 --- /dev/null +++ b/vips/vip-664/addGrantPermissions.ts @@ -0,0 +1,56 @@ +import { ethers } from "hardhat"; + +import { ACM_AGGREGATOR, PERMISSIONS } from "./bsctestnet"; + +const ACM_AGGREGATOR_ABI = [ + { + inputs: [ + { + components: [ + { internalType: "address", name: "contractAddress", type: "address" }, + { internalType: "string", name: "functionSig", type: "string" }, + { internalType: "address", name: "account", type: "address" }, + ], + internalType: "struct ACMCommandsAggregator.Permission[]", + name: "_PERMISSIONS", + type: "tuple[]", + }, + ], + name: "addGrantPermissions", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + anonymous: false, + inputs: [{ indexed: false, internalType: "uint256", name: "index", type: "uint256" }], + name: "GrantPermissionsAdded", + type: "event", + }, +]; + +async function main() { + console.log(`Total PERMISSIONS to add: ${PERMISSIONS.length}`); + + const [signer] = await ethers.getSigners(); + const acmAggregator = new ethers.Contract(ACM_AGGREGATOR, ACM_AGGREGATOR_ABI, signer); + + const tx = await acmAggregator.addGrantPermissions(PERMISSIONS); + console.log(`Transaction hash: ${tx.hash}`); + + const receipt = await tx.wait(); + const event = receipt.events?.find((e: { event: string }) => e.event === "GrantPermissionsAdded"); + + if (event) { + console.log(`GrantPermissionsAdded index: ${event.args?.index.toString()}`); + } else { + console.log("GrantPermissionsAdded event not found in receipt"); + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); diff --git a/vips/vip-664/bsctestnet.ts b/vips/vip-664/bsctestnet.ts new file mode 100644 index 000000000..8dc121e56 --- /dev/null +++ b/vips/vip-664/bsctestnet.ts @@ -0,0 +1,223 @@ +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { bsctestnet } = NETWORK_ADDRESSES; +const { NORMAL_TIMELOCK, FAST_TRACK_TIMELOCK, CRITICAL_TIMELOCK, GUARDIAN, ACCESS_CONTROL_MANAGER } = bsctestnet; + +// ────────────────────────────────────────────────────────────────────── +// Deployed addresses +// ────────────────────────────────────────────────────────────────────── + +export const INSTITUTIONAL_VAULT_CONTROLLER = "0x36bA78812Ffff64B9ec060a1F07FcFa2012f6F89"; +export const LIQUIDATION_ADAPTER = "0x69d79D60abD5A7080C9f178a44c5f1bf1A461541"; +export const INSTITUTION_POSITION_TOKEN = "0x377180882397718D4061d815Df32CF7DF8492f4F"; + +// ────────────────────────────────────────────────────────────────────── +// ACM Aggregator +// ────────────────────────────────────────────────────────────────────── + +export const ACM_AGGREGATOR = "0xB59523628D92f914ec6624Be4281397E8aFD71EF"; +export const DEFAULT_ADMIN_ROLE = "0x0000000000000000000000000000000000000000000000000000000000000000"; +export const ACM_AGGREGATOR_INDEX = 1; + +// ────────────────────────────────────────────────────────────────────── +// ACM-gated function signatures — InstitutionalVaultController +// ────────────────────────────────────────────────────────────────────── + +export const CONTROLLER_FUNCTIONS = [ + "acceptPositionTokenOwnership()", + "createVault(VaultConfig,InstitutionalConfig,RiskConfig,string,string)", + "openVault(address)", + "partialPauseVault(address)", + "completePauseVault(address)", + "unpauseVault(address)", + "closeVault(address)", + "sweep(address,address)", + "approvePositionTransfer(address)", + "revokePositionTransfer(address)", + "setLiquidationThreshold(address,uint256)", + "setLiquidationIncentive(address,uint256)", + "setLatePenaltyRate(address,uint256)", + "setVaultImplementation(address)", + "setLiquidationAdapter(address)", + "setOracle(address)", + "setProtocolShareReserve(address)", + "setComptroller(address)", + "setTreasury(address)", +]; + +export const CONTROLLER_GUARDIAN_FUNCTIONS = [ + "partialPauseVault(address)", + "completePauseVault(address)", + "unpauseVault(address)", + "openVault(address)", + "closeVault(address)", + "sweep(address,address)", +]; + +// ────────────────────────────────────────────────────────────────────── +// ACM-gated function signatures — LiquidationAdapter +// ────────────────────────────────────────────────────────────────────── + +export const ADAPTER_FUNCTIONS = [ + "setLiquidatorWhitelist(address,bool)", + "setSettlerWhitelist(address,bool)", + "setProtocolLiquidationShare(uint256)", + "setCloseFactor(uint256)", + "sweepProtocolShareToReserve(address)", +]; + +export const ADAPTER_GUARDIAN_FUNCTIONS = [ + "sweepProtocolShareToReserve(address)", + "setSettlerWhitelist(address,bool)", + "setLiquidatorWhitelist(address,bool)", +]; + +// Total PermissionGranted events: 19*3 + 6 + 5*3 + 3 = 81 +export const EXPECTED_PERMISSION_GRANTED_EVENTS = 81; + +// ────────────────────────────────────────────────────────────────────── +// Full permissions array (pre-loaded into ACM Aggregator via script) +// ────────────────────────────────────────────────────────────────────── + +export const PERMISSIONS: [string, string, string][] = [ + // InstitutionalVaultController — all 19 functions × 3 timelocks + ...CONTROLLER_FUNCTIONS.flatMap(sig => [ + [INSTITUTIONAL_VAULT_CONTROLLER, sig, NORMAL_TIMELOCK] as [string, string, string], + [INSTITUTIONAL_VAULT_CONTROLLER, sig, FAST_TRACK_TIMELOCK] as [string, string, string], + [INSTITUTIONAL_VAULT_CONTROLLER, sig, CRITICAL_TIMELOCK] as [string, string, string], + ]), + + // InstitutionalVaultController — 6 guardian functions + ...CONTROLLER_GUARDIAN_FUNCTIONS.map( + sig => [INSTITUTIONAL_VAULT_CONTROLLER, sig, GUARDIAN] as [string, string, string], + ), + + // LiquidationAdapter — all 5 functions × 3 timelocks + ...ADAPTER_FUNCTIONS.flatMap(sig => [ + [LIQUIDATION_ADAPTER, sig, NORMAL_TIMELOCK] as [string, string, string], + [LIQUIDATION_ADAPTER, sig, FAST_TRACK_TIMELOCK] as [string, string, string], + [LIQUIDATION_ADAPTER, sig, CRITICAL_TIMELOCK] as [string, string, string], + ]), + + // LiquidationAdapter — 3 guardian functions + ...ADAPTER_GUARDIAN_FUNCTIONS.map(sig => [LIQUIDATION_ADAPTER, sig, GUARDIAN] as [string, string, string]), +]; + +export const vip664 = () => { + const meta = { + version: "v1", + title: "VIP-664 [BNB Chain Testnet] Configure Institutional Fixed Rate Vault System", + description: `#### Summary + +If passed, this VIP will configure the Institutional Fixed Rate Vault system on BNB Chain Testnet: + +1. Grant ACM permissions (81 total) via \`ACMCommandsAggregator\` to all three governance timelocks (Normal, Fast-track, Critical) for all access-controlled functions on \`InstitutionalVaultController\` and \`LiquidationAdapter\`, and to the Guardian for operational functions on both contracts. +2. Accept ownership of \`InstitutionalVaultController\` and \`LiquidationAdapter\` (two-step Ownable2Step transfer initiated in deploy script). +3. Set the \`LiquidationAdapter\` on the controller via \`setLiquidationAdapter()\`. +4. Complete the two-step position token ownership transfer via \`acceptPositionTokenOwnership()\`. +5. Whitelist the Guardian as a liquidator and settler on the \`LiquidationAdapter\`. + +#### Deployed Contracts + +- **InstitutionalVaultController** (proxy): ${INSTITUTIONAL_VAULT_CONTROLLER} +- **LiquidationAdapter** (proxy): ${LIQUIDATION_ADAPTER} +- **InstitutionPositionToken**: ${INSTITUTION_POSITION_TOKEN} + +#### Permission Summary + +| Timelock | Contract | Permissions | +|---|---|---| +| Normal | InstitutionalVaultController | 19 functions (all operational + setter functions) | +| Fast-track | InstitutionalVaultController | 19 functions (all operational + setter functions) | +| Critical | InstitutionalVaultController | 19 functions (all operational + setter functions) | +| Guardian | InstitutionalVaultController | 6 functions (pause/unpause + open/close/sweep) | +| Normal | LiquidationAdapter | 5 functions (all setter functions) | +| Fast-track | LiquidationAdapter | 5 functions (all setter functions) | +| Critical | LiquidationAdapter | 5 functions (all setter functions) | +| Guardian | LiquidationAdapter | 3 functions (sweep + whitelist management) |`, + forDescription: "I agree that Venus Protocol should proceed with this proposal", + againstDescription: "I do not think that Venus Protocol should proceed with this proposal", + abstainDescription: "I am indifferent to whether Venus Protocol proceeds or not", + }; + + return makeProposal( + [ + // ────────────────────────────────────────────────────────────────────── + // Phase 1 — ACM permissions via Aggregator + // ────────────────────────────────────────────────────────────────────── + // Permissions were pre-loaded into ACM Aggregator via addGrantPermissions.ts. + // Grant admin role, execute batched permissions, then revoke admin role. + + { + target: ACCESS_CONTROL_MANAGER, + signature: "grantRole(bytes32,address)", + params: [DEFAULT_ADMIN_ROLE, ACM_AGGREGATOR], + }, + { + target: ACM_AGGREGATOR, + signature: "executeGrantPermissions(uint256)", + params: [ACM_AGGREGATOR_INDEX], + }, + { + target: ACCESS_CONTROL_MANAGER, + signature: "revokeRole(bytes32,address)", + params: [DEFAULT_ADMIN_ROLE, ACM_AGGREGATOR], + }, + + // ────────────────────────────────────────────────────────────────────── + // Phase 2 — Ownership acceptance + // ────────────────────────────────────────────────────────────────────── + // Deploy script called transferOwnership(NORMAL_TIMELOCK) on both contracts. + // acceptOwnership() completes the Ownable2Step transfer. + + { + target: INSTITUTIONAL_VAULT_CONTROLLER, + signature: "acceptOwnership()", + params: [], + }, + { + target: LIQUIDATION_ADAPTER, + signature: "acceptOwnership()", + params: [], + }, + + // ────────────────────────────────────────────────────────────────────── + // Phase 3 — System wiring + // ────────────────────────────────────────────────────────────────────── + // Note: NORMAL_TIMELOCK must have the ACM permission for both calls below, + // which is granted in Phase 1 above. Commands execute atomically in order. + + { + target: INSTITUTIONAL_VAULT_CONTROLLER, + signature: "setLiquidationAdapter(address)", + params: [LIQUIDATION_ADAPTER], + }, + { + target: INSTITUTIONAL_VAULT_CONTROLLER, + signature: "acceptPositionTokenOwnership()", + params: [], + }, + + // ────────────────────────────────────────────────────────────────────── + // Phase 4 — Guardian whitelist configuration + // ────────────────────────────────────────────────────────────────────── + + { + target: LIQUIDATION_ADAPTER, + signature: "setLiquidatorWhitelist(address,bool)", + params: [GUARDIAN, true], + }, + { + target: LIQUIDATION_ADAPTER, + signature: "setSettlerWhitelist(address,bool)", + params: [GUARDIAN, true], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip664;