guys! I am creating my own web 3 project and now I am stuck with charging fee from users. I have 2 options to do it:

  • take percent of user's tokenIn (or tokenA), but in this case user is getting less tokenOut (or tokenB) and this is why I do not like this idea
  • or take as fee part of his native coin, which is using for paying gas (before sending transaction, we set higher gas value to use, then during the transaction we just keep this extra gas to ourselves, user gets his 100% of tokenB for 100% of tokenA and everyone is happy)

I like second variant, but is that variant possible? I mean, from technological programming point of view. Is it possible to keep native coin, which was planned to use as gas, transferring it to the different address?

  • 1
    Even if this were possible, I think it makes for a poor user experience because you're not being explicit about your actions. Savvy users would also be able to bypass. I'd just require a native-coin fee. Commented Feb 2 at 12:00
  • Please accept my answer if it helped you.
    – Mila A
    Commented Feb 11 at 13:33

2 Answers 2


Arran suggested a great solution in the comments above. That's how you can implement your idea №2.

I can't think of any way you can keep a part of the gas coins as a fee.

I'd like to further expand on the idea of collecting native coins as a fee.

You can require the user to pass the native coin fee as a msg.value to your swap functions with something like this.

// SPDX_License-Identifier: UNLICENSED

pragma solidity ^0.8.13;

contract SwapPair {
    enum SwapDirection {

    function swap(address tokenIn, address tokenOut, uint256 amount, SwapDirection swapDirection, uint256 minTokenOut) external payable returns (uint256 outAmount) {
        uint256 fee;
        // calculate the fee

        require(msg.value == fee, "msg.value does not cover the fee expenses");
        // do some logic

    function estimateFee(address tokenIn, address tokenOut, uint256 amount, SwapDirection swapDirection, uint256 swapRatio) external view returns (uint256 fee) {
        // calculate the fee that the user should pay for the swap

FYI, your suggestion №1 is commonly called a fee-on-transfer token swap.


The answer is no.

What users set on the transaction is a gas limit and gas price, they are not sending any amount of ethers anywhere. They are just saying that if the transaction ever costs more than what they are willing to pay as max, stop and fail.

Once the computation stops, the actual computed fees, based on the users' selected gas price, are deducted from the sender's balance and added to the validator's payment address. Only the validator can choose where to receive those payments.

To receive payment for your application, you can think about many methods.

You can use native ethers - so the specific function executes if msg.value is equal to or above a particular threshold only - or you can ask for a third token to be included in the swap. Users can get that third token via a contract, emitting it only if it receives a specific amount of ethers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.