Skip to content

Commit

Permalink
Fix tests
Browse files Browse the repository at this point in the history
  • Loading branch information
ernestognw committed Jun 29, 2023
1 parent f808576 commit 2ed9be3
Show file tree
Hide file tree
Showing 3 changed files with 135 additions and 108 deletions.
89 changes: 51 additions & 38 deletions test/governance/Governor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { constants, expectEvent, expectRevert } = require('@openzeppelin/test-hel
const { expect } = require('chai');
const ethSigUtil = require('eth-sig-util');
const Wallet = require('ethereumjs-wallet').default;
const { fromRpcSig } = require('ethereumjs-util');
const { fromRpcSig, toRpcSig } = require('ethereumjs-util');

const Enums = require('../helpers/enums');
const { getDomain, domainType } = require('../helpers/eip712');
Expand Down Expand Up @@ -311,22 +311,24 @@ contract('Governor', function (accounts) {
this.voterBySig = Wallet.generate();
this.voterBySig.address = web3.utils.toChecksumAddress(this.voterBySig.getAddressString());

this.data = (contract, message) =>
getDomain(contract).then(domain => ({
primaryType: 'Ballot',
types: {
EIP712Domain: domainType(domain),
Ballot: [
{ name: 'proposalId', type: 'uint256' },
{ name: 'support', type: 'uint8' },
{ name: 'voter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
],
},
domain,
message,
}));

this.signature = (contract, message) =>
getDomain(contract)
.then(domain => ({
primaryType: 'Ballot',
types: {
EIP712Domain: domainType(domain),
Ballot: [
{ name: 'proposalId', type: 'uint256' },
{ name: 'support', type: 'uint8' },
{ name: 'voter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
],
},
domain,
message,
}))
this.data(contract, message)
.then(data => ethSigUtil.signTypedMessage(this.voterBySig.getPrivateKey(), { data }))
.then(fromRpcSig);

Expand All @@ -340,35 +342,46 @@ contract('Governor', function (accounts) {
it('if signature does not match signer', async function () {
const nonce = await this.mock.nonces(this.voterBySig.address);

expectRevertCustomError(
this.helper.vote({
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce,
signature: (...params) => {
const sig = this.signature(...params);
sig[69] ^= 0xff;
return sig;
},
}),
'GovernorInvalidSigner',
[],
);
const voteParams = {
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce,
signature: async (...params) => {
const sig = await this.signature(...params);
sig.s[12] ^= 0xff;
return sig;
},
};

const { r, s, v } = await this.helper.sign(voteParams);
const message = this.helper.forgeMessage(voteParams);
const data = await this.data(this.mock, message);

await expectRevertCustomError(this.helper.vote(voteParams), 'GovernorInvalidSigner', [
ethSigUtil.recoverTypedSignature({ sig: toRpcSig(v, r, s), data }),
voteParams.voter,
]);
});

it('if vote nonce is incorrect', async function () {
const nonce = await this.mock.nonces(this.voterBySig.address);

expectRevertCustomError(
this.helper.vote({
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce: nonce.addn(1),
signature: this.signature,
}),
const voteParams = {
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce: nonce.addn(1),
signature: this.signature,
};

const { r, s, v } = await this.helper.sign(voteParams);
const message = this.helper.forgeMessage(voteParams);
const data = await this.data(this.mock, { ...message, nonce });

await expectRevertCustomError(
this.helper.vote(voteParams),
// The signature check implies the nonce can't be tampered without changing the signer
'GovernorInvalidSigner',
[],
[ethSigUtil.recoverTypedSignature({ sig: toRpcSig(v, r, s), data }), voteParams.voter],
);
});
});
Expand Down
101 changes: 57 additions & 44 deletions test/governance/extensions/GovernorWithParams.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ const { expectEvent } = require('@openzeppelin/test-helpers');
const { expect } = require('chai');
const ethSigUtil = require('eth-sig-util');
const Wallet = require('ethereumjs-wallet').default;
const { fromRpcSig } = require('ethereumjs-util');
const { fromRpcSig, toRpcSig } = require('ethereumjs-util');

const Enums = require('../../helpers/enums');
const { getDomain, domainType } = require('../../helpers/eip712');
Expand Down Expand Up @@ -125,24 +125,26 @@ contract('GovernorWithParams', function (accounts) {
this.voterBySig = Wallet.generate();
this.voterBySig.address = web3.utils.toChecksumAddress(this.voterBySig.getAddressString());

this.data = (contract, message) =>
getDomain(contract).then(domain => ({
primaryType: 'ExtendedBallot',
types: {
EIP712Domain: domainType(domain),
ExtendedBallot: [
{ name: 'proposalId', type: 'uint256' },
{ name: 'support', type: 'uint8' },
{ name: 'voter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
{ name: 'reason', type: 'string' },
{ name: 'params', type: 'bytes' },
],
},
domain,
message,
}));

this.signature = (contract, message) =>
getDomain(contract)
.then(domain => ({
primaryType: 'ExtendedBallot',
types: {
EIP712Domain: domainType(domain),
ExtendedBallot: [
{ name: 'proposalId', type: 'uint256' },
{ name: 'support', type: 'uint8' },
{ name: 'voter', type: 'address' },
{ name: 'nonce', type: 'uint256' },
{ name: 'reason', type: 'string' },
{ name: 'params', type: 'bytes' },
],
},
domain,
message,
}))
this.data(contract, message)
.then(data => ethSigUtil.signTypedMessage(this.voterBySig.getPrivateKey(), { data }))
.then(fromRpcSig);

Expand Down Expand Up @@ -185,39 +187,50 @@ contract('GovernorWithParams', function (accounts) {
it('reverts if signature does not match signer', async function () {
const nonce = await this.mock.nonces(this.voterBySig.address);

expectRevertCustomError(
this.helper.vote({
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce,
signature: (...params) => {
const sig = this.signature(...params);
sig[69] ^= 0xff;
return sig;
},
reason: 'no particular reason',
params: encodedParams,
}),
'GovernorInvalidSigner',
[],
);
const voteParams = {
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce,
signature: async (...params) => {
const sig = await this.signature(...params);
sig.s[12] ^= 0xff;
return sig;
},
reason: 'no particular reason',
params: encodedParams,
};

const { r, s, v } = await this.helper.sign(voteParams);
const message = this.helper.forgeMessage(voteParams);
const data = await this.data(this.mock, message);

await expectRevertCustomError(this.helper.vote(voteParams), 'GovernorInvalidSigner', [
ethSigUtil.recoverTypedSignature({ sig: toRpcSig(v, r, s), data }),
voteParams.voter,
]);
});

it('reverts if vote nonce is incorrect', async function () {
const nonce = await this.mock.nonces(this.voterBySig.address);

expectRevertCustomError(
this.helper.vote({
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce: nonce.addn(1),
signature: this.signature,
reason: 'no particular reason',
params: encodedParams,
}),
const voteParams = {
support: Enums.VoteType.For,
voter: this.voterBySig.address,
nonce: nonce.addn(1),
signature: this.signature,
reason: 'no particular reason',
params: encodedParams,
};

const { r, s, v } = await this.helper.sign(voteParams);
const message = this.helper.forgeMessage(voteParams);
const data = await this.data(this.mock, { ...message, nonce });

await expectRevertCustomError(
this.helper.vote(voteParams),
// The signature check implies the nonce can't be tampered without changing the signer
'GovernorInvalidSigner',
[],
[ethSigUtil.recoverTypedSignature({ sig: toRpcSig(v, r, s), data }), voteParams.voter],
);
});
});
Expand Down
53 changes: 27 additions & 26 deletions test/helpers/governance.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,33 +91,17 @@ class GovernorHelper {
return vote.signature
? // if signature, and either params or reason →
vote.params || vote.reason
? vote
.signature(this.governor, {
proposalId: proposal.id,
support: vote.support,
voter: vote.voter,
nonce: vote.nonce,
reason: vote.reason || '',
params: vote.params || '',
})
.then(({ v, r, s }) =>
this.governor.castVoteWithReasonAndParamsBySig(
...concatOpts(
[proposal.id, vote.support, vote.voter, vote.reason || '', vote.params || '', v, r, s],
opts,
),
? this.sign(vote).then(({ v, r, s }) =>
this.governor.castVoteWithReasonAndParamsBySig(
...concatOpts(
[proposal.id, vote.support, vote.voter, vote.reason || '', vote.params || '', v, r, s],
opts,
),
)
: vote
.signature(this.governor, {
proposalId: proposal.id,
support: vote.support,
voter: vote.voter,
nonce: vote.nonce,
})
.then(({ v, r, s }) =>
this.governor.castVoteBySig(...concatOpts([proposal.id, vote.support, vote.voter, v, r, s], opts)),
)
),
)
: this.sign(vote).then(({ v, r, s }) =>
this.governor.castVoteBySig(...concatOpts([proposal.id, vote.support, vote.voter, v, r, s], opts)),
)
: vote.params
? // otherwise if params
this.governor.castVoteWithReasonAndParams(
Expand All @@ -129,6 +113,23 @@ class GovernorHelper {
: this.governor.castVote(...concatOpts([proposal.id, vote.support], opts));
}

sign(vote = {}) {
return vote.signature(this.governor, this.forgeMessage(vote));
}

forgeMessage(vote = {}) {
const proposal = this.currentProposal;

const message = { proposalId: proposal.id, support: vote.support, voter: vote.voter, nonce: vote.nonce };

if (vote.params || vote.reason) {
message.reason = vote.reason || '';
message.params = vote.params || '';
}

return message;
}

async waitForSnapshot(offset = 0) {
const proposal = this.currentProposal;
const timepoint = await this.governor.proposalSnapshot(proposal.id);
Expand Down

0 comments on commit 2ed9be3

Please sign in to comment.