From cf917e0cb2e432c9eccea5732ec34fc9ef7bb278 Mon Sep 17 00:00:00 2001 From: sampocs Date: Tue, 27 Aug 2024 15:42:13 -0500 Subject: [PATCH 1/3] bumped wasmd to v0.46 (#1274) --- go.mod | 4 ++-- go.sum | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/go.mod b/go.mod index 7e6698d4b0..be3697aca1 100644 --- a/go.mod +++ b/go.mod @@ -7,8 +7,8 @@ toolchain go1.21.3 require ( cosmossdk.io/errors v1.0.1 cosmossdk.io/math v1.3.0 - github.com/CosmWasm/wasmd v0.45.0 - github.com/CosmWasm/wasmvm v1.5.2 + github.com/CosmWasm/wasmd v0.46.0 + github.com/CosmWasm/wasmvm v1.5.4 github.com/Stride-Labs/ibc-rate-limiting v1.0.0 github.com/cometbft/cometbft v0.37.4 github.com/cometbft/cometbft-db v0.8.0 diff --git a/go.sum b/go.sum index 6d4357f63e..e3b794ab65 100644 --- a/go.sum +++ b/go.sum @@ -212,10 +212,10 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/ChainSafe/go-schnorrkel v1.0.0 h1:3aDA67lAykLaG1y3AOjs88dMxC88PgUuHRrLeDnvGIM= github.com/ChainSafe/go-schnorrkel v1.0.0/go.mod h1:dpzHYVxLZcp8pjlV+O+UR8K0Hp/z7vcchBSbMBEhCw4= -github.com/CosmWasm/wasmd v0.45.0 h1:9zBqrturKJwC2kVsfHvbrA++EN0PS7UTXCffCGbg6JI= -github.com/CosmWasm/wasmd v0.45.0/go.mod h1:RnSAiqbNIZu4QhO+0pd7qGZgnYAMBPGmXpzTADag944= -github.com/CosmWasm/wasmvm v1.5.2 h1:+pKB1Mz9GZVt1vadxB+EDdD1FOz3dMNjIKq/58/lrag= -github.com/CosmWasm/wasmvm v1.5.2/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= +github.com/CosmWasm/wasmd v0.46.0 h1:78kmiobbVE8JWBcM+ssxiFV2cS+4l9lmZQqPAQ0mA04= +github.com/CosmWasm/wasmd v0.46.0/go.mod h1:BZFz+CFGdLNGomshb3IeccFyD4R+XbnS/mXpytOUyTA= +github.com/CosmWasm/wasmvm v1.5.4 h1:Opqy65ubJ8bMsT08dn85VjRdsLJVPIAgIXif92qOMGc= +github.com/CosmWasm/wasmvm v1.5.4/go.mod h1:Q0bSEtlktzh7W2hhEaifrFp1Erx11ckQZmjq8FLCyys= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg= From 274c1038a908e8459d2c8aab839516319cfef496 Mon Sep 17 00:00:00 2001 From: sampocs Date: Tue, 27 Aug 2024 16:41:44 -0500 Subject: [PATCH 2/3] add admin address to integration test framework (#1276) ## Context Updated build step to swap out the admin address for the local version. --- integration-tests/Makefile | 8 +-- integration-tests/network/configs/keys.json | 1 + integration-tests/network/scripts/build.sh | 54 +++++++++++++++++++ integration-tests/network/scripts/config.sh | 1 + .../network/scripts/init-chain.sh | 2 + 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 integration-tests/network/scripts/build.sh diff --git a/integration-tests/Makefile b/integration-tests/Makefile index e7b105cfce..dbd5b93f00 100644 --- a/integration-tests/Makefile +++ b/integration-tests/Makefile @@ -10,7 +10,10 @@ PYTHON := $(VENV_BIN)/python HELM_CHART=network PLATFORM=linux/amd64 -GCR_REPO = gcr.io/stride-nodes/integration-tests +GCR_REPO=gcr.io/stride-nodes/integration-tests + +ADMINS_FILE=../utils/admins.go +KEYS_FILE=network/configs/keys.json # Builds and pushes a docker image # args: [image-file-suffix] [context] [image-name] @@ -56,8 +59,7 @@ build-api: $(call build_and_push_docker,api,api,api:latest) build-stride: - @$(DOCKER) buildx build --platform linux/amd64 --tag core:stride .. - $(call build_and_push_docker,stride,.,chains/stride:latest) + @bash network/scripts/build.sh stride build-cosmos: $(call build_and_push_docker,cosmos,.,chains/cosmoshub:v18.1.0) diff --git a/integration-tests/network/configs/keys.json b/integration-tests/network/configs/keys.json index 31c0ace230..44cfdb8dfa 100644 --- a/integration-tests/network/configs/keys.json +++ b/integration-tests/network/configs/keys.json @@ -2,6 +2,7 @@ "admin": { "name": "admin", + "address": "stride1u20df3trc2c2zdhm8qvh2hdjx9ewh00sv6eyy8", "mnemonic": "tone cause tribe this switch near host damage idle fragile antique tail soda alien depth write wool they rapid unfold body scan pledge soft" }, "faucet": { diff --git a/integration-tests/network/scripts/build.sh b/integration-tests/network/scripts/build.sh new file mode 100644 index 0000000000..b4bd76d20c --- /dev/null +++ b/integration-tests/network/scripts/build.sh @@ -0,0 +1,54 @@ +#!/bin/bash +set -eu + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +STRIDE_HOME=$SCRIPT_DIR/../../.. + +CHAIN=$1 + +PLATFORM=linux/amd64 +GCR_REPO=gcr.io/stride-nodes/integration-tests +ADMINS_FILE=${STRIDE_HOME}/utils/admins.go +KEYS_FILE=${STRIDE_HOME}/integration-tests/network/configs/keys.json +DOCKERFILES=${STRIDE_HOME}/integration-tests/dockerfiles + +# Builds and pushes a docker image to GCR +build_and_push_docker() { + dockerfile_suffix=$1 + context=$2 + image_name=$3 + + local_tag=stride-tests:$dockerfile_suffix + global_tag=$GCR_REPO/${image_name} + + echo "Building docker image: $dockerfile_suffix" + docker buildx build --platform $PLATFORM --tag $local_tag -f ${DOCKERFILES}/Dockerfile.$dockerfile_suffix $context + docker tag $local_tag $global_tag + + echo "Pushing image to GCR: $global_tag" + docker push $global_tag +} + +main() { + # For stride, we have to update the admin address + if [[ "$CHAIN" == "stride" ]]; then + # Trap SIGINT (Control + C) to cleanup admins file + trap 'echo "Interrupt received, cleaning up..."; git checkout -- $ADMINS_FILE && rm -f ${ADMINS_FILE}-E; exit' INT + + # Update the admin address + admin_address=$(jq -r '.admin.address' $KEYS_FILE) + sed -i -E "s|stride1k8c2m5cn322akk5wy8lpt87dd2f4yh9azg7jlh|$admin_address|g" $ADMINS_FILE + + # First build the main dockerfile in the repo root, then build the integration test specific file + docker buildx build --platform linux/amd64 --tag core:stride .. + build_and_push_docker stride . chains/stride:latest + + # Cleanup the admins file + git checkout -- $ADMINS_FILE && rm -f ${ADMINS_FILE}-E + else + echo "ERROR: Chain not supported" + exit 1 + fi +} + +main diff --git a/integration-tests/network/scripts/config.sh b/integration-tests/network/scripts/config.sh index ff96626524..5c54723e46 100644 --- a/integration-tests/network/scripts/config.sh +++ b/integration-tests/network/scripts/config.sh @@ -27,6 +27,7 @@ DEPOSIT_PERIOD="30s" VOTING_PERIOD="30s" EXPEDITED_VOTING_PERIOD="29s" UNBONDING_TIME="240s" +AIRDROP_PERIOD_SECONDS=86400 STRIDE_DAY_EPOCH_DURATION="140s" STRIDE_EPOCH_EPOCH_DURATION="35s" \ No newline at end of file diff --git a/integration-tests/network/scripts/init-chain.sh b/integration-tests/network/scripts/init-chain.sh index 3169c0421c..f23a7ad9da 100644 --- a/integration-tests/network/scripts/init-chain.sh +++ b/integration-tests/network/scripts/init-chain.sh @@ -139,6 +139,8 @@ update_stride_genesis() { $BINARY add-consumer-section --validator-public-keys $validator_public_keys jq_inplace '.app_state.ccvconsumer.params.unbonding_period |= "'$UNBONDING_TIME'"' $genesis_json + + jq_inplace '.app_state.airdrop.params.period_length_seconds |= "'${AIRDROP_PERIOD_LENGTH}'"' $genesis_json } # Genesis updates specific to non-stride chains From 930d4ebd26e1aee4051f3fcef15c7bbcdcfeab42 Mon Sep 17 00:00:00 2001 From: sampocs Date: Tue, 27 Aug 2024 19:23:37 -0500 Subject: [PATCH 3/3] removed autopilot support for metadata in receiver and increased memo lengths (#1273) --- deps/gaia | 2 +- dockernet/config/relayer_config_stride.yaml | 2 +- dockernet/dockerfiles/Dockerfile.gaia | 19 ++++-- dockernet/src/init_chain.sh | 21 +++--- dockernet/src/register_host.sh | 2 +- dockernet/tests/integration_tests.bats | 46 +++++-------- x/autopilot/README.md | 42 +++++++----- x/autopilot/keeper/airdrop_test.go | 72 +++++++++------------ x/autopilot/keeper/liquidstake_test.go | 54 +++++----------- x/autopilot/keeper/redeem_stake_test.go | 41 ++++++++---- x/autopilot/module_ibc.go | 36 ++++++----- x/autopilot/types/errors.go | 3 +- 12 files changed, 165 insertions(+), 175 deletions(-) diff --git a/deps/gaia b/deps/gaia index 3b9a281247..58b4e54a95 160000 --- a/deps/gaia +++ b/deps/gaia @@ -1 +1 @@ -Subproject commit 3b9a281247ab9bd87483ad7fc1dcea9f26c4b8f6 +Subproject commit 58b4e54a95c7fc6a64272ccd0f09f46213c005ad diff --git a/dockernet/config/relayer_config_stride.yaml b/dockernet/config/relayer_config_stride.yaml index 02f6d0f51d..c31b73a1d0 100644 --- a/dockernet/config/relayer_config_stride.yaml +++ b/dockernet/config/relayer_config_stride.yaml @@ -29,7 +29,7 @@ chains: account-prefix: cosmos keyring-backend: test gas-adjustment: 1.3 - gas-prices: 0.02uatom + gas-prices: 1ufee coin-type: 118 debug: false timeout: 20s diff --git a/dockernet/dockerfiles/Dockerfile.gaia b/dockernet/dockerfiles/Dockerfile.gaia index 7b09562a30..6daf4c83e6 100644 --- a/dockernet/dockerfiles/Dockerfile.gaia +++ b/dockernet/dockerfiles/Dockerfile.gaia @@ -1,17 +1,24 @@ -FROM golang:1.20-alpine3.16 AS builder +FROM golang:1.22-alpine AS builder WORKDIR /opt -RUN apk add --update curl make git libc-dev bash gcc linux-headers eudev-dev python3 +RUN apk add --update curl make git libc-dev bash gcc linux-headers eudev-dev ca-certificates build-base git -ENV COMMIT_HASH=v12.0.0-rc0 +ENV COMMIT_HASH=v18.1.0 RUN git clone https://github.com/cosmos/gaia \ && cd gaia \ - && git checkout $COMMIT_HASH \ - && CGO_ENABLED=0 make install + && git checkout $COMMIT_HASH -FROM alpine:3.16 +WORKDIR /opt/gaia + +RUN WASMVM_VERSION=$(cat go.mod | grep github.com/CosmWasm/wasmvm | awk '{print $2}') \ + && wget https://github.com/CosmWasm/wasmvm/releases/download/$WASMVM_VERSION/libwasmvm_muslc.$(uname -m).a \ + -O /lib/libwasmvm_muslc.a + +RUN CGO_ENABLED=1 BUILD_TAGS="muslc linkstatic" LINK_STATICALLY=true LEDGER_ENABLED=false make install + +FROM alpine:3.17 COPY --from=builder /go/bin/gaiad /usr/local/bin/ RUN apk add bash vim \ && addgroup -g 1000 gaia \ diff --git a/dockernet/src/init_chain.sh b/dockernet/src/init_chain.sh index 7154064021..dfc68e105a 100644 --- a/dockernet/src/init_chain.sh +++ b/dockernet/src/init_chain.sh @@ -28,6 +28,9 @@ STAKE_TOKENS=${STAKE_TOKENS}${MICRO_DENOM_UNITS} ADMIN_TOKENS=${ADMIN_TOKENS}${MICRO_DENOM_UNITS} USER_TOKENS=${USER_TOKENS}${MICRO_DENOM_UNITS} +FEES=1000000000ufee +GENESIS_CMD=$($BINARY 2>&1 | grep -q "genesis-related subcommands" && echo "genesis" || echo "") + set_stride_epochs() { genesis_config=$1 @@ -127,11 +130,13 @@ set_host_genesis() { sed -i -E 's|"downtime_jail_duration": "600s"|"downtime_jail_duration": "10s"|g' $genesis_config sed -i -E 's|"slash_fraction_downtime": "0.010000000000000000"|"slash_fraction_downtime": "0.050000000000000000"|g' $genesis_config - # LSM params + # LSM and feemarket params if [[ "$CHAIN" == "GAIA" ]]; then jq '.app_state.staking.params.validator_bond_factor = $newVal' --arg newVal "$LSM_VALIDATOR_BOND_FACTOR" $genesis_config > json.tmp && mv json.tmp $genesis_config jq '.app_state.staking.params.validator_liquid_staking_cap = $newVal' --arg newVal "$LSM_VALIDATOR_LIQUID_STAKING_CAP" $genesis_config > json.tmp && mv json.tmp $genesis_config jq '.app_state.staking.params.global_liquid_staking_cap = $newVal' --arg newVal "$LSM_GLOBAL_LIQUID_STAKING_CAP" $genesis_config > json.tmp && mv json.tmp $genesis_config + + jq '.app_state.feemarket.params.fee_denom = $newVal' --arg newVal "ufee" $genesis_config > json.tmp && mv json.tmp $genesis_config fi } @@ -161,7 +166,7 @@ add_genesis_account() { create_account "$account_name" "$mnemonic" address=$($MAIN_CMD keys show $account_name --keyring-backend test -a | tr -cd '[:alnum:]._-') - $MAIN_CMD add-genesis-account ${address} ${amount}${DENOM} + $MAIN_CMD $GENESIS_CMD add-genesis-account ${address} ${amount}${DENOM},${FEES} } MAIN_ID=1 # Node responsible for genesis and persistent_peers @@ -225,7 +230,7 @@ for (( i=1; i <= $NUM_NODES; i++ )); do if [[ "$CHAIN" == "NOBLE" ]]; then genesis_coins=${genesis_coins},${VAL_TOKENS}${USDC_DENOM} fi - $cmd add-genesis-account ${val_addr} ${genesis_coins} + $cmd $GENESIS_CMD add-genesis-account ${val_addr} ${genesis_coins},${FEES} # Copy over the provider stride validator keys to the provider (in the event # that we are testing ICS) @@ -238,7 +243,7 @@ for (( i=1; i <= $NUM_NODES; i++ )); do # Only generate the validator txs for host chains if [[ "$CHAIN" != "STRIDE" && "$CHAIN" != "HOST" ]]; then - $cmd gentx $val_acct ${STAKE_TOKENS}${DENOM} --chain-id $CHAIN_ID --keyring-backend test &> /dev/null + $cmd $GENESIS_CMD gentx $val_acct ${STAKE_TOKENS}${DENOM} --chain-id $CHAIN_ID --keyring-backend test &> /dev/null fi # Get the endpoint and node ID @@ -257,7 +262,7 @@ for (( i=1; i <= $NUM_NODES; i++ )); do MAIN_GENESIS=$genesis_json else # also add this account and it's genesis tx to the main node - $MAIN_CMD add-genesis-account ${val_addr} ${VAL_TOKENS}${DENOM} + $MAIN_CMD $GENESIS_CMD add-genesis-account ${val_addr} ${VAL_TOKENS}${DENOM},${FEES} if [ -d "${STATE}/${node_name}/config/gentx" ]; then cp ${STATE}/${node_name}/config/gentx/*.json ${STATE}/${MAIN_NODE_NAME}/config/gentx/ fi @@ -319,7 +324,7 @@ else if [ "$CHAIN" == "NOBLE" ]; then echo "$NOBLE_AUTHORITHY_MNEMONIC" | $MAIN_CMD keys add authority --recover --keyring-backend test >> $KEYS_LOGS 2>&1 AUTHORITHY_ADDRESS=$($MAIN_CMD keys show authority --keyring-backend test -a | tr -cd '[:alnum:]._-') - $MAIN_CMD add-genesis-account ${AUTHORITHY_ADDRESS} ${VAL_TOKENS}${DENOM},${VAL_TOKENS}${USDC_DENOM} + $MAIN_CMD $GENESIS_CMD add-genesis-account ${AUTHORITHY_ADDRESS} ${VAL_TOKENS}${DENOM},${VAL_TOKENS}${USDC_DENOM} sed -i -E 's|"authority": ""|"authority":"'${AUTHORITHY_ADDRESS}'"|g' $genesis_json sed -i -E 's|"mintingDenom": null|"mintingDenom":{"denom":"'${DENOM}'"}|g' $genesis_json @@ -335,12 +340,12 @@ fi # the account should live on both stride and the host chain echo "$USER_MNEMONIC" | $MAIN_CMD keys add $USER_ACCT --recover --keyring-backend=test >> $KEYS_LOGS 2>&1 USER_ADDRESS=$($MAIN_CMD keys show $USER_ACCT --keyring-backend test -a) -$MAIN_CMD add-genesis-account ${USER_ADDRESS} ${USER_TOKENS}${DENOM} +$MAIN_CMD $GENESIS_CMD add-genesis-account ${USER_ADDRESS} ${USER_TOKENS}${DENOM},${FEES} # Only collect the validator genesis txs for host chains if [[ "$CHAIN" != "STRIDE" && "$CHAIN" != "HOST" ]]; then # now we process gentx txs on the main node - $MAIN_CMD collect-gentxs &> /dev/null + $MAIN_CMD $GENESIS_CMD collect-gentxs &> /dev/null fi # wipe out the persistent peers for the main node (these are incorrectly autogenerated for each validator during collect-gentxs) diff --git a/dockernet/src/register_host.sh b/dockernet/src/register_host.sh index e1c9220cb4..3562063e73 100644 --- a/dockernet/src/register_host.sh +++ b/dockernet/src/register_host.sh @@ -55,7 +55,7 @@ for (( i=1; i <= $NUM_VALS; i++ )); do if [[ "$i" == "1" ]]; then echo "$CHAIN - Submitting validator bonds..." fi - $GAIA_MAIN_CMD tx staking validator-bond $delegate_val --from ${VAL_PREFIX}${i} -y | TRIM_TX + $GAIA_MAIN_CMD tx staking validator-bond $delegate_val --from ${VAL_PREFIX}${i} -y --fees 1000000ufee | TRIM_TX fi done diff --git a/dockernet/tests/integration_tests.bats b/dockernet/tests/integration_tests.bats index 486bda787f..8bf4c9bec6 100644 --- a/dockernet/tests/integration_tests.bats +++ b/dockernet/tests/integration_tests.bats @@ -41,6 +41,8 @@ setup_file() { REDEEM_AMOUNT=10000 PACKET_FORWARD_STAKE_AMOUNT=300000 + HOST_FEES="--fees 1000000ufee" + # HELPER FUNCTIONS DECADD () { echo "scale=2; $1+$2" | bc @@ -98,7 +100,7 @@ setup_file() { # do IBC transfer $STRIDE_MAIN_CMD tx ibc-transfer transfer transfer $STRIDE_TRANSFER_CHANNEL $HOST_VAL_ADDRESS ${TRANSFER_AMOUNT}${STRIDE_DENOM} --from $STRIDE_VAL -y - $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL $(STRIDE_ADDRESS) ${TRANSFER_AMOUNT}${HOST_DENOM} --from $HOST_VAL -y + $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL $(STRIDE_ADDRESS) ${TRANSFER_AMOUNT}${HOST_DENOM} --from $HOST_VAL -y $HOST_FEES WAIT_FOR_BLOCK $STRIDE_LOGS 8 @@ -177,11 +179,11 @@ setup_file() { validator_address=$(GET_VAL_ADDR $CHAIN_NAME 1) # delegate on the host chain - $HOST_MAIN_CMD tx staking delegate $validator_address ${TRANSFER_AMOUNT}${HOST_DENOM} --from $USER_ACCT -y + $HOST_MAIN_CMD tx staking delegate $validator_address ${TRANSFER_AMOUNT}${HOST_DENOM} --from $USER_ACCT -y $HOST_FEES WAIT_FOR_BLOCK $STRIDE_LOGS 2 # tokenize shares - $HOST_MAIN_CMD tx staking tokenize-share $validator_address ${TRANSFER_AMOUNT}${HOST_DENOM} $staker_address_on_host --from $USER_ACCT -y --gas 1000000 + $HOST_MAIN_CMD tx staking tokenize-share $validator_address ${TRANSFER_AMOUNT}${HOST_DENOM} $staker_address_on_host --from $USER_ACCT -y --gas 1000000 $HOST_FEES WAIT_FOR_BLOCK $STRIDE_LOGS 2 # get the record id from the tokenized share record @@ -190,7 +192,7 @@ setup_file() { # transfer LSM tokens to stride lsm_token_denom=${validator_address}/${record_id} $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL \ - $staker_address_on_stride ${TRANSFER_AMOUNT}${lsm_token_denom} --from $USER_ACCT -y + $staker_address_on_stride ${TRANSFER_AMOUNT}${lsm_token_denom} --from $USER_ACCT -y $HOST_FEES WAIT_FOR_BLOCK $STRIDE_LOGS 8 @@ -257,14 +259,8 @@ setup_file() { sttoken_balance_start=$($STRIDE_MAIN_CMD q bank balances $(STRIDE_ADDRESS) --denom st$HOST_DENOM | GETBAL) # Send the IBC transfer with the JSON memo - transfer_msg_prefix="$HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL" - if [[ "$CHAIN_NAME" == "GAIA" ]]; then - # For GAIA (ibc-v3), pass the memo into the receiver field - $transfer_msg_prefix "$memo" ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --from $HOST_VAL -y - else - # For all other hosts (ibc-v5), pass an address for a receiver and the memo in the --memo field - $transfer_msg_prefix $(STRIDE_ADDRESS) ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --memo "$memo" --from $HOST_VAL -y - fi + $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL \ + $(STRIDE_ADDRESS) ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --memo "$memo" --from $HOST_VAL -y $HOST_FEES # Wait for the transfer to complete WAIT_FOR_BALANCE_CHANGE STRIDE $(STRIDE_ADDRESS) st$HOST_DENOM @@ -282,14 +278,8 @@ setup_file() { stibctoken_balance_start=$($HOST_MAIN_CMD q bank balances $HOST_VAL_ADDRESS --denom $IBC_STTOKEN 2>/dev/null | GETBAL) # Send the IBC transfer with the JSON memo - transfer_msg_prefix="$HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL" - if [[ "$CHAIN_NAME" == "GAIA" ]]; then - # For GAIA (ibc-v3), pass the memo into the receiver field - $transfer_msg_prefix "$memo" ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --from $HOST_VAL -y - else - # For all other hosts (ibc-v5), pass an address for a receiver and the memo in the --memo field - $transfer_msg_prefix $(STRIDE_ADDRESS) ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --memo "$memo" --from $HOST_VAL -y - fi + $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL \ + $(STRIDE_ADDRESS) ${PACKET_FORWARD_STAKE_AMOUNT}${HOST_DENOM} --memo "$memo" --from $HOST_VAL -y $HOST_FEES # Wait for the transfer to complete WAIT_FOR_BALANCE_CHANGE $CHAIN_NAME $HOST_VAL_ADDRESS $IBC_STTOKEN @@ -312,14 +302,10 @@ setup_file() { memo='{ "autopilot": { "receiver": "'"$(STRIDE_ADDRESS)"'", "stakeibc": { "action": "RedeemStake", "ibc_receiver": "'$HOST_RECEIVER_ADDRESS'" } } }' # do IBC transfer - transfer_msg_prefix="$HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL" - if [[ "$CHAIN_NAME" == "GAIA" ]]; then - # For GAIA (ibc-v3), pass the memo into the receiver field - $transfer_msg_prefix "$memo" ${REDEEM_AMOUNT}${IBC_STTOKEN} --from $HOST_VAL -y - else - # For all other hosts (ibc-v5), pass an address for a receiver and the memo in the --memo field - $transfer_msg_prefix $(STRIDE_ADDRESS) ${REDEEM_AMOUNT}${IBC_STTOKEN} --memo "$memo" --from $HOST_VAL -y - fi + # For all other hosts (ibc-v5), pass an address for a receiver and the memo in the --memo field + $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL \ + $(STRIDE_ADDRESS) ${REDEEM_AMOUNT}${IBC_STTOKEN} --memo "$memo" --from $HOST_VAL -y $HOST_FEES + WAIT_FOR_BLOCK $STRIDE_LOGS 2 # make sure stATOM balance decreased @@ -336,7 +322,9 @@ setup_file() { # attempt to redeem with an invalid receiver address to invoke a failure invalid_memo='{ "autopilot": { "receiver": "'"$(STRIDE_ADDRESS)"'", "stakeibc": { "action": "RedeemStake", "ibc_receiver": "XXX" } } }' - $transfer_msg_prefix "$invalid_memo" ${REDEEM_AMOUNT}${IBC_STTOKEN} --from $HOST_VAL -y + $HOST_MAIN_CMD tx ibc-transfer transfer transfer $HOST_TRANSFER_CHANNEL \ + $(STRIDE_ADDRESS) ${REDEEM_AMOUNT}${IBC_STTOKEN} --memo "$invalid_memo" --from $HOST_VAL -y $HOST_FEES + WAIT_FOR_BLOCK $STRIDE_LOGS 10 # Confirm the stATOM balance was refunded diff --git a/x/autopilot/README.md b/x/autopilot/README.md index 8ae0b87f20..1c4484b5b4 100644 --- a/x/autopilot/README.md +++ b/x/autopilot/README.md @@ -15,40 +15,48 @@ With current implementation of Autopilot module, it supports: Note: This will support more functions that can reduce number of users' operations. ## Memo -### Format + +### Format + ```json -{ - "autopilot": { - "receiver": "strideXXX", - "{module_name}": { "{additiional_field}": "{value}" } - } +{ + "autopilot": { + "receiver": "strideXXX", + "{module_name}": { "{additiional_field}": "{value}" } + } } ``` ### Example (1-Click Liquid Stake) + ```json -{ - "autopilot": { - "receiver": "strideXXX", - "stakeibc": { - "action": "LiquidStake", - } +{ + "autopilot": { + "receiver": "strideXXX", + "stakeibc": { + "action": "LiquidStake" } + } } ``` + ### Example (Update Airdrop Address) + ```json -{ - "autopilot": { - "receiver": "strideXXX", - "claim": {} - } +{ + "autopilot": { + "receiver": "strideXXX", + "claim": {} + } } ``` ### A Note on Parsing + Since older versions of IBC do not have a `Memo` field, they must pass the routing information in the `Receiver` attribute of the IBC packet. To make autopilot backwards compatible with all older IBC versions, the receiver address must be specified in the JSON string. Before passing the packet down the stack to the transfer module, the address in the JSON string will replace the `Receiver` field in the packet data, regardless of the IBC version. +The module also enforces a maximum length for both the `Memo` and `Receiver` fields of 4000 and 100 characters respectively. + ## Params ``` diff --git a/x/autopilot/keeper/airdrop_test.go b/x/autopilot/keeper/airdrop_test.go index a5c92808ab..166f2dc526 100644 --- a/x/autopilot/keeper/airdrop_test.go +++ b/x/autopilot/keeper/airdrop_test.go @@ -51,6 +51,7 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { // in the transfer packet - so for the sake of this test, we'll use arbitrary stride addresses strideAccAddress := s.TestAccs[0] strideAddress := strideAccAddress.String() + differentAddress := s.TestAccs[1].String() // Build the template for the transfer packet (the data and channel fields will get updated from each unit test) packetTemplate := channeltypes.Packet{ @@ -82,21 +83,21 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { airdropShouldUpdate bool }{ { - name: "successful airdrop update from receiver", + name: "successful airdrop update", autopilotClaimActive: true, autopilotClaimEnabledForHost: true, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: strideAddress, + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: true, airdropShouldUpdate: true, }, { - name: "successful airdrop update from memo", - autopilotClaimActive: true, + name: "valid routing schema, but routing inactive", + autopilotClaimActive: false, autopilotClaimEnabledForHost: true, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, @@ -104,70 +105,57 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { Receiver: strideAddress, Memo: getClaimPacketMetadata(strideAddress), }, - transferShouldSucceed: true, - airdropShouldUpdate: true, + transferShouldSucceed: false, + airdropShouldUpdate: false, }, { - name: "memo receiver overrides original receiver field", + name: "valid routing schema, but routing inactive for airdrop", autopilotClaimActive: true, - autopilotClaimEnabledForHost: true, + autopilotClaimEnabledForHost: false, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: "address-will-get-overriden", + Receiver: strideAddress, Memo: getClaimPacketMetadata(strideAddress), }, - transferShouldSucceed: true, - airdropShouldUpdate: true, - }, - { - name: "valid receiver routing schema, but routing inactive", - autopilotClaimActive: false, - autopilotClaimEnabledForHost: true, - destinationChannelID: ibctesting.FirstChannelID, - destinationPortID: transfertypes.PortID, - packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", - }, transferShouldSucceed: false, airdropShouldUpdate: false, }, { - name: "valid receiver routing schema, but routing inactive for airdrop", + name: "invalid stride address in memo", autopilotClaimActive: true, - autopilotClaimEnabledForHost: false, + autopilotClaimEnabledForHost: true, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: strideAddress, + Memo: getClaimPacketMetadata("invalid_address"), }, transferShouldSucceed: false, airdropShouldUpdate: false, }, { - name: "valid memo routing schema, but routing inactive", - autopilotClaimActive: false, + name: "invalid stride address in receiver", + autopilotClaimActive: true, autopilotClaimEnabledForHost: true, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: "invalid-address", + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: false, airdropShouldUpdate: false, }, { - name: "invalid stride address", + name: "memo receiver doesn't match transfer receiver", autopilotClaimActive: true, autopilotClaimEnabledForHost: true, destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: strideAddress, - Memo: getClaimPacketMetadata("invalid_address"), + Receiver: differentAddress, + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: false, airdropShouldUpdate: false, @@ -245,7 +233,7 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ Receiver: strideAddress, - Memo: strings.Repeat("X", 2001), + Memo: strings.Repeat("X", 4001), }, transferShouldSucceed: false, airdropShouldUpdate: false, @@ -257,7 +245,7 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { destinationChannelID: ibctesting.FirstChannelID, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: strings.Repeat("X", 300), + Receiver: strings.Repeat("X", 101), Memo: "", }, transferShouldSucceed: false, @@ -270,8 +258,8 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { destinationChannelID: ibctesting.FirstChannelID, destinationPortID: "invalid_port", packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: strideAddress, + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: false, airdropShouldUpdate: false, @@ -283,8 +271,8 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { destinationChannelID: channelIdForDifferentHostZone, destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: strideAddress, + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: false, airdropShouldUpdate: false, @@ -296,8 +284,8 @@ func (s *KeeperTestSuite) TestAirdropOnRecvPacket() { destinationChannelID: "channel-XXX", destinationPortID: transfertypes.PortID, packetData: transfertypes.FungibleTokenPacketData{ - Receiver: getClaimPacketMetadata(strideAddress), - Memo: "", + Receiver: strideAddress, + Memo: getClaimPacketMetadata(strideAddress), }, transferShouldSucceed: false, airdropShouldUpdate: false, diff --git a/x/autopilot/keeper/liquidstake_test.go b/x/autopilot/keeper/liquidstake_test.go index d3ffba555c..57ac62a952 100644 --- a/x/autopilot/keeper/liquidstake_test.go +++ b/x/autopilot/keeper/liquidstake_test.go @@ -320,6 +320,7 @@ func (s *KeeperTestSuite) TestTryLiquidStake() { func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { liquidStakerOnStride := s.TestAccs[0] depositAddress := s.TestAccs[1] + differentAddress := s.TestAccs[2].String() forwardRecipientOnHost := HostAddress stakeAmount := sdk.NewInt(1000000) @@ -337,16 +338,7 @@ func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { expectedLiquidStake bool }{ { - name: "successful liquid stake with metadata in receiver", - enabled: true, - liquidStakeDenom: Atom, - transferReceiver: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), "", ""), - transferMemo: "", - expectedSuccess: true, - expectedLiquidStake: true, - }, - { - name: "successful liquid stake with metadata in the memo", + name: "successful liquid stake", enabled: true, liquidStakeDenom: Atom, transferReceiver: liquidStakerOnStride.String(), @@ -355,17 +347,7 @@ func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { expectedLiquidStake: true, }, { - name: "successful liquid stake and forward to default host (receiver)", - enabled: true, - liquidStakeDenom: Atom, - transferReceiver: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), forwardRecipientOnHost, ""), - transferMemo: "", - expectedForwardChannelId: ibctesting.FirstChannelID, - expectedSuccess: true, - expectedLiquidStake: true, - }, - { - name: "successful liquid stake and forward to default host (memo)", + name: "successful liquid stake and forward to default host", enabled: true, liquidStakeDenom: Atom, transferReceiver: liquidStakerOnStride.String(), @@ -375,19 +357,7 @@ func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { expectedLiquidStake: true, }, { - name: "successful liquid stake and forward to custom transfer channel (receiver)", - enabled: true, - liquidStakeDenom: Atom, - transferReceiver: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), forwardRecipientOnHost, "channel-0"), - transferMemo: "", - hostZoneChannelID: "channel-1", - inboundTransferChannnelId: "channel-1", - expectedForwardChannelId: "channel-0", // different than host zone, specified in memo - expectedSuccess: true, - expectedLiquidStake: true, - }, - { - name: "successful liquid stake and forward to custom transfer channel (memo)", + name: "successful liquid stake and forward to custom transfer channel", enabled: true, liquidStakeDenom: Atom, transferReceiver: liquidStakerOnStride.String(), @@ -431,6 +401,14 @@ func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { transferMemo: getLiquidStakePacketMetadata("XXX", "", ""), expectedSuccess: false, }, + { + name: "memo and transfer address mismatch", + enabled: true, + liquidStakeDenom: Osmo, + transferReceiver: liquidStakerOnStride.String(), + transferMemo: getLiquidStakePacketMetadata(differentAddress, "", ""), + expectedSuccess: false, + }, { name: "not host denom", enabled: true, @@ -443,16 +421,16 @@ func (s *KeeperTestSuite) TestOnRecvPacket_LiquidStake() { name: "failed to outbound transfer", enabled: true, liquidStakeDenom: Atom, - transferReceiver: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), forwardRecipientOnHost, "channel-999"), // channel DNE - transferMemo: "", + transferReceiver: liquidStakerOnStride.String(), + transferMemo: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), forwardRecipientOnHost, "channel-999"), // channel DNE expectedSuccess: false, }, { name: "valid uatom token from invalid channel", enabled: true, liquidStakeDenom: Atom, - transferReceiver: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), "", ""), - transferMemo: "", + transferReceiver: liquidStakerOnStride.String(), + transferMemo: getLiquidStakePacketMetadata(liquidStakerOnStride.String(), "", ""), hostZoneChannelID: "channel-0", inboundTransferChannnelId: "channel-999", // channel DNE expectedSuccess: false, diff --git a/x/autopilot/keeper/redeem_stake_test.go b/x/autopilot/keeper/redeem_stake_test.go index 57a47efc09..7b85c9e082 100644 --- a/x/autopilot/keeper/redeem_stake_test.go +++ b/x/autopilot/keeper/redeem_stake_test.go @@ -298,6 +298,7 @@ func (s *KeeperTestSuite) TestTryRedeemStake() { func (s *KeeperTestSuite) TestOnRecvPacket_RedeemStake() { redeemerOnStride := s.TestAccs[0] depositAddress := s.TestAccs[1] + differentAddress := s.TestAccs[2].String() redeemerOnHost := HostAddress redeemAmount := sdk.NewInt(1000000) @@ -323,20 +324,20 @@ func (s *KeeperTestSuite) TestOnRecvPacket_RedeemStake() { expSuccess bool }{ { - name: "successful redemption with metadata in receiver", + name: "successful redemption", enabled: true, packetData: transfertypes.FungibleTokenPacketData{ Denom: stAtomTrace, Amount: redeemAmount.String(), Sender: redeemerOnHost, - Receiver: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), - Memo: "", + Receiver: redeemerOnStride.String(), + Memo: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), }, expSuccess: true, }, { - name: "successful redemption with metadata in memo", - enabled: true, + name: "failed because param not enabled", + enabled: false, packetData: transfertypes.FungibleTokenPacketData{ Denom: stAtomTrace, Amount: redeemAmount.String(), @@ -344,29 +345,41 @@ func (s *KeeperTestSuite) TestOnRecvPacket_RedeemStake() { Receiver: redeemerOnStride.String(), Memo: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), }, - expSuccess: true, + expSuccess: false, }, { - name: "failed because param not enabled", - enabled: false, + name: "failed because invalid stride address in memo", + enabled: true, packetData: transfertypes.FungibleTokenPacketData{ Denom: stAtomTrace, Amount: redeemAmount.String(), - Sender: redeemerOnHost, - Receiver: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), - Memo: "", + Sender: "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", + Receiver: redeemerOnStride.String(), + Memo: getRedeemStakeStakeibcPacketMetadata("XXX", redeemerOnHost), }, expSuccess: false, }, { - name: "failed because invalid stride address", + name: "failed because invalid stride address in reciever", enabled: true, packetData: transfertypes.FungibleTokenPacketData{ Denom: stAtomTrace, Amount: redeemAmount.String(), Sender: "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", - Receiver: getRedeemStakeStakeibcPacketMetadata("XXX", redeemerOnHost), - Memo: "", + Receiver: "XXX", + Memo: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), + }, + expSuccess: false, + }, + { + name: "failed because transfer receiver address does not match memo receiver", + enabled: true, + packetData: transfertypes.FungibleTokenPacketData{ + Denom: stAtomTrace, + Amount: redeemAmount.String(), + Sender: "cosmos16plylpsgxechajltx9yeseqexzdzut9g8vla4k", + Receiver: differentAddress, + Memo: getRedeemStakeStakeibcPacketMetadata(redeemerOnStride.String(), redeemerOnHost), }, expSuccess: false, }, diff --git a/x/autopilot/module_ibc.go b/x/autopilot/module_ibc.go index e712aceadf..85937b9f48 100644 --- a/x/autopilot/module_ibc.go +++ b/x/autopilot/module_ibc.go @@ -17,7 +17,10 @@ import ( ibcexported "github.com/cosmos/ibc-go/v7/modules/core/exported" ) -const MaxMemoCharLength = 2000 +const ( + MaxMemoCharLength = 4000 + MaxReceiverCharLength = 100 +) // IBC MODULE IMPLEMENTATION // IBCModule implements the ICS26 interface for transfer given the transfer keeper. @@ -133,31 +136,27 @@ func (im IBCModule) OnRecvPacket( // Error any transactions with a Memo or Receiver field are greater than the max characters if len(tokenPacketData.Memo) > MaxMemoCharLength { - return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(types.ErrInvalidMemoSize, "memo length: %d", len(tokenPacketData.Memo))) + return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(types.ErrInvalidMemoLength, "memo length: %d", len(tokenPacketData.Memo))) } - if len(tokenPacketData.Receiver) > MaxMemoCharLength { - return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(types.ErrInvalidMemoSize, "receiver length: %d", len(tokenPacketData.Receiver))) + if len(tokenPacketData.Receiver) > MaxReceiverCharLength { + return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(types.ErrInvalidReceiverLength, "receiver length: %d", len(tokenPacketData.Receiver))) } - // ibc-go v5 has a Memo field that can store forwarding info - // For older version of ibc-go, the data must be stored in the receiver field - var metadata string - if tokenPacketData.Memo != "" { // ibc-go v5+ - metadata = tokenPacketData.Memo - } else { // before ibc-go v5 - metadata = tokenPacketData.Receiver + // The receiver must always be a valid address + // In the case of autopilot, this address is also duplicated in the autopilot payload + if _, err := sdk.AccAddressFromBech32(tokenPacketData.Receiver); err != nil { + return channeltypes.NewErrorAcknowledgement(errorsmod.Wrap(types.ErrInvalidReceiverAddress, tokenPacketData.Receiver)) } // If a valid receiver address has been provided and no memo, // this is clearly just an normal IBC transfer // Pass down the stack immediately instead of parsing - _, err := sdk.AccAddressFromBech32(tokenPacketData.Receiver) - if err == nil && tokenPacketData.Memo == "" { + if tokenPacketData.Memo == "" { return im.app.OnRecvPacket(ctx, packet, relayer) } // parse out any autopilot forwarding info - autopilotMetadata, err := types.ParseAutopilotMetadata(metadata) + autopilotMetadata, err := types.ParseAutopilotMetadata(tokenPacketData.Memo) if err != nil { return channeltypes.NewErrorAcknowledgement(err) } @@ -171,9 +170,12 @@ func (im IBCModule) OnRecvPacket( //// At this point, we are officially dealing with an autopilot packet - // Update the reciever in the packet data so that we can pass the packet down the stack - // (since the "receiver" may have technically been a full JSON memo) - tokenPacketData.Receiver = autopilotMetadata.Receiver + // Confirm the receiver in the autopilot metadata matched the transfer receiver + if tokenPacketData.Receiver != autopilotMetadata.Receiver { + return channeltypes.NewErrorAcknowledgement(errorsmod.Wrapf(types.ErrInvalidReceiverAddress, + "the transfer receiver (%s) must match the autopilot receiver (%s)", + tokenPacketData.Receiver, autopilotMetadata.Receiver)) + } // For autopilot liquid stake and forward, we'll override the receiver with a hashed address // The hashed address will also be the sender of the outbound transfer diff --git a/x/autopilot/types/errors.go b/x/autopilot/types/errors.go index ac6b59a3cc..d764840e47 100644 --- a/x/autopilot/types/errors.go +++ b/x/autopilot/types/errors.go @@ -13,5 +13,6 @@ var ( ErrUnsupportedAutopilotRoute = errorsmod.Register(ModuleName, 1505, "unsupported autpilot route") ErrInvalidReceiverAddress = errorsmod.Register(ModuleName, 1506, "receiver address must be specified when using autopilot") ErrPacketForwardingInactive = errorsmod.Register(ModuleName, 1507, "autopilot packet forwarding is disabled") - ErrInvalidMemoSize = errorsmod.Register(ModuleName, 1508, "the memo or receiver field exceeded the max allowable size") + ErrInvalidMemoLength = errorsmod.Register(ModuleName, 1508, "the memo field exceeded the max allowable size") + ErrInvalidReceiverLength = errorsmod.Register(ModuleName, 1509, "the receiver field exceeded the max allowable size") )