Cosmos-sdk: Able to increase the tokens on zone which are transferred from hub but unable to transfer back

Created on 1 Jun 2020  Â·  14Comments  Â·  Source: cosmos/cosmos-sdk

Summary of Bug

In GOZ phase 3, we feel we found a bug in ICS 20 specs/implementation. We are able to increase the doubloons on our zone but unable to transfer back to hub.

Version

Tag: goz-phase-3

Steps to Reproduce

  • Modify OnRecvPacket method of 20-transfer module by setting the data.Amount value to custom value (1000doubloons) on your zone
  • Start the zone
  • Send some doubloons (10doubloons) using relay software.
  • The transfer/xxxxx/doubloons will get increased on your zone to 1000 and 10 doubloons will get decreased on the hub.
  • Relay back these 1000 transfer/xxxxx/doubloons to the hub and the transactions will be a success
  • But either 1000 doubloons or 10 doubloons will not be added back on the hub account but will get deducted on the zone.
  • It's actually raising an error saying the escrow account doesn't have enough tokens. But the relayed transaction is a success.
  • Finally, you will lose the original doubloons too.

For Admin Use

  • [x] Not duplicate issue
  • [ ] Appropriate labels applied
  • [ ] Appropriate contributors tagged
  • [ ] Contributor assigned/self-assigned

All 14 comments

I expect the relay transaction with opaque packet from zone to hub should fail on hub and put an acknowledge packet on hub which can be relayed back to zone.

But here is an issue, the developers of zone can write a hidden transaction, exploit it and circulate fake tokens. They can accumulate original tokens on hub when the escrow address has enough tokens locked.

Does it unlock the original tokens if you send back 10doubloons?

Yes, If I send the amount which is LTE to amount of escrow address worked!

Assume ibc0 is the Hub and ibc1 is the zone (modified).
Here is the output of following commands.

rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc0 ibc1 10n0token true `rly chains address ibc1`
rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc1 ibc0 1000n0token false `rly chains address ibc0`
rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc0 ibc1 10n0token true `rly chains address ibc1`
rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc1 ibc0 10n0token false `rly chains address ibc0`
rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc1 ibc0 10n0token false `rly chains address ibc0`
rly query balance ibc0 && rly query balance ibc1

rly tx transfer ibc1 ibc0 10n0token false `rly chains address ibc0`
rly query balance ibc0 && rly query balance ibc1

Image

So this is expected behavior for the hub and ibc protocol. It is actually protecting against a malicious chain connection. This is what I think is occurring:

  • MsgSend is not modified on the the custom zone to switch 1000 doubloons back to 10 doubloons (exchange ratio is set on hub -> zone but not zone -> hub)
  • the zone attempts to send 1000 doubloons back to the hub which only has 10 doubloons in escrow, causing onrecv to fail (on hub), but the 1000 doubloons to still be deducted on the zone (send succeeds (on zone), onrecv fails (on hub)).
  • the onrecv failure counts as a received packet (not replayable ie the transaction was successful) and sets the ack to "failed", acknowledgement processing back to the zone should refund 10 or 1000 doubloons (depends on how code derives amount to refund) since the ack failed. I'm not sure if the relayer does a send, recv, and ack in the transfer func as it isn't strictly required.
  • sending 10 doubloons succeeds because this is the amount in escrow. going above the original amount doesn't succeed because this is effectively trying to print money on the hub which indicates connection to a malicious chain (even if accidental in this case)

The only potential issue I see here is if acknowledgement processing of a failed ack didn't refund the sent amount on the zone. This depends on if the relayer sent the failed ack back to the zone

@colin-axner Thank you for your reply. So means this is the relayer software issue which is not caring about the acknowledgements currently?

@ironman0x7b2 yup, just verified it. Cmd transfer calls SendTransferBothSides which makes a call to send the packet on the source chain and receive the packet on the destination chain, but it doesn't deal with acknowledgements back to the source chain. You may be able to test calling the relay cmd to relay back the acknowledgement.

closing this and opening an issue on the relayer to support relaying acks. This is not an sdk issue

@colin-axner Since relaying the ACK packets back to the zone is not necessary, there is a possibility of circulating fake tokens in the zone and get the more original tokens on the hub, right?

For example, person A and person B transferred 10 doubloons each to the zone where A used special transaction which gave him 20 doubloons on zone, and B used normal transaction so he got 10 doubloons. Now A can get 20 doubloons on Hub, right?

@ironman0x7b2 ~No because the ibc protocol prevents supply inflation. The doubloons in escrow should be by address. So A can only get at most the amount of doubloons originally sent back, regardless of what the zone mints for A.~

~Acks are "not strictly required", but they are necessary to process refunds.~

~There are two ways to get one's token back on the source~

  • ~transfer back. In this case A could transfer back all 20 doubloons, but could only ever unlock 10 doubloons on the hub~
  • ~refund. In this case A's transfer was successful from the hub as shown by the vouchers minted in the zone. Therefore A is not eligible for a refund~

~A zone may be faulty and print arbitrary amounts of money (as any blochchain may do), but IBC prevents this behavior from affecting the security of chains connected to it. It is up to the user to not send tokens to a faulty chain in the same way a user shouldn't buy tokens from a faulty chain.~

@ironman0x7b2 I was mistaken in my above comment. Escrow is done by channel/port as per ics spec. I will follow up on this issue today and find out the reasoning for the current construction and see if it needs to be adjusted.

@ironman0x7b2

@colin-axner Since relaying the ACK packets back to the zone is not necessary, there is a possibility of circulating fake tokens in the zone and get the more original tokens on the hub, right?

For example, person A and person B transferred 10 doubloons each to the zone where A used special transaction which gave him 20 doubloons on zone, and B used normal transaction so he got 10 doubloons. Now A can get 20 doubloons on Hub, right?

this was all correct. I apologize for any confusion. This is allowed because there is no way to prevent it from occurring since the source chain cannot know if the chain is being malicious or if A received a transaction from B with the amount of 10 doubloons.

I now understand that IBC prevents chain from affecting each other's state, but it does not protect the user against malicious activity by a malicious chain. Users must be responsible and take caution when sending tokens to another chain

Yes, Thank you @colin-axner

Do you think there is way to solve this problem on source chain (hub)?

Do you think there is way to solve this problem on source chain (hub)?

Not off the top of my head and definitely not within the value proposition of ICS 20.

The issue is one cannot stop a chain from minting vouchers to whomever. I imagine it'd be possible to add in more restrictive verification checks for balance updates to prove no supply inflation on the counterparty chain. This could possibly be done by proving a changed balance resulted from a valid transfer. However, I have no idea if this is actually possible

Was this page helpful?
0 / 5 - 0 ratings

Related issues

hendrikhofstadt picture hendrikhofstadt  Â·  3Comments

rigelrozanski picture rigelrozanski  Â·  3Comments

ValarDragon picture ValarDragon  Â·  3Comments

ValarDragon picture ValarDragon  Â·  3Comments

rigelrozanski picture rigelrozanski  Â·  3Comments