Light ModeLight
Light ModeDark

One Bug Per Day

One H/M every day from top Wardens

Checkmark

Join over 1020 wardens!

Checkmark

Receive the email at any hour!

Ad

Permanent loss of tokens if swap data gets outdated

mediumCode4rena

Lines of code

https://github.com/code-423n4/2024-01-decent/blob/011f62059f3a0b1f3577c8ccd1140f0cf3e7bb29/src/bridge_adapters/StargateBridgeAdapter.sol#L183

Vulnerability details

Impact

While sending funds through StargateBridgeAdapter, the user passes the swap data as a parameter. The flow is stargate sending tokens on the receiving chain into the StargateBridgeAdapter and executing sgReceive.

The issue here is that sgReceive will fail if the swap data gets outdated, but this is not going to make the whole transaction revert.

Stargate will still send the tokens to the StargateBridgeAdapter, and if the sgReceive fails, the swap will be cached for later execution. See StargateComposer logic here: https://stargateprotocol.gitbook.io/stargate/stargate-composability/stargatecomposer.sol#sgreceive.

Now, tokens will be left sitting in the StargateBridgeAdapter contract, and since the user can only retry the transaction with the same swap data, the tokens will be stuck forever.

The impact is loss of transferred tokens for the user.

Proof of Concept

Consider the following flow:

  1. User invokes StargateBridgeAdapter:bridge() function as part of the whole flow of calling UTB:bridgeAndExecute() function.
  2. He is passing the swapData parameters to the remote chain.
  3. StargateComposer first transfers the tokens to the StargateBridgeAdapter contract.
  4. After that the StargateBridgeAdapter:sgReceive() function is executed.
  5. It then calls UTB:receiveFromBridge that tries to execute the swap.
  6. If the swap fails, which can frequently occur due to the fact that the swap data is outdated, most commonly minimum amount out gets outdated.
  7. The whole payload gets stored inside the StargateComposer contract, and the tokens are left in the StargateBridgeAdapter contract.
  8. As the user can only retry the transaction with the same payload, the tokens will be stuck forever.
  9. An example of StargateComposer contract can be seen on: https://stargateprotocol.gitbook.io/stargate/developers/contract-addresses/mainnet#ethereum

Note: The application needs to use the StargateComposer contract as opposed to StargateRouter because it is transferring funds with payload, i.e. it executes sgReceive on the receiving chain. You can only use StargateRouter directly if you're sending funds empty payload. More on it: https://stargateprotocol.gitbook.io/stargate/stargate-composability

Tools Used

  • Manual review

Recommended Mitigation Steps

Wrap the whole StargateBridgeAdapter:receiveFromBridge() call into a try/catch and if it reverts send the transferred tokens back to the user.

Assessed type

Other