Canto contest - csanuragjain's results

Execution layer for original work.

General Information

Platform: Code4rena

Start Date: 14/06/2022

Pot Size: $100,000 USDC

Total HM: 26

Participants: 59

Period: 7 days

Judge: GalloDaSballo

Total Solo HM: 9

Id: 133

League: ETH

Canto

Findings Distribution

Researcher Performance

Rank: 18/59

Findings: 9

Award: $1,719.86

🌟 Selected for report: 1

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: 0xDjango

Also found by: 0x52, Chom, JMukesh, Picodes, Soosh, WatchPug, csanuragjain, k, oyc_109

Labels

bug
duplicate
3 (High Risk)

Awards

126.3383 USDC - $126.34

782.2807 CANTO - $126.34

External Links

Lines of code

https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/NoteInterest.sol#L118

Vulnerability details

Impact

updateBaseRate is marked public and can be called by any user to update the base rate as per their choice Attacker can simply call this function to change the base rate per year to incur more profits

Proof of Concept

  1. Observe that updateBaseRate places no restriction and is marked public
function updateBaseRate(uint newBaseRatePerYear) public { // check the current block number uint blockNumber = block.number; uint deltaBlocks = blockNumber.sub(lastUpdateBlock); if (deltaBlocks > updateFrequency) { // pass in a base rate per year baseRatePerYear = newBaseRatePerYear; lastUpdateBlock = blockNumber; emit NewInterestParams(baseRatePerYear); } }

Add below check so that only Admin can call this function

require(msg.sender == admin, "only the admin may set the update frequency");

#0 - ecmendenhall

2022-06-21T22:12:24Z

#1 - tkkwon1998

2022-06-22T17:49:50Z

Duplicate of issue #22

Findings Information

🌟 Selected for report: Soosh

Also found by: 0x1f8b, Ruhum, TerrierLover, WatchPug, cccz, csanuragjain, hake, p4st13r4, zzzitron

Labels

bug
duplicate
3 (High Risk)

Awards

126.3383 USDC - $126.34

782.2807 CANTO - $126.34

External Links

Lines of code

https://github.com/Plex-Engineer/manifest/blob/688e9b4e7835854c22ef44b045d6d226b784b4b8/contracts/Proposal-Store.sol#L46

Vulnerability details

Impact

On calling AddProposal function with same propId , the older proposal will get overridden. This can become a problem. User can see a proposal and approve it. But before proposal is queue/executed, user can change it using same proposal id

Proof of Concept

  1. Malicious user creates a genuine proposal id 1
  2. User approves this proposal
  3. queue is called on this proposal using queue function at GovernorBravoDelegate.sol#L37
  4. Admin who is watching mempool, frontrun this transaction and calls AddProposal function again with same proposal id 1 but with malicious parameters
  5. Now user request completes which queue a malicious proposal unknowingly
  6. Once timelock completes the malicious proposal gets executed

If proposal with same id is already existing then AddProposal function should revert

#0 - tkkwon1998

2022-06-22T17:58:20Z

Duplicate of issue #26 . This issue only exists because anyone can add to the proposal store. As such, the root issue of this is issue 26.

Findings Information

🌟 Selected for report: Ruhum

Also found by: 0xmint, cccz, csanuragjain, dipp, hake, zzzitron

Labels

bug
duplicate
3 (High Risk)

Awards

1532.982 CANTO - $247.58

247.5766 USDC - $247.58

External Links

Lines of code

https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/Governance/GovernorBravoDelegate.sol#L63

Vulnerability details

Impact

The queue function marks the transaction execution as true which is incorrect. newProposal.executed should not be set to true as this transaction could never be executed since state(proposalId) will not be equal to ProposalState.Queued, thus failing at execute function

Proof of Concept

  1. Queue function is called on proposal id 1
  2. This sets proposals[unigovProposal.id].executed = true in GovernorBravoDelegate.sol#L63
  3. Once timelock is over execute function is called
  4. Execute function fails since state(proposalId) == ProposalState.Queued is not true

Change GovernorBravoDelegate.sol#L63 to

newProposal.executed = false;

#0 - tkkwon1998

2022-06-22T17:57:14Z

Duplicate of issue #39

Findings Information

🌟 Selected for report: csanuragjain

Also found by: 0xf15ers, gzeon

Labels

bug
2 (Med Risk)
sponsor confirmed

Awards

1635.5547 CANTO - $264.14

264.1421 USDC - $264.14

External Links

Lines of code

https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/CNote.sol#L129

Vulnerability details

Impact

It was observed that in repayBorrowFresh function, User is asked to send repayAmount instead of repayAmountFinal. This can lead to loss of user funds as user might be paying extra

Proof of Concept

  1. User is making a repayment which eventually calls repayBorrowFresh function

  2. Assuming repayAmount == type(uint).max, so repayAmountFinal becomes accountBorrowsPrev

  3. This means User should only transfer in accountBorrowsPrev instead of repayAmount but that is not true. Contract is transferring repayAmount instead of repayAmountFinal as seen at CNote.sol#L129

uint actualRepayAmount = doTransferIn(payer, repayAmount);

Revise CNote.sol#L129 to below:

uint actualRepayAmount = doTransferIn(payer, repayAmountFinal);

#0 - GalloDaSballo

2022-08-07T23:26:29Z

The warden has showed how, due to an oversight, using type(uint).max to signify a complete repayment will actually attempt to transfer 2^256-1 units of token.

While I think High severity would have been reasonable had the tokens gotten transferred, because what will actually happen is a revert, I think Medium Severity to be more appropriate.

Remediation requires using actualRepayAmount or re-assigning the value of repayAmount

Awards

79.9481 USDC - $79.95

687.9945 CANTO - $111.11

Labels

bug
QA (Quality Assurance)
sponsor acknowledged

External Links

Lines of code

https://github.com/Plex-Engineer/lending-market/blob/755424c1f9ab3f9f0408443e6606f94e4f08a990/contracts/NoteInterest.sol#L165

Vulnerability details

Impact

Admin can set a very high value of update frequency which will make sure that updateBaseRate can be never be called. This way only Admin would be sole decider of base rate using _setBaseRatePerYear

Proof of Concept

  1. Observe that Admin can set a very large block.number value for update frequency using _setUpdateFrequency function

  2. Now updateBaseRate cannot be called since the interval set in step 1 is too large to be reached

  3. Admin becomes sole decider of changing base rate whenever Admin wishes using _setBaseRatePerYear function

Add a max cap on updated frequency value

#0 - nivasan1

2022-06-23T20:52:49Z

This value is regulated by governance, as such, it is not necessary to regulate the update frequency value

#1 - GalloDaSballo

2022-08-12T00:45:29Z

I think the finding is valid

I also think the issue is the fact that the function updateBaseRate is public is a bigger severity, but I'm going to assume the function is admin only.

In that case, the value of updateFrequency is a guarantee that interest rate won't change before that time.

I think the observation is correct, the value can be set to any crazy high value, however I don't see any major risk with that as the variable is public and the worst case is a guarantee that the rate will never change (which is not a bad thing necessarily)

For those reasons, am downgrading to QA

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