Revolution Protocol - Udsen'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: 70/110

Findings: 1

Award: $42.48

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: bart1e

Also found by: 00xSEV, 0xAsen, 0xDING99YA, Timenov, Udsen, _eperezok, bart1e, deth, fnanni, ke1caM, nmirchev8, peanuts, shaka

Labels

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

Awards

42.484 USDC - $42.48

External Links

Lines of code

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/main/packages/revolution/src/AuctionHouse.sol#L384-L395 https://github.com/code-423n4/2023-12-revolutionprotocol/blob/main/packages/revolution/src/AuctionHouse.sol#L426-L430

Vulnerability details

Impact

The AuctionHouse._settleAuction function is used to settle an auction by finalizing the bid and paying out to the owner and creators.

The payment transfer to each of the creator of the artPiece is executed as shown below:

if (creatorsShare > 0 && entropyRateBps > 0) { 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); } }

The payment transfer is carried out by calling the _safeTransferETHWithFallback function which uses the low-level call function to transfer the payment ETH amount as shown below:

assembly { // Transfer ETH to the recipient // Limit the call to 50,000 gas success := call(50000, _to, _amount, 0, 0, 0, 0) }

The issue here is that a single malicious creator of the auctioned artPiece can implement a receive function in its smart contract and consume (drain) the entire gas of the transaction (gas bomb can be implemented by a malicious creator) thus reverting the settleAuction transaction. Furthermore this will make the _settleAuction transaction very costly due to draining of gas thus prompting loss of funds to the caller.

As a result the current auction will never be able to be settled. Because it gets reverted since one of the malicious creators of the auctioned artPiece consumes all the gas of the transaction in its receive function.

As a result a new auction can not be created via the AuctionHouse.settleCurrentAndCreateNewAuction function since it initially attempts to settle the current auction but it gets reverted as explained earlier.

As a result the AuctionHouse contract gets DoS for creation and executing new auctions and bids for the Verbs.

Proof of Concept

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

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/main/packages/revolution/src/AuctionHouse.sol#L384-L395

        assembly {
            // Transfer ETH to the recipient
            // Limit the call to 50,000 gas
            success := call(50000, _to, _amount, 0, 0, 0, 0)
        }

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/main/packages/revolution/src/AuctionHouse.sol#L426-L430

Tools Used

Manual Review and VSCode

Hence it is recommended to define a mapping which stores the creator's address and the respective payment amounts of each of the creator, of the auctioned artPiece, and then implement a function claimCreatorPayment callable by each of the creators so they can receive their payment amounts.

Assessed type

DoS

#0 - c4-pre-sort

2023-12-23T03:10:51Z

raymondfam marked the issue as sufficient quality report

#1 - c4-pre-sort

2023-12-23T03:10:59Z

raymondfam marked the issue as duplicate of #93

#2 - c4-pre-sort

2023-12-24T14:36:09Z

raymondfam marked the issue as duplicate of #195

#3 - MarioPoneder

2024-01-06T13:27:27Z

#4 - c4-judge

2024-01-06T13:27:31Z

MarioPoneder marked the issue as partial-25

#5 - c4-judge

2024-01-11T18:20:00Z

MarioPoneder marked the issue as not a duplicate

#6 - c4-judge

2024-01-11T18:38:37Z

MarioPoneder marked the issue as duplicate of #93

#7 - c4-judge

2024-01-11T18:38:41Z

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