IOP _ ThunderNFT 34816 - [Smart Contract - High] users cant call update_order to update the strategy
Submitted on Tue Aug 27 2024 19:13:17 GMT-0400 (Atlantic Standard Time) by @zeroK for IOP | ThunderNFT
Report ID: #34816
Report type: Smart Contract
Report severity: High
Target: https://github.com/ThunderFuel/smart-contracts/tree/main/contracts-v1/thunder_exchange
Impacts:
Permanent freezing of NFTs
Description
Brief/Intro
the update_order function in the thunder_exchange meant to be used to update some important parameter for order makers, makers should be allowed to update the price and amount and strategy and paymentAsset when it get updated(new token or strategy added to whitelist), however the implementation design of thunder_exchange and fixed strategy will not allow users to update the strategy address correctly, this happens because when the thunder_exchange#update_order get called the _validate_maker_order_input function will invoked which require the nonce to be above zero and when the fixed_strategy#update_order get called the line below will get the user order nonce in the new strategy:
/// Updates sell MakerOrder if the nonce is in the right range
#[storage(read, write)]
fn _update_sell_order(order: MakerOrder) {
let nonce = _user_sell_order_nonce(order.maker); //@audit get the nonce for the maker, this will be zero in new strategy contract since user have no storage data in the new deployed contract
let min_nonce = _user_min_sell_order_nonce(order.maker);
if ((min_nonce < order.nonce) && (order.nonce <= nonce)) { //@audit order.nonce is 1 and nonce is zero so this won't execute and revert happened
// Update sell order
let sell_order = _sell_order(order.maker, order.nonce);
_validate_updated_order(sell_order, order);
storage.sell_order.insert((order.maker, order.nonce), Option::Some(order));
} else {
revert(115);
}
}
the issue exist because the maker who want to update its order, he's forced to set nonce to 1 and above(since place_order does not allow creating order with zero nonce) and in the other hand when new strategy get deployed the user storage variable will be zero, this is because the whole codebase is not upgradable and since its not upgradable the storage data from old strategy will not be saved/written in the new strategy contract.
this will prevent updating any parameter like price or nonce or payment asset and strategy which lead to stuck the NFTs.
Vulnerability Details
when user want to update its order, first thing to do is calling update order in the thunder_exchange which invokes some sanity checks as shown below:
as shown above, the nonce input should be above zero, this will prevent users to update their orders when new strategy get deployed and whitelisted, this is because the old storage data in the old strategy does not copied to the new strategy. the issue exist in line belows:
as shown, the call to update will revert and other functions won't be able to execute since strategy or paymentAsset not updated.
this will only affect the NFT seller since the owner of the NFT can not cancel or execute its nft sell order, bidder can transfer out their tokens in the pool
Impact Details
Permanent freezing of NFTs when the strategy get updated.
References
the most recommended fix is updating the codebase to upgradable codebase with following the requirements to set the codebase to correct upgradable contracts.
another fix is allowing updating strategy with nonce zero to avoid reverting, but we don't recommend this.
Proof of concept
Proof of Concept
check the report ID: 34567 notes to execute the POC below:
Last updated
Was this helpful?