From fa7605737417576870da36c434502beef3071556 Mon Sep 17 00:00:00 2001 From: Severin Siffert Date: Mon, 8 Apr 2024 14:20:47 +0200 Subject: [PATCH] add test, use margin --- e2e/bash/send.bash | 43 +++++++++++++++++++++++++++++++++++++++++++ wallet/src/lib.rs | 6 +++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 e2e/bash/send.bash diff --git a/e2e/bash/send.bash b/e2e/bash/send.bash new file mode 100644 index 0000000..078450f --- /dev/null +++ b/e2e/bash/send.bash @@ -0,0 +1,43 @@ +#!/usr/bin/env bats + +# shellcheck source=/dev/null +source "$BATS_SUPPORT/load.bash" + +load util/assertions + +setup() { + # We want to work from a temporary directory, different for every test. + x=$(mktemp -d -t dfx-usage-env-home-XXXXXXXX) + cd "$x" || exit + export DFX_CONFIG_ROOT=$x + + dfx new --no-frontend e2e_project + cd e2e_project || exit 1 + dfx start --background --clean +} + +teardown() { + dfx stop + rm -rf "$DFX_CONFIG_ROOT" +} + +@test "wallet_call_with_max_cycles" { + dfx identity new alice --storage-mode plaintext + dfx identity new bob --storage-mode plaintext + WALLET_ALICE=$(dfx --identity alice identity get-wallet) + WALLET_BOB=$(dfx --identity bob identity get-wallet) + + ALICE_CYCLES_BEFORE_SEND=$(dfx --identity alice wallet balance --precise | sed 's/[^0-9]//g') + if (( ${ALICE_CYCLES_BEFORE_SEND} < 2000000000000 )); then + echo "alice has unexpectedly few cycles before sending: ${ALICE_CYCLES_BEFORE_SEND}" + exit 1 + fi + dfx --identity alice canister call "${WALLET_ALICE}" wallet_call_with_max_cycles "(record { canister = principal \"${WALLET_BOB}\"; method_name = \"wallet_receive\"; args = blob \"\44\49\44\4c\00\00\"; })" + + # has less than 0.2T cycles afterwards + ALICE_CYCLES_AFTER_SEND=$(dfx --identity alice wallet balance --precise | sed 's/[^0-9]//g') + if (( ${ALICE_CYCLES_AFTER_SEND} > 200000000000 )); then + echo "expected alice to have <1TC after wallet_call_with_max_cycles, actually has ${ALICE_CYCLES_AFTER_SEND}, before was ${ALICE_CYCLES_BEFORE_SEND}" + exit 1 + fi +} diff --git a/wallet/src/lib.rs b/wallet/src/lib.rs index d08a956..916e3df 100644 --- a/wallet/src/lib.rs +++ b/wallet/src/lib.rs @@ -949,11 +949,15 @@ mod wallet { )] async fn call_with_max_cycles(args: CallWithMaxCyclesArgs) -> Result { let available_cycles = ic_cdk::api::canister_balance128(); + // If no margin is used then the call either fails locally with `Couldn't send message` or processing the response traps with `Canister out of cycles`. + // On the local network the margin needs to be ~1.7B cycles. (Experimentally determined in August 2024) + // Extrapolating, a margin of 100B should work up to a subnet of ~60 nodes. + const MARGIN: u128 = 100_000_000_000; call128(CallCanisterArgs { canister: args.canister, method_name: args.method_name, args: args.args, - cycles: available_cycles, + cycles: available_cycles.saturating_sub(MARGIN), }) .await }