Update docs
This commit is contained in:
23
test/governance/utils/EIP6372.behavior.js
Normal file
23
test/governance/utils/EIP6372.behavior.js
Normal file
@ -0,0 +1,23 @@
|
||||
const { clock } = require('../../helpers/time');
|
||||
|
||||
function shouldBehaveLikeEIP6372(mode = 'blocknumber') {
|
||||
describe('should implement EIP6372', function () {
|
||||
beforeEach(async function () {
|
||||
this.mock = this.mock ?? this.token ?? this.votes;
|
||||
});
|
||||
|
||||
it('clock is correct', async function () {
|
||||
expect(await this.mock.clock()).to.be.bignumber.equal(await clock[mode]().then(web3.utils.toBN));
|
||||
});
|
||||
|
||||
it('CLOCK_MODE is correct', async function () {
|
||||
const params = new URLSearchParams(await this.mock.CLOCK_MODE());
|
||||
expect(params.get('mode')).to.be.equal(mode);
|
||||
expect(params.get('from')).to.be.equal(mode == 'blocknumber' ? 'default' : null);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
shouldBehaveLikeEIP6372,
|
||||
};
|
||||
@ -6,7 +6,10 @@ const { fromRpcSig } = require('ethereumjs-util');
|
||||
const ethSigUtil = require('eth-sig-util');
|
||||
const Wallet = require('ethereumjs-wallet').default;
|
||||
|
||||
const { EIP712Domain, domainSeparator } = require('../../helpers/eip712');
|
||||
const { shouldBehaveLikeEIP6372 } = require('./EIP6372.behavior');
|
||||
|
||||
const { getDomain, domainType, domainSeparator } = require('../../helpers/eip712');
|
||||
const { clockFromReceipt } = require('../../helpers/time');
|
||||
|
||||
const Delegation = [
|
||||
{ name: 'delegatee', type: 'address' },
|
||||
@ -14,20 +17,16 @@ const Delegation = [
|
||||
{ name: 'expiry', type: 'uint256' },
|
||||
];
|
||||
|
||||
const version = '1';
|
||||
function shouldBehaveLikeVotes(mode = 'blocknumber') {
|
||||
shouldBehaveLikeEIP6372(mode);
|
||||
|
||||
function shouldBehaveLikeVotes () {
|
||||
describe('run votes workflow', function () {
|
||||
it('initial nonce is 0', async function () {
|
||||
expect(await this.votes.nonces(this.account1)).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
it('domain separator', async function () {
|
||||
expect(
|
||||
await this.votes.DOMAIN_SEPARATOR(),
|
||||
).to.equal(
|
||||
await domainSeparator(this.name, version, this.chainId, this.votes.address),
|
||||
);
|
||||
expect(await this.votes.DOMAIN_SEPARATOR()).to.equal(domainSeparator(await getDomain(this.votes)));
|
||||
});
|
||||
|
||||
describe('delegation with signature', function () {
|
||||
@ -35,32 +34,36 @@ function shouldBehaveLikeVotes () {
|
||||
const delegatorAddress = web3.utils.toChecksumAddress(delegator.getAddressString());
|
||||
const nonce = 0;
|
||||
|
||||
const buildData = (chainId, verifyingContract, name, message) => ({
|
||||
data: {
|
||||
const buildAndSignData = async (contract, message, pk) => {
|
||||
const data = await getDomain(contract).then(domain => ({
|
||||
primaryType: 'Delegation',
|
||||
types: { EIP712Domain, Delegation },
|
||||
domain: { name, version, chainId, verifyingContract },
|
||||
types: { EIP712Domain: domainType(domain), Delegation },
|
||||
domain,
|
||||
message,
|
||||
},
|
||||
});
|
||||
}));
|
||||
return fromRpcSig(ethSigUtil.signTypedMessage(pk, { data }));
|
||||
};
|
||||
|
||||
beforeEach(async function () {
|
||||
await this.votes.mint(delegatorAddress, this.NFT0);
|
||||
await this.votes.$_mint(delegatorAddress, this.NFT0);
|
||||
});
|
||||
|
||||
it('accept signed delegation', async function () {
|
||||
const { v, r, s } = fromRpcSig(ethSigUtil.signTypedMessage(
|
||||
delegator.getPrivateKey(),
|
||||
buildData(this.chainId, this.votes.address, this.name, {
|
||||
const { v, r, s } = await buildAndSignData(
|
||||
this.votes,
|
||||
{
|
||||
delegatee: delegatorAddress,
|
||||
nonce,
|
||||
expiry: MAX_UINT256,
|
||||
}),
|
||||
));
|
||||
},
|
||||
delegator.getPrivateKey(),
|
||||
);
|
||||
|
||||
expect(await this.votes.delegates(delegatorAddress)).to.be.equal(ZERO_ADDRESS);
|
||||
|
||||
const { receipt } = await this.votes.delegateBySig(delegatorAddress, nonce, MAX_UINT256, v, r, s);
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
|
||||
expectEvent(receipt, 'DelegateChanged', {
|
||||
delegator: delegatorAddress,
|
||||
fromDelegate: ZERO_ADDRESS,
|
||||
@ -75,20 +78,21 @@ function shouldBehaveLikeVotes () {
|
||||
expect(await this.votes.delegates(delegatorAddress)).to.be.equal(delegatorAddress);
|
||||
|
||||
expect(await this.votes.getVotes(delegatorAddress)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(delegatorAddress, receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(delegatorAddress, timepoint - 1)).to.be.bignumber.equal('0');
|
||||
await time.advanceBlock();
|
||||
expect(await this.votes.getPastVotes(delegatorAddress, receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(delegatorAddress, timepoint)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('rejects reused signature', async function () {
|
||||
const { v, r, s } = fromRpcSig(ethSigUtil.signTypedMessage(
|
||||
delegator.getPrivateKey(),
|
||||
buildData(this.chainId, this.votes.address, this.name, {
|
||||
const { v, r, s } = await buildAndSignData(
|
||||
this.votes,
|
||||
{
|
||||
delegatee: delegatorAddress,
|
||||
nonce,
|
||||
expiry: MAX_UINT256,
|
||||
}),
|
||||
));
|
||||
},
|
||||
delegator.getPrivateKey(),
|
||||
);
|
||||
|
||||
await this.votes.delegateBySig(delegatorAddress, nonce, MAX_UINT256, v, r, s);
|
||||
|
||||
@ -99,14 +103,15 @@ function shouldBehaveLikeVotes () {
|
||||
});
|
||||
|
||||
it('rejects bad delegatee', async function () {
|
||||
const { v, r, s } = fromRpcSig(ethSigUtil.signTypedMessage(
|
||||
delegator.getPrivateKey(),
|
||||
buildData(this.chainId, this.votes.address, this.name, {
|
||||
const { v, r, s } = await buildAndSignData(
|
||||
this.votes,
|
||||
{
|
||||
delegatee: delegatorAddress,
|
||||
nonce,
|
||||
expiry: MAX_UINT256,
|
||||
}),
|
||||
));
|
||||
},
|
||||
delegator.getPrivateKey(),
|
||||
);
|
||||
|
||||
const receipt = await this.votes.delegateBySig(this.account1Delegatee, nonce, MAX_UINT256, v, r, s);
|
||||
const { args } = receipt.logs.find(({ event }) => event === 'DelegateChanged');
|
||||
@ -116,14 +121,16 @@ function shouldBehaveLikeVotes () {
|
||||
});
|
||||
|
||||
it('rejects bad nonce', async function () {
|
||||
const { v, r, s } = fromRpcSig(ethSigUtil.signTypedMessage(
|
||||
delegator.getPrivateKey(),
|
||||
buildData(this.chainId, this.votes.address, this.name, {
|
||||
const { v, r, s } = await buildAndSignData(
|
||||
this.votes,
|
||||
{
|
||||
delegatee: delegatorAddress,
|
||||
nonce,
|
||||
expiry: MAX_UINT256,
|
||||
}),
|
||||
));
|
||||
},
|
||||
delegator.getPrivateKey(),
|
||||
);
|
||||
|
||||
await expectRevert(
|
||||
this.votes.delegateBySig(delegatorAddress, nonce + 1, MAX_UINT256, v, r, s),
|
||||
'Votes: invalid nonce',
|
||||
@ -132,14 +139,16 @@ function shouldBehaveLikeVotes () {
|
||||
|
||||
it('rejects expired permit', async function () {
|
||||
const expiry = (await time.latest()) - time.duration.weeks(1);
|
||||
const { v, r, s } = fromRpcSig(ethSigUtil.signTypedMessage(
|
||||
delegator.getPrivateKey(),
|
||||
buildData(this.chainId, this.votes.address, this.name, {
|
||||
|
||||
const { v, r, s } = await buildAndSignData(
|
||||
this.votes,
|
||||
{
|
||||
delegatee: delegatorAddress,
|
||||
nonce,
|
||||
expiry,
|
||||
}),
|
||||
));
|
||||
},
|
||||
delegator.getPrivateKey(),
|
||||
);
|
||||
|
||||
await expectRevert(
|
||||
this.votes.delegateBySig(delegatorAddress, nonce, expiry, v, r, s),
|
||||
@ -151,10 +160,12 @@ function shouldBehaveLikeVotes () {
|
||||
describe('set delegation', function () {
|
||||
describe('call', function () {
|
||||
it('delegation with tokens', async function () {
|
||||
await this.votes.mint(this.account1, this.NFT0);
|
||||
await this.votes.$_mint(this.account1, this.NFT0);
|
||||
expect(await this.votes.delegates(this.account1)).to.be.equal(ZERO_ADDRESS);
|
||||
|
||||
const { receipt } = await this.votes.delegate(this.account1, { from: this.account1 });
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
|
||||
expectEvent(receipt, 'DelegateChanged', {
|
||||
delegator: this.account1,
|
||||
fromDelegate: ZERO_ADDRESS,
|
||||
@ -169,9 +180,9 @@ function shouldBehaveLikeVotes () {
|
||||
expect(await this.votes.delegates(this.account1)).to.be.equal(this.account1);
|
||||
|
||||
expect(await this.votes.getVotes(this.account1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1, receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(this.account1, timepoint - 1)).to.be.bignumber.equal('0');
|
||||
await time.advanceBlock();
|
||||
expect(await this.votes.getPastVotes(this.account1, receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1, timepoint)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('delegation without tokens', async function () {
|
||||
@ -192,7 +203,7 @@ function shouldBehaveLikeVotes () {
|
||||
|
||||
describe('change delegation', function () {
|
||||
beforeEach(async function () {
|
||||
await this.votes.mint(this.account1, this.NFT0);
|
||||
await this.votes.$_mint(this.account1, this.NFT0);
|
||||
await this.votes.delegate(this.account1, { from: this.account1 });
|
||||
});
|
||||
|
||||
@ -200,6 +211,8 @@ function shouldBehaveLikeVotes () {
|
||||
expect(await this.votes.delegates(this.account1)).to.be.equal(this.account1);
|
||||
|
||||
const { receipt } = await this.votes.delegate(this.account1Delegatee, { from: this.account1 });
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
|
||||
expectEvent(receipt, 'DelegateChanged', {
|
||||
delegator: this.account1,
|
||||
fromDelegate: this.account1,
|
||||
@ -215,16 +228,16 @@ function shouldBehaveLikeVotes () {
|
||||
previousBalance: '0',
|
||||
newBalance: '1',
|
||||
});
|
||||
const prevBlock = receipt.blockNumber - 1;
|
||||
|
||||
expect(await this.votes.delegates(this.account1)).to.be.equal(this.account1Delegatee);
|
||||
|
||||
expect(await this.votes.getVotes(this.account1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getVotes(this.account1Delegatee)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1, receipt.blockNumber - 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1Delegatee, prevBlock)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(this.account1, timepoint - 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1Delegatee, timepoint - 1)).to.be.bignumber.equal('0');
|
||||
await time.advanceBlock();
|
||||
expect(await this.votes.getPastVotes(this.account1, receipt.blockNumber)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(this.account1Delegatee, receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastVotes(this.account1, timepoint)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(this.account1Delegatee, timepoint)).to.be.bignumber.equal('1');
|
||||
});
|
||||
});
|
||||
|
||||
@ -234,10 +247,7 @@ function shouldBehaveLikeVotes () {
|
||||
});
|
||||
|
||||
it('reverts if block number >= current block', async function () {
|
||||
await expectRevert(
|
||||
this.votes.getPastTotalSupply(5e10),
|
||||
'block not yet mined',
|
||||
);
|
||||
await expectRevert(this.votes.getPastTotalSupply(5e10), 'future lookup');
|
||||
});
|
||||
|
||||
it('returns 0 if there are no checkpoints', async function () {
|
||||
@ -245,52 +255,60 @@ function shouldBehaveLikeVotes () {
|
||||
});
|
||||
|
||||
it('returns the latest block if >= last checkpoint block', async function () {
|
||||
const t1 = await this.votes.mint(this.account1, this.NFT0);
|
||||
const { receipt } = await this.votes.$_mint(this.account1, this.NFT0);
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
|
||||
expect(await this.votes.getPastTotalSupply(t1.receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t1.receipt.blockNumber + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(timepoint - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(timepoint + 1)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('returns zero if < first checkpoint block', async function () {
|
||||
await time.advanceBlock();
|
||||
const t2 = await this.votes.mint(this.account1, this.NFT1);
|
||||
const { receipt } = await this.votes.$_mint(this.account1, this.NFT1);
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
|
||||
expect(await this.votes.getPastTotalSupply(t2.receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t2.receipt.blockNumber + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(timepoint - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(timepoint + 1)).to.be.bignumber.equal('1');
|
||||
});
|
||||
|
||||
it('generally returns the voting balance at the appropriate checkpoint', async function () {
|
||||
const t1 = await this.votes.mint(this.account1, this.NFT1);
|
||||
const t1 = await this.votes.$_mint(this.account1, this.NFT1);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
const t2 = await this.votes.burn(this.NFT1);
|
||||
const t2 = await this.votes.$_burn(this.NFT1);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
const t3 = await this.votes.mint(this.account1, this.NFT2);
|
||||
const t3 = await this.votes.$_mint(this.account1, this.NFT2);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
const t4 = await this.votes.burn(this.NFT2);
|
||||
const t4 = await this.votes.$_burn(this.NFT2);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
const t5 = await this.votes.mint(this.account1, this.NFT3);
|
||||
const t5 = await this.votes.$_mint(this.account1, this.NFT3);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
|
||||
expect(await this.votes.getPastTotalSupply(t1.receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t1.receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t1.receipt.blockNumber + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t2.receipt.blockNumber)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t2.receipt.blockNumber + 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t3.receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t3.receipt.blockNumber + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t4.receipt.blockNumber)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t4.receipt.blockNumber + 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t5.receipt.blockNumber)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t5.receipt.blockNumber + 1)).to.be.bignumber.equal('1');
|
||||
t1.timepoint = await clockFromReceipt[mode](t1.receipt);
|
||||
t2.timepoint = await clockFromReceipt[mode](t2.receipt);
|
||||
t3.timepoint = await clockFromReceipt[mode](t3.receipt);
|
||||
t4.timepoint = await clockFromReceipt[mode](t4.receipt);
|
||||
t5.timepoint = await clockFromReceipt[mode](t5.receipt);
|
||||
|
||||
expect(await this.votes.getPastTotalSupply(t1.timepoint - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t1.timepoint)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t1.timepoint + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t2.timepoint)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t2.timepoint + 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t3.timepoint)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t3.timepoint + 1)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t4.timepoint)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t4.timepoint + 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastTotalSupply(t5.timepoint)).to.be.bignumber.equal('1');
|
||||
expect(await this.votes.getPastTotalSupply(t5.timepoint + 1)).to.be.bignumber.equal('1');
|
||||
});
|
||||
});
|
||||
|
||||
@ -298,18 +316,15 @@ function shouldBehaveLikeVotes () {
|
||||
// https://github.com/compound-finance/compound-protocol/blob/master/tests/Governance/CompTest.js.
|
||||
describe('Compound test suite', function () {
|
||||
beforeEach(async function () {
|
||||
await this.votes.mint(this.account1, this.NFT0);
|
||||
await this.votes.mint(this.account1, this.NFT1);
|
||||
await this.votes.mint(this.account1, this.NFT2);
|
||||
await this.votes.mint(this.account1, this.NFT3);
|
||||
await this.votes.$_mint(this.account1, this.NFT0);
|
||||
await this.votes.$_mint(this.account1, this.NFT1);
|
||||
await this.votes.$_mint(this.account1, this.NFT2);
|
||||
await this.votes.$_mint(this.account1, this.NFT3);
|
||||
});
|
||||
|
||||
describe('getPastVotes', function () {
|
||||
it('reverts if block number >= current block', async function () {
|
||||
await expectRevert(
|
||||
this.votes.getPastVotes(this.account2, 5e10),
|
||||
'block not yet mined',
|
||||
);
|
||||
await expectRevert(this.votes.getPastVotes(this.account2, 5e10), 'future lookup');
|
||||
});
|
||||
|
||||
it('returns 0 if there are no checkpoints', async function () {
|
||||
@ -317,22 +332,24 @@ function shouldBehaveLikeVotes () {
|
||||
});
|
||||
|
||||
it('returns the latest block if >= last checkpoint block', async function () {
|
||||
const t1 = await this.votes.delegate(this.account2, { from: this.account1 });
|
||||
const { receipt } = await this.votes.delegate(this.account2, { from: this.account1 });
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
|
||||
const latest = await this.votes.getVotes(this.account2);
|
||||
const nextBlock = t1.receipt.blockNumber + 1;
|
||||
expect(await this.votes.getPastVotes(this.account2, t1.receipt.blockNumber)).to.be.bignumber.equal(latest);
|
||||
expect(await this.votes.getPastVotes(this.account2, nextBlock)).to.be.bignumber.equal(latest);
|
||||
expect(await this.votes.getPastVotes(this.account2, timepoint)).to.be.bignumber.equal(latest);
|
||||
expect(await this.votes.getPastVotes(this.account2, timepoint + 1)).to.be.bignumber.equal(latest);
|
||||
});
|
||||
|
||||
it('returns zero if < first checkpoint block', async function () {
|
||||
await time.advanceBlock();
|
||||
const t1 = await this.votes.delegate(this.account2, { from: this.account1 });
|
||||
const { receipt } = await this.votes.delegate(this.account2, { from: this.account1 });
|
||||
const timepoint = await clockFromReceipt[mode](receipt);
|
||||
await time.advanceBlock();
|
||||
await time.advanceBlock();
|
||||
|
||||
expect(await this.votes.getPastVotes(this.account2, t1.receipt.blockNumber - 1)).to.be.bignumber.equal('0');
|
||||
expect(await this.votes.getPastVotes(this.account2, timepoint - 1)).to.be.bignumber.equal('0');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@ -2,60 +2,70 @@ const { expectRevert, BN } = require('@openzeppelin/test-helpers');
|
||||
|
||||
const { expect } = require('chai');
|
||||
|
||||
const {
|
||||
shouldBehaveLikeVotes,
|
||||
} = require('./Votes.behavior');
|
||||
const { getChainId } = require('../../helpers/chainid');
|
||||
const { clockFromReceipt } = require('../../helpers/time');
|
||||
|
||||
const Votes = artifacts.require('VotesMock');
|
||||
const { shouldBehaveLikeVotes } = require('./Votes.behavior');
|
||||
|
||||
const MODES = {
|
||||
blocknumber: artifacts.require('$VotesMock'),
|
||||
timestamp: artifacts.require('$VotesTimestampMock'),
|
||||
};
|
||||
|
||||
contract('Votes', function (accounts) {
|
||||
const [ account1, account2, account3 ] = accounts;
|
||||
beforeEach(async function () {
|
||||
this.name = 'My Vote';
|
||||
this.votes = await Votes.new(this.name);
|
||||
});
|
||||
const [account1, account2, account3] = accounts;
|
||||
|
||||
it('starts with zero votes', async function () {
|
||||
expect(await this.votes.getTotalSupply()).to.be.bignumber.equal('0');
|
||||
});
|
||||
for (const [mode, artifact] of Object.entries(MODES)) {
|
||||
describe(`vote with ${mode}`, function () {
|
||||
beforeEach(async function () {
|
||||
this.name = 'My Vote';
|
||||
this.votes = await artifact.new(this.name, '1');
|
||||
});
|
||||
|
||||
describe('performs voting operations', function () {
|
||||
beforeEach(async function () {
|
||||
this.tx1 = await this.votes.mint(account1, 1);
|
||||
this.tx2 = await this.votes.mint(account2, 1);
|
||||
this.tx3 = await this.votes.mint(account3, 1);
|
||||
it('starts with zero votes', async function () {
|
||||
expect(await this.votes.getTotalSupply()).to.be.bignumber.equal('0');
|
||||
});
|
||||
|
||||
describe('performs voting operations', function () {
|
||||
beforeEach(async function () {
|
||||
this.tx1 = await this.votes.$_mint(account1, 1);
|
||||
this.tx2 = await this.votes.$_mint(account2, 1);
|
||||
this.tx3 = await this.votes.$_mint(account3, 1);
|
||||
this.tx1.timepoint = await clockFromReceipt[mode](this.tx1.receipt);
|
||||
this.tx2.timepoint = await clockFromReceipt[mode](this.tx2.receipt);
|
||||
this.tx3.timepoint = await clockFromReceipt[mode](this.tx3.receipt);
|
||||
});
|
||||
|
||||
it('reverts if block number >= current block', async function () {
|
||||
await expectRevert(this.votes.getPastTotalSupply(this.tx3.timepoint + 1), 'Votes: future lookup');
|
||||
});
|
||||
|
||||
it('delegates', async function () {
|
||||
await this.votes.delegate(account3, account2);
|
||||
|
||||
expect(await this.votes.delegates(account3)).to.be.equal(account2);
|
||||
});
|
||||
|
||||
it('returns total amount of votes', async function () {
|
||||
expect(await this.votes.getTotalSupply()).to.be.bignumber.equal('3');
|
||||
});
|
||||
});
|
||||
|
||||
describe('performs voting workflow', function () {
|
||||
beforeEach(async function () {
|
||||
this.chainId = await getChainId();
|
||||
this.account1 = account1;
|
||||
this.account2 = account2;
|
||||
this.account1Delegatee = account2;
|
||||
this.NFT0 = new BN('10000000000000000000000000');
|
||||
this.NFT1 = new BN('10');
|
||||
this.NFT2 = new BN('20');
|
||||
this.NFT3 = new BN('30');
|
||||
});
|
||||
|
||||
// includes EIP6372 behavior check
|
||||
shouldBehaveLikeVotes(mode);
|
||||
});
|
||||
});
|
||||
|
||||
it('reverts if block number >= current block', async function () {
|
||||
await expectRevert(
|
||||
this.votes.getPastTotalSupply(this.tx3.receipt.blockNumber + 1),
|
||||
'Votes: block not yet mined',
|
||||
);
|
||||
});
|
||||
|
||||
it('delegates', async function () {
|
||||
await this.votes.delegate(account3, account2);
|
||||
|
||||
expect(await this.votes.delegates(account3)).to.be.equal(account2);
|
||||
});
|
||||
|
||||
it('returns total amount of votes', async function () {
|
||||
expect(await this.votes.getTotalSupply()).to.be.bignumber.equal('3');
|
||||
});
|
||||
});
|
||||
|
||||
describe('performs voting workflow', function () {
|
||||
beforeEach(async function () {
|
||||
this.chainId = await this.votes.getChainId();
|
||||
this.account1 = account1;
|
||||
this.account2 = account2;
|
||||
this.account1Delegatee = account2;
|
||||
this.NFT0 = new BN('10000000000000000000000000');
|
||||
this.NFT1 = new BN('10');
|
||||
this.NFT2 = new BN('20');
|
||||
this.NFT3 = new BN('30');
|
||||
});
|
||||
|
||||
shouldBehaveLikeVotes();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user