Ethereum Credit Guild - rvierdiiev's results

A trust minimized pooled lending protocol.

General Information

Platform: Code4rena

Start Date: 11/12/2023

Pot Size: $90,500 USDC

Total HM: 29

Participants: 127

Period: 17 days

Judge: TrungOre

Total Solo HM: 4

Id: 310

League: ETH

Ethereum Credit Guild

Findings Distribution

Researcher Performance

Rank: 18/127

Findings: 4

Award: $860.47

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: serial-coder

Also found by: 0x70C9, 0xAlix2, 0xmystery, 0xpiken, Arz, DanielArmstrong, Shubham, deth, rbserver, rvierdiiev, xeros

Labels

bug
2 (Med Risk)
satisfactory
sufficient quality report
edited-by-warden
duplicate-1141

Awards

85.8444 USDC - $85.84

External Links

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/governance/LendingTermOffboarding.sol#L139

Vulnerability details

Proof of Concept

LendingTermOffboarding contract is used to offboard gauge. Anyone can create proposal for voting and 1 week should pass till last voting.

Then user have 1 week to vote. In case if proposal receives more than quorum, then canOffboard[term] is set to true, which then allows anyone to call offboard and cleanup functions. After cleanup is done, then canOffboard[term] is set to false, so new voting is needed in case if term will be onboarded again.

But in case if time from proposal creation to get enough amount of votes and execution of offboard and cleanup functions is less than 1 week, then anyone can call supportOffboard again which will make canOffboard[term] to be true again.

As result in case if term will be onboarded again later, then anyone will be able to offboard it immediately.

Example:

  • proposal to offboard term X was created.
  • after 2 days it reaches quorum and is executed
  • 3 days later all loans were settled and cleanup was called
  • on day 6 someone votes for offboarding again and makes canOffboard[term] to be true
  • after 2 months term X was onboarded again
  • it was offboarded immediately by LendingTermOffboarding without new voting

Impact

Users can reuse voting to skip next proposal voting.

Tools Used

VsCode

You can have mapping like block:offboarded and in case if quorum is reached for block, then then set as true and do not allow further voting.

Assessed type

Error

#0 - c4-pre-sort

2024-01-04T16:46:22Z

0xSorryNotSorry marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-04T16:46:41Z

0xSorryNotSorry marked the issue as duplicate of #1141

#2 - c4-judge

2024-01-25T18:53:45Z

Trumpero marked the issue as satisfactory

#3 - Trumpero

2024-02-07T17:12:31Z

dup of #1141 due to the root cause: supportOffboard can still be called after offboarding.

#4 - c4-judge

2024-02-07T17:12:38Z

Trumpero marked the issue as not a duplicate

#5 - c4-judge

2024-02-07T17:12:47Z

Trumpero marked the issue as duplicate of #1141

Findings Information

🌟 Selected for report: niroh

Also found by: EV_om, EllipticPoint, carrotsmuggler, kaden, rvierdiiev

Labels

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

Awards

323.0626 USDC - $323.06

External Links

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/loan/LendingTerm.sol#L316-L317

Vulnerability details

Proof of Concept

GUILD token holder vote for a gauges. When they increase voting power of a gauge then bigger amount of debt is allowed to be issued by that gauge. In case if user would like to decrement his votes to the gauge, then it's checked that gauge's issuance is smaller than debt ceiling without user's votes. This is done to now allow voters to unvote just before a gauge loss and avoid to be slashed.

Now let's look into LendingTerm(gauge).debtCeiling to see how it calculates debt ceiling. In case if gauge is the only gauge of the type, then it's allowed to borrow min(hardCap, creditMinterBuffer). The same is allowed, when tolerated weight of gauge is bigger than 100%. Also when we found correct ceiling for the gauge that is not only of same type, we also cap it with buffer size.

Pls, note that min(hardCap, creditMinterBuffer) is used, which means that usage of buffer decreases allowed amount. So suppose that we have the only gauge of the type with buffer that allows to mint 10_000 tokens at the moment and issuance of 20_000 tokens. As result when user would like to decrement votes from gauge, then debtCeiling will return current buffer amount which is 10_000 and thus the check will revert.

Impact

User can't decrement votes from gauge in some cases

Tools Used

VsCode

I don't see the need of rate limiter buffer check here. This is because if buffer doesn't have enough balance to mint, then it will revert on borrow and will not allow bigger amount to be minted. However debt ceiling in reality doesn't depend on rate limiter at all. And as i showed it will not allow users to decrement gauge weight some times.

Assessed type

Error

#0 - c4-pre-sort

2024-01-04T17:05:36Z

0xSorryNotSorry marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-04T17:05:53Z

0xSorryNotSorry marked the issue as duplicate of #885

#2 - c4-judge

2024-01-30T11:46:01Z

Trumpero changed the severity to QA (Quality Assurance)

