diff --git a/simulations/vip-800/abi/AccessControlManager.json b/simulations/vip-800/abi/AccessControlManager.json new file mode 100644 index 000000000..2ef119947 --- /dev/null +++ b/simulations/vip-800/abi/AccessControlManager.json @@ -0,0 +1,157 @@ +[ + { "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-800/abi/DefaultProxyAdmin.json b/simulations/vip-800/abi/DefaultProxyAdmin.json new file mode 100644 index 000000000..9801cfcc7 --- /dev/null +++ b/simulations/vip-800/abi/DefaultProxyAdmin.json @@ -0,0 +1,76 @@ +[ + { + "inputs": [{ "internalType": "address", "name": "initialOwner", "type": "address" }], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "previousOwner", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { "internalType": "contract TransparentUpgradeableProxy", "name": "proxy", "type": "address" }, + { "internalType": "address", "name": "newAdmin", "type": "address" } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract TransparentUpgradeableProxy", "name": "proxy", "type": "address" }], + "name": "getProxyAdmin", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract TransparentUpgradeableProxy", "name": "proxy", "type": "address" }], + "name": "getProxyImplementation", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract TransparentUpgradeableProxy", "name": "proxy", "type": "address" }, + { "internalType": "address", "name": "implementation", "type": "address" } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "contract TransparentUpgradeableProxy", "name": "proxy", "type": "address" }, + { "internalType": "address", "name": "implementation", "type": "address" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/simulations/vip-800/abi/ERC20.json b/simulations/vip-800/abi/ERC20.json new file mode 100644 index 000000000..28715d783 --- /dev/null +++ b/simulations/vip-800/abi/ERC20.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-800/abi/ProtocolShareReserve.json b/simulations/vip-800/abi/ProtocolShareReserve.json new file mode 100644 index 000000000..b33d7c495 --- /dev/null +++ b/simulations/vip-800/abi/ProtocolShareReserve.json @@ -0,0 +1,356 @@ +[ + { + "inputs": [ + { "internalType": "address", "name": "_corePoolComptroller", "type": "address" }, + { "internalType": "address", "name": "_wbnb", "type": "address" }, + { "internalType": "address", "name": "_vbnb", "type": "address" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { "inputs": [], "name": "InvalidAddress", "type": "error" }, + { "inputs": [], "name": "InvalidTotalPercentage", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "loopsLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "requiredLoops", "type": "uint256" } + ], + "name": "MaxLoopsLimitExceeded", + "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" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "destination", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "indexed": false, "internalType": "uint256", "name": "percent", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "AssetReleased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "comptroller", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "indexed": false, + "internalType": "enum IProtocolShareReserve.IncomeType", + "name": "incomeType", + "type": "uint8" + }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" } + ], + "name": "AssetsReservesUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "destination", "type": "address" }, + { "indexed": false, "internalType": "uint16", "name": "percentage", "type": "uint16" }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" } + ], + "name": "DistributionConfigAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "destination", "type": "address" }, + { "indexed": false, "internalType": "uint16", "name": "percentage", "type": "uint16" }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" } + ], + "name": "DistributionConfigRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "destination", "type": "address" }, + { "indexed": false, "internalType": "uint16", "name": "oldPercentage", "type": "uint16" }, + { "indexed": false, "internalType": "uint16", "name": "newPercentage", "type": "uint16" }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" } + ], + "name": "DistributionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldMaxLoopsLimit", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newmaxLoopsLimit", "type": "uint256" } + ], + "name": "MaxLoopsLimitUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "address", "name": "oldAccessControlManager", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "newAccessControlManager", "type": "address" } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "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": "oldPoolRegistry", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newPoolRegistry", "type": "address" } + ], + "name": "PoolRegistryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "comptroller", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "indexed": false, "internalType": "uint256", "name": "oldBalance", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newBalance", "type": "uint256" } + ], + "name": "ReservesUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "CORE_POOL_COMPTROLLER", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "MAX_PERCENT", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "WBNB", + "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": [ + { + "components": [ + { "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "internalType": "uint16", "name": "percentage", "type": "uint16" }, + { "internalType": "address", "name": "destination", "type": "address" } + ], + "internalType": "struct ProtocolShareReserve.DistributionConfig[]", + "name": "configs", + "type": "tuple[]" + } + ], + "name": "addOrUpdateDistributionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "enum ProtocolShareReserve.Schema", "name": "", "type": "uint8" } + ], + "name": "assetsReserves", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "distributionTargets", + "outputs": [ + { "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "internalType": "uint16", "name": "percentage", "type": "uint16" }, + { "internalType": "address", "name": "destination", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "destination", "type": "address" }, + { "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" } + ], + "name": "getPercentageDistribution", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "internalType": "address", "name": "destination", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" } + ], + "name": "getUnreleasedFunds", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_accessControlManager", "type": "address" }, + { "internalType": "uint256", "name": "_loopsLimit", "type": "uint256" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "maxLoopsLimit", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "poolRegistry", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "address[]", "name": "assets", "type": "address[]" } + ], + "name": "releaseFunds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "enum ProtocolShareReserve.Schema", "name": "schema", "type": "uint8" }, + { "internalType": "address", "name": "destination", "type": "address" } + ], + "name": "removeDistributionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "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": "_poolRegistry", "type": "address" }], + "name": "setPoolRegistry", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "totalAssetReserve", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalDistributions", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" }, + { "internalType": "enum IProtocolShareReserve.IncomeType", "name": "incomeType", "type": "uint8" } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "vBNB", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-800/abi/SingleTokenConverter.json b/simulations/vip-800/abi/SingleTokenConverter.json new file mode 100644 index 000000000..8ea10cc8d --- /dev/null +++ b/simulations/vip-800/abi/SingleTokenConverter.json @@ -0,0 +1,587 @@ +[ + { "inputs": [], "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMaxMantissa", "type": "uint256" } + ], + "name": "AmountInHigherThanMax", + "type": "error" + }, + { "inputs": [], "name": "AmountInMismatched", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMinMantissa", "type": "uint256" } + ], + "name": "AmountOutLowerThanMinRequired", + "type": "error" + }, + { "inputs": [], "name": "AmountOutMismatched", "type": "error" }, + { "inputs": [], "name": "ConversionConfigNotEnabled", "type": "error" }, + { "inputs": [], "name": "ConversionEnabledOnlyForPrivateConversions", "type": "error" }, + { "inputs": [], "name": "ConversionTokensActive", "type": "error" }, + { "inputs": [], "name": "ConversionTokensPaused", "type": "error" }, + { "inputs": [], "name": "DeflationaryTokenNotSupported", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "incentive", "type": "uint256" }, + { "internalType": "uint256", "name": "maxIncentive", "type": "uint256" } + ], + "name": "IncentiveTooHigh", + "type": "error" + }, + { "inputs": [], "name": "InputLengthMisMatch", "type": "error" }, + { "inputs": [], "name": "InsufficientInputAmount", "type": "error" }, + { "inputs": [], "name": "InsufficientOutputAmount", "type": "error" }, + { "inputs": [], "name": "InsufficientPoolLiquidity", "type": "error" }, + { "inputs": [], "name": "InvalidConverterNetwork", "type": "error" }, + { "inputs": [], "name": "InvalidMinimumAmountToConvert", "type": "error" }, + { "inputs": [], "name": "InvalidToAddress", "type": "error" }, + { "inputs": [], "name": "InvalidTokenConfigAddresses", "type": "error" }, + { "inputs": [], "name": "NonZeroIncentiveForPrivateConversion", "type": "error" }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" }, + { "internalType": "address", "name": "calledContract", "type": "address" }, + { "internalType": "string", "name": "methodSignature", "type": "string" } + ], + "name": "Unauthorized", + "type": "error" + }, + { "inputs": [], "name": "ZeroAddressNotAllowed", "type": "error" }, + { "inputs": [], "name": "ZeroValueNotAllowed", "type": "error" }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "comptroller", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "asset", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "AssetTransferredToDestination", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldBaseAsset", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "newBaseAsset", "type": "address" } + ], + "name": "BaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "oldIncentive", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newIncentive", "type": "uint256" }, + { + "indexed": false, + "internalType": "enum IAbstractTokenConverter.ConversionAccessibility", + "name": "oldAccess", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "enum IAbstractTokenConverter.ConversionAccessibility", + "name": "newAccess", + "type": "uint8" + } + ], + "name": "ConversionConfigUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "sender", "type": "address" }], + "name": "ConversionPaused", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": true, "internalType": "address", "name": "sender", "type": "address" }], + "name": "ConversionResumed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "name": "ConvertedExactTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "name": "ConvertedExactTokensSupportingFeeOnTransferTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "name": "ConvertedForExactTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "sender", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "receiver", "type": "address" }, + { "indexed": false, "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "amountOut", "type": "uint256" } + ], + "name": "ConvertedForExactTokensSupportingFeeOnTransferTokens", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldConverterNetwork", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "converterNetwork", "type": "address" } + ], + "name": "ConverterNetworkAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "oldDestinationAddress", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "destinationAddress", "type": "address" } + ], + "name": "DestinationAddressUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [{ "indexed": false, "internalType": "uint8", "name": "version", "type": "uint8" }], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": false, "internalType": "uint256", "name": "oldMinAmountToConvert", "type": "uint256" }, + { "indexed": false, "internalType": "uint256", "name": "newMinAmountToConvert", "type": "uint256" } + ], + "name": "MinAmountToConvertUpdated", + "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": "contract ResilientOracle", "name": "oldPriceOracle", "type": "address" }, + { "indexed": true, "internalType": "contract ResilientOracle", "name": "priceOracle", "type": "address" } + ], + "name": "PriceOracleUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { "indexed": true, "internalType": "address", "name": "token", "type": "address" }, + { "indexed": true, "internalType": "address", "name": "to", "type": "address" }, + { "indexed": false, "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "SweepToken", + "type": "event" + }, + { + "inputs": [], + "name": "MAX_INCENTIVE", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "acceptOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [{ "internalType": "contract IAccessControlManagerV8", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "tokenAddress", "type": "address" }], + "name": "balanceOf", + "outputs": [{ "internalType": "uint256", "name": "tokenBalance", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "baseAsset", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "address", "name": "", "type": "address" } + ], + "name": "conversionConfigurations", + "outputs": [ + { "internalType": "uint256", "name": "incentive", "type": "uint256" }, + { + "internalType": "enum IAbstractTokenConverter.ConversionAccessibility", + "name": "conversionAccess", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "conversionPaused", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMinMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "convertExactTokens", + "outputs": [ + { "internalType": "uint256", "name": "actualAmountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "actualAmountOut", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMinMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "convertExactTokensSupportingFeeOnTransferTokens", + "outputs": [ + { "internalType": "uint256", "name": "actualAmountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "actualAmountOut", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMaxMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "convertForExactTokens", + "outputs": [ + { "internalType": "uint256", "name": "actualAmountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "actualAmountOut", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMaxMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" } + ], + "name": "convertForExactTokensSupportingFeeOnTransferTokens", + "outputs": [ + { "internalType": "uint256", "name": "actualAmountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "actualAmountOut", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "converterNetwork", + "outputs": [{ "internalType": "contract IConverterNetwork", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "destinationAddress", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" } + ], + "name": "getAmountIn", + "outputs": [ + { "internalType": "uint256", "name": "amountConvertedMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" } + ], + "name": "getAmountOut", + "outputs": [ + { "internalType": "uint256", "name": "amountConvertedMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" } + ], + "name": "getUpdatedAmountIn", + "outputs": [ + { "internalType": "uint256", "name": "amountConvertedMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "amountInMantissa", "type": "uint256" }, + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" } + ], + "name": "getUpdatedAmountOut", + "outputs": [ + { "internalType": "uint256", "name": "amountConvertedMantissa", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMantissa", "type": "uint256" } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "accessControlManager_", "type": "address" }, + { "internalType": "contract ResilientOracle", "name": "priceOracle_", "type": "address" }, + { "internalType": "address", "name": "destinationAddress_", "type": "address" }, + { "internalType": "address", "name": "baseAsset_", "type": "address" }, + { "internalType": "uint256", "name": "minAmountToConvert_", "type": "uint256" } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "minAmountToConvert", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "pauseConversion", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "priceOracle", + "outputs": [{ "internalType": "contract ResilientOracle", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { "inputs": [], "name": "renounceOwnership", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { "inputs": [], "name": "resumeConversion", "outputs": [], "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [{ "internalType": "address", "name": "accessControlManager_", "type": "address" }], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "baseAsset_", "type": "address" }], + "name": "setBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address", "name": "tokenAddressOut", "type": "address" }, + { + "components": [ + { "internalType": "uint256", "name": "incentive", "type": "uint256" }, + { + "internalType": "enum IAbstractTokenConverter.ConversionAccessibility", + "name": "conversionAccess", + "type": "uint8" + } + ], + "internalType": "struct IAbstractTokenConverter.ConversionConfig", + "name": "conversionConfig", + "type": "tuple" + } + ], + "name": "setConversionConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddressIn", "type": "address" }, + { "internalType": "address[]", "name": "tokenAddressesOut", "type": "address[]" }, + { + "components": [ + { "internalType": "uint256", "name": "incentive", "type": "uint256" }, + { + "internalType": "enum IAbstractTokenConverter.ConversionAccessibility", + "name": "conversionAccess", + "type": "uint8" + } + ], + "internalType": "struct IAbstractTokenConverter.ConversionConfig[]", + "name": "conversionConfigs", + "type": "tuple[]" + } + ], + "name": "setConversionConfigs", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract IConverterNetwork", "name": "converterNetwork_", "type": "address" }], + "name": "setConverterNetwork", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "destinationAddress_", "type": "address" }], + "name": "setDestination", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "minAmountToConvert_", "type": "uint256" }], + "name": "setMinAmountToConvert", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "contract ResilientOracle", "name": "priceOracle_", "type": "address" }], + "name": "setPriceOracle", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "tokenAddress", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "newOwner", "type": "address" }], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "address", "name": "asset", "type": "address" } + ], + "name": "updateAssetsState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-800/abi/TokenBuyback.json b/simulations/vip-800/abi/TokenBuyback.json new file mode 100644 index 000000000..8cd3bd6cc --- /dev/null +++ b/simulations/vip-800/abi/TokenBuyback.json @@ -0,0 +1,97 @@ +[ + { + "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": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "router", "type": "address" }, + { "internalType": "bool", "name": "allowed", "type": "bool" } + ], + "name": "setAllowedRouter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "allowedRouters", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "router", "type": "address" }, + { "internalType": "uint256", "name": "amountIn", "type": "uint256" }, + { "internalType": "uint256", "name": "amountOutMin", "type": "uint256" }, + { "internalType": "uint256", "name": "deadline", "type": "uint256" }, + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "bytes", "name": "path", "type": "bytes" }, + { "internalType": "address", "name": "tokenIn", "type": "address" } + ], + "name": "executeBuyback", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "comptroller", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "forwardBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "address", "name": "to", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "sweepToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "PROTOCOL_SHARE_RESERVE", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "BASE_ASSET", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DESTINATION", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + } +] diff --git a/simulations/vip-800/bscmainnet.ts b/simulations/vip-800/bscmainnet.ts new file mode 100644 index 000000000..7ae2d1e92 --- /dev/null +++ b/simulations/vip-800/bscmainnet.ts @@ -0,0 +1,145 @@ +import { expect } from "chai"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { forking, testVip } from "src/vip-framework"; + +import vip800, { + BUYBACKS, + DEFAULT_PROXY_ADMIN, + NEW_RISK_FUND_V2_IMPL, + OPERATOR, + PANCAKE_ROUTER, + PROTOCOL_SHARE_RESERVE, + RISK_FUND_V2, + SHORTFALL, + USDT, +} from "../../vips/vip-800/bscmainnet"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import DEFAULT_PROXY_ADMIN_ABI from "./abi/DefaultProxyAdmin.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import PSR_ABI from "./abi/ProtocolShareReserve.json"; +import BUYBACK_ABI from "./abi/TokenBuyback.json"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +// TODO: pin after deploy on feat/VPD-1087 so fork includes deployed buyback proxies +// + new RiskFundV2 impl. Pick a recent block >= first post-deploy block. +const FORK_BLOCK = 0; + +const SHORTFALL_MIN_ABI = ["function auctionsPaused() view returns (bool)"]; + +forking(FORK_BLOCK, async () => { + const acm = new ethers.Contract(bscmainnet.ACCESS_CONTROL_MANAGER, ACM_ABI, ethers.provider); + const proxyAdmin = new ethers.Contract(DEFAULT_PROXY_ADMIN, DEFAULT_PROXY_ADMIN_ABI, ethers.provider); + const psr = new ethers.Contract(PROTOCOL_SHARE_RESERVE, PSR_ABI, ethers.provider); + const usdt = new ethers.Contract(USDT, ERC20_ABI, ethers.provider); + const shortfall = new ethers.Contract(SHORTFALL, SHORTFALL_MIN_ABI, ethers.provider); + + let riskFundV2UsdtBalanceBefore: BigNumber; + let shortfallAuctionsPausedBefore: boolean; + + before(async () => { + riskFundV2UsdtBalanceBefore = await usdt.balanceOf(RISK_FUND_V2); + shortfallAuctionsPausedBefore = await shortfall.auctionsPaused(); + }); + + describe("Pre-VIP state", () => { + it("each buyback proxy's pendingOwner is NormalTimelock", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.pendingOwner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + } + }); + + it("PancakeSwap router is not yet allowlisted on buybacks", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.allowedRouters(PANCAKE_ROUTER)).to.be.false; + } + }); + + it("operator has no executeBuyback / forwardBaseAsset grants yet", async () => { + for (const b of BUYBACKS) { + expect( + await acm.isAllowedToCall( + OPERATOR, + b, + "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)", + ), + ).to.be.false; + expect(await acm.isAllowedToCall(OPERATOR, b, "forwardBaseAsset(address,uint256)")).to.be.false; + } + }); + + it("captures Shortfall.auctionsPaused() pre-state (informational)", async () => { + // No assertion on the pre-state: isolated pools are wound down so the flag + // could be either value depending on prior governance actions. The post-VIP + // assertion is what matters. + expect(typeof shortfallAuctionsPausedBefore).to.equal("boolean"); + }); + }); + + testVip("VIP-800 TokenBuyback migration", await vip800()); + + describe("Post-VIP state", () => { + it("NormalTimelock owns each buyback proxy", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.owner()).to.equal(bscmainnet.NORMAL_TIMELOCK); + } + }); + + it("PancakeSwap V2 router allowlisted on each buyback", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.allowedRouters(PANCAKE_ROUTER)).to.be.true; + } + }); + + it("operator granted executeBuyback + forwardBaseAsset on each buyback", async () => { + for (const b of BUYBACKS) { + expect( + await acm.isAllowedToCall( + OPERATOR, + b, + "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)", + ), + ).to.be.true; + expect(await acm.isAllowedToCall(OPERATOR, b, "forwardBaseAsset(address,uint256)")).to.be.true; + } + }); + + it("RiskFundV2 proxy upgraded to new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(RISK_FUND_V2)).to.equal(NEW_RISK_FUND_V2_IMPL); + }); + + it("RiskFundV2 USDT balance non-decreasing across upgrade", async () => { + // New impl keeps funds physically in the contract (no migration). + const after = await usdt.balanceOf(RISK_FUND_V2); + expect(after).to.be.gte(riskFundV2UsdtBalanceBefore); + }); + + // TODO: enumerate PSR.distributionTargets(i) and assert each of the 10 new buybacks + // is a destination, no legacy converter remains, and percentages sum to 1e4 + // per schema. Placeholder assertion below; flesh out after PSR rows filled. + it("PSR distribution configs repointed", async () => { + // Example shape — iterate until the getter reverts to enumerate: + // const rows = []; + // for (let i = 0; ; i++) { + // try { rows.push(await psr.distributionTargets(i)); } catch { break; } + // } + // expect(rows.map(r => r.destination)).to.include.members(BUYBACKS); + void psr; + }); + + // TODO: legacy converter residual balances == 0 for drained tokens + it("legacy converter balances drained", async () => { + // TODO + }); + + it("Shortfall auctions are paused (defense in depth)", async () => { + expect(await shortfall.auctionsPaused()).to.be.true; + }); + }); +}); diff --git a/simulations/vip-800/bsctestnet.ts b/simulations/vip-800/bsctestnet.ts new file mode 100644 index 000000000..345c9dd0d --- /dev/null +++ b/simulations/vip-800/bsctestnet.ts @@ -0,0 +1,144 @@ +import { expect } from "chai"; +import { BigNumber } from "ethers"; +import { ethers } from "hardhat"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { forking, testVip } from "src/vip-framework"; + +import vip800, { + BUYBACKS, + DEFAULT_PROXY_ADMIN, + NEW_RISK_FUND_V2_IMPL, + OPERATOR, + PANCAKE_ROUTER, + PROTOCOL_SHARE_RESERVE, + RISK_FUND_V2, + SHORTFALL, + USDT, +} from "../../vips/vip-800/bsctestnet"; +import ACM_ABI from "./abi/AccessControlManager.json"; +import DEFAULT_PROXY_ADMIN_ABI from "./abi/DefaultProxyAdmin.json"; +import ERC20_ABI from "./abi/ERC20.json"; +import PSR_ABI from "./abi/ProtocolShareReserve.json"; +import BUYBACK_ABI from "./abi/TokenBuyback.json"; + +const { bsctestnet } = NETWORK_ADDRESSES; + +// TODO +const FORK_BLOCK = 0; + +const SHORTFALL_MIN_ABI = ["function auctionsPaused() view returns (bool)"]; + +forking(FORK_BLOCK, async () => { + const acm = new ethers.Contract(bsctestnet.ACCESS_CONTROL_MANAGER, ACM_ABI, ethers.provider); + const proxyAdmin = new ethers.Contract(DEFAULT_PROXY_ADMIN, DEFAULT_PROXY_ADMIN_ABI, ethers.provider); + const psr = new ethers.Contract(PROTOCOL_SHARE_RESERVE, PSR_ABI, ethers.provider); + const usdt = new ethers.Contract(USDT, ERC20_ABI, ethers.provider); + const shortfall = new ethers.Contract(SHORTFALL, SHORTFALL_MIN_ABI, ethers.provider); + + let riskFundV2UsdtBalanceBefore: BigNumber; + let shortfallAuctionsPausedBefore: boolean; + + before(async () => { + riskFundV2UsdtBalanceBefore = await usdt.balanceOf(RISK_FUND_V2); + shortfallAuctionsPausedBefore = await shortfall.auctionsPaused(); + }); + + describe("Pre-VIP state", () => { + it("each buyback proxy's pendingOwner is NormalTimelock", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.pendingOwner()).to.equal(bsctestnet.NORMAL_TIMELOCK); + } + }); + + it("PancakeSwap router is not yet allowlisted on buybacks", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.allowedRouters(PANCAKE_ROUTER)).to.be.false; + } + }); + + it("operator has no executeBuyback / forwardBaseAsset grants yet", async () => { + for (const b of BUYBACKS) { + expect( + await acm.isAllowedToCall( + OPERATOR, + b, + "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)", + ), + ).to.be.false; + expect(await acm.isAllowedToCall(OPERATOR, b, "forwardBaseAsset(address,uint256)")).to.be.false; + } + }); + + it("captures Shortfall.auctionsPaused() pre-state (informational)", async () => { + // No assertion on the pre-state: isolated pools are wound down so the flag + // could be either value depending on prior governance actions. + expect(typeof shortfallAuctionsPausedBefore).to.equal("boolean"); + }); + }); + + testVip("VIP-800 [BNB Chain Testnet] TokenBuyback migration", await vip800()); + + describe("Post-VIP state", () => { + it("NormalTimelock owns each buyback proxy", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.owner()).to.equal(bsctestnet.NORMAL_TIMELOCK); + } + }); + + it("PancakeSwap V2 router allowlisted on each buyback", async () => { + for (const b of BUYBACKS) { + const buyback = new ethers.Contract(b, BUYBACK_ABI, ethers.provider); + expect(await buyback.allowedRouters(PANCAKE_ROUTER)).to.be.true; + } + }); + + it("operator granted executeBuyback + forwardBaseAsset on each buyback", async () => { + for (const b of BUYBACKS) { + expect( + await acm.isAllowedToCall( + OPERATOR, + b, + "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)", + ), + ).to.be.true; + expect(await acm.isAllowedToCall(OPERATOR, b, "forwardBaseAsset(address,uint256)")).to.be.true; + } + }); + + it("RiskFundV2 proxy upgraded to new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(RISK_FUND_V2)).to.equal(NEW_RISK_FUND_V2_IMPL); + }); + + it("RiskFundV2 USDT balance non-decreasing across upgrade", async () => { + // New impl keeps funds physically in the contract (no migration). + const after = await usdt.balanceOf(RISK_FUND_V2); + expect(after).to.be.gte(riskFundV2UsdtBalanceBefore); + }); + + // TODO: enumerate PSR.distributionTargets(i) and assert each of the 10 new buybacks + // is a destination, no legacy converter remains, and percentages sum to 1e4 + // per schema. Placeholder assertion below; flesh out after PSR rows filled. + it("PSR distribution configs repointed", async () => { + // Example shape — iterate until the getter reverts to enumerate: + // const rows = []; + // for (let i = 0; ; i++) { + // try { rows.push(await psr.distributionTargets(i)); } catch { break; } + // } + // expect(rows.map(r => r.destination)).to.include.members(BUYBACKS); + void psr; + }); + + // TODO: legacy converter residual balances == 0 for drained tokens + // (skipped on testnet if amounts are below gas-worth per PRD note). + it("legacy converter balances drained", async () => { + // TODO + }); + + it("Shortfall auctions are paused (defense in depth)", async () => { + expect(await shortfall.auctionsPaused()).to.be.true; + }); + }); +}); diff --git a/vips/vip-800/bscmainnet.ts b/vips/vip-800/bscmainnet.ts new file mode 100644 index 000000000..e29fc6527 --- /dev/null +++ b/vips/vip-800/bscmainnet.ts @@ -0,0 +1,186 @@ +import { ethers } from "ethers"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { bscmainnet } = NETWORK_ADDRESSES; + +export const DEFAULT_PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; +export const PROTOCOL_SHARE_RESERVE = "0xCa01D5A9A248a830E9D93231e791B1afFed7c446"; +export const RISK_FUND_V2 = "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42"; +export const PRIME_LIQUIDITY_PROVIDER = "0x23c4F844ffDdC6161174eB32c770D4D8C07833F2"; +export const XVS_VAULT_TREASURY = "0x269ff7818DB317f60E386D2be0B259e1a324a40a"; +export const PANCAKE_ROUTER = "0x10ED43C718714eb63d5aA57B78B54704E256024E"; +export const SHORTFALL = "0xf37530A8a810Fcb501AA0Ecd0B0699388F0F2209"; + +// ===== Tokens ===== +export const USDT = "0x55d398326f99059fF775485246999027B3197955"; +export const USDC = "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d"; +export const BTCB = "0x7130d2A12B9BCbFAe4f2634d864A1Ee1Ce3Ead9c"; +export const ETH = "0x2170Ed0880ac9A755fd29B2688956BD959F933F8"; +export const XVS = "0xcF6BB5389c92Bdda8a3747Ddb454cB7a64626C63"; +export const U = "0xcE24439F2D9C6a2289F741120FE202248B666666"; +export const WBNB = "0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c"; + +// ===== Legacy converters (drain + revoke) ===== +export const RISK_FUND_CONVERTER = "0xA5622D276CcbB8d9BBE3D1ffd1BB11a0032E53F0"; +export const USDT_PRIME_CONVERTER = "0xD9f101AA67F3D72662609a2703387242452078C3"; +export const USDC_PRIME_CONVERTER = "0xa758c9C215B6c4198F0a0e3FA46395Fa15Db691b"; +export const BTCB_PRIME_CONVERTER = "0xE8CeAa79f082768f99266dFd208d665d2Dd18f53"; +export const ETH_PRIME_CONVERTER = "0xca430B8A97Ea918fF634162acb0b731445B8195E"; +export const XVS_VAULT_CONVERTER = "0xd5b9AE835F4C59272032B3B954417179573331E0"; +export const WBNB_BURN_CONVERTER = "0x9eF79830e626C8ccA7e46DCEd1F90e51E7cFCeBE"; +export const CONVERTER_NETWORK = "0xF7Caad5CeB0209165f2dFE71c92aDe14d0F15995"; + +// ===== New TokenBuyback proxies (10 instances) ===== +// TODO: fill deployed proxy addresses from `npx hardhat deploy --tags RiskFundBuyback, +// PrimeBuyback,XVSBuyback,TreasuryBuyback --network bscmainnet` on feat/VPD-1087. +export const RISK_FUND_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDT_PRIME_BUYBACK = ethers.constants.AddressZero; // TODO +export const U_PRIME_BUYBACK = ethers.constants.AddressZero; // TODO +export const XVS_BUYBACK = ethers.constants.AddressZero; // TODO +export const U_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const BTCB_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const ETH_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDT_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDC_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const XVS_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO + +export const BUYBACKS: string[] = [ + RISK_FUND_BUYBACK, + USDT_PRIME_BUYBACK, + U_PRIME_BUYBACK, + XVS_BUYBACK, + U_TREASURY_BUYBACK, + BTCB_TREASURY_BUYBACK, + ETH_TREASURY_BUYBACK, + USDT_TREASURY_BUYBACK, + USDC_TREASURY_BUYBACK, + XVS_TREASURY_BUYBACK, +]; + +// ===== New RiskFundV2 implementation ===== +// TODO: fill post-deploy. New impl drops updatePoolState / sweepTokenFromPool / +// poolAssetsFunds mapping; transferReserveForAuction reads raw balance. +export const NEW_RISK_FUND_V2_IMPL = ethers.constants.AddressZero; // TODO + +// ===== Cron operator ===== +// TODO: finance-team EOA / multisig +export const OPERATOR = ethers.constants.AddressZero; // TODO + +// Sighashes (strings — ACM grants are keyed by full signature) +const EXECUTE_BUYBACK_SIG = "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)"; +const FORWARD_BASE_ASSET_SIG = "forwardBaseAsset(address,uint256)"; + +export const vip800 = () => { + const meta = { + version: "v2", + title: "VIP-800 TokenBuyback migration", + description: `#### Summary + +If passed, this VIP replaces the community-driven Token Converter system (RiskFundConverter + 4 *PrimeConverter + XVSVaultConverter + WBNBBurnConverter + ConverterNetwork) with **10 ACM-authorized TokenBuyback proxies** driven by a finance-team cron. BSC-only; this VIP targets **BNB Chain**. + +#### Proposed Changes + +1. **Upgrade RiskFundV2 implementation** — new impl removes \`updatePoolState\`, \`sweepTokenFromPool\`, and the \`poolAssetsFunds\` mapping (storage slot preserved as \`__deprecatedSlotPoolAssetsFunds\`). \`transferReserveForAuction\` now reads raw balance. Per-pool accounting was dead weight since isolated pools are wound down and the core pool does not auction via Shortfall. +2. **Accept ownership** on each of the 10 new buyback proxies (deploy script already called \`transferOwnership(NormalTimelock)\`). +3. **Allowlist PancakeSwap V2 router** on each of the 10 buybacks. +4. **Grant ACM permissions** on \`executeBuyback\` + \`forwardBaseAsset\` for the cron operator on each of the 10 buybacks. +5. **Drain legacy converters** (remaining tokens → new buyback or VTreasury). +6. **Revoke ACM permissions** on legacy converters. +7. **Repoint ProtocolShareReserve distributions** from legacy converters to the 10 new buybacks. +8. **Defensively call \`Shortfall.pauseAuctions()\`** to keep the auction surface closed post-upgrade. The shortfall auction mechanism is exclusive to isolated pools, and isolated pools are no longer operational; there are no ongoing or upcoming auctions, so the migration window cannot encounter a STARTED auction carrying a stale pre-upgrade \`seizedRiskFund\` snapshot. The \`auctionsPaused\` flag, the \`transferReserveForAuction\` global balance check, and any on-chain status verification step are therefore not needed in the upgrade path — \`pauseAuctions()\` is included purely as defense in depth. + +Because the new RiskFundV2 impl removes \`updatePoolState\`, RiskFundConverter drain + ACM revoke are ordered **before** the upgrade to prevent in-flight \`convertExactTokens\` callbacks reverting. + +Implementation: [VenusProtocol/protocol-reserve PR #158](https://github.com/VenusProtocol/protocol-reserve/pull/158). Testnet sign-off gate: 24–48h of green cron operation covering at least one \`executeBuyback\` per instance and one \`forwardBaseAsset\` per destination. + +#### Retired contracts + +- WBNBBurnConverter — no longer burns BNB (protocol shifted away from buy-and-burn). +- ConverterNetwork — routing layer no longer needed with direct PSR → Buyback wiring. + +#### Conclusion + +Replaces a complex multi-contract converter system with 10 single-purpose buybacks and an off-chain operator, ending the 50% premium and oracle coupling while consolidating custody under NormalTimelock-owned proxies.`, + 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( + [ + // PRE-UPGRADE: drain + revoke RiskFundConverter (must precede RiskFundV2 upgrade) + // TODO: sweepToken for each held asset, then revokeCallPermission for each grant + + // 1. Upgrade RiskFundV2 implementation + { + target: DEFAULT_PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [RISK_FUND_V2, NEW_RISK_FUND_V2_IMPL], + }, + + // 2. Accept ownership of each of the 10 TokenBuyback proxies + ...BUYBACKS.map(b => ({ + target: b, + signature: "acceptOwnership()", + params: [], + })), + + // 3. Allowlist PancakeSwap V2 router on each buyback + ...BUYBACKS.map(b => ({ + target: b, + signature: "setAllowedRouter(address,bool)", + params: [PANCAKE_ROUTER, true], + })), + + // 4. Grant cron-operator ACM permissions on each buyback (executeBuyback + forwardBaseAsset) + ...BUYBACKS.flatMap(b => [ + { + target: bscmainnet.ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [b, EXECUTE_BUYBACK_SIG, OPERATOR], + }, + { + target: bscmainnet.ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [b, FORWARD_BASE_ASSET_SIG, OPERATOR], + }, + ]), + + // 5. Drain remaining legacy converters (RiskFundConverter already drained above) + // TODO: sweepToken per held asset per converter + + // 6. Revoke ACM permissions on remaining legacy converters + // TODO: revokeCallPermission per existing grant + + // 7. Repoint ProtocolShareReserve distribution targets to the 10 new buybacks + // TODO: fill [schema, percentage, destination] rows (sum per schema = 1e4) + { + target: PROTOCOL_SHARE_RESERVE, + signature: "addOrUpdateDistributionConfigs((uint8,uint16,address)[])", + params: [ + [ + // [schema, percentage, destination] + // TODO + ], + ], + }, + // TODO: removeDistributionConfig for any stale rows pointing at retired contracts + + // 8. Defensively pause Shortfall auctions. Isolated pools are wound down — no live + // or upcoming auctions exist — so this is purely defense in depth to keep the + // auction surface closed after the RiskFundV2 upgrade. NormalTimelock already + // holds `pauseAuctions()` permission (granted in VIP-170). + { + target: SHORTFALL, + signature: "pauseAuctions()", + params: [], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip800; diff --git a/vips/vip-800/bsctestnet.ts b/vips/vip-800/bsctestnet.ts new file mode 100644 index 000000000..f75416920 --- /dev/null +++ b/vips/vip-800/bsctestnet.ts @@ -0,0 +1,170 @@ +import { ethers } from "ethers"; +import { NETWORK_ADDRESSES } from "src/networkAddresses"; +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +const { bsctestnet } = NETWORK_ADDRESSES; + +export const DEFAULT_PROXY_ADMIN = "0x7877ffd62649b6a1557b55d4c20fcbab17344c91"; +export const PROTOCOL_SHARE_RESERVE = "0x25c7c7D6Bf710949fD7f03364E9BA19a1b3c10E3"; +export const RISK_FUND_V2 = "0x487CeF72dacABD7E12e633bb3B63815a386f7012"; +export const PRIME_LIQUIDITY_PROVIDER = "0xAdeddc73eAFCbed174e6C400165b111b0cb80B7E"; +export const XVS_VAULT_TREASURY = "0x317c6C4c9AA7F87170754DB08b4804dD689B68bF"; +export const PANCAKE_ROUTER = "0xD99D1c33F9fC3444f8101754aBC46c52416550D1"; +export const SHORTFALL = "0x503574a82fE2A9f968d355C8AAc1Ba0481859369"; + +// ===== Tokens ===== +export const USDT = "0xA11c8D9DC9b66E209Ef60F0C8D969D3CD988782c"; +export const USDC = "0x16227D60f7a0e586C66B005219dfc887D13C9531"; +export const BTCB = "0xA808e341e8e723DC6BA0Bb5204Bafc2330d7B8e4"; +export const ETH = "0x98f7A83361F7Ac8765CcEBAB1425da6b341958a7"; +export const XVS = "0xB9e0E753630434d7863528cc73CB7AC638a7c8ff"; +export const U = "0xcE24439F2D9C6a2289F741120FE202248B666666"; +export const WBNB = "0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd"; + +// ===== Legacy converters ===== +export const RISK_FUND_CONVERTER = "0x32Fbf7bBbd79355B86741E3181ef8c1D9bD309Bb"; +export const USDT_PRIME_CONVERTER = "0xf1FA230D25fC5D6CAfe87C5A6F9e1B17Bc6F194E"; +export const USDC_PRIME_CONVERTER = "0x2ecEdE6989d8646c992344fF6C97c72a3f811A13"; +export const BTCB_PRIME_CONVERTER = "0x989A1993C023a45DA141928921C0dE8fD123b7d1"; +export const ETH_PRIME_CONVERTER = "0xf358650A007aa12ecC8dac08CF8929Be7f72A4D9"; +export const XVS_VAULT_CONVERTER = "0x258f49254C758a0E37DAb148ADDAEA851F4b02a2"; +export const WBNB_BURN_CONVERTER = "0x42DBA48e7cCeB030eC73AaAe29d4A3F0cD4facba"; +export const CONVERTER_NETWORK = "0xC8f2B705d5A2474B390f735A5aFb570e1ce0b2cf"; + +// ===== New TokenBuyback proxies — TODO: fill from deploy on feat/VPD-1087 ===== +export const RISK_FUND_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDT_PRIME_BUYBACK = ethers.constants.AddressZero; // TODO +export const U_PRIME_BUYBACK = ethers.constants.AddressZero; // TODO +export const XVS_BUYBACK = ethers.constants.AddressZero; // TODO +export const U_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const BTCB_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const ETH_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDT_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const USDC_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO +export const XVS_TREASURY_BUYBACK = ethers.constants.AddressZero; // TODO + +export const BUYBACKS: string[] = [ + RISK_FUND_BUYBACK, + USDT_PRIME_BUYBACK, + U_PRIME_BUYBACK, + XVS_BUYBACK, + U_TREASURY_BUYBACK, + BTCB_TREASURY_BUYBACK, + ETH_TREASURY_BUYBACK, + USDT_TREASURY_BUYBACK, + USDC_TREASURY_BUYBACK, + XVS_TREASURY_BUYBACK, +]; + +export const NEW_RISK_FUND_V2_IMPL = ethers.constants.AddressZero; // TODO: fill from deploy +export const OPERATOR = ethers.constants.AddressZero; // TODO: finance-team cron EOA + +const EXECUTE_BUYBACK_SIG = "executeBuyback(address,uint256,uint256,uint256,address,bytes,address)"; +const FORWARD_BASE_ASSET_SIG = "forwardBaseAsset(address,uint256)"; + +export const vip800 = () => { + const meta = { + version: "v2", + title: "VIP-800 [BNB Chain Testnet] TokenBuyback migration", + description: `#### Summary + +If passed, this VIP replaces the community-driven Token Converter system (RiskFundConverter + 4 *PrimeConverter + XVSVaultConverter + WBNBBurnConverter + ConverterNetwork) with **10 ACM-authorized TokenBuyback proxies** driven by a finance-team cron. BSC-only; this VIP targets **BNB Chain Testnet**. + +#### Proposed Changes + +1. **Upgrade RiskFundV2 implementation** — new impl removes \`updatePoolState\`, \`sweepTokenFromPool\`, and the \`poolAssetsFunds\` mapping (storage slot preserved as \`__deprecatedSlotPoolAssetsFunds\`). \`transferReserveForAuction\` now reads raw balance. +2. **Accept ownership** on each of the 10 new buyback proxies (deploy script already called \`transferOwnership(NormalTimelock)\`). +3. **Allowlist PancakeSwap V2 router** on each of the 10 buybacks. +4. **Grant ACM permissions** on \`executeBuyback\` + \`forwardBaseAsset\` for the cron operator on each of the 10 buybacks. +5. **Drain legacy converters** (remaining tokens → new buyback or VTreasury). +6. **Revoke ACM permissions** on legacy converters. +7. **Repoint ProtocolShareReserve distributions** from legacy converters to the 10 new buybacks. +8. **Defensively call \`Shortfall.pauseAuctions()\`** to keep the auction surface closed post-upgrade. Isolated pools are wound down on testnet as on mainnet — no live or upcoming auctions exist, so this is purely defense in depth. + +RiskFundConverter drain + revoke is ordered **before** the upgrade — new impl removes \`updatePoolState\`, so in-flight \`convertExactTokens\` callbacks would revert. + +Implementation: [VenusProtocol/protocol-reserve PR #158](https://github.com/VenusProtocol/protocol-reserve/pull/158). + +#### Retired contracts + +- WBNBBurnConverter — protocol shifted away from buy-and-burn. +- ConverterNetwork — routing layer no longer needed with direct PSR → Buyback wiring.`, + 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( + [ + // PRE-UPGRADE: drain + revoke RiskFundConverter (must precede RiskFundV2 upgrade) + // TODO: sweepToken for each held asset, then revokeCallPermission for each grant + + // 1. Upgrade RiskFundV2 implementation + { + target: DEFAULT_PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [RISK_FUND_V2, NEW_RISK_FUND_V2_IMPL], + }, + + // 2. Accept ownership of 10 TokenBuyback proxies + ...BUYBACKS.map(b => ({ + target: b, + signature: "acceptOwnership()", + params: [], + })), + + // 3. Allowlist PancakeSwap V2 router + ...BUYBACKS.map(b => ({ + target: b, + signature: "setAllowedRouter(address,bool)", + params: [PANCAKE_ROUTER, true], + })), + + // 4. Grant cron-operator ACM permissions (executeBuyback + forwardBaseAsset × 10) + ...BUYBACKS.flatMap(b => [ + { + target: bsctestnet.ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [b, EXECUTE_BUYBACK_SIG, OPERATOR], + }, + { + target: bsctestnet.ACCESS_CONTROL_MANAGER, + signature: "giveCallPermission(address,string,address)", + params: [b, FORWARD_BASE_ASSET_SIG, OPERATOR], + }, + ]), + + // 5. Drain remaining legacy converters (RiskFundConverter already drained above) + // TODO: sweepToken per held asset per converter + + // 6. Revoke ACM permissions on remaining legacy converters + // TODO: revokeCallPermission per existing grant + + // 7. Repoint ProtocolShareReserve distribution targets to the 10 new buybacks + // TODO: fill [schema, percentage, destination] rows (sum per schema = 1e4) + { + target: PROTOCOL_SHARE_RESERVE, + signature: "addOrUpdateDistributionConfigs((uint8,uint16,address)[])", + params: [ + [ + // [schema, percentage, destination] + // TODO + ], + ], + }, + // TODO: removeDistributionConfig for any stale rows pointing at retired contracts + + // 8. Defensively pause Shortfall auctions (defense in depth post-upgrade). + { + target: SHORTFALL, + signature: "pauseAuctions()", + params: [], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip800;