Dopex - 0xTiwa's results

A rebate system for option writers in the Dopex Protocol.

General Information

Platform: Code4rena

Start Date: 21/08/2023

Pot Size: $125,000 USDC

Total HM: 26

Participants: 189

Period: 16 days

Judge: GalloDaSballo

Total Solo HM: 3

Id: 278

League: ETH

Dopex

Findings Distribution

Researcher Performance

Rank: 76/189

Findings: 2

Award: $115.50

QA:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

Awards

96.3292 USDC - $96.33

Labels

bug
3 (High Risk)
satisfactory
upgraded by judge
sufficient quality report
duplicate-549

External Links

Lines of code

https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/perp-vault/PerpetualAtlanticVaultLP.sol#L274-L284

Vulnerability details

Impact

In the PerpetualAtlanticVaultLP contract, the convertToShares function was to return a given amount of shares received for a given amount of assets but the amounts of shares received has to be converted from a 1e18 precision to a 1e8 precision but instead a 1e8 precision was used directly.

Proof of Concept

function convertToShares(
    uint256 assets
  ) public view returns (uint256 shares) {
    uint256 supply = totalSupply;
    uint256 rdpxPriceInAlphaToken = perpetualAtlanticVault.getUnderlyingPrice();

    uint256 totalVaultCollateral = totalCollateral() +
      ((_rdpxCollateral * rdpxPriceInAlphaToken) / 1e8);
    return
      supply == 0 ? assets : assets.mulDivDown(supply, totalVaultCollateral);
  }

As seen above, the price is gotten from the perpetualAtlanticVault.getUnderlyingPrice()

function getUnderlyingPrice() public view returns (uint256) {
    return IRdpxEthOracle(addresses.assetPriceOracle).getRdpxPriceInEth();
  }

which in turn returns the rdpxEthOracle.getRdpxPriceInEth function, which returns the price of rdpx in eth in 1e18 decimals not 1e8, therefore there is a surplus of 1e10 decimals after each conversion.

Tools Used

Manual review

The amount of assets converted to shares should be converted in the 1e18 precision not 1e8 precision to avoid surplus 1e10 decimals.

uint256 totalVaultCollateral = totalCollateral() +
      ((_rdpxCollateral * rdpxPriceInAlphaToken) / 1e18);

Assessed type

Decimal

#0 - c4-pre-sort

2023-09-12T09:00:58Z

bytes032 marked the issue as duplicate of #397

#1 - c4-pre-sort

2023-09-12T09:01:06Z

bytes032 marked the issue as sufficient quality report

#2 - c4-judge

2023-10-15T18:39:58Z

GalloDaSballo marked the issue as duplicate of #549

#3 - c4-judge

2023-10-20T18:28:00Z

GalloDaSballo marked the issue as satisfactory

#4 - c4-judge

2023-10-20T18:28:12Z

GalloDaSballo changed the severity to 2 (Med Risk)

#5 - c4-judge

2023-10-20T18:28:21Z

GalloDaSballo changed the severity to 3 (High Risk)

Awards

19.1724 USDC - $19.17

Labels

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

External Links

Lines of code

https://github.com/code-423n4/2023-08-dopex/blob/eb4d4a201b3a75dd4bddc74a34e9c42c71d0d12f/contracts/core/RdpxV2Core.sol#L270-L290

Vulnerability details

Impact

The removeAssetFromtokenReserves() is used to remove assets from the reserve tokens and also the reserve assets. It removes the assets details from the reserve assets array and pops the last element of the reserve assets array after overwriting the removed asset but it does not remove the symbol from the reserve token array instead it removes the last symbol without overwriting the removed symbol.

Proof of Concept

function removeAssetFromtokenReserves(
    string memory _assetSymbol
  ) external onlyRole(DEFAULT_ADMIN_ROLE) {
    uint256 index = reservesIndex[_assetSymbol];
    _validate(index != 0, 18);

    // remove the asset from the mapping
    reservesIndex[_assetSymbol] = 0;

    // add new index for the last element
    reservesIndex[reserveTokens[reserveTokens.length - 1]] = index;

    // update the index of reserveAsset with the last element
    reserveAsset[index] = reserveAsset[reserveAsset.length - 1];

    // remove the last element 
    reserveAsset.pop();
    reserveTokens.pop();

    emit LogAssetRemovedFromtokenReserves(_assetSymbol, index);
  }

Tools Used

Manual review.

Update the removeAssetFromtokenReserves() to be able to pop the right symbol.

function removeAssetFromtokenReserves(
    string memory _assetSymbol
  ) external onlyRole(DEFAULT_ADMIN_ROLE) {
    uint256 index = reservesIndex[_assetSymbol];
    _validate(index != 0, 18);

    // remove the asset from the mapping
    reservesIndex[_assetSymbol] = 0;

    // add new index for the last element
    reservesIndex[reserveTokens[reserveTokens.length - 1]] = index;

    // update the index of reserveAsset with the last element
    reserveAsset[index] = reserveAsset[reserveAsset.length - 1];
    reserveTokens[index] = reserveTokens[reserveTokens.length - 1];

    // remove the last element 
    reserveAsset.pop();
    reserveTokens.pop();

    emit LogAssetRemovedFromtokenReserves(_assetSymbol, index);
  }

Assessed type

Other

#0 - c4-pre-sort

2023-09-07T09:49:13Z

bytes032 marked the issue as duplicate of #33

#1 - c4-pre-sort

2023-09-11T15:04:44Z

bytes032 marked the issue as sufficient quality report

#2 - c4-judge

2023-10-15T09:06:46Z

GalloDaSballo changed the severity to 2 (Med Risk)

#3 - c4-judge

2023-10-15T13:11:25Z

GalloDaSballo changed the severity to QA (Quality Assurance)

#4 - c4-judge

2023-10-20T18:18:07Z

GalloDaSballo 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