Practical Tx Fee Management for Developers and Users

This page references how to retrieve and deposit gas fee from a practical standpoint. For more information on theoretical explanation of how gas works, see Theoretical Tx Fee Explanation

The internet computer employs a reverse gas model, necessitating a custom fee for our canister to mitigate the risks of distributed denial-of-service (DDoS) attacks and spam. As such, we created a custom fee model that automatically computes depending on the function call. Cycles are used for many reasons such as when a function needs to make an outcall to the price feed canisters, storage of balances, any sort of update calls, etc. As such we created a fee model to account for this. Fees are sent directly to a fee manager. Currently the fee manager is just our own principal but will be upgraded to automated canister that will algorithmically distribute cycles to all necessary canisters of our protocol.

To ensure that funds are being used properly by the team, the canister's fee manager is given:

e72ak-uu5s4-t3uba-ldsg5-yx7du-cn5t4-cvqoc-fkgoz-akjmp-3bljs-3qe

Our canister functions on a "view fee then pay" approach, where you first call a function to determine the fee, then send it to a designated sub account within our canister. You will most likely have to use this reference when calling any functions in further sections.

Paying Fee

The steps to paying your fee involve:

  1. Retrieving the gas fee in ICP

  2. Retrieving your deposit account

  3. Sending the ICP to the deposit account using the estimated fee in 1.

  4. Then calling the function you'd like to deposit to.

1. Retrieving The Fee

- Retrieving Fee Candid Notation

The candid for the fee for a specific function call is

get_fee_in_icp: (FunctionCall) -> (nat64);

Function call is a variant as specified.

type FunctionCall =
    variant {
        Borrow: record {
            amount: nat;
            borrower: principal;
            tokenToBorrow: Token;
        };
        DepositDip: record {
            amount: nat;
            depositor: principal;
            tokenToDeposit: Token;
        };
        DepositIcp: record {
            amount: nat64;
            depositor: principal;
            tokenToDeposit: Token;
        };
        DepositIcrc1: record {
            amount: nat;
            depositor: principal;
            tokenToDeposit: Token;
        };
        FixedFee;
        Liquidate: record {
            amount: nat;
            borrower: principal;
            liquidator: principal;
            tokenBorrowed: Token;
            tokenCollateral: Token;
        };
        Mint: record {
            amount: nat;
            minter: principal;
            tokenToMint: Token;
        };
        Redeem: record {
            amount: nat;
            redeemer: principal;
            tokenToRedeem: Token;
        };
        RedeemUnderlying: record {
            amount: nat;
            redeemer: principal;
            tokenToRedeem: Token;
        };
        Repay: record {
            amount: nat;
            borrower: principal;
            tokenToRepay: Token;
        };
        UpdateAllMarkets;
        WithdrawDip: record {
            amount: nat;
            tokenToWithdraw: Token;
            withdrawer: principal;
        };
        WithdrawIcp: record {
            amount: nat64;
            tokenToWithdraw: Token;
            withdrawer: principal;
        };
        WithdrawIcrc1: record {
            amount: nat;
            tokenToWithdraw: Token;
            withdrawer: principal;
        };
};

The Token type is below

type Token = principal

For amount, please put in the exact number you plan to enter when call the specific function.

- Retrieving Fee with dfx

To call the function from the command line we give an example for borrowing 0.03 ICP equivalent to 3_000_000 ICP in integer decimal representation. For other functions, please reference the variant above and plug in the desired FunctionCall.

dfx canister --network ic call z4viz-kiaaa-aaaal-qbxmq-cai get_fee_in_icp "(variant { Borrow = record { amount = 3_000_000; borrower = principal \"$(dfx identity get-principal)\"; tokenToBorrow = principal \"ryjl3-tyaaa-aaaaa-aaaba-cai\" } })"

The steps to deposit Icp Fee involve, finding your deposit account, transferring ICP to that deposit account based on the Fee you retrieved, then calling the specified function.

2. Retrieving Deposit Account

dfx canister --network ic call z4viz-kiaaa-aaaal-qbxmq-cai getDepositAccountIdAsText

3. Transferring ICP to Deposit Account

Given that transferring ICP is covered in the Internet Computer's official documentation and the Dfinity Ledger, we recommend visiting this link for further details on ICP transfers if you're interested: https://internetcomputer.org/docs/current/developer-docs/integrations/ledger/interact-with-ledger/. Otherwise, simply follow the code blocks provided below.

NOTE: You can always add more to your deposit account to ensure that the transaction goes through than specified in the initial fee estimate. Only the calculated amount will be taken and the rest will remain in your deposit account to #Withdraw !!!

NOTE 2: If the fee payment is too little or fails, you will not be charged anything. But you will lose time. This is especially important for those trying to liquidate others or make fast repayments!!!

- Transferring to Deposit Account with dfx

dfx ledger --network ic transfer "$DEPOSIT-ACCOUNT" --memo 1 --amount "$RETRIEVED-FEE-AMOUNT" --fee 0.0001

To clear up what to put in those "$XYZ" here's a concrete examplecode

dfx ledger --network ic transfer 4ee4eb645821d3960db2c81db0b0d5e3b01a2ba48207c958c603b70cc2f5c67b --memo 1 --amount 0.1 --fee 0.0001

4. Call the Function that you Planned to Call

Last updated