In order to determine the quality and analyze all the aspects of created transfer logic by Osmosis team, including ibc hooks module and 2 smart contracts, the current design is measured against ics-20 properties that are expected to be met in every ics-20 transfer created. In addition, e2e test scenarios are created and executed to confirm the state of the design and its congruence with ics-20 specifications.
The desired properties of the ics-20 fungible token transfer:
- Preservation of fungibility (two-way peg).
- Preservation of total supply (constant or inflationary on a single source chain & module).
- Permissionless token transfers, no need to whitelist connections, modules, or denominations.
- Symmetric (all chains implement the same logic, no in-protocol differentiation of hubs & zones).
- Fault containment: prevents Byzantine-inflation of tokens originating on chain
A
, as a result of chainB
's Byzantine behaviour (though any users who sent tokens to chainB
may be at risk).
The ics-20 transfer is performed and in addition to it the swapping of tokens using ibc hooks module and two smart contracts. The key points in design and implementation regarding property of preservation of fungibility in ics-20 transfer are the following:
- The denomination used on Osmosis chain is in accordance to ics-20 denomination form (Denomination on receiver chain)
- If the transfer fails, there is a mechanism to retrieve the funds in appropriate amount and denomination, using recovery addresses(Failed delivery handling)
- Once the swap is executed, new ibc transfer is created to send the desired tokens back to sender chain (Creating new ibc transfer after the swap)
The issues we discovered that could affect this ics-20 property are:
The sum of total supply before and after the execution flow: transfer-swap-transfer is preserved. The design of this particular transfer overrides the base ics-20 transfer and is created with a few useful means to handle supply invariance:
- In case of failed execution of any of the contracts, recovery of funds is obtained (Failed delivery handling)
- In case of an incorrect format of packet memo field, function from core ibc is called to complete the transfer as it is without the contract (the swap) (e.g. in OnRecvPacketOverride())
- Core calculation of token swapping is performed in such a way to keep the total supply unchanged (Swap calculation)
The issues discovered in this audit that could have an impact on total supply preservation:
Since Osmosis team did not change the permission policy regarding creating channels or any other aspect of ibc relaying, we consider this ics-20 property to be guaranteed. The only part of the audited code that could be considered connected to this property is the denomination creation on Osmosis chain (Denomination on receiver chain), which has been done in accordance to ics-20 specs, particularly the denom representation.
The ics-20 packet memo field is the key feature being used in the created Osmosis solution to swapping tokens. All the chains requesting the swap on Osmosis chain have to follow certain rules for creating memo field (json format, the exact key, etc.). If the memo field is included, the Osmosis chain does the appropriate validation of its format and data written in it. Other aspects of fungible token transfer changed on Osmosis chain include override of packet handling methods from ibc, but do not change the core ibc protocol (core ibc methods also called from the overridden ones). We consider these two points of the current design the crucial ones to guarantee the symmetry between the chains in terms of ibc fungible token transfer.
The issues discovered during this audit that could break this symmetry:
Prevents Byzantine-inflation of tokens originating on chain A, as a result of chain B's Byzantine behaviour (though any users who sent tokens to chain B may be at risk). In other words, Any byzantine chain B can’t influence the token circulation on chain A in any way, except the tokens that have been sent explicitly via token transfer from A to B. Wrt. those tokens anything can happen, and they may be lost under a byzantine behavior of B. The flow that occurs on Osmosis chain, which in this case acts as the receiving chain, can be observed in two phases: the ibc methods override and the execution of smart contracts. The methods from ibc that are overridden by Osmosis (OnRecvPacket(), SendPacket(), OnTimeoutPacket(), OnAcknowledgmentPacket()) mainly consist of validations of the received packet and its data and then sending the messages to smart contracts. No observable influence on chain A token circulation is confirmed, nor we found any during code inspection, integration, and e2e testing. The contract execution also has 2 steps: the crosschain swaps contract receives the message and forwards it to the swaprouter contract, whereas swaprouter contract does the actual swap. Since all these actions are contained on chain B (Osmosis chain in this case) we do not find them eligible to break the guarantee of Fault containment property.
Another point to carefully inspect was the fact that after the smart contracts are executed, a new ibc transfer is created and sent to chain A. Now, Osmosis chain acts as the sender chain, so the fault containment property should be guaranteed on chain A as well, in regards to the complete flow of send-swap-receive. However, chain A in this case is only responsible for keeping the format of the sending packet memo field and returning the appropriate response upon receiving the transfer from Osmosis chain. There is no particular processing of the received transfer on chain A, and it is also considered that the property of Fault containment is preserved.
To complete this phase in the most valuable way for the team, after consulting with some of the experts for ibc, fungible token transfer, and testing environments on local machines, the testing environment provided by Osmosis team was a bit tweaked, and a few additional steps added in order to execute the prepared test cases.
The setup for Osmosis swap provided could be improved with a few small changes:
- Defining the VALIDATOR address to avoid receiving errors for "non-existing key":
VALIDATOR=$(osmosisd keys show validator -a --keyring-backend test)
- The command to create pool on chain B (some errors also showed when using the provided command):
chainB tx gamm create-pool --pool-file sample_pool.json --from validator --yes -b block --keyring-backend test --gas auto --gas-prices 0.1uosmo --gas-adjustment 1.3
- Modify the message to instantiate crosschain contract:
MSG=$(jq --null-input \
--arg gov "$VALIDATOR" \
--arg sc "$SWAPROUTER_ADDRESS" \
--arg cid "$CHANNEL_ID" \
'{"governor":$gov, "swap_contract": $sc, "channels": [["osmo", $cid]]}')
- In order to be able to execute the relaying process manually, step by step (relay, receive, ack) we removed the automatic start of the relayer in the script osmosis/tests/localrelayer/scripts/setup_hermes.sh
echo "✉️ Start Hermes"
hermes start
- We added a sleep infinity, just to start the container, and leave the relaying actions for later manual execution:
echo "🔌 Keeping the container on"
echo "📬 Operate Hermes manually"
sleep infinity
- We used the Hermes CLI commands to send relaying transactions/queries. The explanation and various commands that can be used with hermes can be found here. The most commonly used ones are the following:
hermes query packet pending --chain localosmosis-b --port transfer --channel channel-0
hermes tx packet-recv --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel channel-0
hermes tx packet-ack --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel channel-0
hermes query transfer denom-trace --chain localosmosis-b --hash ED07A3391A112B175915CD8FAF43A2DA8E4790EDE12566649D0C2F97716B8518
hermes query tx events --chain localosmosis-b --hash AA1783800C810F5B8B00E8BF6161C32691BFFABF3D248137045C64FF0446D5FD
hermes listen --chain localosmosis-a
Besides using hermes manually, we also had some test cases where the idea was to simulate the unavailable relayer, or its failure. In these cases stopped the hermes docker container, while localosmosis and faucet containers were still running. This gave us an opportunity to observe the behaviour of a chain in different conditions when relayer is not available.
In addition, several log outputs, events, if conditions, and other code changes were added to the repo after which the complete enivronment was rebuilt to inspect the desired behaviours. In order to achieve this, the complete environment needs to be built from the ground up, and for this, we recomment using the following procedure:
- Delete both .osmosisd-local-a and .osmosisd-local-b folders created after the first build
- Delete all osmosis and hermes docker images
- Build the environment but instead of using make build, use:
DOCKER_BUILDKIT=1 docker-compose build --no-cache
Created test cases with short description and observed outputs are shown in the table below.
Description | Balances before |
Balances after |
Result | Commands list |
|
---|---|---|---|---|---|
1. | - SendTransfer - Stop Hermes - OnTimeoutPacket exec - OnRecvPacket not exec |
Sender: 9899976905uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000 : 1000000 Escrow: 100000000 |
Sender: 9899965837uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000 : 1000000 Escrow: 100000000 |
- timeout timestamp: 10s - gas: 11068 - sender: -11068 |
$MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"200","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver": $VALIDATOR, "on_failed_delivery": "do_nothing"}}}}') $chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 200uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" --packet-timeout-timestamp 10000000000 #hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" |
2. | - SendTransfer - OnRecvPacket Timeout - OnTimeoutPacket chain Ok - Stop Hermes - OnTimeoutPacket SC Fail - Start Hermes |
Sender: 9899958354uosmo, 6686ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1006800uosmo : 993314ibc Escrow: 100006800uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 9899947117uosmo, 6686ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1006800uosmo : 993314ibc Escrow: 100006800uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11237uosmo - sender: −11237uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"6900","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 6900uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" --packet-timeout-timestamp 30000000000 # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min - Timeout ~ Stop Hermes container ~ Sleep Over - Timeout ~ Start Hermes container |
3. | - SendTransfer - OnRecvPacket Failed - Stop Hermes - OnAckPacket(failed) not exec -Restart Hermes |
Sender: 9799887028uosmo : 294ibc Receiver IbcHooks: - Crosschain SC: 1000ibc Swaprouter SC: - Pool: 1000300ibc : 999706uosmo Escrow: 200001400uosmo |
Sender: 9799875567uosmo : 294ibc Receiver IbcHooks: - Crosschain SC: 1000ibc Swaprouter SC: - Pool: 1000300ibc : 999706uosmo Escrow: 200001400uosmo |
- gas: 10482 - VALIDATOR A: -11461 - VALIDATOR B: 0 - ESCROW: 0 |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"100","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 100uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" ~ 60s sleep before returning from OnRecvPacket |
4. | - SendTransfer - OnRecvPacket Timeout - Stop Hermes - OnTimeoutPacket not exec -Restart Hermes |
Sender: 9799840984uosmo : 392ibc Receiver IbcHooks: - Crosschain SC: 1000ibc Swaprouter SC: - Pool: 1000400ibc : 999608uosmo Escrow: 200001600uosmo |
Sender: 9799829523uosmo : 392ibc Receiver IbcHooks: - Crosschain SC: 1000ibc Swaprouter SC: - Pool: 1000400ibc : 999608uosmo Escrow: 200001700uosmo |
- gas: 11461 - VALIDATOR A: -11461 - VALIDATOR B: 0 - ESCROW: 0 |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"100","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 100uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" --packet-timeout-timestamp 30000000000 ~ 60s sleep > timeout ~ Hermes stopped |
5. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket router SC Fail before saving to SWAP_REPLY_STATES - Stop Hermes -Restart Hermes |
Sender: 4899976466uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899965194uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000111uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11161uosmo - sender: -11272uosmo - escrow +111uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +111uosmo Escrow -111uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"111","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": "do_nothing"}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 111uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
6. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket router SC Fail after saving to SWAP_REPLY_STATES - Stop Hermes -Restart Hermes |
Sender: 4899954144uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899942761uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000222uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11161uosmo - sender: -11383uosmo - escrow +222uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +222uosmo Escrow -222uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"222","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": "do_nothing"}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 222uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
7. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket router SC Fail on BankMsg:Send - Stop Hermes |
Sender: 98 ibs/hash | 4899976171 uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000100 ibc/hash | 999902 uosmo Escrow: 100000000 |
Sender: 98 ibs/hash | 4899964703 uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000100 ibc/hash | 999902 uosmo Escrow: 100000100 |
The memo is filled with a large number for swap amount. The transfer failed on calling contract execution. Tokens are left on escrow address. |
MEMO=$(jq --null-input --arg cc "$CROSSCHAIN_SWAPS_ADDRESS" --arg val "$VALIDATOR" '{"wasm": {"contract": $cc, "msg": {"osmosis_swap":{"swap_amount":"1000000000000","output_denom":"uosmo","slippage":{"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$val, "on_failed_delivery": "do_nothing"}}}}') chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 100uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" |
8. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC Fail before saving to SWAP_REPLY_STATES - Stop Hermes -Restart Hermes |
Sender: 4899942983uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899931489uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000333uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11161uosmo - sender: -11494uosmo - escrow +333uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +333uosmo Escrow -333uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"333","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": "do_nothing"}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 333uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
9. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC Fail after saving to SWAP_REPLY_STATES (and after deleting) - Stop Hermes -Restart Hermes |
Sender: 4899942983uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899942983uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11161uosmo - sender: -11494uosmo - escrow +333uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +333uosmo Escrow -333uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"1500","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": "do_nothing"}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 1500uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
10. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC Fail between two replies - Stop Hermes -Restart Hermes |
Sender: 4899898258uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899884515uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100002500uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11243uosmo - sender: −13743uosmo - escrow +2500uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +2500uosmo Escrow -2500uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"2500","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 2500uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
11. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC Fail in handle_forward_reply - Stop Hermes |
Sender: 4899887015uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899872272uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100003500uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11243uosmo - sender: −14743uosmo - escrow +3500uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +3500uosmo Escrow -3500uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"3500","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 3500uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container |
12. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC (ibc transfer M2) - Relay M2 - Ack M1 |
Sender: 4899987625uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo |
Sender: 4899976171uosmo | 98ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 999902uosmo : 1000100ibc Escrow: 100000100uosmo |
-gas: 11353 -sender: -11454uosmo -escrow: +100uosmo Sender received 98uosmo according to swap. Escrow balance increased by 100 uosmo. |
$MEMO=$(jq --null-input --arg cc "$CROSSCHAIN_SWAPS_ADDRESS" --arg val "$VALIDATOR" '{"wasm": {"contract": $cc, "msg": {"osmosis_swap":{"swap_amount":"100","output_denom":"uosmo","slippage":{"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$val, "on_failed_delivery": "do_nothing"}}}}') $chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 100uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" #hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel channel-0 #hermes tx packet-recv --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel channel-0 #hermes tx packet-ack --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel channel-0 #hermes tx packet-ack --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel channel-0 |
13. | - SendTransfer - OnRecvPacket Ok - OnAckPacket Ok - OnAckPacket SC Fail |
Sender: 9899987626uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 9899969591uosmo, 6686ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1006800uosmo : 993314ibc Escrow: 100006800uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11235uosmo - sender: −18035uosmo, +6686ibc - escrow +6800uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"6800","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 6800uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" # hermes tx packet-ack --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel "channel-0" |
14. | - SendTransfer - OnRecvPacket Ok - OnTimeoutPacket Ok - OnTimeoutPacket SC Fail |
Sender: 9899969591uosmo, 6686ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1006800uosmo : 993314ibc Escrow: 100006800uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 9899958354uosmo, 6686ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1006800uosmo : 993314ibc Escrow: 100006800uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11237uosmo - sender: −11237uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"6800","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 6800uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" --packet-timeout-timestamp 30000000000 # hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min |
15. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC (ibc transfer M2) Ok - … - Stop Hermes before Ack M2 - Ack M2 |
Sender: 4899976171uosmo | 98ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 999902uosmo : 1000100ibc Escrow: 100000100uosmo |
Sender: 4899964716uosmo | 196ibc Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 999804uosmo : 1000200ibc Escrow: 100000200uosmo |
Balances are checked after the hermes was stopped. - gas: 11354 - sender: -11455 - escrow: +100 After restarting hermes, ack is in unreceived acks. It can be relayed using manual commands. |
$MEMO=$(jq --null-input --arg cc "$CROSSCHAIN_SWAPS_ADDRESS" --arg val "$VALIDATOR" '{"wasm": {"contract": $cc, "msg": {"osmosis_swap":{"swap_amount":"100","output_denom":"uosmo","slippage":{"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$val, "on_failed_delivery": "do_nothing"}}}}') $chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 100uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" #hermes tx packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel channel-0 #hermes tx packet-ack --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel channel-0 #hermes tx packet-recv --dst-chain localosmosis-a --src-chain localosmosis-b --src-port transfer --src-channel channel-0 Stop hermes Restart hermes #hermes tx packet-ack --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel channel-0 |
16. | - SendTransfer - OnRecvPacket WasmHook Ok - OnRecvPacket Router SC Ok - OnRecvPacket Crosschain SC Fail in handle_forward_reply – LocalRecoveryAddr - Restart Hermes during OnRecvPacket |
Sender: 4899875772uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100000000uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
Sender: 4899861029uosmo Receiver IbcHooks: - Crosschain SC: - Swaprouter SC: - Pool: 1000000uosmo : 1000000ibc Escrow: 100003500uosmo Swap Reply State SR: - Swap Reply State CCS: - Forward Reply State CCS: - |
- gas: 11243uosmo - sender: −14743uosmo - escrow +3500uosmo After restarting Hermes, packet is in the unreceived packets. Balances: Sender +3500uosmo Escrow -3500uosmo |
$ MEMO=$(jenv -c '{"wasm": {"contract": $CROSSCHAIN_SWAPS_ADDRESS, "msg": {"osmosis_swap":{"swap_amount":"3500","output_denom":"uosmo","slippage": {"twap": {"slippage_percentage":"20", "window_seconds": 10}},"receiver":$VALIDATOR, "on_failed_delivery": {"local_recovery_addr":$VALIDATOR}}}}}') $ chainA tx ibc-transfer transfer transfer $CHANNEL_ID $CROSSCHAIN_SWAPS_ADDRESS 3500uosmo --from validator -y "${TX_FLAGS[@]}" --memo "$MEMO" # hermes tx <br>packet-recv --dst-chain localosmosis-b --src-chain localosmosis-a --src-port transfer --src-channel "channel-0" ~ Sleep 1min ~ Stop Hermes container ~ Start Hermes container ~ Sleep Over |