#3 - Trumpero

2024-01-31T12:26:24Z

I consider this issue as a dup of #868 since it shares the same idea about the problem, where capping debtCeiling with creditMinterBuffer causes the debtCeiling to be lower than it should.

Findings Information

🌟 Selected for report: 3docSec

Also found by: aslanbek, btk, ether_sky, rvierdiiev

Labels

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

Awards

430.7502 USDC - $430.75

External Links

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/governance/ProfitManager.sol#L331-L334

Vulnerability details

Proof of Concept

In case if bad debt has occurred in the term, then it's is socialized over all holders of credit token. As you can see CreditToken(_credit).totalSupply function is used to get current supply of credit token.

CreditToken is rebase token and all accrued interests are distributed during the next 30 days. And its totalSupply function will return total supply on current moment. For example if profit of 3000 tokens were distributed 10 days ago, then totalSupply will add extra 1000 tokens to the supply.

Also ERC20RebaseDistributor has targetTotalSupply function and this function will return us 3000 extra tokens even if distribution period hasn't finished yet.

So the problem is that ProfitManager distributes bad debt to not all tokens in the system and after they all will be redeemed then bigger amount than a loss will be taken from token holders.

Example(just random numbers to make calculations simple):

  • gUSDC market
  • creditMultiplier is 1, so user provides 1 usdc and get 1 gUSDC
  • totalSupply is 1000 and 100 more tokens are going to be distributed in next 30 days, so totalSupply will be 1100 in 30 days
  • 100 token loss occurs(100 gUSDC = 100 usdc) right after ERC20RebaseDistributor.distribute is called, which makes multiplier to be 0.9(1000 - 100 / 1000)
  • after 30 days we have 1100 tokens in supply and all users redeem with multiplier 0.9, so they are able to get 990 usdc back, but extra 10 usdc were left in the PSM contract
  • correct multiplier should be 0.909(1100 - 100 / 1100), in this case debt will be distributed correctly

Impact

Debt is distributed incorrectly, which makes loss for credit token holders

Tools Used

VsCode

Use targetTotalSupply to get correct token supply. uint256 creditTotalSupply = CreditToken(_credit).targetTotalSupply();

Assessed type

Error

#0 - c4-pre-sort

2024-01-03T16:54:15Z

0xSorryNotSorry marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-03T16:54:47Z

0xSorryNotSorry marked the issue as duplicate of #292

#2 - c4-judge

2024-01-29T18:32:49Z

Trumpero marked the issue as satisfactory

Awards

20.8157 USDC - $20.82

Labels

bug
downgraded by judge
grade-b
QA (Quality Assurance)
sufficient quality report
edited-by-warden
duplicate-885
Q-18

External Links

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/tokens/ERC20Gauges.sol#L435

Vulnerability details

Proof of Concept

In case if term is taking loss, then it will be offboarded, which will remove gauge and then allows to auction all loans. In case if auction will create a loss, then profit manager will be notified and gauge will be notified about loss. This means that gauge voters will be slashed and that they will not be able to withdraw those votes.

So in case if gauge voter will notice, that a loss will occur, then he would like to withdraw votes from a gauge. That's why GUILD token has check that current issuance of gauge should be smaller than debtCeiling after user will withdraw his votes from gauge.

When gauge is removed, then it's votes are not removed, only type weight is decreased with gauge's votes. This actually means that now debt ceiling has increased for the gauge, because total votes were decreased.

This creates 2 problems:

  • Debt ceiling is increasing for the term, which means that some gauge voters can now remove votes from the gauge to avoid slashing. For example if 2 gauges were only and removed gauge had more votes than other, then after remove debtCeiling function will think that gauge has more than 100% of votes and thus will allow maximum ceiling, so voters will be able to remove some votes. Also in such scenario user can withdraw delta amount(gaugeVotes - totalTypeVotes), as then this condition will be met.

  • Another problem that can occur is when gauge is the only of the type, then after offboarding type weight will be 0, but gauge weight will not be 0. And as result function will revert, which will not allow users to remove votes in case if loss didn't happen after offboarding.

Impact

Some gauge voters can avoid slashing after offboarding. Unvoting can be stucked until gauge will not be added again.

Tools Used

VsCode

You can query if gauge is deprecated. In case if yes, then inside debtCeiling function you can increase type weight with gauge weight to get correct weight ratio for the gauge.

Assessed type

Error

#0 - c4-pre-sort

2024-01-04T13:24:48Z

0xSorryNotSorry marked the issue as sufficient quality report

#1 - c4-pre-sort

2024-01-04T13:25:03Z

0xSorryNotSorry marked the issue as duplicate of #885

#2 - c4-judge

2024-01-30T11:46:02Z

Trumpero changed the severity to QA (Quality Assurance)

#3 - c4-judge

2024-01-31T15:46:06Z

Trumpero marked the issue as grade-b

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