IOP _ ThunderNFT 34636 - [Smart Contract - Critical] The amount is set to when creating the Executio

Submitted on Sun Aug 18 2024 21:31:54 GMT-0400 (Atlantic Standard Time) by @Schnilch for IOP | ThunderNFT

Report ID: #34636

Report type: Smart Contract

Report severity: Critical

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

Impacts:

  • Permanent freezing of NFTs

Description

Brief/Intro

When an order is executed, the ExecutionResult includes, among other details, how many NFTs the buyer receives. The amount parameter, however, is not taken from the order but is instead set to 1. This could result in only one token being sold while the remaining tokens remain stuck in the contract.

Vulnerability Details

The execution result is generated by the function s1 (see 1. reference) in the strategy with the function execute_order (see 2. reference). As can be seen in the function s1, the amount is simply set to 1 there, and the amount specified in the order is not used. Afterwards, this execution result is returned by the strategy to the Thunder Exchange. The Thunder Exchange uses the execution_result in the functions _execute_sell_taker_order (see 3. reference) and _execute_buy_taker_order (see 4. reference) to send the buyer their tokens based on this result. However, the buyer only receives one token because the amount is always set to 1, but they pay the full price for all tokens offered by the seller. The remaining tokens then get stuck in the contract.

Impact Details

Tokens are stuck in the contract if the seller sells a larger amount of tokens than 1, for example with an ERC1155 token (Normal NFTs should be unique and an amount of 1 would be correct in this case). In addition, the buyer also pays too much because he pays the full price for the actual amount of tokens but only receives one.

References

  1. https://github.com/ThunderFuel/smart-contracts/blob/260c9859e2cd28c188e8f6283469bcf57c9347de/contracts-v1/libraries/src/execution_result.sw#L16-L34

  2. https://github.com/ThunderFuel/smart-contracts/blob/260c9859e2cd28c188e8f6283469bcf57c9347de/contracts-v1/execution_strategies/strategy_fixed_price_sale/src/main.sw#L146

  3. https://github.com/ThunderFuel/smart-contracts/blob/260c9859e2cd28c188e8f6283469bcf57c9347de/contracts-v1/thunder_exchange/src/main.sw#L407-L411

  4. https://github.com/ThunderFuel/smart-contracts/blob/260c9859e2cd28c188e8f6283469bcf57c9347de/contracts-v1/thunder_exchange/src/main.sw#L387-L391

Proof of concept

Proof of Concept

Since the POC is in rust some setup is required.

  1. Execute cargo new thunder-tests in the smart-contracts folder

  2. Add the following dependencies to the Cargo.toml in the thunder-tests folder:

  1. Then paste the following code into thunder-tests/src/main.rs:

Since normal NFTs only have an amount of 1 per NFT, an ERC1155 token will be used in this example. For this one must be created in the contracts-v1 folder:

  1. Execute force new erc1155 in the contracts-v1 folder

  2. Add these dependency to the Forc.toml of the erc1155 contract:

  1. Paste this code into contracts-v1/erc1155/src/main.sw (The code was mainly copied from here: https://docs.fuel.network/docs/sway/blockchain-development/native_assets/#multi-native-asset-example):

  1. Run forc build in all smart contract folders that are needed:

    • contracts-v1/asset_manager

    • contracts-v1/erc1155

    • contracts-v1/execution_manager

    • contracts-v1/execution_strategies/strategy_fixed_price_sale

    • contracts-v1/interfaces

    • contracts-v1/libraries

    • contracts-v1/pool

    • contracts-v1/royalty_manager

    • contracts-v1/thunder_exchange

  2. The POC can be started with the command cargo test test_poc -- --nocapture in the thunder-tests folder

Last updated

Was this helpful?