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: 30/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/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/BlurExchange.sol#L145 https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/matchingPolicies/StandardPolicyERC1155.sol#L33 https://github.com/code-423n4/2022-10-blur/blob/2fdaa6e13b544c8c11d1c022a575f16c3a72e3bf/contracts/matchingPolicies/StandardPolicyERC1155.sol#L59
StandardPolicyERC1155
functions canMatchMakerBid
and canMatchMakerBid
always return amount == 1
, regardless of the function arguments.
This means that calling execute()
on an agreed order of ERC1155
token with an amount > 1
will always transfer amount == 1
of the token.
ERC1155
token, of tokenID
and amount == 100
ERC1155
token, of tokenID
and amount == 100
.BlurExchange.execute(AliceOrder, BobOrder)
.order.price
, but Bob only receive 1
token of tokenId
. Given that the price was agreed for 100
tokens, Bob has effectively lost 99% of order.price
.You can run the test below - add it to execution.test.ts
it('always transfers 1 token for ERC1155 orders', 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: 100, //@audit buyer order amount 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(1); //@audit buyer receives 1 token await checkBalances( aliceBalance, aliceBalanceWeth.add(priceMinusFee), bobBalance, bobBalanceWeth.sub(price), feeRecipientBalance, feeRecipientBalanceWeth.add(fee), ); });
Manual Analysis, Hardhat
Amend StandardPolicyERC1155.canMatchMakerAsk
and StandardPolicyERC1155.canMatchMakerBid
so that the amount returned is makerAmount
, not 1
31: makerAsk.price, 32: makerAsk.tokenId, -33: 1, + makerAsk.amount, 34: AssetType.ERC1155
57: makerBid.price, 58: makerBid.tokenId, -59: 1, + makerBid.amount, 60: AssetType.ERC1155
#0 - GalloDaSballo
2022-10-13T22:27:38Z