current location:Home >> Blockchain knowledge >> how to route bridging aggregator fees to treasury

how to route bridging aggregator fees to treasury

admin Blockchain knowledge 1067

Here is a comprehensive guide, broken down by the key architectural decisions and implementation steps.


Core Concept

how to route bridging aggregator fees to treasury

The fundamental idea is to intercept a portion of the fee a user pays for a cross-chain swap (via a bridging aggregator like Socket, Li.Fi, etc.) and divert it to a designated treasury address instead of letting the aggregator's protocol keep 100% of it.

There are two primary architectural patterns to achieve this:

  1. Direct Integration (Using the Aggregator's Built-in Fee Mechanism)

  2. Meta-Transaction / Relay-Based Model (Implementing Your Own Fee Take)


1. Direct Integration (Using Aggregator's Fee Mechanism)

Most major bridging aggregators have a built-in concept of "affiliate fees" or "integrator fees." This is the simplest and most efficient way to achieve your goal. You act as an "integrator," and the aggregator's contract is programmed to send a portion of the fee to your specified address.

How it Works:

  1. Your dApp/frontend integrates with the aggregator's API/SDK.

  2. When requesting a quote for a bridge/swap, you include your integrator ID and treasury address.

  3. The aggregator's API returns a quote that includes your fee.

  4. When the user executes the transaction, the aggregator's smart contract automatically splits the fee, sending your share to your treasury.

Implementation Steps (Generic):

Step 1: Register with the Aggregator

  • Go to the aggregator's developer portal (e.g., Socket Dashboard, Li.Fi Developer Portal).

  • Create an account and register your project to get an Integrator ID (or a similar identifier).

Step 2: Integrate the SDK/API in Your Frontend

  • Use the aggregator's SDK (e.g., @socket.tech/socket-sdk@lifi/sdk) in your application.

  • When generating a transaction, pass your integratorId and feeTreasury address in the quote request parameters.

Example using a hypothetical Socket-like SDK:

javascript
import { Socket } from '@socket.tech/socket-sdk';const socket = new Socket({ apiKey: 'YOUR_API_KEY' });// Request a quote for a cross-chain swapconst 
quote = await socket.getQuote({
  fromChainId: 1, // Ethereum
  toChainId: 137, // Polygon
  
  fromToken: '0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE', // Native ETH
  toToken: '0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619', // WETH on Polygon
  fromAmount: '1000000000000000000', // 1 ETH
  userAddress: '0xUserAddress...',
  // --- Key Parameters for Fees ---
  integratorId: 'your_project_name', // Your registered Integrator ID
  feeTreasury: '0xYourTreasuryAddress...', // The address to receive fees
  // The fee is typically a percentage of the fromAmount, configurable in the dashboard.});// The returned quote will have the final 'txn' object which 
  includes the computed fee.const transaction = quote.txn;// Send this transaction to the user's wallet for signing.

Step 3: The Smart Contract Handles the Rest

  • The user signs and submits the transaction. The to address of this transaction is the aggregator's verified contract (e.g., SocketGateway).

  • Inside its execute function, the aggregator's contract logic calculates the total fee, deducts your share, and sends it to your feeTreasury address on the source chain as part of the same atomic transaction.

Pros & Cons of Direct Integration:

  • Pros:

    • Simple: No need to deploy or maintain your own smart contracts.

    • Secure: Leverages the aggregator's audited and battle-tested fee logic.

    • Automatic: Fee routing happens atomically with the user's bridge transaction.

  • Cons:

    • Less Flexible: You are bound by the aggregator's fee model (e.g., max fee percentage).

    • Vendor Lock-in: You must repeat this process for each aggregator you use.


2. Meta-Transaction / Relay-Based Model

If you need more control, want to use multiple aggregators under a single fee model, or if the aggregator doesn't have a built-in affiliate system, you can build this yourself.

How it Works:

  1. Your dApp acts as a "relayer." You get a quote from any bridging aggregator.

  2. You wrap this original transaction data into your own "Fee Router" smart contract.

  3. The user signs a meta-transaction, or more simply, approves your contract to spend their tokens.

  4. Your contract takes a fee in the source token and then calls the aggregator's contract with the remaining amount.

Implementation Steps:

Step 1: Deploy a "Fee Router" Smart Contract

This contract will hold the logic for deducting fees and making the external call to the bridging aggregator.

solidity
// SPDX-License-Identifier: MITpragma solidity ^0.8.19;import "@openzeppelin/contracts/token/ERC20/IERC20.sol";import "
@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";import "@openzeppelin/contracts/access/Ownable.sol";contract BridgingFeeRouter is Ownable {
    using SafeERC20 for IERC20;

    address public immutable treasury;
    uint256 public feeBasisPoints; // e.g., 10 = 0.1%, 50 = 0.5%

    event FeeCollected(address indexed token, uint256 amount);

    constructor(address _treasury, uint256 _feeBasisPoints) {
        treasury = _treasury;
        feeBasisPoints = _feeBasisPoints;
    }

    /**
     * @dev The main function to route a bridge via an aggregator while taking a fee.
     * @param target The address of the aggregator's contract (e.g., SocketGateway).
     * @param approvalToken The token the user is spending (address(0) for native gas token).
     * @param approvalAmount The total amount the user wants to bridge.
     * @param aggregatorCallData The encoded function call for the aggregator's contract.
     */
    function bridgeWithFee(
        address target,
        address approvalToken,
        uint256 approvalAmount,
        bytes calldata aggregatorCallData    ) external payable {
        uint256 fee = (approvalAmount * feeBasisPoints) / 10000;
        uint256 amountAfterFee = approvalAmount - fee;

        if (approvalToken == address(0)) {
            // Native ETH/MTIC case
            require(msg.value == approvalAmount, "Incorrect value sent");
            // Take fee for treasury
            (bool success, ) = treasury.call{value: fee}("");
            require(success, "Fee transfer failed");
            // Call the aggregator with the remaining value
            (success, ) = target.call{value: amountAfterFee}(aggregatorCallData);
            require(success, "Aggregator call failed");
        } else {
            // ERC20 token case
            // Transfer tokens from user to this contract
            IERC20(approvalToken).safeTransferFrom(msg.sender, address(this), approvalAmount);
            // Take fee for treasury
            IERC20(approvalToken).safeTransfer(treasury, fee);
            // Approve the aggregator to spend the tokens
            IERC20(approvalToken).safeApprove(target, amountAfterFee);
            // Call the aggregator's function
            (bool success, ) = target.call(aggregatorCallData);
            require(success, "Aggregator call failed");
        }
        emit FeeCollected(approvalToken, fee);
    }

    // Admin function to update fee, if necessary
    function setFeeBasisPoints(uint256 _newFeeBasisPoints) external onlyOwner {
        feeBasisPoints = _newFeeBasisPoints;
    }}

Step 2: Integrate Your Contract into the Flow

  1. Get a quote from an aggregator (Socket, Li.Fi, etc.) as you normally would.

  2. Instead of having the user send the transaction directly to the aggregator, you encode a call to your BridgingFeeRouter.bridgeWithFee function.

  3. The target is the aggregator's contract address, and the aggregatorCallData is the data from the original quote.

Step 3: User Interaction

  • The user interacts with your dApp.

  • Your dApp creates the meta-transaction calling your FeeRouter.

  • The user signs this transaction, which transfers the tokens to your contract, which then takes the fee and executes the bridge.

Pros & Cons of the Meta-Transaction Model:

  • Pros:

    • Maximum Control: You set the fee structure and logic.

    • Aggregator Agnostic: Works with any aggregator or even direct bridges.

    • Unified Treasury: All fees from all sources go through one contract.

  • Cons:

    • Complex: Requires developing, deploying, and maintaining a secure smart contract.

    • Security Risk: A bug in your contract could lead to loss of user funds. AUDITING IS MANDATORY.

    • Worse UX: Requires an extra approve step for ERC20 tokens and is generally more complex for the user.


Summary & Recommendation

FeatureDirect Integration (Affiliate Fees)Meta-Transaction Model
Development EffortLow (SDK Integration)High (Smart Contract Dev)
SecurityHigh (Uses audited code)Your Responsibility (Needs audit)
FlexibilityLow (Set by aggregator)High (You have full control)
UXExcellent (Single transaction)Good (May require extra approval)

Recommendation:

Start with the Direct Integration method. It is by far the safest, fastest, and most reliable way to start collecting fees. Register with the major aggregators you use and integrate their affiliate fee parameters.

Only consider building your own Meta-Transaction Model if you have a specific business need that the aggregators' built-in systems cannot fulfill and you have the significant expertise and resources required to do it securely.

If you have any questions or uncertainties, please join the official Telegram group: https://t.me/GToken_EN

GTokenTool

GTokenTool is the most comprehensive one click coin issuance tool, supporting multiple public chains such as TON, SOL, BSC, etc. Function: Create tokensmarket value managementbatch airdropstoken pre-sales IDO、 Lockpledge mining, etc. Provide a visual interface that allows users to quickly create, deploy, and manage their own cryptocurrencies without writing code.

Similar recommendations