From 93cba0abf6f92afe9a501d19dd82cbe6fbbfcc33 Mon Sep 17 00:00:00 2001 From: Alex Rea Date: Tue, 9 May 2023 08:52:27 +0100 Subject: [PATCH] Stop nested multicalls --- contracts/common/Multicall.sol | 6 ++++++ test/contracts-network/colony.js | 9 +++++++++ 2 files changed, 15 insertions(+) diff --git a/contracts/common/Multicall.sol b/contracts/common/Multicall.sol index f1ccd9838e..6fd8223ee7 100644 --- a/contracts/common/Multicall.sol +++ b/contracts/common/Multicall.sol @@ -6,6 +6,9 @@ pragma experimental "ABIEncoderV2"; import "./MetaTransactionMsgSender.sol"; abstract contract Multicall is MetaTransactionMsgSender { + + bytes4 constant multicallSig = bytes4(keccak256("multicall(bytes[])")); + function multicall(bytes[] calldata data) public returns (bytes[] memory results) { // First off, is this a metatransaction? address sender = msgSender(); @@ -15,8 +18,11 @@ abstract contract Multicall is MetaTransactionMsgSender { affix = abi.encodePacked(METATRANSACTION_FLAG, sender); } + + results = new bytes[](data.length); for (uint256 i; i < data.length; i++) { + require(bytes4(data[i]) != multicallSig, "colony-multicall-cannot-multicall"); (bool success, bytes memory result) = address(this).delegatecall(abi.encodePacked(data[i], affix)); if (!success) { diff --git a/test/contracts-network/colony.js b/test/contracts-network/colony.js index 807f0ddf15..8e10f02175 100755 --- a/test/contracts-network/colony.js +++ b/test/contracts-network/colony.js @@ -412,6 +412,15 @@ contract("Colony", (accounts) => { }); }); + describe("when executing a multicall transaction", () => { + it("a multicall transaction cannot call multicall", async function () { + const txData1 = await colony.contract.methods.setArchitectureRole(1, UINT256_MAX, USER1, 1, true).encodeABI(); + const txData2 = await colony.contract.methods.multicall([txData1]).encodeABI(); + + await checkErrorRevert(colony.multicall([txData1, txData2]), "colony-multicall-cannot-multicall"); + }); + }); + describe("when burning tokens", async () => { beforeEach(async () => { await colony.mintTokens(WAD);