Skip to content

User could get his funds locked using a particular type of tokens #52

Closed
@c4-bot-6

Description

@c4-bot-6

Lines of code

https://github.com/code-423n4/2024-06-thorchain/blob/e3fd3c75ff994dce50d6eb66eb290d467bd494f5/chain/ethereum/contracts/THORChain_Router.sol#L26

Vulnerability details

Impact

Whenever a user deposits a fee on transfer token like PAXG or STA (both are whitelisted), there are a few ways he could get his funds locked into the contract.

Proof of Concept

Fee on transfer tokens are tokens that charge a fee on transfer making recipients receive less than the sent amount.

This creates a few possible issues for the contract.

Imagine the following scenario:

  1. User deposits PAXG (an allowed token) into the contract using depositWithExpiry() specifying that he wants to call transferOutAndCallV5() using the memo input parameter

This is the part of _transferOutAndCallV5() responsible for swapping from a token to another token:

      _vaultAllowance[msg.sender][aggregationPayload.fromAsset] -= aggregationPayload.fromAmount;

      (bool transferSuccess, bytes memory data) = aggregationPayload.fromAsset.call(
          abi.encodeWithSignature(
            "transfer(address,uint256)",
            aggregationPayload.target,
            aggregationPayload.fromAmount
          )
        );

      require(
        transferSuccess && (data.length == 0 || abi.decode(data, (bool))),
        "Failed to transfer token before dex agg call"
      );

      (bool _dexAggSuccess, ) = aggregationPayload.target.call{value: 0}(
        abi.encodeWithSignature(
          "swapOutV5(address,uint256,address,address,uint256,bytes,string)",
          aggregationPayload.fromAsset,
          aggregationPayload.fromAmount,
          aggregationPayload.toAsset,
          aggregationPayload.recipient,
          aggregationPayload.amountOutMin,
          aggregationPayload.payload,
          aggregationPayload.originAddress
        )
      );
  1. We transfer the aggregationPayload.fromAmount of the PAXG asset to the target aggregator contract and the target contract will receive less than the amount specified
  2. We then call swapOutV5 on the target contract with that same fromAmount and that contract will conduct the swap
  3. Since the contract would have received less than the specified amount, this will definitely revert upon calling Uniswap or any other protocol they are using for the swap as the fromAmount specified is not actually available in the aggregator contract

Now, the funds will be locked in the aggregator contract until they are manually rescued.

Tools Used

Manual Review

Recommended Mitigation Steps

Handle such cases appropriate or disallow such tokens altogether.

Assessed type

Under/Overflow

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions