Lucene search

K
code423n4Code4renaCODE423N4:2023-09-ONDO-FINDINGS-ISSUES-446
HistorySep 07, 2023 - 12:00 a.m.

All the funds will be lost if the destination bridge is paused

2023-09-0700:00:00
Code4rena
github.com
4
pausable contract
token loss
vulnerable function
mitigation step

Lines of code
<https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/bridge/DestinationBridge.sol#L31&gt;

Vulnerability details

Impact

Destination bridge is pausable, so if for a chain a destination bridge is paused, all the funds being bridged from different source bridges from different chains will be lost.

Proof of Concept

Destination bridge inherits from the openzeppelin pausable.sol. And _execute function cannot be called if the contract is paused. As discussed in my other submissions for one transaction if _execute is once called and it reverts it become not replayable ever again.

<https://github.com/code-423n4/2023-09-ondo/blob/47d34d6d4a5303af5f46e907ac2292e6a7745f6c/contracts/bridge/DestinationBridge.sol#L85-L114&gt;

  function _execute(
    string calldata srcChain,
    string calldata srcAddr,
    bytes calldata payload

  // @audit contract is pausable and hence is vulnerable.
  ) internal override whenNotPaused {
    (bytes32 version, address srcSender, uint256 amt, uint256 nonce) = abi
      .decode(payload, (bytes32, address, uint256, uint256));

    if (version != VERSION) {
      revert InvalidVersion();
    }
    if (chainToApprovedSender[srcChain] == bytes32(0)) {
      revert ChainNotSupported();
    }
    if (chainToApprovedSender[srcChain] != keccak256(abi.encode(srcAddr))) {
      revert SourceNotSupported();
    }
    if (isSpentNonce[chainToApprovedSender[srcChain]][nonce]) {
      revert NonceSpent();
    }

    isSpentNonce[chainToApprovedSender[srcChain]][nonce] = true;

    bytes32 txnHash = keccak256(payload);
    txnHashToTransaction[txnHash] = Transaction(srcSender, amt);
    _attachThreshold(amt, txnHash, srcChain);
    _approve(txnHash);
    _mintIfThresholdMet(txnHash);
    emit MessageReceived(srcChain, srcSender, amt, nonce);
  }

So the _execute function must not revert at any point else the tokens burnt on source chain are done and dusted.

As there are multiple chains and each have its own source and destination contracts, there is always a chance that if some source is working but the destination contract for that is paused hence the _execute function called by the axelar node will revert.

Tools Used

Manual review

Recommended Mitigation Steps

Will need to change the whenNotPaused modifier in a way that if the protocol is paused, simply mint the tokens incoming to a recovery address controlled by the ondo. So those tokens can be than dealt with later on.

Assessed type

Other


The text was updated successfully, but these errors were encountered:

All reactions