Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: wallet_call_with_max_cycles #170

Merged
merged 14 commits into from
Apr 10, 2024
43 changes: 43 additions & 0 deletions e2e/bash/send.bash
Original file line number Diff line number Diff line change
@@ -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
}
6 changes: 5 additions & 1 deletion wallet/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -949,11 +949,15 @@ mod wallet {
)]
async fn call_with_max_cycles(args: CallWithMaxCyclesArgs) -> Result<CallResult, String> {
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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

August 2024

Time travel ¯_(ツ)_/¯

// 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
}
Expand Down
Loading