Revolution Protocol - wangxx2026's results

A protocol to empower communities to raise funds, fairly distribute governance, and maximize their impact in the world.

General Information

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

Collective

Findings Distribution

Researcher Performance

Rank: 55/110

Findings: 2

Award: $54.98

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

25.1638 USDC - $25.16

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
duplicate-397

External Links

Lines of code

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

Vulnerability details

Impact

The difference between the token that the user buys and the token that they see may be large

Proof of Concept

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.

Tools Used

Manual Review

Add Slippage Protection

Assessed type

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

Findings Information

Awards

29.8238 USDC - $29.82

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
duplicate-160

External Links

Lines of code

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

Vulnerability details

Impact

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.

Proof of Concept

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.

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/d42cc62b873a1b2b44f57310f9d4bbfdd875e8d6/packages/revolution/src/AuctionHouse.sol#L383-L409

--->          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)

Tools Used

Manual Revew && foundry

Support for entropyRateBps = 0 to get the code to work properly

Assessed type

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

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter