Skip to content

Commit

Permalink
Fix reentrancy bug (#36)
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLucca authored Sep 4, 2023
1 parent 540d87e commit 32c39b2
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 7 deletions.
2 changes: 1 addition & 1 deletion artifacts/multisig/multisig.contract

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion artifacts/multisig/multisig.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"source": {
"hash": "0xc93664205f298556415eae3f4e37ed7e585a03ca641b9f725ad235646c182688",
"hash": "0x666d9f46a96e595c8a26ddf51dd4eada8344b1f1872566d587883b604e606c97",
"language": "ink! 4.2.0",
"compiler": "rustc 1.69.0-nightly",
"build_info": {
Expand Down
3 changes: 3 additions & 0 deletions contracts/multisig/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -625,6 +625,9 @@ mod multisig {
}

fn _try_execute_tx(&mut self, tx_id: TxId) {
// Save current changes to storage
self.flush();

// check threshold met
if self.check_threshold_met(tx_id) {
// execute transaction
Expand Down
88 changes: 88 additions & 0 deletions tests/txId.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import { expect } from "chai";
import Constructors from "../typed_contracts/multisig/constructors/multisig";
import ContractAbi from "../artifacts/multisig/multisig.json";
import { ApiPromise, WsProvider, Keyring } from "@polkadot/api";
import {
assignKeyringPairs,
buildTransaction,
proposeTransaction,
} from "./utils/testHelpers";
import { MessageIndex } from "./utils/MessageIndex";
import Contract from "../typed_contracts/multisig/contracts/multisig";

let api;
let keyring;
let keypairs;
let aliceKeyringPair;
let bobKeyringPair;
let multisigMessageIndex;

before(async () => {
try {
// Perform async operations to obtain the api instance
const wsProvider = new WsProvider("ws://127.0.0.1:9944");

api = await ApiPromise.create({ provider: wsProvider });

if (!wsProvider.isConnected) {
throw new Error("Unable to connect to WebSocket");
}

// Create a keyring instance
keyring = new Keyring({ type: "sr25519" });
} catch (error) {
console.error(error);
process.exit(1); // Terminate the execution
}
});

after(() => {
// Disconnect from the API on completion
api.disconnect();
});

describe("TxId Test", () => {
before(() => {
// call function to create keyring pairs
keypairs = assignKeyringPairs(keyring, 2);
[aliceKeyringPair, bobKeyringPair] = keypairs;
});

it.only("TxId should increment", async () => {
multisigMessageIndex = new MessageIndex(ContractAbi);

// Initial args
const init_threshold = 1;

// Create a new contract
const constructors = new Constructors(api, aliceKeyringPair);

const { address } = await constructors.new(init_threshold, [
aliceKeyringPair.address,
]);

// Assert that the contract was created
expect(address).to.exist;

// Bind the contract to the new address
const multisig = new Contract(address, aliceKeyringPair, api);

const addOwnerTx = await buildTransaction(
api,
address,
"add_owner",
[bobKeyringPair.address],
multisigMessageIndex
);

// Propose the transaction on chain
await proposeTransaction(multisig, addOwnerTx, 0);

// Propose the same transaction on chain
await proposeTransaction(multisig, addOwnerTx, 1);

// Check that the txId has been incremented
const nextTxId = (await multisig.query.getNextTxId()).value.unwrap().toNumber();
expect(nextTxId).to.equal(2);
});
});
11 changes: 8 additions & 3 deletions tests/utils/testHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,22 @@ export const buildTransaction = async (
};

export const proposeTransaction = async (multisig, txToPropose, txIndex) => {
//TODO: Check threshold
// If the threshold is 1, the transaction is executed automatically so we cannot check the state

// Propose the transaction on chain
await multisig.tx.proposeTx(txToPropose);

// Check the state after the proposeTx call
let tx = await multisig.query.getTx(txIndex);
expect(tx).to.exist;
let nextTxId = (await multisig.query.getNextTxId()).value.unwrap().toNumber();
//expect(tx).to.exist;
expect(nextTxId).to.equal(txIndex + 1);

// The proposed transaction has 1 approval and 0 rejections
const approvals = (await multisig.query.getTxApprovals(0)).value.ok;
expect(approvals).to.equal(1);
//expect(approvals).to.equal(1);

const rejections = (await multisig.query.getTxRejections(0)).value.ok;
expect(rejections).to.equal(0);
//expect(rejections).to.equal(0);
};
4 changes: 2 additions & 2 deletions typed_contracts/multisig/contract-info/multisig.ts

Large diffs are not rendered by default.

0 comments on commit 32c39b2

Please sign in to comment.