Platform: Code4rena
Start Date: 05/10/2022
Pot Size: $50,000 USDC
Total HM: 2
Participants: 80
Period: 5 days
Judge: GalloDaSballo
Id: 168
League: ETH
Rank: 52/80
Findings: 1
Award: $114.82
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: dipp
Also found by: 0x4non, 0x52, 0xRobocop, 0xc0ffEE, 8olidity, Ch_301, Jeiwan, Junnon, KIntern_NA, Lambda, M4TZ1P, MiloTruck, Nyx, PaludoX0, Ruhum, RustyRabbit, Soosh, TomJ, Trust, arcoun, aviggiano, bardamu, cryptonue, csanuragjain, d3e4, enckrish, exd0tpy, hansfriese, jayphbee, joestakey, ladboy233, minhquanym, minhtrng, nicobevi, obront, polymorphism, rokinot, romand, rotcivegaf, rvierdiiev, saian, serial-coder, trustindistrust, zzykxx
114.8239 USDC - $114.82
https://github.com/code-423n4/2022-10-blur/blob/main/contracts/BlurExchange.sol#L416-L434 https://github.com/code-423n4/2022-10-blur/blob/main/contracts/matchingPolicies/StandardPolicyERC1155.sol#L12-L62 https://github.com/code-423n4/2022-10-blur/blob/main/contracts/BlurExchange.sol#L128-L175
Order struct has amount
as a member variable that specifies the number of tokens to be traded in the case of ERC1155. BlurExchange.execute
is a function that executes a transaction with the information of the orders.
During the execution of BlurExchange.execute
, BlurExchange._canMatchOrders
decides amount of ERC1155 to be transferred to buyer by invoking StandardPolicyERC1155.canMatchBid
or StandardPolicyERC1155.canMatchMakerAsk
.
There is an issue where both functions do not check whether the token amounts to be exchanged of the sell order and buy order are the same. This leads to a problem in which the orders are matched even if the amount of ERC1155 that the buyer and seller want to trade is different.
In addition, since both function always returns 1 as the amount, the amount specified in the orders will be ignored and only 1 ERC1155 token will be sent.
This may result in unintended losses to traders who wish to trade a certain number of ERC1155 tokens.
Please append the following test in line 129 of tests/execution.test.ts This test should fail to demonstrate the described scenario.
it('can exchange multiple ERC1155', async () => { await mockERC1155.mint(alice.address, tokenId, 100); sell = generateOrder(alice, { side: Side.Sell, tokenId, amount: 100, collection: mockERC1155.address, matchingPolicy: matchingPolicies.standardPolicyERC1155.address, }); buy = generateOrder(bob, { side: Side.Buy, tokenId, amount: 98, collection: mockERC1155.address, matchingPolicy: matchingPolicies.standardPolicyERC1155.address, }); sellInput = await sell.pack(); buyInput = await buy.pack(); await waitForTx(exchange.execute(sellInput, buyInput)); expect(await mockERC1155.balanceOf(bob.address, tokenId)).to.be.equal(98); await checkBalances( aliceBalance, aliceBalanceWeth.add(priceMinusFee), bobBalance, bobBalanceWeth.sub(price), feeRecipientBalance, feeRecipientBalanceWeth.add(fee), ); });
Sublime Text
https://github.com/code-423n4/2022-10-blur/blob/main/contracts/matchingPolicies/StandardPolicyERC1155.sol#L12-L62 can be changed to the following code.
function canMatchMakerAsk(Order calldata makerAsk, Order calldata takerBid) external pure override returns ( bool, uint256, uint256, uint256, AssetType ) { return ( (makerAsk.side != takerBid.side) && (makerAsk.paymentToken == takerBid.paymentToken) && (makerAsk.collection == takerBid.collection) && (makerAsk.tokenId == takerBid.tokenId) && (makerAsk.matchingPolicy == takerBid.matchingPolicy) && (makerAsk.amount == takerBid.amount) && (makerAsk.price == takerBid.price), makerAsk.price, makerAsk.tokenId, makerAsk.amount, AssetType.ERC1155 ); } function canMatchMakerBid(Order calldata makerBid, Order calldata takerAsk) external pure override returns ( bool, uint256, uint256, uint256, AssetType ) { return ( (makerBid.side != takerAsk.side) && (makerBid.paymentToken == takerAsk.paymentToken) && (makerBid.collection == takerAsk.collection) && (makerBid.tokenId == takerAsk.tokenId) && (makerBid.matchingPolicy == takerAsk.matchingPolicy) && (makerBid.amount == takerAsk.amount) && (makerBid.price == takerAsk.price), makerBid.price, makerBid.tokenId, makerBid.amount, AssetType.ERC1155 ); }
#0 - blur-io-toad
2022-10-16T23:38:33Z
This was an oversight on my part for not putting this contract as out-of-scope. Our marketplace does not handle ERC1155 yet and so we haven't concluded what the matching critieria for those orders will be. This contract was mainly created to test ERC1155 transfers through the rest of the exchange, but shouldn't be deployed initially. When we are prepared to handle ERC1155 orders we will have to develop a new matching policy that determines the amount from the order parameters. Acknowledging that it's incorrect, but won't be making any changes as the contract won't be deployed.
#1 - trust1995
2022-10-28T00:02:24Z
Dup #711
#2 - GalloDaSballo
2022-10-28T00:06:45Z
#3 - trust1995
2022-10-28T00:08:33Z
"There is an issue where both functions do not check whether the token amounts to be exchanged of the sell order and buy order are the same. This leads to a problem in which the orders are matched even if the amount of ERC1155 that the buyer and seller want to trade is different."
Warden has clearly identified the issue highlighted in #711 rather than the one in #666