Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BUG: cw-ICS721 cannot mint tokens received. #501

Open
giansalex opened this issue Mar 15, 2023 · 7 comments
Open

BUG: cw-ICS721 cannot mint tokens received. #501

giansalex opened this issue Mar 15, 2023 · 7 comments
Labels
bug Something isn't working ics-721 Possible protocol vulnerability wasm

Comments

@giansalex
Copy link
Contributor

giansalex commented Mar 15, 2023

Summary of Bug

That happens when a token is sent in a second flow and the cw-ics721 has not received IBC Acknowledge in time.
e.g:

  1. i -> j (OK)
  2. j -> i (JUNO does not receive IBC ACK in time)
  3. i -> j (JUNO cannot mint the token on IBC Recv)

Looking in the code, this occurs because cw-ics721 burns the token sent to the remote chain in IBC ACK event, but due to spam it does not receive the ACK in time.
https://github.com/public-awesome/ics721/blob/main/contracts/cw-ics721-bridge/src/ibc.rs#L172

Steps to Reproduce

Expected and Actual Behavior

  • Expected: Successful token receipt
  • Actual: ACK with error: execute wasm contract failed

Additional Context

The burn event must occur at the time of transfer, as does nft-transfer module.
https://github.com/bianjieai/nft-transfer/blob/v1.1.1-beta/keeper/relay.go#L259

@0xekez
Copy link

0xekez commented Mar 16, 2023

@giansalex thanks for the detailed write up of this. i appreciate the simple example, and link to the code. i'll get to this early next week likely.

@0xekez
Copy link

0xekez commented Mar 16, 2023

reposting my thoughts on this from the Discord:

I feel that the CW implementation is behaving correctly and in line with the spec here. the state machine is:

  1. send,
  2. on error, return
  3. on success, burn

the SDK module approach is:

  1. send & burn
  2. on error, re-mint
  3. on success, do nothing

the trouble with this is that the NFT is destroyed before it is confirmed to have been transferred! this feels like an invariant violation to me. imagine if other code performed an action when the NFT is destroyed - the author would probably be surprised to learn that the NFT can be re-minted. we are building a bridge, so in my view we should prioritise correctness over all else.

additionally, NFTs are not locked by the CW approach, you just need to self-relay your ACK, in addition to the packet. If you do that, it will happily burn the NFT on completion.

@giansalex
Copy link
Contributor Author

https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer#packet-relay

  • When a packet times out, tokens represented in the packet are either unescrowed or minted back to the sender appropriately -- depending on whether the tokens are being moved away from or back toward their source.

According to this, it is understood that the token must have been burned when it was sent.

@0xekez
Copy link

0xekez commented Mar 16, 2023

@giansalex, what's your opinion on how the spec should work? it feels strange to me to allow transferring a NFT that has not been ACK'd as being received yet.

@taitruong
Copy link
Contributor

https://github.com/cosmos/ibc/tree/main/spec/app/ics-721-nft-transfer#packet-relay

  • When a packet times out, tokens represented in the packet are either unescrowed or minted back to the sender appropriately -- depending on whether the tokens are being moved away from or back toward their source.

According to this, it is understood that the token must have been burned when it was sent.

This is a heavy bug and exploit. Check my explanation here: #705 (comment)

The issue you are pointing out is due to congestions by IBC messages relaying issues, where ACK success and fail messages are delivered very late due to mass amount of packets (e.g. by vector attacks). IBC though guarantees sending ACKs - no matter how long it takes. Only solution here is to self-relay or wait :). But for ICS721 transfer it is good that NFT is locked until then.

@giansalex
Copy link
Contributor Author

giansalex commented Mar 23, 2023

This is a heavy bug and exploit. Check my explanation here: #705 (comment)

can you demonstrate this exploit on the chain?
My comment: #705 (comment)

@giansalex
Copy link
Contributor Author

giansalex commented Mar 23, 2023

@giansalex, what's your opinion on how the spec should work? it feels strange to me to allow transferring a NFT that has not been ACK'd as being received yet.

sorry, I had not seen this.

I agree with the current implementation, generally nft-transfers will be successful, ACK+error and Timeout events occur rarely or exceptionally (in testnet occurred due to a malicious contract attack).

it is also more optimal for the relayers, since the gas consumed in the NFT burning will be charged to the user (nft-transfer Tx)

@taramakage taramakage added wasm and removed cw-721 CosmWasm erc-721 implementation labels Mar 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working ics-721 Possible protocol vulnerability wasm
Projects
None yet
Development

No branches or pull requests

4 participants