diff --git a/simulations/vip-182/vip-182-testnet/abi/rewardsDistributor.json b/simulations/vip-182/vip-182-testnet/abi/rewardsDistributor.json new file mode 100644 index 000000000..7035bb9a5 --- /dev/null +++ b/simulations/vip-182/vip-182-testnet/abi/rewardsDistributor.json @@ -0,0 +1,1129 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] diff --git a/simulations/vip-182/vip-182-testnet/simulations.ts b/simulations/vip-182/vip-182-testnet/simulations.ts new file mode 100644 index 000000000..f323d99a4 --- /dev/null +++ b/simulations/vip-182/vip-182-testnet/simulations.ts @@ -0,0 +1,109 @@ +import { TransactionResponse } from "@ethersproject/providers"; +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; + +import { expectEvents } from "../../../src/utils"; +import { forking, testVip } from "../../../src/vip-framework"; +import { + RewardsDistributor_ANGLE_Stablecoin, + RewardsDistributor_HAY_LiquidStakedBNB, + vip182, +} from "../../../vips/vip-182/vip-182-testnet"; +import REWARDS_DISTRIBUTOR_ABI from "./abi/rewardsDistributor.json"; + +const BLOCKS_56_DAYS = (60 * 60 * 24 * 56) / 3; +const BLOCKS_7_DAYS = (60 * 60 * 24 * 7) / 3; + +const snBNB_FirstRewardingBlock = 33709004; +const agEUR_FirsRewardingBlock = 33764104; + +const snBNB_LastRewardingBlock = snBNB_FirstRewardingBlock + BLOCKS_56_DAYS; +const agEUR_LastRewardingBlock = agEUR_FirsRewardingBlock + BLOCKS_7_DAYS; + +forking(33878000, () => { + let rewardsDistributor_HAY_LiquidStakedBNB: Contract; + let rewardsDistributor_ANGLE_Stablecoin: Contract; + + before(async () => { + rewardsDistributor_HAY_LiquidStakedBNB = await ethers.getContractAt( + REWARDS_DISTRIBUTOR_ABI, + RewardsDistributor_HAY_LiquidStakedBNB.address, + ); + rewardsDistributor_ANGLE_Stablecoin = await ethers.getContractAt( + REWARDS_DISTRIBUTOR_ABI, + RewardsDistributor_ANGLE_Stablecoin.address, + ); + }); + + describe("Pre-VIP behavior", () => { + it("Verify Last Rewarding block for supply side for snBNB market", async () => { + const supplyState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenSupplyState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for borrow side for snBNB market", async () => { + const borrowState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenBorrowState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for supply side for agEUR market", async () => { + const supplyState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenSupplyState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for borrow side for agEUR market", async () => { + const borrowState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenBorrowState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(0); + }); + }); + + testVip("VIP-182", vip182(), { + callbackAfterExecution: async (txResponse: TransactionResponse) => { + await expectEvents( + txResponse, + [REWARDS_DISTRIBUTOR_ABI], + ["SupplyLastRewardingBlockUpdated", "BorrowLastRewardingBlockUpdated"], + [2, 2], + ); + }, + }); + + describe("Post-VIP Behaviour", () => { + it("Verify Last Rewarding block for supply side for snBNB market", async () => { + const supplyState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenSupplyState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(snBNB_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for borrow side for snBNB market", async () => { + const borrowState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenBorrowState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(snBNB_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for supply side for agEUR market", async () => { + const supplyState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenSupplyState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(agEUR_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for borrow side for agEUR market", async () => { + const borrowState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenBorrowState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(agEUR_LastRewardingBlock); + }); + }); +}); diff --git a/simulations/vip-182/vip-182/abi/rewardsDistributor.json b/simulations/vip-182/vip-182/abi/rewardsDistributor.json new file mode 100644 index 000000000..7035bb9a5 --- /dev/null +++ b/simulations/vip-182/vip-182/abi/rewardsDistributor.json @@ -0,0 +1,1129 @@ +[ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "stateMutability": "payable", + "type": "fallback" + }, + { + "inputs": [], + "name": "admin", + "outputs": [ + { + "internalType": "address", + "name": "admin_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "changeAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "implementation", + "outputs": [ + { + "internalType": "address", + "name": "implementation_", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "stateMutability": "payable", + "type": "receive" + }, + { + "inputs": [ + { + "internalType": "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": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "BorrowLastRewardingBlockUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "ContributorRewardTokenSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardAccrued", + "type": "uint256" + } + ], + "name": "ContributorRewardsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenBorrowIndex", + "type": "uint256" + } + ], + "name": "DistributedBorrowerRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "supplier", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenDelta", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenTotal", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewardTokenSupplyIndex", + "type": "uint256" + } + ], + "name": "DistributedSupplierRewardToken", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "MarketInitialized", + "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": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "RewardTokenBorrowIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenBorrowSpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "RewardTokenGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "RewardTokenSupplyIndexUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract VToken", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "newSpeed", + "type": "uint256" + } + ], + "name": "RewardTokenSupplySpeedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint32", + "name": "newBlock", + "type": "uint32" + } + ], + "name": "SupplyLastRewardingBlockUpdated", + "type": "event" + }, + { + "inputs": [], + "name": "INITIAL_INDEX", + "outputs": [ + { + "internalType": "uint224", + "name": "", + "type": "uint224" + } + ], + "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": "holder", + "type": "address" + }, + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "holder", + "type": "address" + } + ], + "name": "claimRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "distributeBorrowerRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "internalType": "address", + "name": "supplier", + "type": "address" + } + ], + "name": "distributeSupplierRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getBlockNumber", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "grantRewardToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract Comptroller", + "name": "comptroller_", + "type": "address" + }, + { + "internalType": "contract IERC20Upgradeable", + "name": "rewardToken_", + "type": "address" + }, + { + "internalType": "uint256", + "name": "loopsLimit_", + "type": "uint256" + }, + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "initializeMarket", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "lastContributorBlock", + "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": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "rewardToken", + "outputs": [ + { + "internalType": "contract IERC20Upgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenAccrued", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenBorrowerIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenContributorSpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplierIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplySpeeds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "rewardTokenSupplyState", + "outputs": [ + { + "internalType": "uint224", + "name": "index", + "type": "uint224" + }, + { + "internalType": "uint32", + "name": "block", + "type": "uint32" + }, + { + "internalType": "uint32", + "name": "lastRewardingBlock", + "type": "uint32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "accessControlManager_", + "type": "address" + } + ], + "name": "setAccessControlManager", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + }, + { + "internalType": "uint256", + "name": "rewardTokenSpeed", + "type": "uint256" + } + ], + "name": "setContributorRewardTokenSpeed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint32[]", + "name": "supplyLastRewardingBlocks", + "type": "uint32[]" + }, + { + "internalType": "uint32[]", + "name": "borrowLastRewardingBlocks", + "type": "uint32[]" + } + ], + "name": "setLastRewardingBlocks", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "limit", + "type": "uint256" + } + ], + "name": "setMaxLoopsLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract VToken[]", + "name": "vTokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "supplySpeeds", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "borrowSpeeds", + "type": "uint256[]" + } + ], + "name": "setRewardTokenSpeeds", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contributor", + "type": "address" + } + ], + "name": "updateContributorRewards", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "mantissa", + "type": "uint256" + } + ], + "internalType": "struct ExponentialNoError.Exp", + "name": "marketBorrowIndex", + "type": "tuple" + } + ], + "name": "updateRewardTokenBorrowIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "vToken", + "type": "address" + } + ], + "name": "updateRewardTokenSupplyIndex", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_logic", + "type": "address" + }, + { + "internalType": "address", + "name": "admin_", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "stateMutability": "payable", + "type": "constructor" + } +] diff --git a/simulations/vip-182/vip-182/simulations.ts b/simulations/vip-182/vip-182/simulations.ts new file mode 100644 index 000000000..dcaadce9f --- /dev/null +++ b/simulations/vip-182/vip-182/simulations.ts @@ -0,0 +1,109 @@ +import { TransactionResponse } from "@ethersproject/providers"; +import { expect } from "chai"; +import { Contract } from "ethers"; +import { ethers } from "hardhat"; + +import { expectEvents } from "../../../src/utils"; +import { forking, testVip } from "../../../src/vip-framework"; +import { + RewardsDistributor_ANGLE_Stablecoin, + RewardsDistributor_HAY_LiquidStakedBNB, + vip182, +} from "../../../vips/vip-182/vip-182"; +import REWARDS_DISTRIBUTOR_ABI from "./abi/rewardsDistributor.json"; + +const BLOCKS_56_DAYS = (60 * 60 * 24 * 56) / 3; +const BLOCKS_7_DAYS = (60 * 60 * 24 * 7) / 3; + +const snBNB_FirstRewardingBlock = 32228156; +const agEUR_FirsRewardingBlock = 32338350; + +const snBNB_LastRewardingBlock = snBNB_FirstRewardingBlock + BLOCKS_56_DAYS; +const agEUR_LastRewardingBlock = agEUR_FirsRewardingBlock + BLOCKS_7_DAYS; + +forking(32338400, () => { + let rewardsDistributor_HAY_LiquidStakedBNB: Contract; + let rewardsDistributor_ANGLE_Stablecoin: Contract; + + before(async () => { + rewardsDistributor_HAY_LiquidStakedBNB = await ethers.getContractAt( + REWARDS_DISTRIBUTOR_ABI, + RewardsDistributor_HAY_LiquidStakedBNB.address, + ); + rewardsDistributor_ANGLE_Stablecoin = await ethers.getContractAt( + REWARDS_DISTRIBUTOR_ABI, + RewardsDistributor_ANGLE_Stablecoin.address, + ); + }); + + describe("Pre-VIP behavior", () => { + it("Verify Last Rewarding block for supply side for snBNB market", async () => { + const supplyState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenSupplyState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for borrow side for snBNB market", async () => { + const borrowState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenBorrowState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for supply side for agEUR market", async () => { + const supplyState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenSupplyState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(0); + }); + + it("Verify Last Rewarding block for borrow side for agEUR market", async () => { + const borrowState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenBorrowState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(0); + }); + }); + + testVip("VIP-182", vip182(), { + callbackAfterExecution: async (txResponse: TransactionResponse) => { + await expectEvents( + txResponse, + [REWARDS_DISTRIBUTOR_ABI], + ["SupplyLastRewardingBlockUpdated", "BorrowLastRewardingBlockUpdated"], + [2, 2], + ); + }, + }); + + describe("Post-VIP Behaviour", () => { + it("Verify Last Rewarding block for supply side for snBNB market", async () => { + const supplyState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenSupplyState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(snBNB_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for borrow side for snBNB market", async () => { + const borrowState = await rewardsDistributor_HAY_LiquidStakedBNB.rewardTokenBorrowState( + RewardsDistributor_HAY_LiquidStakedBNB.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(snBNB_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for supply side for agEUR market", async () => { + const supplyState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenSupplyState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(supplyState.lastRewardingBlock).to.equal(agEUR_LastRewardingBlock); + }); + + it("Verify Last Rewarding block for borrow side for agEUR market", async () => { + const borrowState = await rewardsDistributor_ANGLE_Stablecoin.rewardTokenBorrowState( + RewardsDistributor_ANGLE_Stablecoin.vToken, + ); + expect(borrowState.lastRewardingBlock).to.equal(agEUR_LastRewardingBlock); + }); + }); +}); diff --git a/vips/vip-182/vip-182-testnet.ts b/vips/vip-182/vip-182-testnet.ts new file mode 100644 index 000000000..293015166 --- /dev/null +++ b/vips/vip-182/vip-182-testnet.ts @@ -0,0 +1,63 @@ +import { ProposalType } from "../../src/types"; +import { makeProposal } from "../../src/utils"; + +export const BLOCKS_56_DAYS = 1_612_800; +export const BLOCKS_7_DAYS = 201_600; + +export const RewardsDistributor_HAY_LiquidStakedBNB = { + address: "0xc1Ea6292C49D6B6E952baAC6673dE64701bB88cB", + vToken: "0xeffE7874C345aE877c1D893cd5160DDD359b24dA", // vSNBNB + rewardStartBlock: 33709004, +}; + +export const RewardsDistributor_ANGLE_Stablecoin = { + address: "0x78d32FC46e5025c29e3BA03Fcf2840323351F26a", + vToken: "0x4E1D35166776825402d50AfE4286c500027211D1", // vagEUR + rewardStartBlock: 33764104, +}; + +const commands = [ + { + target: RewardsDistributor_HAY_LiquidStakedBNB.address, + signature: "setLastRewardingBlocks(address[],uint32[],uint32[])", + params: [ + [RewardsDistributor_HAY_LiquidStakedBNB.vToken], + [RewardsDistributor_HAY_LiquidStakedBNB.rewardStartBlock + BLOCKS_56_DAYS], + [RewardsDistributor_HAY_LiquidStakedBNB.rewardStartBlock + BLOCKS_56_DAYS], + ], + }, + { + target: RewardsDistributor_ANGLE_Stablecoin.address, + signature: "setLastRewardingBlocks(address[],uint32[],uint32[])", + params: [ + [RewardsDistributor_ANGLE_Stablecoin.vToken], + [RewardsDistributor_ANGLE_Stablecoin.rewardStartBlock + BLOCKS_7_DAYS], + [RewardsDistributor_ANGLE_Stablecoin.rewardStartBlock + BLOCKS_7_DAYS], + ], + }, +]; + +export const vip182 = () => { + const meta = { + version: "v2", + title: "VIP-182 Isolated Lending Pools: Configure Liquidity Mining (SnBNB and agEUR)", + description: `#### Summary + +If passed, this VIP will set the last block with rewards for the SnBNB market in the Liquid Staked BNB pool, and the agEUR market in the Stablecoins pool. + +#### Description + +This VIP sets the last block with rewards for the SnBNB market in the Liquid Staked BNB pool, and the agEUR market in the Stablecoins pool. + +In [vSnBNB_LiquidStakedBNB](https://app.venus.io/#/isolated-pools/pool/0xd933909A4a2b7A4638903028f44D1d38ce27c352/market/0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A), the last block with rewards will be 33840956. That means around 56 days (1,612,800 blocks) after [being enabled](https://app.venus.io/#/governance/proposal/177). + +In [vagEUR_Stablecoins](https://app.venus.io/#/isolated-pools/pool/0x94c1495cD4c557f1560Cbd68EAB0d197e6291571), the last block with rewards will be 32539950. That means around 7 days (201,600 blocks) after [being enabled](https://app.venus.io/#/governance/proposal/178). + +Simulation of the VIP: https://github.com/VenusProtocol/vips/pull/82`, + forDescription: "Process to configure Liquidity Mining", + againstDescription: "Defer configuration of Liquidity Mining", + abstainDescription: "No opinion on the matter", + }; + + return makeProposal(commands, meta, ProposalType.REGULAR); +}; diff --git a/vips/vip-182/vip-182.ts b/vips/vip-182/vip-182.ts new file mode 100644 index 000000000..94081ce74 --- /dev/null +++ b/vips/vip-182/vip-182.ts @@ -0,0 +1,63 @@ +import { ProposalType } from "../../src/types"; +import { makeProposal } from "../../src/utils"; + +export const BLOCKS_56_DAYS = 1_612_800; +export const BLOCKS_7_DAYS = 201_600; + +export const RewardsDistributor_HAY_LiquidStakedBNB = { + address: "0x888E317606b4c590BBAD88653863e8B345702633", + vToken: "0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A", // vSNBNB + rewardStartBlock: 32228156, +}; + +export const RewardsDistributor_ANGLE_Stablecoin = { + address: "0x177ED4625F57cEa2804EA3A396c8Ff78f314F1CA", + vToken: "0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F", // vagEUR + rewardStartBlock: 32338350, +}; + +const commands = [ + { + target: RewardsDistributor_HAY_LiquidStakedBNB.address, + signature: "setLastRewardingBlocks(address[],uint32[],uint32[])", + params: [ + [RewardsDistributor_HAY_LiquidStakedBNB.vToken], + [RewardsDistributor_HAY_LiquidStakedBNB.rewardStartBlock + BLOCKS_56_DAYS], + [RewardsDistributor_HAY_LiquidStakedBNB.rewardStartBlock + BLOCKS_56_DAYS], + ], + }, + { + target: RewardsDistributor_ANGLE_Stablecoin.address, + signature: "setLastRewardingBlocks(address[],uint32[],uint32[])", + params: [ + [RewardsDistributor_ANGLE_Stablecoin.vToken], + [RewardsDistributor_ANGLE_Stablecoin.rewardStartBlock + BLOCKS_7_DAYS], + [RewardsDistributor_ANGLE_Stablecoin.rewardStartBlock + BLOCKS_7_DAYS], + ], + }, +]; + +export const vip182 = () => { + const meta = { + version: "v2", + title: "VIP-182 Isolated Lending Pools: Configure Liquidity Mining (SnBNB and agEUR)", + description: `#### Summary + +If passed, this VIP will set the last block with rewards for the SnBNB market in the Liquid Staked BNB pool, and the agEUR market in the Stablecoins pool. + +#### Description + +This VIP sets the last block with rewards for the SnBNB market in the Liquid Staked BNB pool, and the agEUR market in the Stablecoins pool. + +In [vSnBNB_LiquidStakedBNB](https://app.venus.io/#/isolated-pools/pool/0xd933909A4a2b7A4638903028f44D1d38ce27c352/market/0xd3CC9d8f3689B83c91b7B59cAB4946B063EB894A), the last block with rewards will be 33840956. That means around 56 days (1,612,800 blocks) after [being enabled](https://app.venus.io/#/governance/proposal/177). + +In [vagEUR_Stablecoins](https://app.venus.io/#/isolated-pools/pool/0x94c1495cD4c557f1560Cbd68EAB0d197e6291571/market/0x795DE779Be00Ea46eA97a28BDD38d9ED570BCF0F), the last block with rewards will be 32539950. That means around 7 days (201,600 blocks) after [being enabled](https://app.venus.io/#/governance/proposal/178). + +Simulation of the VIP: https://github.com/VenusProtocol/vips/pull/82`, + forDescription: "Process to configure Liquidity Mining", + againstDescription: "Defer configuration of Liquidity Mining", + abstainDescription: "No opinion on the matter", + }; + + return makeProposal(commands, meta, ProposalType.REGULAR); +};