Platform: Code4rena
Start Date: 13/12/2023
Pot Size: $36,500 USDC
Total HM: 18
Participants: 110
Period: 8 days
Judge: 0xTheC0der
Id: 311
League: ETH
Rank: 55/110
Findings: 2
Award: $54.98
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: deepplus
Also found by: 0xDING99YA, 0xmystery, Aymen0909, DanielArmstrong, Inference, KupiaSec, SadeeqXmosh, SpicyMeatball, Tricko, adeolu, jnforja, passteque, rvierdiiev, wangxx2026, zhaojie
25.1638 USDC - $25.16
https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L152-L230 https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L271-L281 https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L254-L264
The difference between the token that the user buys and the token that they see may be large
The price at which a user purchases an ERC20TokenEmitter is defined based on the VRGDA curve. README.md said:
If the emission is ahead of schedule, the price increases exponentially. If it is behind schedule, the price of each token decreases by some constant decay rate.
For example, many users check how many tokens can be purchased with a certain amount by calling the function getTokenQuoteForPayment, and after waiting for a suitable price, submit an order to purchase. When multiple users buy at the same time, the price will rise exponentially if they buy more, and the difference between the number of tokens bought and the number seen by some users will be relatively large, and this part of the user will have to bear the loss. With slippage protection, you can reverse the transaction if the price does not meet the user's expectations, avoiding the user to suffer losses.
Manual Review
Add Slippage Protection
Other
#0 - c4-pre-sort
2023-12-22T16:20:28Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-12-22T16:20:35Z
raymondfam marked the issue as duplicate of #26
#2 - c4-pre-sort
2023-12-24T06:00:49Z
raymondfam marked the issue as duplicate of #397
#3 - c4-judge
2024-01-06T16:30:20Z
MarioPoneder marked the issue as satisfactory
🌟 Selected for report: ayden
Also found by: 0xCiphky, AS, Brenzee, Inference, KupiaSec, SpicyMeatball, ast3ros, ayden, fnanni, hals, ktg, mahdirostami, nmirchev8, rvierdiiev, wangxx2026
29.8238 USDC - $29.82
https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/AuctionHouse.sol#L383-L409 https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/AuctionHouse.sol#L253-L258
When settling the last bid, the ratio of eth that the creators will receive and use to buy ERC20TokenEmitter is controlled by entropyRateBps. entropyRateBps has a value range of [0, 10000]. When entropyRateBps=0, the creator will use all the eth received to buy ERC20TokenEmitter, and the code will not work properly at this time.
entropyRateBps:The split of (purchase proceeds * creatorRate) that is sent to the creator as ether in basis points
Through the setEntropyRateBps function, we can see that the value range of entropyRateBps is [0,10000].If the value is equal to 0, all the profit will be used to buy ERC20TokenEmitter, if the value is equal to 10000, all the profit will be sent to all the creators proportionally in the form of eth, and if the value is equal to 0, the purchase of ERC20TokenEmitter will fail.
---> if (creatorsShare > 0 && entropyRateBps > 0) { // Only entropyRateBps>0 enters the branch for (uint256 i = 0; i < numCreators; i++) { ICultureIndex.CreatorBps memory creator = verbs.getArtPieceById(_auction.verbId).creators[i]; vrgdaReceivers[i] = creator.creator; vrgdaSplits[i] = creator.bps; //Calculate paymentAmount for specific creator based on BPS splits - same as multiplying by creatorDirectPayment uint256 paymentAmount = (creatorsShare * entropyRateBps * creator.bps) / (10_000 * 10_000); ethPaidToCreators += paymentAmount; //Transfer creator's share to the creator _safeTransferETHWithFallback(creator.creator, paymentAmount); } } //Buy token from ERC20TokenEmitter for all the creators if (creatorsShare > ethPaidToCreators) { creatorTokensEmitted = erc20TokenEmitter.buyToken{ value: creatorsShare - ethPaidToCreators }( ---> vrgdaReceivers, // If entropyRateBps = 0, this will be [address(0),address(0)...]. vrgdaSplits, IERC20TokenEmitter.ProtocolRewardAddresses({ builder: address(0), purchaseReferral: address(0), deployer: deployer }) ); }
In buyToken it will call _mint to assign a token to the user with the following code: https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/ERC20TokenEmitter.sol#L209-L215
for (uint256 i = 0; i < addresses.length; i++) { if (totalTokensForBuyers > 0) { // transfer tokens to address ----> _mint(addresses[i], uint256((totalTokensForBuyers * int(basisPointSplits[i])) / 10_000)); } bpsSum += basisPointSplits[i]; }
_mint requires that address cannot be equal to 0.
poc:
Add the following code to the top of the AuctionHouseSettleTest.testSettlingAuctionWithWinningBid method.
uint256 erBps = 0; auction.setEntropyRateBps(erBps);
Run forge test ---match-test testSettlingAuctionWithWinningBid
Result: Failing tests: Encountered 1 failing test in test/auction/AuctionSettling.t.sol:AuctionHouseSettleTest [FAIL. Reason: ERC20InvalidReceiver(0x0000000000000000000000000000000000000000); counterexample: calldata=0xee358b4a0000000000000000000000000000000000000000000000000000000000000000 args=[0]] testSettlingAuctionWithWinningBid(uint8) (runs: 0, μ: 0, ~: 0)
Manual Revew && foundry
Support for entropyRateBps = 0 to get the code to work properly
Invalid Validation
#0 - c4-pre-sort
2023-12-22T07:56:12Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-12-22T07:57:38Z
raymondfam marked the issue as duplicate of #335
#2 - c4-judge
2024-01-06T01:25:32Z
MarioPoneder changed the severity to QA (Quality Assurance)
#3 - c4-judge
2024-01-06T15:11:22Z
This previously downgraded issue has been upgraded by MarioPoneder
#4 - c4-judge
2024-01-06T15:12:24Z
MarioPoneder marked the issue as duplicate of #160
#5 - c4-judge
2024-01-06T15:13:44Z
MarioPoneder marked the issue as satisfactory