Aggregator Smart Contract Interface

Aggregator Contract (On-Chain)

The Aggregator contract is the core on-chain interface that powers Madhouse swaps. It handles routing across multiple adapters and liquidity sources, applies protocol and integrator fees, and enforces all swap validations.

All swaps whether initiated via the API, SDK, or directly on-chain ultimately route through this contract.

Overview

The Aggregator contract supports three swap patterns, each using the same underlying logic:

  1. Basic Swap – Simple swap execution without any integrator attribution or fees. Ideal for personal wallets, internal protocol use, or when you don't need fee collection. This is the most gas-efficient option since it skips fee accounting logic.

  2. Tracked Swap – tags your integratorAddress for volume tracking and attribution purposes, but doesn't charge any fee. Useful when the integrator wants to monitor the integration's usage without taking a cut. The protocol can use this data for partnership analytics and incentive programs.

  3. Fee-Bearing Swap – tags your integratorAddress and charges a custom integratorFee , which is automatically deducted from the input amount and sent to your address. This enables monetization for integrators. The protocol may also take a share of integrators’ fee based on governance settings.

All three patterns are handled via a single unified interface for simplicity and consistency.

Swap Parameters

Below are the key parameters used in all swap() variants.

Parameter
Type
Description

tokenFromAddress

address

Token being sold (input token).

tokenFromAmount

uint256

Amount of the input token to swap.

tokenToAddress

address

Token being received (output token).

tokenToAmount

uint256

Expected output amount (used to calculate positive slippage).

tokenToMinAmount

uint256

Minimum output amount accepted after slippage.

routes

Route[]

List of routes and adapters used in the swap.

integratorAddress

address

Address credited for tracking or fee sharing (optional).

integratorFee

uint128

Optional integrator fee as a percentage (1e18 = 100%).

Route Structure

Each Route defines one segment of the trade and allows splitting swaps across multiple DEXs or adapters.

Field
Type
Description

tokenFrom

address

Token being sold for this route.

tokenTo

address

Token being received for this route.

adapter

address

Adapter contract handling execution on a DEX.

percent

uint256

Percentage of input to route here, scaled by ROUTE_PERCENT_BASE (1e16 = 100%).

additionalParams

bytes

Optional adapter-specific data (e.g., pool IDs, extra calldata).

Note: The sum of all percent values in a swap must equal 1e16 (100%). Otherwise, the contract reverts with InvalidRoutePercent.

Fee Model

Madhouse implements a flexible and transparent fee model consisting of three layers:

1. Protocol Fee

  • A single configurable fee applied to all swaps.

  • Exemption rule: single-hop swaps through a fee-free adapter (marked in freeOfChargeFeeAdapters) pay no protocol fee.

2. Integrator Fee (Optional)

  • Integrators can specify their own integratorFee on any swap.

  • The fee must be between minIntegratorFee and maxIntegratorFee.

  • Fees are automatically split between the integrator and the protocol using protocolIntegratorFeeShare.

3. Positive Slippage Share

  • When a swap executes at a better rate than expected, the profit (positive slippage) is shared between:

    • The user

    • The protocol’s fee receiver (feeReceiver)

  • Controlled by protocolPositiveSlippageShare.

Default Fee Configuration

Note: The protocolIntegratorFeeShare represents the percentage of the integrator fee that the protocol receives when an integrator charges a fee.

Example

If an integrator sets a 0.10% fee (i.e., 1e18-scaled value = 1000000000000000000 / 1000):

  • The integrator keeps 0.08%

  • The protocol receives 0.02% (20% of 0.10%)

Fee Configuration & View Functions

Function
Returns
Description

protocolFee()

uint128

Current protocol fee (scaled by 1e18).

minIntegratorFee()

uint128

Minimum allowed integrator fee.

maxIntegratorFee()

uint128

Maximum allowed integrator fee.

protocolIntegratorFeeShare()

uint128

