UNPKG

@dydxfoundation/governance

Version:
199 lines (198 loc) 13.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.addSnapshotsTestCases = void 0; const chai_1 = require("chai"); const types_1 = require("../../../src/types"); const describe_contract_1 = require("../../helpers/describe-contract"); const evm_1 = require("../../helpers/evm"); function addSnapshotsTestCases(getStakers) { // Users. let staker1; let staker2; // Initial balance. let staker1InitialTokenBalance; // Safety Module contract connected to the first user by default. let safetyModule; async function init(ctx) { [staker1, staker2] = await getStakers(ctx); safetyModule = ctx.safetyModule.connect(staker1); // Send tokens to first user. await ctx.dydxToken.transfer(staker1.address, 100000000); await ctx.dydxToken.connect(staker1).approve(ctx.safetyModule.address, 100000000); staker1InitialTokenBalance = await ctx.dydxToken.balanceOf(staker1.address); } (0, describe_contract_1.describeContractHardhatRevertBeforeEach)('Safety Module snapshots - getPowerAtBlock()', init, (ctx) => { it('Governance power is initially zero', async () => { await expectPowerAtBlock(staker1, 0, 0); await expectPowerRelativeBlock(staker1, 0, 0); await (0, chai_1.expect)(expectPowerRelativeBlock(staker1, 1, 0)).to.be.revertedWith('SM1Snapshots: INVALID_BLOCK_NUMBER'); }); it('Governance power increases by staking', async () => { await safetyModule.stake(1250); await expectPowerRelativeBlock(staker1, -1, 0); await expectPowerRelativeBlock(staker1, 0, 1250); }); it('Governance power can be delegated', async () => { await safetyModule.stake(1250); await safetyModule.delegateByType(staker2.address, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -1, 1250, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, 0, 0, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, -1, 0, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, 0, 1250, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -1, 1250, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, 0, 1250, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -1, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, 0, 0, types_1.DelegationType.VOTING_POWER); await safetyModule.delegateByType(staker2.address, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, -1, 1250, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, 0, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -1, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, 0, 1250, types_1.DelegationType.VOTING_POWER); }); it('Governance power can be transfered', async () => { await safetyModule.stake(1250); // [1250, 0] await safetyModule.transfer(staker2.address, 100); // [1150, 100] await safetyModule.transfer(staker2.address, 200); // [950, 300] await safetyModule.transfer(staker2.address, 400); // [550, 700] await safetyModule.connect(staker2).transfer(staker1.address, 250); // [800, 450] await safetyModule.transfer(staker2.address, 800); // [0, 1250] await safetyModule.connect(staker2).transfer(staker1.address, 625); // [625, 625] await expectPowerRelativeBlock(staker1, -7, 0); await expectPowerRelativeBlock(staker2, -7, 0); await expectPowerRelativeBlock(staker1, -6, 1250); await expectPowerRelativeBlock(staker2, -6, 0); await expectPowerRelativeBlock(staker1, -5, 1150); await expectPowerRelativeBlock(staker2, -5, 100); await expectPowerRelativeBlock(staker1, -4, 950); await expectPowerRelativeBlock(staker2, -4, 300); await expectPowerRelativeBlock(staker1, -3, 550); await expectPowerRelativeBlock(staker2, -3, 700); await expectPowerRelativeBlock(staker1, -2, 800); await expectPowerRelativeBlock(staker2, -2, 450); await expectPowerRelativeBlock(staker1, -1, 0); await expectPowerRelativeBlock(staker2, -1, 1250); await expectPowerRelativeBlock(staker1, 0, 625); await expectPowerRelativeBlock(staker2, 0, 625); }); it('Governance power is affected by slashing', async () => { await safetyModule.stake(1250); // [1250, 0] await ctx.safetyModule.slash(250, ctx.deployer.address); await expectPowerRelativeBlock(staker1, -1, 1250); await expectPowerRelativeBlock(staker1, 0, 1000); // Skip some blocks. for (let i = 0; i < 10; i++) { await (0, evm_1.advanceBlock)(); } await expectPowerRelativeBlock(staker1, -11, 1250); await expectPowerRelativeBlock(staker1, -10, 1000); await expectPowerRelativeBlock(staker1, 0, 1000); // Transfer one fifth of the staked position. await safetyModule.transfer(staker2.address, 250); // [1000, 250] await expectPowerRelativeBlock(staker1, -1, 1000); await expectPowerRelativeBlock(staker2, -1, 0); await expectPowerRelativeBlock(staker1, 0, 800); await expectPowerRelativeBlock(staker2, 0, 200); // Delegate the rest of the position, for voting power only. await safetyModule.delegateByType(staker2.address, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, -2, 1000); await expectPowerRelativeBlock(staker2, -2, 0); await expectPowerRelativeBlock(staker1, -1, 800); await expectPowerRelativeBlock(staker2, -1, 200); await expectPowerRelativeBlock(staker1, 0, 800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, 0, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, 0, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, 0, 1000, types_1.DelegationType.VOTING_POWER); // Stake some more. await safetyModule.stake(1000); // [2250, 250] await expectPowerRelativeBlock(staker1, -1, 800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, -1, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -1, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -1, 1000, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, 0, 1800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, 0, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, 0, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, 0, 2000, types_1.DelegationType.VOTING_POWER); // Skip some blocks. for (let i = 0; i < 7; i++) { await (0, evm_1.advanceBlock)(); } // Slash again, by 40%. await ctx.safetyModule.slash(800, ctx.deployer.address); await expectPowerRelativeBlock(staker1, -9, 800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, -9, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -9, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -9, 1000, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, -8, 1800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, -8, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -8, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -8, 2000, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, -7, 1800, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, -7, 200, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, -7, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, -7, 2000, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker1, 0, 1080, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker2, 0, 120, types_1.DelegationType.PROPOSITION_POWER); await expectPowerRelativeBlock(staker1, 0, 0, types_1.DelegationType.VOTING_POWER); await expectPowerRelativeBlock(staker2, 0, 1200, types_1.DelegationType.VOTING_POWER); }); it('Governance power is not affected by withdrawal requests', async () => { await safetyModule.stake(1250); // [1250, 0] await ctx.safetyModule.slash(250, ctx.deployer.address); await safetyModule.requestWithdrawal(1250); await expectPowerRelativeBlock(staker1, 0, 1000); // Elapse epochs... await (0, evm_1.increaseTimeAndMine)((await safetyModule.getTimeRemainingInCurrentEpoch()).toNumber()); await expectPowerRelativeBlock(staker1, 0, 1000); await (0, evm_1.increaseTimeAndMine)((await safetyModule.getTimeRemainingInCurrentEpoch()).toNumber()); await expectPowerRelativeBlock(staker1, 0, 1000); await (0, evm_1.increaseTimeAndMine)((await safetyModule.getTimeRemainingInCurrentEpoch()).toNumber()); await expectPowerRelativeBlock(staker1, 0, 1000); }); it('Governance power is affected by withdrawals', async () => { await safetyModule.stake(1250); // [1250, 0] await ctx.safetyModule.slash(250, ctx.deployer.address); await safetyModule.requestWithdrawal(1250); await (0, evm_1.increaseTimeAndMine)((await safetyModule.getTimeRemainingInCurrentEpoch()).toNumber()); await expectPowerRelativeBlock(staker1, 0, 1000); const tokenBalanceAfterStaking = staker1InitialTokenBalance.sub(1250); await expectBalances(staker1, tokenBalanceAfterStaking, 1250); await safetyModule.withdrawStake(staker1.address, 125); await expectPowerRelativeBlock(staker1, 0, 900); await expectBalances(staker1, tokenBalanceAfterStaking.add(100), 1125); await safetyModule.withdrawStake(staker1.address, 125); await expectPowerRelativeBlock(staker1, 0, 800); await expectBalances(staker1, tokenBalanceAfterStaking.add(200), 1000); await safetyModule.withdrawStake(staker1.address, 250); await expectPowerRelativeBlock(staker1, 0, 600); await expectBalances(staker1, tokenBalanceAfterStaking.add(400), 750); // Slash again, by 50%. await ctx.safetyModule.slash(300, ctx.deployer.address); await expectPowerRelativeBlock(staker1, 0, 300); // Withdraw the remaining stake. await safetyModule.withdrawStake(staker1.address, 750); await expectPowerRelativeBlock(staker1, 0, 0); await expectPowerRelativeBlock(staker1, -1, 300); await expectPowerRelativeBlock(staker1, -2, 600); await expectPowerRelativeBlock(staker1, -3, 800); await expectPowerRelativeBlock(staker1, -4, 900); await expectPowerRelativeBlock(staker1, -5, 1000); await expectBalances(staker1, tokenBalanceAfterStaking.add(700), 0); }); async function expectBalances(user, tokenBalance, stakedTokenBalance) { (0, chai_1.expect)(await ctx.dydxToken.balanceOf(user.address)).to.equal(tokenBalance); (0, chai_1.expect)(await ctx.safetyModule.balanceOf(user.address)).to.equal(stakedTokenBalance); } async function expectPowerRelativeBlock(user, relativeBlockNumber, amount, optionalType = null) { return expectPowerAtBlock(user, await (0, evm_1.latestBlock)() + relativeBlockNumber, amount, optionalType); } async function expectPowerAtBlock(user, blockNumber, amount, optionalType = null) { if (optionalType !== types_1.DelegationType.VOTING_POWER) { (0, chai_1.expect)(await ctx.safetyModule.getPowerAtBlock(user.address, blockNumber, types_1.DelegationType.PROPOSITION_POWER)).to.equal(amount); } if (optionalType !== types_1.DelegationType.PROPOSITION_POWER) { (0, chai_1.expect)(await ctx.safetyModule.getPowerAtBlock(user.address, blockNumber, types_1.DelegationType.VOTING_POWER)).to.equal(amount); } } }); } exports.addSnapshotsTestCases = addSnapshotsTestCases;