Skip to content

Commit

Permalink
fix: pass previous transactions for final usability
Browse files Browse the repository at this point in the history
  • Loading branch information
daveroga committed Sep 23, 2022
1 parent 9db1eb2 commit 5d860ea
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 39 deletions.
53 changes: 35 additions & 18 deletions test/multisig/administrator.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ chai.use(chaiAsPromised);
const environment = config.ENVIRONMENTS[process.env.ENVIRONMENT] || config.ENVIRONMENTS.localhost;

const { mnemonics, signingKeys, addresses } = config.TEST_OPTIONS;
const amount1 = 10;
const amount2 = 100;

const getContractInstance = async (contractName, nf3) => {
const abi = contractABIs[contractName];
Expand Down Expand Up @@ -77,37 +79,40 @@ describe(`Testing Administrator`, () => {
});

it('Set boot proposer with the multisig', async () => {
await contractMultiSig.setBootProposer(
const transactions = await contractMultiSig.setBootProposer(
signingKeys.user1,
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.setBootProposer(
signingKeys.user1,
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
const bootProposer = await shieldContractInstance.methods.getBootProposer().call();

expect(bootProposer.toUpperCase()).to.be.equal(nf3User.ethereumAddress.toUpperCase());
});

it('Set boot challenger with the multisig', async () => {
await contractMultiSig.setBootChallenger(
const transactions = await contractMultiSig.setBootChallenger(
signingKeys.user1,
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.setBootChallenger(
signingKeys.user1,
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -117,21 +122,23 @@ describe(`Testing Administrator`, () => {
});

it('Set restriction with the multisig', async () => {
await contractMultiSig.setTokenRestrictions(
const transactions = await contractMultiSig.setTokenRestrictions(
nf3User.ethereumAddress, // simulate a token address
10,
100,
amount1,
amount2,
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.setTokenRestrictions(
nf3User.ethereumAddress, // simulate a token address
10,
100,
amount1,
amount2,
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -142,22 +149,24 @@ describe(`Testing Administrator`, () => {
.getRestriction(nf3User.ethereumAddress, 1)
.call();

expect(Number(restrictionDeposit)).to.be.equal(10);
expect(Number(restrictionWithdraw)).to.be.equal(100);
expect(Number(restrictionDeposit)).to.be.equal(amount1);
expect(Number(restrictionWithdraw)).to.be.equal(amount2);
});

it('Remove restriction with the multisig', async () => {
await contractMultiSig.removeTokenRestrictions(
const transactions = await contractMultiSig.removeTokenRestrictions(
nf3User.ethereumAddress, // simulate a token address
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.removeTokenRestrictions(
nf3User.ethereumAddress, // simulate a token address
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -173,17 +182,19 @@ describe(`Testing Administrator`, () => {
});

it('Set MATIC address with the multisig', async () => {
await contractMultiSig.setMaticAddress(
const transactions = await contractMultiSig.setMaticAddress(
addresses.user1,
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.setMaticAddress(
addresses.user1,
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -194,15 +205,17 @@ describe(`Testing Administrator`, () => {

it('Pause contracts with the multisig', async () => {
const paused1 = await stateContractInstance.methods.paused().call();
await contractMultiSig.pauseContracts(
const transactions = await contractMultiSig.pauseContracts(
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.pauseContracts(
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -215,15 +228,17 @@ describe(`Testing Administrator`, () => {

it('Unpause contracts with the multisig', async () => {
const paused1 = await stateContractInstance.methods.paused().call();
await contractMultiSig.unpauseContracts(
const transactions = await contractMultiSig.unpauseContracts(
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.unpauseContracts(
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand All @@ -235,17 +250,19 @@ describe(`Testing Administrator`, () => {
});

it('Be able to transfer ownership of contracts from multisig to a specific one', async () => {
await contractMultiSig.transferOwnership(
const transactions = await contractMultiSig.transferOwnership(
signingKeys.user1,
signingKeys.user1,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
[],
);
const approved = await contractMultiSig.transferOwnership(
signingKeys.user1,
signingKeys.user2,
addresses.user1,
await multisigContractInstance.methods.nonce().call(),
transactions,
);

await contractMultiSig.multiSig.executeMultiSigTransactions(approved, signingKeys.user1);
Expand Down Expand Up @@ -273,7 +290,7 @@ describe(`Testing Administrator`, () => {

it('Set restriction without multisig', async () => {
await shieldContractInstance.methods
.setRestriction(nf3User.ethereumAddress, 10, 100)
.setRestriction(nf3User.ethereumAddress, amount1, amount2)
.send({ from: nf3User.ethereumAddress });
const restrictionDeposit = await shieldContractInstance.methods
.getRestriction(nf3User.ethereumAddress, 0)
Expand All @@ -282,8 +299,8 @@ describe(`Testing Administrator`, () => {
.getRestriction(nf3User.ethereumAddress, 1)
.call();

expect(Number(restrictionDeposit)).to.be.equal(10);
expect(Number(restrictionWithdraw)).to.be.equal(100);
expect(Number(restrictionDeposit)).to.be.equal(amount1);
expect(Number(restrictionWithdraw)).to.be.equal(amount2);
});

it('Remove restriction without multisig', async () => {
Expand Down
30 changes: 16 additions & 14 deletions test/multisig/multisig.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ import logger from 'common-files/utils/logger.mjs';

// eslint-disable-next-line import/prefer-default-export
export class MultiSig {
transactions = [];

MULTISIG_CONSTANTS = {};

SIGNATURE_THRESHOLD = 2;
Expand Down Expand Up @@ -89,41 +87,44 @@ export class MultiSig {
/**
Function to save a signed transaction, ready for the multisig
*/
async saveSigned(signed) {
this.transactions.push({ _id: signed.messageHash.concat(signed.by.slice(2)), ...signed });
// eslint-disable-next-line class-methods-use-this
async saveSigned(signed, transactions) {
transactions.push({ _id: signed.messageHash.concat(signed.by.slice(2)), ...signed });
}

/**
Function to get the signatures
*/
async getSigned(messageHash) {
return this.transactions.filter(t => t.messageHash === messageHash);
// eslint-disable-next-line class-methods-use-this
async getSigned(messageHash, transactions) {
return transactions.filter(t => t.messageHash === messageHash);
}

/**
Function to check that there are enough transactions to send some signed data
*/
async checkThreshold(messageHash) {
return this.transactions.filter(t => t.messageHash === messageHash).length;
// eslint-disable-next-line class-methods-use-this
async checkThreshold(messageHash, transactions) {
return transactions.filter(t => t.messageHash === messageHash).length;
}

// This function saves a signed transaction and will return the array of so-far signed
// transactions
async addSignedTransaction(signed) {
async addSignedTransaction(signed, transactions) {
// save the signed transaction until we meet the signature threshold, only if it's actually signed
if (signed.r) {
try {
await this.saveSigned(signed);
await this.saveSigned(signed, transactions);
} catch (err) {
if (err.message.includes('duplicate key'))
console.log('You have already signed this message - no action taken');
else throw new Error(err);
}
}
const numberOfSignatures = await this.checkThreshold(signed.messageHash);
const numberOfSignatures = await this.checkThreshold(signed.messageHash, transactions);
logger.info(`Number of signatures for this transaction is ${numberOfSignatures}`);
if (numberOfSignatures === this.SIGNATURE_THRESHOLD) logger.info(`Signature threshold reached`);
const signedArray = (await this.getSigned(signed.messageHash)).sort((a, b) => {
const signedArray = (await this.getSigned(signed.messageHash, transactions)).sort((a, b) => {
const x = BigInt(a.by);
const y = BigInt(b.by);
return x < y ? -1 : x > y ? 1 : 0; // eslint-disable-line no-nested-ternary
Expand Down Expand Up @@ -158,6 +159,7 @@ export class MultiSig {
contractAddress,
executorAddress,
nonce,
transactions,
) {
// compute a signature over the unsigned transaction data
const messageHash = await this.createMultiSigMessageHash(
Expand All @@ -168,7 +170,7 @@ export class MultiSig {
executorAddress,
this.gas,
);
if (!signingKey) return this.addSignedTransaction({ messageHash }); // if no signing key is given, don't create a new signed transaction
if (!signingKey) return this.addSignedTransaction({ messageHash }, transactions); // if no signing key is given, don't create a new signed transaction
const { r, s, v } = ecsign(
Buffer.from(messageHash.slice(2), 'hex'),
Buffer.from(signingKey.slice(2), 'hex'),
Expand All @@ -182,7 +184,7 @@ export class MultiSig {
contractAddress,
data: unsignedTransactionData,
};
return this.addSignedTransaction(signed);
return this.addSignedTransaction(signed, transactions);
}

async executeMultiSigTransaction(signedArray, executor) {
Expand Down
Loading

0 comments on commit 5d860ea

Please sign in to comment.