veRWA - HChang26's results

Incentivization Primitive for Real World Assets on Canto

General Information

Platform: Code4rena

Start Date: 07/08/2023

Pot Size: $36,500 USDC

Total HM: 11

Participants: 125

Period: 3 days

Judge: alcueca

Total Solo HM: 4

Id: 274

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 84/125

Findings: 1

Award: $9.82

QA:
grade-a

🌟 Selected for report: 0

πŸš€ Solo Findings: 0

Lines of code

https://github.com/code-423n4/2023-08-verwa/blob/main/src/LendingLedger.sol#L153-L182

Vulnerability details

Impact

Claim() will revert when marketBalance = 0. Caller will waste gas doing complex computations and the function call will revert anyways.

Proof of Concept

Let's take a look at claim(). The recommended input is as follow: / @param _claimFromTimestamp From which epoch (provided as timestmap) should the claim start. Usually, this parameter should be set to 0, in which case the epoch of the last claim will be used. / However, it can be useful to skip certain epochs, e.g. when the balance was very low or 0 (after everything was withdrawn) and the gas usage should be reduced. / Note that all rewards are forfeited forever if epochs are explicitly skipped by providing this parameter / @param _claimUpToTimestamp Until which epoch (provided as timestamp) should the claim be applied. If it is higher than the timestamp of the previous epoch, this will be used / Set to type(uint256).max to claim all possible epochs.

marketBalance may be 0 for specific epoch in between _claimFromTimestamp and _claimUpToTimestamp period. Solidity will revert when a dividing by 0. The only way to get around this issue, is to make multiple claim() calls avoiding all epochs where marketBalance = 0 across different markets. However, this does seem unrealistic especially for a regular user. It will also likely cost more gas.

if (claimEnd >= claimStart) { // This ensures that we only set userClaimedEpoch when a claim actually happened for (uint256 i = claimStart; i <= claimEnd; i += WEEK) { uint256 userBalance = lendingMarketBalances[_market][lender][i]; uint256 marketBalance = lendingMarketTotalBalance[_market][i]; RewardInformation memory ri = rewardInformation[i]; require(ri.set, "Reward not set yet"); uint256 marketWeight = gaugeController.gauge_relative_weight_write(_market, i); cantoToSend += (marketWeight * userBalance * ri.amount) / (1e18 * marketBalance); } userClaimedEpoch[_market][lender] = claimEnd + WEEK; } if (cantoToSend > 0) { (bool success, ) = msg.sender.call{value: cantoToSend}(""); require(success, "Failed to send CANTO"); }

Tools Used

Manual Review

if (claimEnd >= claimStart) { // This ensures that we only set userClaimedEpoch when a claim actually happened for (uint256 i = claimStart; i <= claimEnd; i += WEEK) { uint256 userBalance = lendingMarketBalances[_market][lender][i]; uint256 marketBalance = lendingMarketTotalBalance[_market][i]; RewardInformation memory ri = rewardInformation[i]; require(ri.set, "Reward not set yet"); uint256 marketWeight = gaugeController.gauge_relative_weight_write(_market, i); + if(marketBalance != 0){ cantoToSend += (marketWeight * userBalance * ri.amount) / (1e18 * marketBalance); + } } userClaimedEpoch[_market][lender] = claimEnd + WEEK; } if (cantoToSend > 0) { (bool success, ) = msg.sender.call{value: cantoToSend}(""); require(success, "Failed to send CANTO"); }

Assessed type

Math

#0 - 141345

2023-08-12T01:53:27Z

loss is only on gas

QA might be more appropriate.

#1 - c4-pre-sort

2023-08-12T07:38:07Z

141345 marked the issue as primary issue

#2 - c4-sponsor

2023-08-16T13:46:57Z

OpenCoreCH marked the issue as sponsor acknowledged

#3 - c4-sponsor

2023-08-16T13:47:02Z

OpenCoreCH marked the issue as disagree with severity

#4 - OpenCoreCH

2023-08-16T13:49:32Z

Problem can be circumvented by the user, a UX improvement in my opinion. Note that per definition, the user balances in this market will also be 0 for this epoch (otherwise, the overall market balance cannot be 0), so the user would just need to skip the epochs where they did not have any funds in the market (which they may do anyway to reduce gas usage).

#5 - alcueca

2023-08-24T06:43:02Z

Agree with sponsor

#6 - c4-judge

2023-08-24T06:43:12Z

alcueca changed the severity to QA (Quality Assurance)

#7 - c4-judge

2023-08-24T06:43:19Z

alcueca marked the issue as grade-b

#8 - c4-judge

2023-08-24T21:22:49Z

alcueca marked the issue as grade-a

#9 - alcueca

2023-08-24T21:23:13Z

Function incorrect as to spec, and a hassle for users

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