IOP _ ThunderNFT 34930 - [Smart Contract - Critical] User can only trade token when ERC is used

Submitted on Sun Sep 01 2024 11:13:08 GMT-0400 (Atlantic Standard Time) by @jasonxiale for IOP | ThunderNFT

Report ID: #34930

Report type: Smart Contract

Report severity: Critical

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

Impacts:

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

Description

Brief/Intro

According to discord chat history, ERC1155 tokens are also in scope. In current implementation, there is a issue than when the order maker tries to trade more than 1 tokens for assetId_X, he/she can only get 1 assetId_X token.

Which will cause the user losses assets.

Vulnerability Details

I'll use Side::Buy order as an example.

When a buyer calls thunder_exchange.place_order to fill a Side::Buy order, he can set the amount of ERC1155 asset he wants to buy by MakerOrderInput.amount.

Then the seller see the order, and he will call thunder_exchange.execute_order to fill a Side::Sell order, and at the same time, the tx will sent the specified ERC1155 token along with the tx. Then in thunder_exchange._execute_sell_taker_order, strategy.execute_order is called.

In strategy_fixed_price_sale.execute_order, ExecutionResult::s1 is called to generate an execution_result.

As function execution_result.s1 shows, the amount is always set to 1, which causes the issue

Then back to thunder_exchange._execute_sell_taker_order, the function check if the amount of ERC1155 received equals to execution_result.amount(which is set to 1 by execution_result::s1 function) in thunder_exchange#L404, and then sends execution_result.amount(which is 1) amount of ERC1155 to the buyer in thunder_exchange#L407-L411

Impact Details

As the code flow shows, Alice(the buyer) fills an order to buy X amount of ERC1155 with Y amount payment asset. Bob(the seller) fill sell order for Alice's order, and Bob only need to pay 1 ERC1155 and will get all Alice's Y amount payment asset.

References

Add any relevant links to documentation or code

Proof of concept

To mock ERC1155, I make a litter change in erc721's source code:

Then generate a Rust test template under thunder_exchange folder, and puts the following code in thunder_exchange/tests/harness.rs and run cargo test -- --nocapture

In the testcase, wallet_3 fills a Buy tx and specify 2 amount of token to buy. And wallet_1 execution a Sell tx to fill wallet_3's order. And as the result shows, after the tx, wallet_3 only get 1 amount token

Last updated

Was this helpful?