Platform: Code4rena
Start Date: 11/11/2022
Pot Size: $36,500 USDC
Total HM: 5
Participants: 62
Period: 3 days
Judge: berndartmueller
Id: 181
League: ETH
Rank: 41/62
Findings: 2
Award: $64.77
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xSmartContract
Also found by: 0x4non, 0xNazgul, 0xhacksmithh, Aymen0909, HE1M, IllIllI, Josiah, RaymondFam, Rolezn, Tricko, brgltd, c3phas, chrisdior4, joestakey, ladboy233, martin, neko_nyaa, rotcivegaf, tnevler, trustindistrust
42.5508 USDC - $42.55
The Pool
contract uses events to log deposits and withdrawals. However, it uses the same event for both deposits and withdrawals. This makes log tracking on-chain harder to understand.
Create specific Deposit
and Withdraw
events for those actions.
The Pool
contract uses events to log deposits and withdrawals. However, the code inserts the 0 address instead of the address of the contract, confusing the output.
Replace address(0)
with address(this)
.
The Pool
contract acts as a source of ETH funds for use in executing purchases on the Exchange
. Users may deposit ETH and use that ETH for purchases, or withdraw it.
However, the contract is upgradable for no clear reason. It's simple in form and purpose. Since it holds user's ETH directly, it should be immutable and unable to defraud users later, either maliciously or by accident of management.
Remove all upgradable features from the Pool contract.
_transferFees
While there is no risk of malicious effects, it is best practice to move changes to state or scoped state above side effects like transfers ("Checks Effects Interactions" pattern).
return
statement from _canMatchOrders
as it is unnecessary_canMatchOrders
uses named return values, and contains a branch that ensures that the named return values can't be shadowed. As such, the final return
statement is unnecessary and can be removed.
0
values, causing execute
to consume more gas than expected to process trades.When a sell order is created, it includes provision for a dynamic Fee
array. This struct is designed to allow the seller to indicate the amount and destination for fees owed during a trade.
The loop that processes the trades in Exchange._transferFees()
has a cap of 255 such fee entries. As such, a seller that wanted to grief buyers could create and sign a sell Order
with an array of at least 256 members with the rate
set to 0. While this would still result in a sum of 0 for fees, the dapp itself is unlikely to indicate the higher cost of gas to perform the trade.
If possible, modify the Order
struct to contain a sized Fee
array that is set to a reasonable value based on business case.
If that isn't possible, insert a check for 0
at line 599 that continue
s if the value is 0, thus reducing the gas impact of such an attack.
#0 - c4-judge
2022-11-17T12:32:45Z
berndartmueller marked the issue as grade-b
🌟 Selected for report: ReyAdmirado
Also found by: 0x4non, 0xRoxas, 0xab00, Awesome, Aymen0909, Bnke0x0, Deivitto, Diana, IllIllI, Rahoz, RaymondFam, Rolezn, Sathish9098, ajtra, aphak5010, aviggiano, c3phas, carlitox477, ch0bu, cryptostellar5, erictee, lukris02, martin, rotcivegaf, saian, shark, trustindistrust, zaskoh
22.2155 USDC - $22.22
OrdersMatched
event emissionUnless there is a compelling business case for recording the maker/taker relationship of a trade, removing the computation for who was the maker and taker would save nearly 500 gas on a protocol hotpath. The effect is compounded if a bulk order is the source of the calls to _execute()
Consider instead simply recording the seller and buyer addresses. Since the inputs to _execute
already contain the listingTime
via the Order
struct, the information can be computed offchain rather than forcing users to pay for the computation.
#0 - c4-judge
2022-11-15T22:44:28Z
berndartmueller marked the issue as grade-b