Revolution Protocol - n1punp'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: 69/110

Findings: 1

Award: $44.03

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

44.0266 USDC - $44.03

Labels

bug
3 (High Risk)
satisfactory
sufficient quality report
duplicate-210

External Links

Lines of code

https://github.com/code-423n4/2023-12-revolutionprotocol/blob/main/packages/revolution/src/ERC20TokenEmitter.sol#L177-L184

Vulnerability details

Impact

Leftover ETH may get stuck in ERC20TokenEmitter forever.

Proof of Concept

When a user calls buyToken , the user pays Ether to the token emitter contract. The ETH then gets split and transferred to other relevant parties like builder, referral, deployer, treasury, and creators. In the function, msgValueRemaining is calculated after the ether amount is split between builder, referrer, and deployer (the ethers are transferred to protocolRewards contract).

uint256 msgValueRemaining = _handleRewardsAndGetValueToSend( msg.value, protocolRewardsRecipients.builder, protocolRewardsRecipients.purchaseReferral, protocolRewardsRecipients.deployer );

After that, the remaining amount is further split to treasury and creators:

uint256 toPayTreasury = (msgValueRemaining * (10_000 - creatorRateBps)) / 10_000; uint256 creatorDirectPayment = ((msgValueRemaining - toPayTreasury) * entropyRateBps) / 10_000;

Now, the only transfers of this msgValueRemaining remaining ETH is only to these 2 parties (treasury and creator) in the following lines:

(bool success, ) = treasury.call{ value: toPayTreasury }(new bytes(0)); require(success, "Transfer failed."); if (creatorDirectPayment > 0) { (success, ) = creatorsAddress.call{ value: creatorDirectPayment }(new bytes(0)); require(success, "Transfer failed."); }

Other than these lines, there are no other functions that allow outflow of the ether in the contract, so the leftover ETH will not be retrievable.

Tools Used

Manual Review

Some options are:

  • Consider implementing an access-controlled function to withdraw remaining ETH
  • Transfer the remaining ETH to handle in another contract, or
  • Make certain assertion on the msg.value to prevent leftover ETH.

Assessed type

Payable

#0 - c4-pre-sort

2023-12-21T21:16:48Z

raymondfam marked the issue as insufficient quality report

#1 - c4-pre-sort

2023-12-21T21:16:53Z

raymondfam marked the issue as primary issue

#2 - raymondfam

2023-12-21T21:17:06Z

(msgValueRemaining - toPayTreasury) - creatorDirectPayment) will be stuck indeed.

#3 - c4-pre-sort

2023-12-21T21:21:40Z

raymondfam marked the issue as sufficient quality report

#4 - c4-pre-sort

2023-12-24T02:55:26Z

raymondfam marked the issue as duplicate of #406

#5 - c4-judge

2024-01-05T23:21:43Z

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