From b084bba04cc2e75139fd2e65185418f1aca9642a Mon Sep 17 00:00:00 2001 From: web3rover Date: Mon, 29 Dec 2025 19:35:55 +0530 Subject: [PATCH] feat: added vip and simulation --- simulations/vip-780/abi/ProxyAdmin.json | 151 ++++++ simulations/vip-780/abi/RiskFundV2.json | 626 ++++++++++++++++++++++++ simulations/vip-780/bscmainnet.ts | 57 +++ simulations/vip-780/bsctestnet.ts | 57 +++ vips/vip-780/bscmainnet.ts | 31 ++ vips/vip-780/bsctestnet.ts | 31 ++ 6 files changed, 953 insertions(+) create mode 100644 simulations/vip-780/abi/ProxyAdmin.json create mode 100644 simulations/vip-780/abi/RiskFundV2.json create mode 100644 simulations/vip-780/bscmainnet.ts create mode 100644 simulations/vip-780/bsctestnet.ts create mode 100644 vips/vip-780/bscmainnet.ts create mode 100644 vips/vip-780/bsctestnet.ts diff --git a/simulations/vip-780/abi/ProxyAdmin.json b/simulations/vip-780/abi/ProxyAdmin.json new file mode 100644 index 000000000..b4c51d8df --- /dev/null +++ b/simulations/vip-780/abi/ProxyAdmin.json @@ -0,0 +1,151 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeProxyAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyAdmin", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + } + ], + "name": "getProxyImplementation", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract TransparentUpgradeableProxy", + "name": "proxy", + "type": "address" + }, + { + "internalType": "address", + "name": "implementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } +] diff --git a/simulations/vip-780/abi/RiskFundV2.json b/simulations/vip-780/abi/RiskFundV2.json new file mode 100644 index 000000000..4371b652d --- /dev/null +++ b/simulations/vip-780/abi/RiskFundV2.json @@ -0,0 +1,626 @@ +[ + { + "inputs": [], + "name": "InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "poolReserve", + "type": "uint256" + } + ], + "name": "InsufficientPoolReserve", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidRiskFundConverter", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidShortfallAddress", + "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": "oldConvertibleBaseAsset", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newConvertibleBaseAsset", + "type": "address" + } + ], + "name": "ConvertibleBaseAssetUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "oldAccessControlManager", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAccessControlManager", + "type": "address" + } + ], + "name": "NewAccessControlManager", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "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": "comptroller", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "PoolAssetsDecreased", + "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" + } + ], + "name": "PoolAssetsIncreased", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldRiskFundConverter", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newRiskFundConverter", + "type": "address" + } + ], + "name": "RiskFundConverterUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "oldShortfallContract", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newShortfallContract", + "type": "address" + } + ], + "name": "ShortfallContractUpdated", + "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" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "SweepTokenFromPool", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TransferredReserveForAuction", + "type": "event" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract IAccessControlManagerV8", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "convertibleBaseAsset", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + } + ], + "name": "getPoolsBaseAssetReserves", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "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": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "poolAssetsFunds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "riskFundConverter", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "convertibleBaseAsset_", + "type": "address" + } + ], + "name": "setConvertibleBaseAsset", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "riskFundConverter_", + "type": "address" + } + ], + "name": "setRiskFundConverter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "shortfallContractAddress_", + "type": "address" + } + ], + "name": "setShortfallContractAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shortfall", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "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": "tokenAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "receiver", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "sweepTokenFromPool", + "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": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferReserveForAuction", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "comptroller", + "type": "address" + }, + { + "internalType": "address", + "name": "asset", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "updatePoolState", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] diff --git a/simulations/vip-780/bscmainnet.ts b/simulations/vip-780/bscmainnet.ts new file mode 100644 index 000000000..060865bb1 --- /dev/null +++ b/simulations/vip-780/bscmainnet.ts @@ -0,0 +1,57 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { forking, testVip } from "src/vip-framework"; + +import { + DEFAULT_PROXY_ADMIN, + RISK_FUND_V2_NEW_IMPLEMENTATION, + RISK_FUND_V2_PROXY, + vip780, +} from "../../vips/vip-780/bscmainnet"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; +import RISK_FUND_V2_ABI from "./abi/RiskFundV2.json"; + +forking(73352569, async () => { + let proxyAdmin: Contract; + let riskFundV2: Contract; + let oldImplementation: string; + + before(async () => { + proxyAdmin = await ethers.getContractAt(PROXY_ADMIN_ABI, DEFAULT_PROXY_ADMIN); + riskFundV2 = await ethers.getContractAt(RISK_FUND_V2_ABI, RISK_FUND_V2_PROXY); + oldImplementation = await proxyAdmin.getProxyImplementation(RISK_FUND_V2_PROXY); + }); + + describe("Pre-VIP state", async () => { + it("should have the old implementation", async () => { + expect(oldImplementation).to.equal("0x7Ef5ABbcC9A701e728BeB7Afd4fb5747fAB15A28"); + }); + + it("should be able to call existing functions", async () => { + // Verify the contract is working by checking a basic function + const owner = await riskFundV2.owner(); + expect(owner).to.not.equal(ethers.constants.AddressZero); + }); + }); + + testVip("VIP-780 Upgrade RiskFundV2", await vip780()); + + describe("Post-VIP state", async () => { + it("should have the new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(RISK_FUND_V2_PROXY)).to.equal(RISK_FUND_V2_NEW_IMPLEMENTATION); + }); + + it("should maintain proxy state after upgrade", async () => { + // Verify the contract still works and maintains its state + const owner = await riskFundV2.owner(); + expect(owner).to.not.equal(ethers.constants.AddressZero); + }); + + it("should still have access to proxy functions", async () => { + // Check that standard proxy functions still work + const shortfall = await riskFundV2.shortfall(); + expect(shortfall).to.not.equal(ethers.constants.AddressZero); + }); + }); +}); diff --git a/simulations/vip-780/bsctestnet.ts b/simulations/vip-780/bsctestnet.ts new file mode 100644 index 000000000..2e49ef782 --- /dev/null +++ b/simulations/vip-780/bsctestnet.ts @@ -0,0 +1,57 @@ +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; +import { forking, testVip } from "src/vip-framework"; + +import { + DEFAULT_PROXY_ADMIN, + RISK_FUND_V2_NEW_IMPLEMENTATION, + RISK_FUND_V2_PROXY, + vip780, +} from "../../vips/vip-780/bsctestnet"; +import PROXY_ADMIN_ABI from "./abi/ProxyAdmin.json"; +import RISK_FUND_V2_ABI from "./abi/RiskFundV2.json"; + +forking(81335432, async () => { + let proxyAdmin: Contract; + let riskFundV2: Contract; + let oldImplementation: string; + + before(async () => { + proxyAdmin = await ethers.getContractAt(PROXY_ADMIN_ABI, DEFAULT_PROXY_ADMIN); + riskFundV2 = await ethers.getContractAt(RISK_FUND_V2_ABI, RISK_FUND_V2_PROXY); + oldImplementation = await proxyAdmin.getProxyImplementation(RISK_FUND_V2_PROXY); + }); + + describe("Pre-VIP state", async () => { + it("should have the old implementation", async () => { + expect(oldImplementation).to.equal("0x394C9a8cDbbFcAbEAb21fB105311B6B1f09b667a"); + }); + + it("should be able to call existing functions", async () => { + // Verify the contract is working by checking a basic function + const owner = await riskFundV2.owner(); + expect(owner).to.not.equal(ethers.constants.AddressZero); + }); + }); + + testVip("VIP-780 Upgrade RiskFundV2", await vip780()); + + describe("Post-VIP state", async () => { + it("should have the new implementation", async () => { + expect(await proxyAdmin.getProxyImplementation(RISK_FUND_V2_PROXY)).to.equal(RISK_FUND_V2_NEW_IMPLEMENTATION); + }); + + it("should maintain proxy state after upgrade", async () => { + // Verify the contract still works and maintains its state + const owner = await riskFundV2.owner(); + expect(owner).to.not.equal(ethers.constants.AddressZero); + }); + + it("should still have access to proxy functions", async () => { + // Check that standard proxy functions still work + const shortfall = await riskFundV2.shortfall(); + expect(shortfall).to.not.equal(ethers.constants.AddressZero); + }); + }); +}); diff --git a/vips/vip-780/bscmainnet.ts b/vips/vip-780/bscmainnet.ts new file mode 100644 index 000000000..0589a9762 --- /dev/null +++ b/vips/vip-780/bscmainnet.ts @@ -0,0 +1,31 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const DEFAULT_PROXY_ADMIN = "0x6beb6D2695B67FEb73ad4f172E8E2975497187e4"; +export const RISK_FUND_V2_PROXY = "0xdF31a28D68A2AB381D42b380649Ead7ae2A76E42"; +export const RISK_FUND_V2_NEW_IMPLEMENTATION = "0x60e322C3418EcAEA5E6859551c299c968adc9816"; + +export const vip780 = () => { + const meta = { + version: "v2", + title: "VIP-780 Upgrade RiskFundV2 Implementation", + description: ``, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + { + target: DEFAULT_PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [RISK_FUND_V2_PROXY, RISK_FUND_V2_NEW_IMPLEMENTATION], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip780; diff --git a/vips/vip-780/bsctestnet.ts b/vips/vip-780/bsctestnet.ts new file mode 100644 index 000000000..a32bbb9d2 --- /dev/null +++ b/vips/vip-780/bsctestnet.ts @@ -0,0 +1,31 @@ +import { ProposalType } from "src/types"; +import { makeProposal } from "src/utils"; + +export const DEFAULT_PROXY_ADMIN = "0x7877ffd62649b6a1557b55d4c20fcbab17344c91"; +export const RISK_FUND_V2_PROXY = "0x487CeF72dacABD7E12e633bb3B63815a386f7012"; +export const RISK_FUND_V2_NEW_IMPLEMENTATION = "0x36b236c62AB32430016EC0EaE8e40ebe29d95869"; + +export const vip780 = () => { + const meta = { + version: "v2", + title: "VIP-780 Upgrade RiskFundV2 Implementation", + description: ``, + forDescription: "Execute this proposal", + againstDescription: "Do not execute this proposal", + abstainDescription: "Indifferent to execution", + }; + + return makeProposal( + [ + { + target: DEFAULT_PROXY_ADMIN, + signature: "upgrade(address,address)", + params: [RISK_FUND_V2_PROXY, RISK_FUND_V2_NEW_IMPLEMENTATION], + }, + ], + meta, + ProposalType.REGULAR, + ); +}; + +export default vip780;