Protocol share of integrator fee.

protocolPositiveSlippageShare()

uint128

Protocol share of positive slippage profit.

feeReceiver()

address

Address receiving all protocol fees and shares.

PERCENTAGE_BASE()

uint128

Constant base (1e18 = 100%).

ROUTE_PERCENT_BASE()

uint128

Constant route base (1e16 = 100%).

freeOfChargeFeeAdapters(address)

bool

Returns true if adapter is exempt from protocol fees (single-hop only).

activeAdapters(address)

bool

Returns true if the adapter is currently active.

Events

Event
Description

SwapExecuted(tokenFrom, tokenFromAmount, tokenTo, tokenToAmount)

Emitted when a swap completes successfully.

IntegratorFeePaid(integrator, token, amount)

Emitted when an integrator receives their fee share.

ProtocolFeeUpdated(protocolFee)

Emitted when the protocol fee is changed.

MinIntegratorFeeUpdated(minIntegratorFee)

Emitted when the minimum allowed integrator fee is updated.

MaxIntegratorFeeUpdated(maxIntegratorFee)

Emitted when the maximum allowed integrator fee is updated.

ProtocolIntegratorFeeShareUpdated(protocolIntegratorFeeShare)

Emitted when the protocol share of integrator fee is changed.

ProtocolPositiveSlippageShareUpdated(protocolPositiveSlippageShare)

Emitted when the slippage profit share ratio is updated.

FreeOfChargeFeeAdapterUpdated(adapter, isFreeOfCharge)

Emitted when an adapter’s fee-free status changes.

Errors

Fee Validation Errors

  • FeeReceiverAddressZero() – Attempt to set feeReceiver to zero address.

  • ProtocolFeeTooHigh() – protocolFee exceeds PERCENTAGE_BASE.

  • ProtocolFeeAlreadySet() – New value equals the current protocolFee.

  • MaxIntegratorFeeTooHigh() / MinIntegratorFeeTooHigh() – Value exceeds limits.

  • MaxIntegratorFeeLessThanMinIntegratorFee(max, min) – Inconsistent bounds.

  • MinIntegratorFeeGreaterThanMaxIntegratorFee(min, max) – Inconsistent bounds.

  • ProtocolIntegratorFeeShareTooHigh() / ProtocolIntegratorFeeShareAlreadySet() – Invalid or duplicate protocol share.

  • ProtocolPositiveSlippageShareTooHigh() / ProtocolPositiveSlippageShareAlreadySet() – Invalid or duplicate slippage share.

  • IntegratorAddressZero() – integratorFee > 0 but no integratorAddress provided.

  • IntegratorFeeExceedsMaxIntegratorFee(fee, max) – Exceeds maximum allowed.

  • IntegratorFeeBelowMinIntegratorFee(fee, min) – Below minimum allowed.

Swap Validation Errors

  • RoutesLengthZero() – No routes provided.

  • TokenFromCannotBeEqualToTokenTo() – Input and output tokens identical.

  • TokenFromAddressMismatch() / TokenToAddressMismatch() – Route mismatch with top-level swap params.

  • TokenFromAmountZero() – Input amount is zero.

  • TokenToAmountLessThanMinAmount() – Minimum output exceeds expected.

  • TokenFromAmountExceedsBalance() – Sender balance too low.

  • ReceivedAmountLessThanMinAmount() – Received less than tokenToMinAmount.

  • AdapterNotActive(adapter) – Route adapter inactive.

  • InvalidRoutePercent(percent) – Route percent invalid or > 100%.

  • InputAmountNotFullyUsed(remainingAmount) – Unused input left over.

  • NativeTokenAmountMismatch(expected, received) – Mismatch between sent and expected native value.

  • UnexpectedNativeTokenSent() – ETH sent for non-native token swap.

  • TransferFailed() – Native token transfer failed.

Example Usage

Below is an example of executing a swap directly on Monad:

Last updated