Ondo Finance - gkrastenov's results

Institutional-Grade Finance. On-Chain. For Everyone.

General Information

Platform: Code4rena

Start Date: 01/09/2023

Pot Size: $36,500 USDC

Total HM: 4

Participants: 70

Period: 6 days

Judge: kirk-baird

Id: 281

League: ETH

Ondo Finance

Findings Distribution

Researcher Performance

Rank: 2/70

Findings: 2

Award: $2,830.59

QA:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: adriro

Also found by: gkrastenov, lsaudit

Labels

bug
2 (Med Risk)
low quality report
satisfactory
duplicate-444

Awards

2743.0149 USDC - $2,743.01

External Links

Lines of code

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L234

Vulnerability details

Impact

Axelar currently supports around 10 EVM-compatible blockchains. However, if they decide not to support some of these blockchains in the future, it could potentially pose a problem for contracts. Once destinationChain or srcChain has been added to SourceBridge/DestinationBridge, it can not be removed. The contract can be paused by the owner, but the corresponding contracts on the other blockchains will still support them and transactions can still be executed to them.

  function setDestinationChainContractAddress(
    string memory destinationChain,
    address contractAddress
  ) external onlyOwner { 
    //@audit M1: what if Axelar remove some blockchain
    destChainToContractAddr[destinationChain] = AddressToString.toString(
      contractAddress
    );
    emit DestinationChainContractAddressSet(destinationChain, contractAddress);
  }

And in the DestinationBridge contract:

  function addChainSupport(
    string calldata srcChain,
    string calldata srcContractAddress
  ) external onlyOwner {
    chainToApprovedSender[srcChain] = keccak256(abi.encode(srcContractAddress));
    emit ChainIdSupported(srcChain, srcContractAddress);
  }

Removing an already added src/dest contract address is not possible.

Tools Used

Manual Review

Add the possibility to remove support for some of the blockchains in the future.

Assessed type

Context

#0 - raymondfam

2023-09-08T04:35:28Z

Just set the mapping to the default value and the following if block will prevent the source chain from executing through Axelar:

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L96-L98

    if (chainToApprovedSender[srcChain] == bytes32(0)) {
      revert ChainNotSupported();
    }

#1 - c4-pre-sort

2023-09-08T04:35:33Z

raymondfam marked the issue as low quality report

#2 - c4-pre-sort

2023-09-08T04:35:38Z

raymondfam marked the issue as primary issue

#3 - c4-judge

2023-09-19T10:18:47Z

kirk-baird marked the issue as unsatisfactory: Invalid

#4 - c4-judge

2023-09-27T00:52:57Z

kirk-baird removed the grade

#5 - c4-judge

2023-09-27T00:53:11Z

kirk-baird marked issue #444 as primary and marked this issue as a duplicate of 444

#6 - c4-judge

2023-09-27T00:55:08Z

kirk-baird marked the issue as satisfactory

#7 - kirk-baird

2023-09-27T01:00:36Z

Just set the mapping to the default value and the following if block will prevent the source chain from executing through Axelar:

https://github.com/code-423n4/2023-09-ondo/blob/main/contracts/bridge/DestinationBridge.sol#L96-L98

    if (chainToApprovedSender[srcChain] == bytes32(0)) {
      revert ChainNotSupported();
    }

This is actually not possible see #444 for a detailed description of why. tl;dr It's since the setters do keccak(address) so we can't set things to bytes(0).

Awards

87.5807 USDC - $87.58

Labels

bug
grade-a
QA (Quality Assurance)
sponsor confirmed
sufficient quality report
Q-02

External Links

Low issues

[L-01] Elapsed time should be % day == 0

Impact

When setting a new range, the elapsed time between the start and end of the period should be % DAY == 0 to minimize precision errors in the calculation of elapsed days.

Add an additional check for (lastRange.end - endTimestamp) % day == 0 in the setRange function.

[L-02] Incorrect events

Impact

When Transfer and TransferShares events are emitted, the wrong value is set. The USDY amount should be multiplied by BPS_DENOMINATOR.

Make the following changes:

emit Transfer(address(0), msg.sender, getRUSDYByShares(_USDYAmount * BPS_DENOMINATOR));

emit TransferShares(address(0), msg.sender, _USDYAmount * BPS_DENOMINATOR);

[L-03] Missing check for sharesAmount >= BPS_DENOMINATOR in transferShares

In the transferShares function, a check for sharesAmount >= BPS_DENOMINATOR is missing,it should be similar to unwrap function. Small share amounts may result in precision errors.

[L-04] setThresholds should not accept empty arrays

Impact

If the setThresholds function receives empty arrays for amounts and numOfApprovers, it will delete chainToThresholds[srcChain] and the _attachThreshold function will fail.

Add an additional check for that:

f (amounts.length == 0) { revert ArrayLengthIsZero(); }

[L-05] if numOfApprovers[i] <= 2 than tx will be approved everytime

Impact

If numOfApprovers[i] <= 2, every transaction for this amount will be approved only for one approver.

Add an additional check for that:

if(numOfApprovers[i] <= 2){ revert SmallNumOfApprovers }

[L-06] if numOfApprovers[i] <= 2 than tx will be approved everytime

Impact

If numOfApprovers[i] <= 2, every transaction for this amount will be approved only for one approver.

Add an additional check for that:

if(numOfApprovers[i] <= 2){ revert SmallNumOfApprovers }

[L-07] Next threshold should be strictly more thna previous

Impact

The next threshold should be strictly greater than the previous one. Currently, it is possible for two thresholds for different amounts to be equal.

Make the following changes:

-if (chainToThresholds[srcChain][i - 1].amount > amounts[i]) {
+if (chainToThresholds[srcChain][i - 1].amount >= amounts[i]) {
}

[L-08] Implement the same ordering restriction for amounts as for thresholds

Impact

Implement the same ordering restriction for amounts as for thresholds. Amounts should always be in ascending order.

Non-critical issues

[NC-01] multiexcall function does not need to return results

The multiexcall function does not need to return results because if some of the calls fail, the whole transaction will revert. The result will always be an array of booleans, all equal to true.

[NC-02] msg.value should be equal to the sum of exCallData[i].value

It should be checked whether msg.value is equal to the sum of exCallData[i].value in the multiexcall function. If msg.value is greater, any excess ether will be stuck in the contract.

[NC-03] t.approvers.length > 0 check can be removed

The t.approvers.length > 0 check in the _approve function can be removed because it will have the same behavior. The for loop condition i < t.approvers.length already covers the same condition.

[NC-04] Owner should not remove Axelar Relayer as approver

Owner should not be possible to remove Axelar Relayer as approver.

function removeApprover(address approver) external onlyOwner { delete approvers[approver]; //@audit nc: shoulde not be able to remove Axelar Relayer emit ApproverRemoved(approver); }

#0 - c4-pre-sort

2023-09-08T08:38:52Z

raymondfam marked the issue as sufficient quality report

#1 - c4-judge

2023-09-23T00:19:06Z

kirk-baird marked the issue as grade-a

#2 - c4-sponsor

2023-09-25T14:02:41Z

ali2251 (sponsor) confirmed

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