From 12204c47dd1a30d9b99dae04e24d3e3434676963 Mon Sep 17 00:00:00 2001 From: Neeraj Kashyap Date: Tue, 22 Nov 2022 08:18:36 -0800 Subject: [PATCH 1/2] A fix for the mintBatch vulnerability to bypass pool capacity --- contracts/terminus/ERC1155WithTerminusStorage.sol | 11 ++++------- dao/test_terminus.py | 8 ++++++-- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/contracts/terminus/ERC1155WithTerminusStorage.sol b/contracts/terminus/ERC1155WithTerminusStorage.sol index a31a7a6..b01dc7a 100644 --- a/contracts/terminus/ERC1155WithTerminusStorage.sol +++ b/contracts/terminus/ERC1155WithTerminusStorage.sol @@ -386,18 +386,15 @@ contract ERC1155WithTerminusStorage is LibTerminus.TerminusStorage storage ts = LibTerminus.terminusStorage(); - for (uint256 i = 0; i < ids.length; i++) { - require( - ts.poolSupply[ids[i]] + amounts[i] <= ts.poolCapacity[ids[i]], - "ERC1155WithTerminusStorage: _mintBatch -- Minted tokens would exceed pool capacity" - ); - } - address operator = _msgSender(); _beforeTokenTransfer(operator, address(0), to, ids, amounts, data); for (uint256 i = 0; i < ids.length; i++) { + require( + ts.poolSupply[ids[i]] + amounts[i] <= ts.poolCapacity[ids[i]], + "ERC1155WithTerminusStorage: _mintBatch -- Minted tokens would exceed pool capacity" + ); ts.poolSupply[ids[i]] += amounts[i]; ts.poolBalances[ids[i]][to] += amounts[i]; } diff --git a/dao/test_terminus.py b/dao/test_terminus.py index 3ff8285..10c8380 100644 --- a/dao/test_terminus.py +++ b/dao/test_terminus.py @@ -333,12 +333,16 @@ class TestPoolOperations(TerminusTestCase): ) def test_mint_batch_fails_if_it_exceeds_capacity(self): + capacity = 10 + self.diamond_terminus.create_pool_v1( + capacity, True, True, {"from": accounts[1]} + ) pool_id = self.diamond_terminus.total_pools() with self.assertRaises(Exception): self.diamond_terminus.mint_batch( accounts[2].address, - pool_i_ds=[pool_id], - amounts=[11], + pool_i_ds=[pool_id, pool_id], + amounts=[int(capacity / 2) + 1, int(capacity / 2) + 1], data=b"", transaction_config={"from": accounts[1]}, ) From 8f34b14fb5285bb109927251ece4add753ac9f76 Mon Sep 17 00:00:00 2001 From: Neeraj Kashyap Date: Tue, 22 Nov 2022 08:25:50 -0800 Subject: [PATCH 2/2] Added additional test for mintBatch exploit Inspired by @kompotkot --- dao/test_terminus.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/dao/test_terminus.py b/dao/test_terminus.py index 10c8380..6c885e9 100644 --- a/dao/test_terminus.py +++ b/dao/test_terminus.py @@ -353,6 +353,27 @@ class TestPoolOperations(TerminusTestCase): supply = self.diamond_terminus.terminus_pool_supply(pool_id) self.assertEqual(supply, 0) + def test_mint_batch_fails_if_it_exceeds_capacity_one_at_a_time(self): + capacity = 10 + self.diamond_terminus.create_pool_v1( + capacity, True, True, {"from": accounts[1]} + ) + pool_id = self.diamond_terminus.total_pools() + with self.assertRaises(Exception): + self.diamond_terminus.mint_batch( + accounts[2].address, + pool_i_ds=[pool_id for _ in range(capacity + 1)], + amounts=[1 for _ in range(capacity + 1)], + data=b"", + transaction_config={"from": accounts[1]}, + ) + + balance = self.diamond_terminus.balance_of(accounts[2].address, pool_id) + self.assertEqual(balance, 0) + + supply = self.diamond_terminus.terminus_pool_supply(pool_id) + self.assertEqual(supply, 0) + def test_pool_mint_batch(self): pool_id = self.diamond_terminus.total_pools() target_accounts = [account.address for account in accounts[:5]]