Estimating Fees

Learn more about estimating fees associated with Stargate transfers.

Stargate offers five distinct methods to estimate transfer fees. Let's begin by exploring the most commonly utilized ones.

High level functions

The two highest level functions are:

  1. quoteOFT

  2. quoteSend

They are both part of IStargate interface.

quoteOFT

This method provides a quote for sending OFT to another chain. It can be used to calculate minimum amount of tokens you will receive on destination chain after you swap.

This function also returns maximum number of tokens possible to bridge to a particular chain. It is very important taking into consideration the Credits mechanism in Stargate.

This is how the interface of the function looks like:

/// @notice Provides a quote for sending OFT to another chain.
/// @dev Implements the IOFT interface
/// @param _sendParam The parameters for the send operation
/// @return limit The information on OFT transfer limits
/// @return oftFeeDetails The details of OFT transaction cost or reward
/// @return receipt The OFT receipt information, indicating how many tokens would be sent and received
function quoteOFT(
    SendParam calldata _sendParam
) external view returns (
    OFTLimit memory limit,
    OFTFeeDetail[] memory oftFeeDetails,
    OFTReceipt memory receipt
)

As you can see, the only input parameter is SendParam:

/**
 * @dev Struct representing token parameters for the OFT send() operation.
 */
struct SendParam {
    uint32 dstEid; // Destination endpoint ID.
    bytes32 to; // Recipient address.
    uint256 amountLD; // Amount to send in local decimals.
    uint256 minAmountLD; // Minimum amount to send in local decimals.
    bytes extraOptions; // Additional options supplied by the caller to be used in the LayerZero message.
    bytes composeMsg; // The composed message for the send() operation.
    bytes oftCmd; // The OFT command to be executed, unused in default OFT implementations.
}

It contains all the information required to send the transfer. If you want to learn more about preparing this struct please read How to Swap.

Now, let's analyze the output of quoteOFT():

  • OFTLimit limit - it returns minimum and maximum amounts of tokens in local decimals that can be transferred to the receiver. The maximum amount of tokens received on the destination chain might be limited by the credits mechanism in Stargate. Example value: OFTLimit({ minAmountLD: 1000000000000 [1e12], maxAmountLD: 18446744073709551615000000000000 [1.844e31] })

  • OFTFeeDetail[] oftFeeDetails - array of structs containing information about fees or rewards in local decimals with their descriptions. Note that feeAmountLD is int256 so it can be positive or negative. If you would like to learn more read Treasury fees and rewards. Example value: [OFTFeeDetail({ feeAmountLD: 1000000000000 [1e12], description: "reward" })]

  • OFTReceipt receipt:

struct OFTReceipt {
    uint256 amountSentLD; // Amount of tokens ACTUALLY debited from the sender in local decimals.
    // @dev In non-default implementations, the amountReceivedLD COULD differ from this value.
    uint256 amountReceivedLD; // Amount of tokens to be received on the remote side.
}

Example value: OFTReceipt({ amountSentLD: 100000000000000 [1e14], amountReceivedLD: 100000000000000 [1.01e14] }) amountReceivedLD from quoteOFT() can be used to override SendParam.minAmountLD that is later passed to quoteSend(). minAmountLD is minimum amount of tokens to send. If due to applied fees/reward the actual amount sent would drop below this value then the fee library will revert with SlippageTooHigh.

quoteSend

This method provides a way to calculate total fee for a given send() operation. It reverts with InvalidAmount if send mode is drive but value is specified.

This is an interface of the function:

function quoteSend(
    SendParam calldata _sendParam,
    bool _payInLzToken
) external view returns (MessagingFee memory fee)

It accepts SendParam and a boolean whether to pay in LayerZero token. For more information on how to prepare the SendParam please read How to Swap.

quoteSend returns MessagingFee struct:

struct MessagingFee {
    uint256 nativeFee;
    uint256 lzTokenFee;
}

Lower level functions

Below you can see some of the lower level functions which might be useful for advanced use cases. In a typical use case, when you call quoteSend these lower level functions are called automatically and there's no need to call them directly.

quoteTaxi

This function is part of ITokenMessaging interface:

function quoteTaxi(
    TaxiParams calldata _params,
    bool _payInLzToken
) external view returns (MessagingFee memory fee);

This function accepts TaxiParams and a boolean indicating whether to pay in LayerZero token as input parameters. It returns a quote for how much needs to be paid for the transfer.

Let's focus on the TaxiParams here:

struct TaxiParams {
    address sender;
    uint32 dstEid;
    bytes32 receiver;
    uint64 amountSD;
    bytes composeMsg;
    bytes extraOptions;
}

This is what you need to provide to the above function. You can also programatically convert SendParam to TaxiParams by calling:

using MessagingHelper for SendParam;

// ...

function _ld2sd(uint256 _amountLD) internal view returns (uint64 amountSD) {
    unchecked {
        amountSD = SafeCast.toUint64(_amountLD / convertRate);
    }
}

// ...

uint64 amountSD = _ld2sd(sendParam.amountLD);

sendParam.toTaxiParams(amountSD)

quoteRideBus

This function is part of theITokenMessaging interface:

function quoteRideBus(
    uint32 _dstEid, bool _nativeDrop
) external view returns (MessagingFee memory fee);

It returns a total fee for the bus ride transfer and accepts Destination Endpoint Id (_dstEid) and a boolean that represents whether to pay for a native drop on the destination.

Treasury fees and rewards

There are two types of Stargate token instances that can exist on particular chain. Only one instance will exist per asset per chain. A token on specific chain is either using a Pool or it is a Hydra OFT.

When sending tokens from Pool it can either charge a treasury fee or reward you for the transfer.

If you transfer from Hydra OFT there is no reward, but the treasury fee can be charged.

As a reminder you can query treasury fees or rewards using quoteOFT(). Fees within the Stargate protocol are dynamic, and are set by the AI Planning Module on a per pathway basis.

Reward

The reward is capped by the treasury fee pool. The function addTreasuryFee() can be called by the treasurer, which will emit the following event:

event TreasuryFeeAdded(uint64 amountSD);

Last updated