Supermigrate is a protocol designed to facilitate the seamless migration of liquidity from Ethereum (L1) to the Superchain. The primary focus is on migrating liquidity from Uniswap V2 and V3 pools on Ethereum to Aerodrome pools on Base. This documentation provides a comprehensive overview of the protocol's components, functionality, and usage.
The Supermigrate protocol consists of two main components:
-
LiquidityMigration Contract (L1): Deployed on Ethereum, this contract handles the removal of liquidity from Uniswap pools and initiates the cross-chain transfer.
-
L2LiquidityManager Contract (L2): Deployed on Base (Layer 2), this contract receives the migrated assets and manages their deployment into Aerodrome pools.
The system utilizes LayerZero for cross-chain messaging and asset bridging.
migrateERC20Liquidity
: Initiates the migration process for ERC20 tokens._removeLiquidity
: Internal function to remove liquidity from Uniswap V2 or V3 pools._bridgeTokens
: Internal function to bridge tokens to L2.
- Supports both Uniswap V2 and V3 pools
- Handles ERC20 tokens and ETH (wrapped as WETH)
- Utilizes LayerZero for cross-chain messaging
_lzReceive
: Receives cross-chain messages and processes migrated liquidity._depositLiquidity
: Internal function to deposit liquidity into Aerodrome pools._balanceTokenRatio
: Ensures optimal token ratio before liquidity provision.
- Supports various Aerodrome pool types (stable, volatile, concentrated)
- Manages user positions and staked LP tokens
- Handles token swaps to balance liquidity ratios
- User initiates migration by calling
migrateERC20Liquidity
on the L1 contract. - LiquidityMigration removes liquidity from Uniswap.
- Assets are bridged to L2 using the L1 Standard Bridge.
- A cross-chain message is sent to L2 via LayerZero.
- L2LiquidityManager receives the message and bridged assets.
- Liquidity is automatically deposited into corresponding Aerodrome pools.
- LP tokens are minted and sent to the user.
- Cross-Chain Compatibility: Seamless migration between Ethereum and Base.
- Multi-Pool Support: Handles Uniswap V2, V3, and Aerodrome pools.
- Optimized Liquidity Provision: Balances token ratios for optimal liquidity deployment.
- Flexible Asset Handling: Supports ERC20 tokens and ETH.
- User Position Tracking: Maintains records of user liquidity and staked LP tokens.
- Fee Mechanism: Incorporates a fee system for protocol sustainability.
- Slippage Protection: Implements slippage checks to protect users during token swaps and liquidity provision.
- Access Control: Utilizes OpenZeppelin's Ownable for critical functions.
- Cross-Chain Security: Leverages LayerZero's security features for cross-chain messaging.
- Decimal Handling: Properly manages token decimals to prevent rounding errors.
Initiates the migration of liquidity from Uniswap V2 or V3 pools to L2.
function migrateERC20Liquidity(MigrationParams calldata params, bytes calldata _options)
external
payable
returns (MessagingReceipt memory receipt)
params
: A struct containing migration parameters:dstEid
: Destination chain ID (uint32)tokenA
: Address of the first token in the pairtokenB
: Address of the second token in the pairl2TokenA
: Address of the first token on L2l2TokenB
: Address of the second token on L2liquidity
: Amount of liquidity to migrate (uint256)tokenId
: Token ID for Uniswap V3 positions (uint256)amountAMin
: Minimum amount of tokenA to receive (uint256)amountBMin
: Minimum amount of tokenB to receive (uint256)deadline
: Expiration timestamp for the transaction (uint256)minGasLimit
: Minimum gas limit for the L2 transaction (uint32)poolType
: Enum representing the pool type (STABLE, VOLATILE, CONCENTRATED)stakeLPtokens
: Boolean indicating whether to stake LP tokens on L2
_options
: LayerZero options for cross-chain messaging
receipt
: A struct containing information about the cross-chain message
- This function requires
msg.value
to cover the LayerZero fee. - Ensure tokens are approved for the contract before calling.
Provides a quote for the LayerZero fee required for migration.
function quote(
uint32 _dstEid,
address tokenA,
address tokenB,
uint256 liquidity,
bytes memory _options,
bool _payInLzToken
) public view returns (MessagingFee memory fee)
_dstEid
: Destination chain IDtokenA
: Address of the first token in the pairtokenB
: Address of the second token in the pairliquidity
: Amount of liquidity to migrate_options
: LayerZero options_payInLzToken
: Whether to pay the fee in LZ token
fee
: A struct containing the fee details
Checks if a given token pair has a Uniswap V3 pool.
function isV3Pool(address tokenA, address tokenB) public view returns (bool)
tokenA
: Address of the first tokentokenB
: Address of the second token
bool
: True if a V3 pool exists, false otherwise
Adds a new pool to the Supermigrate system. Only callable by the contract owner.
function setPool(address tokenA, address tokenB, address pool, address gauge) external onlyOwner
tokenA
: Address of the first token in the pairtokenB
: Address of the second token in the pairpool
: Address of the Aerodrome poolgauge
: Address of the gauge for the pool
Sets the migration fee. Only callable by the contract owner.
function setFee(uint256 _newFee) external onlyOwner
_newFee
: New fee percentage (based on FEE_DENOMINATOR)
Retrieves pool and gauge addresses for a token pair.
function getPool(address tokenA, address tokenB) external view returns (address pool, address gauge)
tokenA
: Address of the first tokentokenB
: Address of the second token
pool
: Address of the Aerodrome poolgauge
: Address of the gauge
Returns the total number of pools in the Supermigrate system.
function getPoolsCount() external view returns (uint256)
uint256
: Number of pools
Retrieves a range of pools within the Supermigrate system.
function getPools(uint256 start, uint256 end) external view returns (address[] memory pools, address[] memory gauges)
start
: Start index of the rangeend
: End index of the range (exclusive)
pools
: Array of pool addressesgauges
: Array of corresponding gauge addresses
Gets the liquidity amount for a user and token.
function getUserLiquidity(address user, address token) external view returns (uint256)
user
: Address of the usertoken
: Address of the token
uint256
: Liquidity amount
Gets the staked LP token amount for a user and pool.
function getUserStakedLP(address user, address pool) external view returns (uint256)
user
: Address of the userpool
: Address of the pool
uint256
: Staked LP token amount
Stakes LP tokens in the corresponding gauge.
function stakeLPToken(uint256 amount, address tokenA, address tokenB) external
amount
: The amount of LP tokens to staketokenA
: The address of the first token in the pairtokenB
: The address of the second token in the pair
- User must approve the gauge to spend their LP tokens before calling this function
Unstakes LP tokens from the corresponding gauge.
function unstakeLPToken(uint256 amount, address tokenA, address tokenB) external
amount
: The amount of LP tokens to unstaketokenA
: The address of the first token in the pairtokenB
: The address of the second token in the pair
- This function will fail if the user tries to unstake more than they have staked
Claims Aero rewards for the caller from the specified pool's gauge.
function claimAeroRewards(address tokenA, address tokenB) external
tokenA
: The address of the first token in the pairtokenB
: The address of the second token in the pair
- Always check return values and handle potential reverts.
- For functions that modify state, ensure proper gas estimation.
- Use
quote
function before callingmigrateERC20Liquidity
to estimate required ETH for LayerZero fees. - Monitor emitted events for additional information and transaction confirmation.
- For L2 operations, ensure proper token approvals before staking or unstaking LP tokens.
For any questions or issues, please refer to the full contract code or contact the Supermigrate development team.
- Support for additional Superchain networks and DEXes.
- Integration with yield farming protocols on L2.
For more information or support, please contact the Supermigrate team or refer to our GitHub repository.