IOP _ ThunderNFT 34630 - [Smart Contract - Critical] Incorrect Token Sale Amount

Incorrect Token Sale Amount

Submitted on Sun Aug 18 2024 18:35:30 GMT-0400 (Atlantic Standard Time) by @Blockian for IOP | ThunderNFT

Report ID: #34630

Report type: Smart Contract

Report severity: Critical

Target: https://github.com/ThunderFuel/smart-contracts/tree/main/contracts-v1/libraries

Impacts:

  • Permanent freezing of funds

  • Direct theft of any user funds, whether at-rest or in-motion, other than unclaimed yield

Description

Thunder Exchange

Incorrect Token Sale Amount

Description

An issue has been identified that allows a malicious actor to sell only one token, even if the Buy Order specifies a greater quantity. This vulnerability effectively bypasses the intended order amount.

Root Cause

As discussed in our Discord exchange, the Order.amount field was introduced to accommodate ERC1155-style tokens:

Hi! Yes, amount is added in case of Erc1155 style token standard

This clearly states that the Order.amount can be greater than 1. However, when executing an order, the ExecutionResult has a hardcoded amount of 1:

As a result, the specified amount in the Order is effectively ignored.

Impact

This issue has two significant impacts:

Buy Order

For a Maker Order of type Buy, an attacker can sell a single token instead of the specified quantity, receiving full payment and effectively defrauding the buyer.

Sell Order

For a Maker Order of type Sell, an innocent buyer may pay the full price but only receive a single token, with the remainder of the tokens being locked away.

Proposed fix

To resolve this issue, the maker_order.amount should be included when crafting the ExecutionResult.

Proof of concept

Proof of Concept

Due to the relatively new nature of the Sway language and the limited availability of reliable testing tools, the proof of concept (PoC) is complex.

Below is a pseudo-PoC followed by a detailed actual PoC.

Pseudo POC

  1. An innocent user creates a Buy Order for an asset, specifying an amount greater than one.

  2. A malicious actor executes the Buy Order but only sells one token.

Actual POC

There are some steps to follow:

To create an actual PoC, some modifications to the protocol are necessary.

  1. The protocol currently only allows addresses to interact, which is generally fine. However, when transferring coins in the Fuel ecosystem, a Variable Output needs to be added to the transaction — this isn't supported by the current Sway testing tools.

  2. Since this vulnerability is unrelated to the nature of who interacts with the protocol, adjustments will be made to allow contracts to interact, enabling the PoC. These changes are strictly for testing purposes and do not affect the core issue.

Changes to the protocol for the POC

  • Add the following changes to the thunder_exchange contract:

In addition, To make an MakerOrderInput Struct, we need to make the ExtraParams Struct public, so in the order_types.sw file, lets add a pub in line 37.

The tests files.

  • Create forc.toml in contracts-v1 and add the below in the forc.toml:

  • Create 4 new folder called tests, test_user, test_attacker, and test_asset under the contracts-v1 directory:

  • In the each folder create a folder named src with a file called main.sw, and a forc.toml file. The folder tree will look like this:

tests folder

In the tests folder.

  • Add the below in the forc.toml:

  • Add the below in the main.sw:

test_user folder

In the test_user folder.

  • Add the below in the forc.toml:

  • Add the below in the main.sw:

test_attacker folder

In the test_attacker folder.

  • Add the below in the forc.toml:

  • Add the below in the main.sw:

test_asset folder

In the test_asset folder. The test asset is simply the Fuel Team SRC3 example

  • Add the below in the forc.toml:

  • Add the below in the main.sw:

Interfaces

Now we need to add the test_user and test_attacker interfaces to interact with. In the interfaces/src folder, in the lib.sw add the following lines:

Additionally, create a file called test_user_interface.sw in the interfaces/src folder and add the following:

Create a file called test_attacker_interface.sw in the interfaces/src folder and add the following:

Run it all!

Simply run forc test in smart-contracts/contracts-v1.

POC TL;DR

  1. Initializing the project contracts

  2. Minting some coins to the test_user and test_attacker

  3. Test User creates an innocent Sell Order

  4. Test Attacker steals Test User's deposited tokens

Last updated

Was this helpful?