Skip to main content

Fee Splitter Preset

The Immutable Fee Splitter contract contains functionality that collects fees from transactions and divide them amongst recipients. This can be used for a variety of use cases included when royalties are paid to more than one wallet address

Fee SplitterFee Splitter

Key functionalityRecommended usage
  • Sending fees to multiple recipients
  • Sending royalties to multiple recipients
  • Sending staking rewards to multiple recipients
  • Collecting fees from transactions and dividing them between recipients in a gas efficent manner

Installation, usage and deployment

Installation

The preset contract is contained within the contracts repository which can be easily added to your project via:

npm install @imtbl/contracts

We recommend using existing frameworks such as Hardhat or Foundry in order to set up your own smart contract development environment from scratch.

The fee splitting contract can be found in the contracts repository here

Usage

tip

Immutable’s fee splitting contract deployment is exclusive to clients in partnership with Immutable. If you wish to deploy Immutable's, or your own, fee splitting smart contract on zkEVM, please contact your Immutable account manager.

The fee splitting contract is a smart contract designed for the collection and distribution of ERC20 tokens. It offers key benefits such as:

  • Multi-Recipient Support: Enables allocation of transaction fees to multiple recipients, expanding beyond the traditional single-recipient model.
  • On-Chain Transparency: Details fee recipient's wallet addresses and their shares on the blockchain, ensuring transparency and trust.
  • Gas Efficiency: More gas efficient than real-time fee splitting and allocating, especially beneficial for repeated transactions.

Immutable’s fee splitting contracts support predefined fee allocations set by the admin user. ERC20 tokens sent to the contract are held for fee distribution. The releaseAll([Array of ERC20 tokens]) function facilitates the release of accumulated fees to the designated recipients to the amount specified by the contract.

note

The releaseAll([Array of ERC20 tokens]) function requires specifying each ERC20 token address to be released. Native tokens, like IMX for zkEVM, are automatically released without specification. Calling releaseAll() with no inputs releases all IMX held by the fee splitter contract to the recipients specified by the contract.

Fee Splitting Contract Splitting Fees

The diagram above shows multiple fee splitting contracts, as each contract has a fixed allocation. Multiple contracts are required in scenarios like:

  • Different Recipients: A unique fee splitter contract is required for each unique combination of fee recipients.
  • Varied Distribution Percentages: Different fee allocation percentages to the same recipients necessitate separate contracts. For example, two assets demanding a 50/50 split and a 70/30 split between the same recipients' wallets would require two separate contracts.

Smart contract development

Typescript client

@imtbl/contracts comes with a Typescript client that can be used to interact with a deployed Fee Splitter contract:

Deployment

To deploy smart contracts on Immutable zkEVM, see the deploying smart contracts quickstart guide.

Configure Hardhat

Update your project's hardhat.config.js/ts file with the following code. This file is located in your smart contract repository. If you want to be able to manage multiple solidity versions, refer to the Hardhat documentation on Multiple Solidity Versions.

solidity: {
version: "0.8.17",
settings: {
optimizer: {
enabled: true,
runs: 200,
},
},
},

Functionality and design

Whilst the contract embeds the recommended functionality, it can also be extended or refactored to fit the developer's needs. With a caveat of extending functionality may introduce vulnerabilities inside your smart contracts, care should be taken.

Functionality

Release Funds to Fee Recipients

The fee splitter contract serves as a centralized wallet, collecting fees in the form of ERC20 tokens. Executing the releaseAll(tokens[]) function triggers the distribution of all specified ERC20 tokens (identified by contract addresses in the array) and the chain's native token (e.g., IMX) to the fee recipients according to the smart contract's predefined allocation.

If releaseAll() is called without specifying ERC20 contract addresses, only the native token will be released to the fee recipients. The party initiating the releaseAll() function bears the gas costs for the entire fee distribution process.

note

The releaseAll(tokens[]) function releases funds to the fee recipients as per the contract's current allocation configuration. If the admin user updates the fee structure while there are unreleased fees in the contract, these will be distributed according to the new, not the old, allocation configuration.

Access Control for Releasing Funds

Admin users have the authority to grant or revoke access to the releaseAll() function. Given that the function does not permit alteration of the fee allocation, it can be made accessible to all fee recipients, enabling them to autonomously collect their fees. The caller, however, must cover the gas fees for the entire fee distribution (i.e. to send gas to themselves and all other recipients).

ERC20 Allowlist

The fee splitter contract incorporates an ERC20 allowlist, which determines the eligibility of specific ERC20 tokens as fees to be distributed to recipients. While the contract can receive any ERC20 token as a fee, only approved tokens will be allocated to the fee recipients.

Adding an ERC20 to the Allowlist

If an ERC20 token not listed on your fee splitter contract's allowlist is received by the contract, it will not be released when the releaseAll(tokens[]) function is triggered. To add a specific zkEVM ERC20 contract to your fee splitter allowlist, use the addToAllowlist([ERC20_ADDRESS]) function.

Before adding an ERC20 token to your allowlist, Immutable recommends ensuring the following:

  • The address corresponds to the correct ERC20 address for the desired token. Immutable maintains a list of common ERC20 token addresses here.
  • Ensure that your compliance team approves your studio accepting payment in the ERC20 token you intend to add to this list.

Removing an ERC20 from the Allowlist

To remove an ERC20 token from your allowlist, use the removeFromAllowlist([ERC20_ADDRESS]) function.

Removing an ERC20 token from the allowlist will not prevent users and smart contracts from forwarding unwanted ERC20 tokens to your fee splitter contract. However, it will prevent these tokens from being distributed to your recipients.

The unwanted ERC20 tokens will accumulate in the fee splitter contract until they have been added to the allowlist.

tip

Immutable will soon introduce an additional field to the Blockchain Data API endpoint - Tokens. This new field will provide information to the Web3 community about registered ERC20 tokens.

Registered tokens are ERC20 contracts recognized by Immutable, serving to prevent consumers from transacting in fraudulent tokens that have been mislabeled. This flag can assist in identifying the desired ERC20 token address for your payment.

Stay tuned to this page for further updates.

Override Payee Configuration

As royalty configurations may evolve over the lifespan of a game, the fee splitter contract allows admin users to update fee allocations in the contract. When the contract's fee allocation is adjusted, all fees held by the contract are reallocated according to the new setup. Consequently, it's recommended to use the releaseAll() function before any amendments to ensure that fees are distributed according to the allocation present at the time of their accrual.

If a previously minted asset routes fees to this contract, it will automatically adopt the new configuration without having to update each minted asset individually.

Interface

FunctionDescription
releaseAll(tokens[])Release specified ERC20 tokens + IMX to payees
releasable(address - payeeAddress)Return the amount of IMX tokens held for payee
releasable(address - erc20, address - payeeAddress)Return the amount of specified ERC20 tokens held for payee
overridePayees(address payable[] memory payees, uint256[] memory shares_)Allows admin role to replace an existing payee allocation and distribution of fee splitter contract
addToAllowlist(erc20)Admin role can add ERC20 tokens to allow list permitting them for fee distribution
removeFromAllowlist(erc20)Admin role can remove ERC20 tokens from allow list restricting them for fee distribution
grantReleaseFundsRole(address)Admin role can add users to be able to release funds held by the contract via the releaseAll() function. User cannot change fee distribution
shares(address)
totalShares()
payee(uint256 index)