Skip to content

How to set up a new polytone connection

noah edited this page Dec 15, 2023 · 4 revisions

Setup

This is a guide to setting up a Polytone connection between two chains.

  1. Set up Hermes for each new chain by adding config to config.toml
[[chains]]
id = "<CHAIN_ID>"
type = "CosmosSdk"
rpc_addr = "<RPC>"
websocket_addr = "<WEBSOCKET>"
grpc_addr = "<GRPC>"
rpc_timeout = "10s"
batch_delay = "500ms"
trusted_node = false
account_prefix = "<BECH32_ADDRESS_PREFIX>"
key_name = "key"
key_store_type = "Test"
store_prefix = "ibc"
default_gas = 100000
max_gas = 4000000
gas_multiplier = 1.3
max_msg_num = 30
max_tx_size = 180000
max_grpc_decoding_size = 33554432
clock_drift = "5s"
max_block_time = "30s"
ccv_consumer_chain = false
memo_prefix = ""
sequential_batch_tx = false
gas_price = { price = 0.1, denom = "<NATIVE_DENOM>" }
trust_threshold = { numerator = "1", denominator = "3" }
address_type = { derivation = "cosmos" }

[chains.packet_filter]
policy = "allow"
list = []
  1. Add a key to Hermes for both chains
hermes keys add --key-name key --chain <chain_a_id> --mnemonic-file ./mnemonic
hermes keys add --key-name key --chain <chain_b_id> --mnemonic-file ./mnemonic
  1. Upload contracts to both chains
# Build Polytone contracts
git clone https://github.com/DA0-DA0/polytone
cd polytone
just optimize

# REPLACE BELOW:
# - BINARY
# - ADDRESS
# - DENOM

# Upload polytone contracts. Do this once for each chain.

for f in ./artifacts/*.wasm
do
  tx=$(BINARY tx wasm store $f --from ADDRESS --gas-prices 0.1DENOM --gas auto --gas-adjustment 2 --yes --output json | jq -r '.txhash')
  echo "$(basename $f) $tx"
  sleep 10
  code_id=$(BINARY query tx $tx --output json | jq -r '.logs[0].events[1].attributes[1].value')
  echo "$(basename $f) $code_id"
done
  1. Instantiate contracts on both chains
# REPLACE BELOW:
# - SRC_BINARY
# - DEST_BINARY

SRC_NOTE_CODE_ID=
SRC_LISTENER_CODE_ID=
SRC_ADDRESS=
SRC_GAS_PRICES=
SRC_CHAIN_ID=
SRC_BLOCK_MAX_GAS=

DEST_VOICE_CODE_ID=
DEST_PROXY_CODE_ID=
DEST_ADDRESS=
DEST_GAS_PRICES=
DEST_CHAIN_ID=
DEST_BLOCK_MAX_GAS=

# Source chain
echo "\n$SRC_CHAIN_ID\n"

## Note
NOTE_TX=$(SRC_BINARY tx wasm init $SRC_NOTE_CODE_ID "{\"block_max_gas\":\"$SRC_BLOCK_MAX_GAS\"}" --label "polytone_note_to_$DEST_CHAIN_ID" --no-admin --from $SRC_ADDRESS --gas-prices $SRC_GAS_PRICES --gas auto --gas-adjustment 2 --yes --output json | jq -r '.txhash')
echo "note: $NOTE_TX"
sleep 12
NOTE_CONTRACT=$(SRC_BINARY query tx $NOTE_TX --output json | jq -r '.logs[0].events[] | select(.type=="instantiate") | .attributes[] | select(.key=="_contract_address") | .value')
echo "note: $NOTE_CONTRACT"

## Listener
LISTENER_TX=$(SRC_BINARY tx wasm init $SRC_LISTENER_CODE_ID "{\"note\":\"$NOTE_CONTRACT\"}" --label "polytone_listener_from_$DEST_CHAIN_ID" --no-admin --from $SRC_ADDRESS --gas-prices $SRC_GAS_PRICES --gas auto --gas-adjustment 2 --yes --output json | jq -r '.txhash')
echo "listener: $LISTENER_TX"
sleep 12
LISTENER_CONTRACT=$(SRC_BINARY query tx $LISTENER_TX --output json | jq -r '.logs[0].events[] | select(.type=="instantiate") | .attributes[] | select(.key=="_contract_address") | .value')
echo "listener: $LISTENER_CONTRACT"

# Destination chain
echo "\n$DEST_CHAIN_ID\n"

## Voice
VOICE_TX=$(DEST_BINARY tx wasm init $DEST_VOICE_CODE_ID "{\"proxy_code_id\":\"$DEST_PROXY_CODE_ID\", \"block_max_gas\":\"$DEST_BLOCK_MAX_GAS\"}" --label "polytone_voice_from_$SRC_CHAIN_ID" --no-admin --from $DEST_ADDRESS --gas-prices $DEST_GAS_PRICES --gas auto --gas-adjustment 2 --yes --output json | jq -r '.txhash')
echo "voice: $VOICE_TX"
sleep 12
VOICE_CONTRACT=$(DEST_BINARY query tx $VOICE_TX --output json | jq -r '.logs[0].events[] | select(.type=="instantiate") | .attributes[] | select(.key=="_contract_address") | .value')
echo "voice: $VOICE_CONTRACT"
  1. Create channel between contracts

Ideally, find an existing highly-used connection between the chains. For example, between Juno and Osmosis, there is a primary transfer channel used for exchanging tokens. Because these channels are very active, their clients are unlikely to expire, and if they expire, many people will be motivated to reactivate them via governance. Thus, we can use the same connection these channels use for our new channel pair.

SRC_CHAIN_ID=
SRC_CONNECTION=
NOTE_CONTRACT=

VOICE_CONTRACT=

hermes create channel --a-chain $SRC_CHAIN_ID --a-connection $SRC_CONNECTION --a-port wasm.$NOTE_CONTRACT --b-port wasm.$VOICE_CONTRACT --channel-version polytone-1

OR in the event that we have to create a new connection:

SRC_CHAIN_ID=
NOTE_CONTRACT=

DEST_CHAIN_ID=
VOICE_CONTRACT=

hermes create channel --a-chain $SRC_CHAIN_ID --b-chain $DEST_CHAIN_ID --a-port wasm.$NOTE_CONTRACT --b-port wasm.$VOICE_CONTRACT --new-client-connection --channel-version polytone-1

When creating a new connection, you risk the light client expiring, which requires a governance proposal to restart it. To prevent this, you can use this keepalive script to update the clients periodically, keeping them alive.