@dydxfoundation/governance
Version:
dYdX governance smart contracts
66 lines (65 loc) • 3.57 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const chai_1 = require("chai");
const types_1 = require("../../src/types");
const describe_contract_1 = require("../helpers/describe-contract");
const staking_helper_1 = require("../helpers/staking-helper");
const stakerInitialBalance = 1000000;
// Users.
let stakers;
let operator;
// Smart contract callers.
let operatorSigner;
let contract;
async function init(ctx) {
// Users.
stakers = ctx.users.slice(1, 3); // 2 stakers
operator = ctx.users[3];
operatorSigner = ctx.safetyModule.connect(operator);
// Use helper class to automatically check contract invariants after every update.
contract = new staking_helper_1.StakingHelper(ctx, ctx.safetyModule, ctx.dydxToken, ctx.rewardsTreasury.address, ctx.deployer, ctx.deployer, stakers.concat([ctx.deployer, operator]), true);
// Mint staked tokens and set allowances.
await Promise.all(stakers.map((s) => contract.mintAndApprove(s, stakerInitialBalance)));
}
(0, describe_contract_1.describeContractHardhatRevertBeforeEach)('SM1Operator', init, (ctx) => {
before(() => {
contract.saveSnapshot('main');
});
afterEach(() => {
contract.loadSnapshot('main');
});
describe('Stake and claim operators', () => {
it('The stake operator can withdraw stake on behalf of a user', async () => {
const largeBalance = stakerInitialBalance * 100;
await contract.addOperator(operator, types_1.Role.STAKE_OPERATOR_ROLE);
await contract.mintAndApprove(operator, largeBalance);
// Stake using the operator's funds, and withdraw back to the operator.
await operatorSigner.stakeFor(stakers[0].address, largeBalance);
await operatorSigner.requestWithdrawalFor(stakers[0].address, largeBalance);
await contract.elapseEpoch();
await operatorSigner.withdrawStakeFor(stakers[0].address, operator.address, largeBalance);
(0, chai_1.expect)(await ctx.dydxToken.balanceOf(operator.address)).to.equal(largeBalance);
});
it('Another user can stake on behalf of a user, but not withdraw', async () => {
const stakerSigner = ctx.safetyModule.connect(stakers[1]);
await stakerSigner.stakeFor(stakers[0].address, stakerInitialBalance);
await (0, chai_1.expect)(stakerSigner.requestWithdrawalFor(stakers[0].address, 1)).to.be.revertedWith('AccessControl: account');
});
it('The claim operator can claim rewards on behalf of a user', async () => {
// Safety module rewards first begin in the middle of the epoch.
// Advance to the start of an epoch.
await contract.elapseEpoch();
await contract.addOperator(operator, types_1.Role.CLAIM_OPERATOR_ROLE);
const initialBalance = await ctx.dydxToken.balanceOf(operator.address);
const rewardsRate = 16;
await contract.setRewardsPerSecond(rewardsRate);
await contract.stake(stakers[0], stakerInitialBalance);
await contract.elapseEpoch();
await operatorSigner.claimRewardsFor(stakers[0].address, operator.address);
const finalBalance = await ctx.dydxToken.balanceOf(operator.address);
const amountReceived = finalBalance.sub(initialBalance).toNumber();
const expectedReceived = ctx.config.EPOCH_LENGTH * rewardsRate;
(0, chai_1.expect)(amountReceived).to.be.closeTo(expectedReceived, 100);
});
});
});