Connext Amarok contest - 0xNineDec's results

The interoperability protocol of L2 Ethereum.

General Information

Platform: Code4rena

Start Date: 08/06/2022

Pot Size: $115,000 USDC

Total HM: 26

Participants: 72

Period: 11 days

Judge: leastwood

Total Solo HM: 14

Id: 132

League: ETH

Connext

Findings Distribution

Researcher Performance

Rank: 22/72

Findings: 2

Award: $484.46

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: xiaoming90

Also found by: 0xNineDec, Ruhum, hyh, slywaters

Labels

bug
duplicate
2 (Med Risk)

Awards

340.9262 USDC - $340.93

External Links

Lines of code

https://github.com/code-423n4/2022-06-connext/blob/b4532655071566b33c41eac46e75be29b4a381ed/contracts/contracts/core/connext/facets/BridgeFacet.sol#L389 https://github.com/code-423n4/2022-06-connext/blob/b4532655071566b33c41eac46e75be29b4a381ed/contracts/contracts/core/connext/facets/BridgeFacet.sol#L1025 https://github.com/code-423n4/2022-06-connext/blob/b4532655071566b33c41eac46e75be29b4a381ed/contracts/contracts/core/connext/libraries/AssetLogic.sol#L347 https://github.com/code-423n4/2022-06-connext/blob/b4532655071566b33c41eac46e75be29b4a381ed/contracts/contracts/core/connext/libraries/AssetLogic.sol#L347

Vulnerability details

Context of relevant lines of code and functions:

L389: BridgeFacet.sol: handle function

L1025: BridgeFacet.sol: Comment About This

L1029: BridgeFacet.sol: SafeIncrease of Allowance

L347: AssetLogic.sol: Usage of SafeApprove

Impact

Each call apart from the first one that relies on the swapFromLocalAssetIfNeededForExactOut function will be reverted and the whole call will suffer a reversal in cascade. This will deny future nomad relayers calls to handle and as a consequence, jam the relayer logic.

Proof of Concept

The relayer logic according to the comments and description provided by the Connext team suggests that the handle function is called once a router message has been optimistically verified. The flow of how the calls are being triggered will be the following:

  1. A relayer calls handle, L389.
  2. This call triggers the internal call of _reconcile, L541. This function will handle how the balance of tokens is managed regarding minting and AMM swapping.
  3. If the condition under L600 is true and the following one is false, _reconcileProcessPortal is called in order to repay Aave Portal.
  4. Under L1011, the call triggering the swap is made by executing swapFromLocalAssetIfNeededForExactOut L226 logic managed by the AssetLogic library.
  5. The last call also triggers _swapAssetOut, trigger made at L226, where the implementation is at L304.
  6. Last at L342, if the conditional statement is true, the call that reverts (at Ncalls having N>0) will be triggered L347: SafeERC20.safeApprove(IERC20(_assetIn), address(pool), _amountIn).

The first time this whole loop is called, every step will pass and the transaction will be mined. But when the second call is triggered, the step 6 will be reverted by following the SafeERC20 function logic:

/** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove( IERC20 token, address spender, uint256 value ) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); }

The reversal comes from the require statement under the execution of the safeApprove call, more precisely the last argument of the or logic operator.

As the handle function is meant to be called several times, this may incur in a severe jamming of the relayer logic preventing them to perform further calls.

OpenZeppelin suggests not using this implementation as is deprecated and it should only be called if the initial allowance wants to be set (initial state of the contract allowances). In order to manage the allowances, following the SafeERC20 standard suggestions, it is advisable to use instead SafeERC20.safeIncreaseAllowance and SafeERC20.safeDecreaseAllowance.

#0 - ecmendenhall

2022-06-20T15:36:43Z

Duplicate of #154

#1 - LayneHaber

2022-06-25T20:00:41Z

See #154

#2 - 0xleastwood

2022-08-13T22:35:44Z

Good description of the same issue in #154.

L: Unresolved TODO's

The following lines of code contain unresolved commented TODO's that must be reviewed, deleted or implemented depending each case.

It is important to remark that by developing the implementations pointed by those to do's; their logics, possible impacts and plausible attack vectors associated that could happen will require further audits to determine if they convey or not further risks.

BridgeFacet.sol L:492

BridgeFacet.sol L:579

BridgeFacet.sol L:1027

LibConnextStorage.sol L:303

UpgradeBeaconController.sol

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