Skip to content

Instantly share code, notes, and snippets.

@shapeshed
Last active July 6, 2023 22:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shapeshed/445f158d95c116061a14df326654bc95 to your computer and use it in GitHub Desktop.
Save shapeshed/445f158d95c116061a14df326654bc95 to your computer and use it in GitHub Desktop.
stake.sh
#!/usr/bin/env sh
#
# A script to test
# * the creation of a CW20 contract
# * the creation of a CW4 contract
# * the staking of CW20 tokens in the CW4 contract
CW20_CONTRACT_NAME=cw20_base.wasm
CW20_CONTRACT_URL=https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw20_base.wasm
CW4_CONTRACT_NAME=cw4_stake.wasm
CW4_CONTRACT_URL=https://github.com/CosmWasm/cw-plus/releases/download/v0.13.4/cw4_stake.wasm
NODE_ADDRESS=127.0.0.1:9988
# Check ccw is installed
if ! command -v ccw >/dev/null; then
echo "ccw command not found" >&2
exit 1
fi
# Download the CW20 contract if it doesn't exist locally
if [ ! -e $CW20_CONTRACT_NAME ]; then
wget $CW20_CONTRACT_URL
fi
# Download the CW4 contract if it doesn't exist locally
if [ ! -e $CW4_CONTRACT_NAME ]; then
wget $CW4_CONTRACT_URL
fi
# Store the CW20 contract
printf '%s\n' '--- STORE CW20 CONTRACT ---'
CW20_STORE_CODE_OUTPUT=$(
ccw substrate --node ws://$NODE_ADDRESS \
--from alice --output json \
tx store ./$CW20_CONTRACT_NAME
)
printf '\n%s\n' '--- STORE CW20 CODE RESPONSE ---'
echo "$CW20_STORE_CODE_OUTPUT"
CW20_CODE_ID=$(echo "$CW20_STORE_CODE_OUTPUT" | jq '.extrinsic.details.code_id')
# Instantiate the CW20 contract
printf '\n%s\n' '--- INSTANTIATE CW20 CONTRACT ---'
CW20_INSTANTIATE_OUTPUT=$(
ccw substrate --node ws://$NODE_ADDRESS \
--from alice --output json tx instantiate "$CW20_CODE_ID" \
'{ "decimals" : 18, "initial_balances": [], "name" : "STAKE", "symbol" : "STAKE", "mint": {"minter" : "5yNZjX24n2eg7W6EVamaTXNQbWCwchhThEaSWB7V3GRjtHeL"} }' \
--salt 0x9999 --label 0x1111 --gas 10000000000
)
printf '\n%s\n' '--- INSTANTIATE CW20 CONTRACT RESPONSE ---'
echo "$CW20_INSTANTIATE_OUTPUT"
CW20_CONTRACT_ADDRESS=$(echo "$CW20_INSTANTIATE_OUTPUT" | jq '.cosmwasm_events[0].contract' -r)
# Mint some stake tokens for Alice
printf '\n%s\n' '--- MINTING TOKENS FOR ALICE ---'
ccw substrate --node ws://$NODE_ADDRESS \
--from alice --output json tx execute --contract \
"$CW20_CONTRACT_ADDRESS" --gas 10000000000 --message \
'{ "mint" : { "amount" : "123456789", "recipient" : "5yNZjX24n2eg7W6EVamaTXNQbWCwchhThEaSWB7V3GRjtHeL" }}'
# Query Alice's balance
printf '\n%s\n' '--- QUERY ALICE BALANCE ---'
ccw substrate --node http://$NODE_ADDRESS \
--output json rpc query --contract "$CW20_CONTRACT_ADDRESS" \
--gas 10000000000 \
--query '{"balance": {"address": "5yNZjX24n2eg7W6EVamaTXNQbWCwchhThEaSWB7V3GRjtHeL"}}'
# Store the CW4 contract
printf '%s\n' '--- STORE CW4 CONTRACT ---'
CW4_STORE_CODE_OUTPUT=$(
ccw substrate --node ws://$NODE_ADDRESS \
--from alice --output json \
tx store ./$CW4_CONTRACT_NAME
)
printf '\n%s\n' '--- STORE CW4 CODE RESPONSE ---'
echo "$CW4_STORE_CODE_OUTPUT"
CW4_CODE_ID=$(echo "$CW4_STORE_CODE_OUTPUT" | jq '.extrinsic.details.code_id')
# Instantiate the CW4 contract
printf '\n%s\n' '--- INSTANTIATE CW4 CONTRACT ---'
CW4_INSTANTIATE_OUTPUT=$(
ccw substrate --node ws://$NODE_ADDRESS \
--from alice --output json tx instantiate "$CW4_CODE_ID" \
'{ "denom" : "'"$CW20_CONTRACT_ADDRESS"'", "tokens_per_weight": 1000, "min_bond": 5000, "unbonding_period": 10000 }' \
--salt 0x9991 --label 0x1112 --gas 10000000000
)
printf '\n%s\n' '--- INSTANTIATE CW4 CONTRACT RESPONSE ---'
echo "$CW4_INSTANTIATE_OUTPUT"
exit 0
The script fails at the intantiation of the CW4 Contract.
... Lots (like +2000 lines) of output like this ...
0, 0, 0, 0, 0, 0], docs: [" Minimum connection delay period in seconds for ibc connections that can be created or", " accepted. Ensure that this is non-zero in production as it's a critical vulnerability."] }, ConstantMetadata { name: "SpamProtectionDeposit", ty: 6, value: [0, 128, 198, 164, 126, 141, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0], docs: [" Amount to be reserved for client and connection creation"] }, ConstantMetadata { name: "CleanUpPacketsPeriod", ty: 4, value: [100, 0, 0, 0], docs: [" Cleanup packets period (in blocks)"] }, ConstantMetadata { name: "ServiceChargeOut", ty: 410, value: [0, 9, 61, 0], docs: [" `ServiceChargeOut` represents the service charge rate applied to assets that will be", " sent via IBC.", "", " The charge is applied before assets are transffered from the sender side, during", " transfer extrinsic (before to burn or send assets to escrow account) before the packet", " send via IBC Inter-Blockchain Communication (IBC) protocol.", "", " For example, if the service charge rate for incoming assets is 0.04%, `ServiceChargeIn`", " will be configured in rutime as", " parameter_types! { pub IbcIcs20ServiceChargeOut: Perbill = Perbill::from_rational(4_u32,", " 1000_u32 ) };"] }], map: {"CleanUpPacketsPeriod": 6, "ExpectedBlockTime": 3, "NativeAssetId": 0, "LightClientProtocol": 2, "MinimumConnectionDelay": 4, "SpamProtectionDeposit": 5, "PalletPrefix": 1, "ServiceChargeOut": 7} }, docs: [] }, PalletMetadataInner { name: "Ics20Fee", index: 191, storage: Some(StorageMetadata { prefix: "Ics20Fee", entries: OrderedMap { values: [StorageEntryMetadata { name: "ServiceChargeIn", modifier: Optional, entry_type: Plain(410), default: [0], docs: [] }, StorageEntryMetadata { name: "FeeLessChannelIds", modifier: Default, entry_type: Map { hashers: [Blake2_128Concat], key_ty: 618, value_ty: 31 }, default: [], docs: [" storage map. key is tuple of (source_channel.sequence(), destination_channel.sequence()) and", " value () that means that this group of channels is feeless"] }], map: {"ServiceChargeIn": 0, "FeeLessChannelIds": 1} } }), call_ty: Some(409), call_variant_index: VariantIndex { by_name: {"set_charge": 0, "remove_channels_from_feeless_channel_list": 2, "add_channels_to_feeless_channel_list": 1}, by_index: {1: 1, 0: 0, 2: 2} }, event_ty: Some(215), event_variant_index: VariantIndex { by_name: {"IbcTransferFeeCollected": 0, "FeeLessChannelIdsAdded": 1, "FeeLessChannelIdsRemoved": 2}, by_index: {0: 0, 1: 1, 2: 2} }, error_ty: None, error_variant_index: VariantIndex { by_name: {}, by_index: {} }, constants: OrderedMap { values: [ConstantMetadata { name: "ServiceChargeIn", ty: 410, value: [0, 9, 61, 0], docs: [" `ServiceChargeIn` represents the service charge rate applied to assets upon receipt via", " IBC.", "", " The charge is applied when assets are delivered to the receiving side, on", " deliver(before to mint, send assets to destination account) extrinsic using the", " Inter-Blockchain Communication (IBC) protocol.", "", " For example, if the service charge rate for incoming assets is 0.04%, `ServiceChargeIn`", " will be configured in rutime as", " parameter_types! { pub IbcIcs20ServiceChargeIn: Perbill = Perbill::from_rational(4_u32,", " 1000_u32 ) };"] }, ConstantMetadata { name: "PalletId", ty: 473, value: [105, 99, 115, 50, 48, 102, 101, 101], docs: [] }], map: {"PalletId": 1, "ServiceChargeIn": 0} }, docs: [] }], map: {"AssetTxPayment": 4, "TransactionPayment": 3, "Multisig": 8, "CollatorSelection": 12, "PolkadotXcm": 29, "BondedFinance": 39, "System": 0, "Preimage": 26, "AssetsTransactorRouter": 43, "AssetsRegistry": 40, "Farming": 45, "CallFilter": 46, "Ics20Fee": 49, "ReleaseMembership": 23, "Pablo": 41, "CumulusXcm": 30, "CouncilMembership": 17, "FarmingRewards": 44, "TechnicalCommittee": 20, "Authorship": 11, "XcmpQueue": 28, "ReleaseCommittee": 22, "Scheduler": 24, "ParachainSystem": 9, "DmpQueue": 31, "Ibc": 48, "Democracy": 19, "Treasury": 18, "Identity": 7, "Proxy": 27, "Cosmwasm": 47, "ParachainInfo": 10, "Vesting": 38, "Session": 13, "CrowdloanRewards": 37, "Sudo": 2, "XTokens": 32, "Utility": 25, "TechnicalCommitteeMembership": 21, "CurrencyFactory": 35, "Council": 16, "Aura": 14, "Timestamp": 1, "UnknownTokens": 33, "GovernanceRegistry": 36, "Indices": 5, "Balances": 6, "AuraExt": 15, "Tokens": 34, "Oracle": 42} }, pallets_by_index: {31: 17, 74: 22, 2: 2, 57: 39, 7: 7, 8: 8, 23: 14, 33: 19, 22: 13, 72: 20, 56: 38, 44: 32, 10: 9, 54: 36, 60: 42, 62: 44, 53: 35, 100: 46, 190: 48, 191: 49, 36: 26, 37: 27, 41: 29, 35: 25, 42: 30, 52: 34, 63: 45, 11: 10, 32: 18, 40: 28, 30: 16, 21: 12, 5: 5, 59: 41, 45: 33, 43: 31, 61: 43, 12: 4, 75: 23, 55: 37, 180: 47, 34: 24, 58: 40, 6: 6, 20: 11, 4: 3, 1: 1, 0: 0, 24: 15, 73: 21}, extrinsic: ExtrinsicMetadata { ty: 629, version: 4, signed_extensions: [SignedExtensionMetadata { identifier: "CheckNonZeroSender", extra_ty: 631, additional_ty: 31 }, SignedExtensionMetadata { identifier: "CheckSpecVersion", extra_ty: 632, additional_ty: 4 }, SignedExtensionMetadata { identifier: "CheckTxVersion", extra_ty: 633, additional_ty: 4 }, SignedExtensionMetadata { identifier: "CheckGenesis", extra_ty: 634, additional_ty: 11 }, SignedExtensionMetadata { identifier: "CheckMortality", extra_ty: 635, additional_ty: 11 }, SignedExtensionMetadata { identifier: "CheckNonce", extra_ty: 637, additional_ty: 31 }, SignedExtensionMetadata { identifier: "CheckWeight", extra_ty: 638, additional_ty: 31 }, SignedExtensionMetadata { identifier: "ChargeAssetTxPayment", extra_ty: 639, additional_ty: 31 }] }, runtime_ty: 640, dispatch_error_ty: Some(24), apis: OrderedMap { values: [], map: {} } } }, raw: RawModuleError { pallet_index: 180, error: [35, 0, 0, 0] } })
Polkadot.js offers this error
system.ExtrinsicFailed
An extrinsic failed.
dispatchError: SpRuntimeDispatchError
{
Module: {
index: 180
error: 0x23000000
}
}
dispatchInfo: FrameSupportDispatchDispatchInfo
weight: SpWeightsWeightV2Weight
refTime: Compact<u64>
proofSize: Compact<u64>
class: FrameSupportDispatchDispatchClass
Normal
paysFee: FrameSupportDispatchPays
Yes
@dzmitry-lahoda
Copy link

sleep at least 6 seconds after each call to substrate so that new nonce is catched up.

@dzmitry-lahoda
Copy link

i tested some errors, they will be string and shorte. just Module part (for some cases I tested), but mapped to strings

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment