FeeWrapper Contracts

This page provides an overview of the fee-wrapping smart contracts, which are built on top of DeFi project deposit functions to facilitate the collection and distribution of fees. The contracts are owned, allowing the owner to perform privileged operations such as setting the fee recipient or configuring the deposit parameters. The contracts act as an intermediary, facilitating deposits, deducting fees, transferring funds to the recipient, and not holding any funds.

Introduction

The FeeWrapper smart contracts allow wallets, dApps, and integrators to capture a fee on deposits made to vaults, lending protocols, and LSTs enabling them to monetize their services. Collected fees are split between a provider (StakeKit) and a specified fee recipient (the client). The contract owner can configure deposit contracts, manage whitelist statuses, and set fee rates.

We have two types of FeeWrapper contracts — FeeWrapper4626 which are applied to ERC-4626 compliant DeFi yields and Protocol Specific FeeWrapper contracts which are applied to all other non-ERC4626 compliant yields such as Aave V3 and Lido stETH liquid staking.

Contracts

FeeWrapper4626

Overview

The FeeWrapper4626 is built to capture fees on top of any ERC4626 compatible yield vault, such as YearnV3, Ethena, and Angle protocol

The contract maintains:

  • A mapping of deposit contract configurations, each with a whitelist status and a fee rate.
  • A mapping of fee configurations, each with a fee percentage and a fee recipient.

The contract allows for:

  • Setting a provider fee recipient, which is the address that receives the provider fees.
  • Configuring deposit contracts, including setting their whitelist status and fee rate.
  • Setting the fee configuration for each deposit contract, including the fee percentage and the fee recipient.

The contract provides:

  • A function for depositing tokens into the deposit contract and distributing fees.
  • The deposit function checks that the deposit contract is whitelisted, calculates the fee, and transfers the fee and deposit amount to the appropriate addresses.
  • The fee is split between the provider and the fee recipient according to the fee configuration.
  • Helper functions for computing the fee and the fee split.

Functions

setProviderFeeRecipient

 /**
     * @notice Sets a new provider fee recipient
     * @dev Only callable by the owner
     * @param newProviderFeeRecipient The new provider fee recipient address
     * @return The new provider fee recipient address
     */
    function setProviderFeeRecipient(address newProviderFeeRecipient) external onlyOwner returns (address)

setDepositContractConfig

    /**
     * @notice Sets the configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist Whether the contract is whitelisted
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The configuration for the deposit contract
     */
    function setDepositContractConfig(
        address depositContract,
        bool whitelist,
        uint16 fee
    )
        external
        onlyOwner
        returns (DepositContractConfig memory) 

setDepositContractWhitelist

  /**
     * @notice Sets the whitelist status for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist The whitelist status
     * @return The whitelist status of the deposit contract
     */
    function setDepositContractWhitelist(address depositContract, bool whitelist) external onlyOwner returns (bool)

setDepositContractFee

   /**
     * @notice Sets the fee for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The fee of the deposit contract
     */
    function setDepositContractFee(address depositContract, uint16 fee) external onlyOwner returns (uint16)

setFeeConfig

   /**
     * @notice Sets the fee configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        address depositContract,
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

setFeeRecipient

  /**
     * @notice Sets the fee recipient for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feeRecipient The address that will receive the fee share
     * @return The fee recipient of the deposit contract
     */
    function setFeeRecipient(address depositContract, address feeRecipient) external onlyOwner returns (address)

setFeePercentage

  /**
     * @notice Sets the fee share percentage for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The fee in basis points
     * @return The fee share percentage of the deposit contract
     */
    function setFeePercentage(address depositContract, uint8 feePercentage) external onlyOwner returns (uint8)

deposit

 /**
     * @notice Deposits tokens into the deposit contract and distributes fees to provider and feeReecipient
     * @param depositAddress The address of the deposit contract
     * @param amount The amount of tokens to deposit
     * @return shares The number of shares minted
     */
    function deposit(address depositAddress, uint256 amount) external returns (uint256 shares)

Project Specific FeeWrapper Contract Functions

FeeWrapperAaveV3

setDepositContractConfig

    /**
     * @notice Sets the configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist Whether the contract is whitelisted
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The configuration for the deposit contract
     */
    function setDepositContractConfig(
        address depositContract,
        bool whitelist,
        uint16 fee
    )
        external
        onlyOwner
        returns (DepositContractConfig memory) 

setFeeConfig

   /**
     * @notice Sets the fee configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        address depositContract,
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

supply

  /**
   * @notice Supplies an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
   * - E.g. User supplies 100 USDC and gets in return 100 aUSDC
   * @param depositAddress The address of the deposit contract
   * @param asset The address of the underlying asset to supply
   * @param amount The amount to be supplied
   * @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
   *   wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
   *   is a different wallet
   * @param referralCode Code used to register the integrator originating the operation, for potential rewards.
   *   0 if the action is executed directly by the user, without any middle-man
   **/
  function supply(
    address depositAddress
    address asset,
    uint256 amount,
    address onBehalfOf,
    uint16 referralCode
  ) external;

FeeWrapperCompoundV3

setDepositContractConfig

    /**
     * @notice Sets the configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist Whether the contract is whitelisted
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The configuration for the deposit contract
     */
    function setDepositContractConfig(
        address depositContract,
        bool whitelist,
        uint16 fee
    )
        external
        onlyOwner
        returns (DepositContractConfig memory) 

setFeeConfig

   /**
     * @notice Sets the fee configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        address depositContract,
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

supply

    /**
     * @notice Supply an amount of asset to the protocol
     * @param depositAddress The address of the deposit contract
     * @param asset The asset to supply
     * @param amount The quantity to supply
     */
    function supply(address depositAddress, address asset, uint amount) external

FeeWrapperYearnV2

setProviderFeeRecipient

    /**
     * @notice Supply an amount of asset to the protocol
     * @param depositAddress The address of the deposit contract
     * @param asset The asset to supply
     * @param amount The quantity to supply
     */
    function supply(address depositAddress, address asset, uint amount) external
    

setProviderFeeRecipient

 		/**
     * @notice Sets a new provider fee recipient
     * @dev Only callable by the owner
     * @param newProviderFeeRecipient The new provider fee recipient address
     * @return The new provider fee recipient address
     */
    function setProviderFeeRecipient(address newProviderFeeRecipient) external onlyOwner returns (address)

setDepositContractConfig

   /**
     * @notice Sets the configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist Whether the contract is whitelisted
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The configuration for the deposit contract
     */
    function setDepositContractConfig(
        address depositContract,
        bool whitelist,
        uint16 fee
    )
        external
        onlyOwner
        returns (DepositContractConfig memory) 

setDepositContractWhitelist

  /**
     * @notice Sets the whitelist status for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist The whitelist status
     * @return The whitelist status of the deposit contract
     */
    function setDepositContractWhitelist(address depositContract, bool whitelist) external onlyOwner returns (bool)

setDepositContractFee

   /**
     * @notice Sets the fee for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The fee of the deposit contract
     */
    function setDepositContractFee(address depositContract, uint16 fee) external onlyOwner returns (uint16)

setFeeConfig

   /**
     * @notice Sets the fee configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        address depositContract,
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

setFeeRecipient

  	/**
     * @notice Sets the fee recipient for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feeRecipient The address that will receive the fee share
     * @return The fee recipient of the deposit contract
     */
    function setFeeRecipient(address depositContract, address feeRecipient) external onlyOwner returns (address) 

setFeePercentage

  	/**
     * @notice Sets the fee share percentage for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The fee in basis points
     * @return The fee share percentage of the deposit contract
     */
    function setFeePercentage(address depositContract, uint8 feePercentage) external onlyOwner returns (uint8)

deposit

 		/**
     * @notice Deposits tokens into the deposit contract and distributes fees to provider and feeReecipient
     * @param depositAddress The address of the deposit contract
     * @param amount The amount of tokens to deposit
     * @return shares The number of shares minted
     */
    function deposit(address depositAddress, uint256 amount) external returns (uint256 shares)

FeeWrapperEtherfi

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

deposit

    /**
     * @notice  Send funds to the pool with optional referral parameter
     * @param   referral The referral address to use for the deposit (can be address(0) if none)
     * @return mintedAmount the amount of eETH minted to the caller
     */
    function deposit(address referral) external payable returns (uint256)

depositWithERC20

    /**
     * @notice Deposit Liquid Staking Token such as stETH and Mint eETH
     * @param token The address of the token to deposit
     * @param amount The amount of the token to deposit
     * @param referral The referral address
     * @return mintedAmount the amount of eETH minted to the caller (= msg.sender)
     */
    function depositWithERC20(address token, uint256 amount, address referral) external returns (uint256)

FeeWrapperLidoLiquidETH

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

submit

    /**
     * @notice Send funds to the pool with optional referral parameter
     * @dev This function is alternative way to submit funds. Supports optional referral address. 
     * @param   referral The referral address to use for the deposit (can be address(0) if none)
     * @return Amount of StETH shares generated
     */
    function submit(address referral) external payable returns (uint256)

FeeWrapperRenzo

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

deposit

    /**
     * @notice  Deposits an ERC20 collateral token into the protocol
     * @param   collateralToken  The address of the collateral ERC20 token to deposit
     * @param   amount The amount of the collateral token to deposit in base units
     * @param   referralId The referral ID to use for the deposit (can be 0 if none)
     */
    function deposit(IERC20 collateralToken, uint256 amount, uint256 referralId) external

depositETH

```
    /**
     * @notice  Allows a user to deposit ETH into the protocol and get back ezETH
     * @param   referralId The referral ID to use for the deposit (can be 0 if none)
     */
    function depositETH(uint256 referralId) external payable 
```

FeeWrapperKelpDAO


setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

depositAsset

    /**
     * @notice  helps user stake LST to the protocol
     * @param   asset LST asset address to stake
     * @param   depositAmount LST asset amount to stake
     * @param   minRSETHAmountExpected Minimum amount of rseth to receive
     * @param   referralId referral id
     */
    function depositAsset(
        address asset,
        uint256 depositAmount,
        uint256 minRSETHAmountExpected,
        string calldata referralId
    ) external


depositETH

    /**
     * @notice  Allows user to deposit ETH to the protocol
     * @param minRSETHAmountExpected Minimum amount of rseth to receive
     * @param referralId referral id
     */
    function depositETH(
        uint256 minRSETHAmountExpected,
        string calldata referralId
    ) external payable 

FeeWrapperMorphoAave

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

supply

    /**
     * @notice  Supplies underlying tokens to a specific market.
     * @param   poolToken The address of the market the user wants to interact with
     * @param   amount The amount of token (in underlying) to supply
     */
    function supply(address poolToken, uint256 amount) external


FeeWrapperMorphoCompound

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

supply

    /**
     * @notice  Supplies underlying tokens to a specific market.
     * @param   poolToken The address of the market the user wants to interact with
     * @param   amount The amount of token (in underlying) to supply
     */
    function supply(address poolToken, uint256 amount) external


FeeWrapperStakeWiseV3

setDepositContractConfig

    /**
     * @notice Sets the configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param whitelist Whether the contract is whitelisted
     * @param fee The fee (in basis points) to deduct on deposit
     * @return The configuration for the deposit contract
     */
    function setDepositContractConfig(
        address depositContract,
        bool whitelist,
        uint16 fee
    )
        external
        onlyOwner
        returns (DepositContractConfig memory) 

setFeeConfig

   /**
     * @notice Sets the fee configuration for a deposit contract
     * @dev Only callable by the owner
     * @param depositContract The address of the deposit contract
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        address depositContract,
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

deposit

  /**
   * @notice Deposit ETH to the Vault
   * @param depositAddress The address of the deposit contract
   * @param receiver The address that will receive Vault's shares
   * @param referrer The address of the referrer. Set to zero address if not used.
   * @return shares The number of shares minted
   */
  function deposit(address depositAddress, address receiver, address referrer) external payable returns (uint256 shares)

updatedStateAndDeposit

  /**
   * @notice Updates Vault state and deposits ETH to the Vault
   * @param depositAddress The address of the deposit contract
   * @param receiver The address that will receive Vault's shares
   * @param referrer The address of the referrer. Set to zero address if not used.
   * @param harvestParams The parameters for harvesting Keeper rewards
   * @return shares The number of shares minted
   */
  function updateStateAndDeposit(
    address depositAddress,
    address receiver,
    address referrer,
    IKeeperRewards.HarvestParams calldata harvestParams
  ) external payable returns (uint256 shares)


FeeWrapperBenqiLiquidAVAX

setEnabled

   /**
     * @notice Sets if fee contract is enabled
     * @dev Only callable by the owner
     * @param enabled whether the fee contract is enabled or not
     */
    function setEnabled(
        bool enabled,
    )
        external
        onlyOwner

setFeeConfig

   /**
     * @notice Sets the fee configuration
     * @dev Only callable by the owner
     * @param feePercentage The percentage of the deposit contract fee to share with fee recipient
     * @param feeRecipient the fee recipient
     * @return The fee configuration for the deposit contract
     */
    function setFeeConfig(
        uint8 feePercentage,
        address feeRecipient
    )
        external
        onlyOwner
        returns (FeeConfig memory)

submit

   /**
     * @notice Process user deposit, mints liquid tokens and increase the pool buffer
     * @return Amount of sAVAX shares generated
     */
    function submit() public payable returns (uint)

Security Considerations

  • Only the contract owner can update the fee percentage and other configurations by implementing the onlyOwner modifier.
  • Perform thorough testing and Trail of Bits audit before deploying to the mainnet.
  • The contracts are not designed to be behind a proxy, for simplicity.
  • The contracts will only act as intermediaries, facilitating deposits, deducting fees, transferring funds to the recipient, and not holding any funds.
  • Regularly review and deploy new contract versions to address any discovered vulnerabilities.