Open fulldecent opened 2 years ago
Because
nft_transfer
performsnft_revoke_all
in addition to other activity, it is possible thatnft_revoke_all
could succeed andnft_transfer
could fail.
I think there's another misunderstanding. In the implementation this is specifically called out, unless there's something far deeper I'm unaware of.
When a user calls nft_transfer
they will hit:
fn nft_transfer(
…
) {
…
self.internal_transfer(&sender_id, &receiver_id, &token_id, approval_id, memo);
}
then calls that function where it calls it out:
pub fn internal_transfer(
…
) -> (AccountId, Option<HashMap<AccountId, u64>>) {
let owner_id =
self.owner_by_id.get(token_id).unwrap_or_else(|| env::panic_str("Token not found"));
// clear approvals, if using Approval Management extension
// this will be rolled back by a panic if sending fails
let approved_account_ids =
self.approvals_by_id.as_mut().and_then(|by_id| by_id.remove(token_id));
…
When a panic occurs within a Rust smart contract on NEAR, the transaction is reverted along with state changes.
@mikedotexe Thank you for the references.
I agree that the nft_transfer
function does clear approvals. This is coded as expected. ✅
I agree that nft_transfer
will fail if there is not enough gas to clear approvals. This is coded as expected. ✅
It is possible that the amount of gas required to successfully call nft_transfer
will exceed the single-block gas limit. This is bad. 💣
Problem
These two specifications are incompatible:
and:
Why is this a problem
Because
nft_transfer
performsnft_revoke_all
in addition to other activity, it is possible thatnft_revoke_all
could succeed andnft_transfer
could fail.Impact
A token owner could get into a situation where they are not able to transfer a token. The workaround is that they would need to perform
nft_revoke_all
before performing a transfer and everything will be okay.But if the token owner is a smart contract, and the contract does not support calls to
nft_revoke_all
(which is a reasonable design decision), then it could become impossible for that token owner to transfer tokens.Recommendations
nft_revoke_all
.nft_approve
. Specify that panic must occur not only if addition would causenft_revoke_all
to panic, but also if addition would causenft_transfer
to panic.