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: 5/62
Findings: 3
Award: $1,083.73
🌟 Selected for report: 0
🚀 Solo Findings: 0
612.4275 USDC - $612.43
https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L40-L46 https://github.com/code-423n4/2022-11-non-fungible/blob/323b7cbf607425dd81da96c0777c8b12e800305d/contracts/Exchange.sol#L168-L210
The setupExecution can be re-entered by calling bulkExecute inside an _execution
.
Because the global state remainingETH and isInternal are modified (reset to 0 and flase) after the latter reentrant call, the previous call is affected:
At the same time, the ETH lost is taken away by _returnDust() in the re-entered calling if it carries msg.value greater than 0.
Use a custom contract which will re-enter Exchange by calling bulkExecute
.
The logic of the custom contract can be invoked by the execution of a malicious constructed order in Exchange.sol#L631 or Exchange.sol#L663 or Exchange.sol#L665.
n/a
Adding require(!isInternal)
to setupExecution will avoid this problem:
modifier setupExecution() { require(!isInternal); // added remainingETH = msg.value; isInternal = true; _; remainingETH = 0; isInternal = false; }
#0 - trust1995
2022-11-14T22:10:31Z
It is not explained how to bypass the nonReentrant modifier applied to _execute(), so the report is lacking.
#1 - c4-judge
2022-11-16T14:15:37Z
berndartmueller marked the issue as duplicate of #96
#2 - c4-judge
2022-11-16T14:16:36Z
berndartmueller marked the issue as partial-50
#3 - c4-judge
2022-11-16T14:16:43Z
berndartmueller marked the issue as satisfactory
🌟 Selected for report: rotcivegaf
Also found by: 0x4non, 0xDecorativePineapple, 9svR6w, Trust, V_B, adriro, ajtra, aviggiano, brgltd, carlitox477, chaduke, codexploder, corerouter, joestakey, ladboy233, s3cunda, saian, wait
66.8068 USDC - $66.81
User may lose remaining ETH of the transaction
As the returned status of the call in _returnDust
is ignored, the tx will success even if the call failed, which means the caller does not get his ETH back.
n/a
Revert the whole transaction when the call failed (returns 0).
#0 - trust1995
2022-11-14T22:11:41Z
Report is lacking specifics. It is similar to #185 , but without details on how this issue manifests.
#1 - c4-judge
2022-11-16T11:59:00Z
berndartmueller marked the issue as duplicate of #90
#2 - c4-judge
2022-11-16T11:59:13Z
berndartmueller marked the issue as satisfactory
#3 - c4-judge
2022-12-06T14:17:30Z
berndartmueller changed the severity to 2 (Med Risk)
404.489 USDC - $404.49
Pool has no owner and will be un-upgradeable.
Pool does not provide an initialize interface to initialize the owner, so the owner will never be set.
Pool as a UUPSUpgradeable can not be upgraded without a valid owner.
n/a
Implement the initialize function to set the owner just like Exchange.sol#L112-L118.
#0 - trust1995
2022-11-14T22:12:48Z
dup of #186
#1 - trust1995
2022-11-14T22:13:25Z
Believe risk is exaggerated, as there is no loss of funds or freeze at risk.
#2 - c4-judge
2022-11-16T12:16:30Z
berndartmueller marked the issue as duplicate of #186
#3 - c4-judge
2022-11-16T12:16:35Z
berndartmueller changed the severity to 2 (Med Risk)
#4 - c4-judge
2022-11-16T12:17:09Z
berndartmueller marked the issue as satisfactory