Cudos contest - dirk_y's results

Decentralised cloud computing for Web3.

General Information

Platform: Code4rena

Start Date: 03/05/2022

Pot Size: $75,000 USDC

Total HM: 6

Participants: 55

Period: 7 days

Judge: Albert Chon

Total Solo HM: 2

Id: 116

League: COSMOS

Cudos

Findings Distribution

Researcher Performance

Rank: 6/55

Findings: 3

Award: $4,927.30

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: CertoraInc

Also found by: 0x1337, AmitN, WatchPug, cccz, danb, dipp, dirk_y, hubble, jah

Labels

bug
duplicate
2 (Med Risk)

Awards

620.336 USDC - $620.34

External Links

Lines of code

https://github.com/code-423n4/2022-05-cudos/blob/main/solidity/contracts/Gravity.sol#L276

Vulnerability details

Impact

When batches are submitted by validators in the current valset, they are checked for validity based on signatures and cumulative powers. Each validator in the valset has an associated power which can give certain validators more voting power than others. For a batch to be valid, the cumulative power of all "YES" signatures needs to be greater than _powerThreshold, which is set once during contract initialisation in the constructor.

In the constructor, there is a check for cumulative power here. However, when updating a valset, there is no check for the cumulative power of the new valset. Therefore it is theoretically possible to submit a valset that doesn't have enough cumulative power to succeed in any transactions, and then the bridge will be locked (since the valset can't be updated either).

Proof of Concept

In updateValset there is no logic for checking the cumulative power of the new valset. See below for recommended actions to resolve this.

Tools Used

VSCode

A check for cumulative power of the new valset should be added to updateValset:

uint256 cumulativePower = 0; for (uint256 i = 0; i < _newValset.powers.length; i++) { cumulativePower = cumulativePower + _newValset.powers[i]; if (cumulativePower > _powerThreshold) { break; } } require( cumulativePower > _powerThreshold, "Submitted validator set signatures do not have enough power." );

#0 - V-Staykov

2022-05-11T11:07:18Z

Duplicate of #123

Findings Information

🌟 Selected for report: p_crypt0

Also found by: 0x1337, GermanKuber, IllIllI, WatchPug, csanuragjain, danb, dirk_y, kirk-baird

Labels

bug
duplicate
2 (Med Risk)

Awards

502.4722 USDC - $502.47

External Links

Lines of code

https://github.com/code-423n4/2022-05-cudos/blob/main/solidity/contracts/Gravity.sol#L632-L638

Vulnerability details

Impact

Currently it is possible for the admin to pull all tokens belonging to the Gravity bridge. In normal circumstances this is probably fine, but if the admin account were compromised this would lead to the bridge being drained of locked funds. Furthermore, a contract that is liable to potential rugpulls is usually not trusted by users following multiple high profile rugpulls of other projects in the past.

Proof of Concept

The withdrawERC20 method here gives the admin the ability to send the full balance of the Gravity.sol contract of any token to themselves.

Tools Used

VSCode

I assume this method exists in case the contract has to be updated and funds moved across to a new implementation. Thus, I see two potential solutions:

  1. Set up a DAO that votes on transfers of ERC20 tokens by the admin
  2. Remove the method altogether and utilise an upgradeable proxy pattern

#0 - mlukanova

2022-05-10T14:28:47Z

Awards

302.6663 USDC - $302.67

Labels

bug
QA (Quality Assurance)

External Links

Low severity findings

During my audit of this project I found 5 low priority findings in the Gravity.sol contract that I think are worth mentioning:

  1. Any whitelisted address can remove all other whitelisted addresses. This is in the manageWhitelist method here. This pattern doesn't make sense to me since you only need 1 bad actor in the whitelist for this situation to occur. The offending address can then frontrun any attempts from the admin to remove them from the whitelist by adding new addresses to the whitelist. I decided not to mark this as medium severity since I can't see the whitelist being used anywhere yet. I would update this method to only be callable by the admin.

  2. The comment strings explaining submitBatch and updateValset say "anyone can call this function", but in reality the msg.sender has to be an orchestrator (i.e. one of the existing validators in the valset)

  3. makeCheckpoint has the following comment string:

// The format of the checkpoint is: // h(gravityId, "checkpoint", valsetNonce, validators[], powers[])

This should be updated to:

// h(gravityId, "checkpoint", valsetNonce, validators[], powers[], rewardAmount, rewardToken)
  1. There is no check in checkValidatorSignatures to confirm whether or not the array of validator powers is decreasing. The validators should be passed in as arguments in decreasing power order to optimise gas. If you wanted to enforce this you could add a check as you loop through the array to verify that the current power is less than the previous power (in the array). This might use more gas than the arrays being out of order though, depending on the length of the arrays.

  2. Test fixtures are still there and should be removed (seems obvious but easily forgotten)

#0 - albertchon

2022-05-17T09:52:29Z

On point 2, actually anyone can call submitBatch and updateValset

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