### Example: Using getStableInfo for Stable Swaps Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Demonstrates how to use `getStableInfo` to get pool details and then perform an exchange. Ensure you have the correct factory, token addresses, and pool type flag. ```Solidity (uint256 inputIdx, uint256 outputIdx, address pool) = UniversalRouterHelper.getStableInfo( stableFactory, USDC, USDT, 2 // 2-pool ); // Use for IStableSwap.exchange(inputIdx, outputIdx, amountIn, 0) IStableSwap(pool).exchange(inputIdx, outputIdx, 1000e6, 0); ``` -------------------------------- ### V2Swap Example with Minimum Output Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/errors.md Example of performing a V2 swap with a calculated minimum output amount to account for slippage. This demonstrates how to set amountOutMinimum to prevent the V2TooLittleReceived error. ```solidity uint256 expectedOut = 100e18; uint256 amountOutMin = (expectedOut * 99) / 100; // 1% slippage v2SwapExactInput(recipient, amountIn, amountOutMin, path, payer); ``` -------------------------------- ### V2SwapRouter v2SwapExactInput Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/V2SwapRouter.md Example of how to call the v2SwapExactInput function. Ensure the path array is correctly populated with token addresses and slippage protection is set via amountOutMinimum. ```solidity address[] memory path = new address[](2); path[0] = USDC; path[1] = WETH; v2SwapExactInput( recipient, 1000e6, // 1000 USDC 900e18, // minimum 900 WETH path, userAddress // payer ); ``` -------------------------------- ### V3SwapRouter: v3SwapExactInput Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/V3SwapRouter.md Example of how to use the v3SwapExactInput function to swap USDC to WETH to USDT through pools with 0.3% fees. Ensure correct path encoding and slippage protection. ```solidity // Swap USDC -> WETH -> USDT through pools with 0.3% fees bytes memory path = abi.encodePacked( USDC, uint24(3000), WETH, uint24(3000), USDT ); v3SwapExactInput( recipient, 1000e6, // 1000 USDC 900e6, // min 900 USDT path, userAddress ); ``` -------------------------------- ### V3 Path Encoding Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/V3SwapRouter.md Demonstrates how to encode a V3 path for a multi-hop swap involving USDC, WETH, and USDT with a 0.3% fee. ```Solidity abi.encodePacked( USDC, // 20 bytes uint24(3000), // 3 bytes (0.3% fee) WETH, // 20 bytes uint24(3000), // 3 bytes USDT // 20 bytes ) // total 66 bytes ``` -------------------------------- ### Initialize Concentrated Liquidity Pool Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md This example shows how to initialize a new Concentrated Liquidity pool using the INFI_CL_INITIALIZE_POOL command. It requires a PoolKey and the initial price. ```Solidity PoolKey memory poolKey = PoolKey({ currency0: Currency.wrap(USDC), currency1: Currency.wrap(WETH), hooks: IHooks(address(0)), // No hooks poolManager: ICLPoolManager(clPoolManager), fee: 3000, // 0.3% parameters: bytes32(0) }); uint160 initialPrice = 2000 << 96; // 2000 WETH per USDC (example) bytes memory input = abi.encode(poolKey, initialPrice); router.execute(abi.encodePacked(uint8(0x13)), [input], deadline); ``` -------------------------------- ### V2SwapRouter v2SwapExactOutput Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/V2SwapRouter.md Example of how to call the v2SwapExactOutput function. The path array is used in reverse order for calculations, and amountInMaximum protects against excessive input costs. ```solidity address[] memory path = new address[](2); path[0] = USDC; path[1] = WETH; v2SwapExactOutput( recipient, 100e18, // want exactly 100 WETH 2000e6, // max 2000 USDC path, userAddress ); ``` -------------------------------- ### InfinitySwapRouter Integration Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Demonstrates the integration pattern for the InfinitySwapRouter, showing how to encode commands and inputs for atomic execution, including Permit2 approvals, Infinity swaps, and output sweeping. Ensure Permit2 is approved once per token before executing. ```solidity bytes memory commands = abi.encodePacked( uint8(0x03), // PERMIT2_PERMIT_BATCH (if new approval) uint8(0x10), // INFI_SWAP uint8(0x04) // SWEEP output ); bytes[] memory inputs = new bytes[](3); inputs[0] = encodePermits(...); inputs[1] = encodeInfinityActions(...); inputs[2] = abi.encode(outputToken, userAddress, 0); router.execute(commands, inputs, deadline); ``` -------------------------------- ### Example: Using getStableAmountsIn for Multi-Pool Swaps Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Shows how to set up the path and flags arrays to calculate input amounts for a multi-hop stable swap. The returned array includes the final desired output amount. ```Solidity address[] memory path = new address[](3); path[0] = USDC; path[1] = USDT; path[2] = BUSD; uint256[] memory flags = new uint256[](2); flags[0] = 2; // USDC->USDT in 2-pool flags[1] = 2; // USDT->BUSD in 2-pool uint256[] memory amounts = UniversalRouterHelper.getStableAmountsIn( stableFactory, stableInfo, path, flags, 1000e18 // want 1000 BUSD output ); // amounts[0] = required USDC input // amounts[1] = intermediate USDT amount // amounts[2] = 1000e18 (output we want) ``` -------------------------------- ### PermitSingle Usage Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Demonstrates how to construct and sign a PermitSingle structure for user authorization. The signature is then encoded with the permit for command execution. ```solidity // User signs this structure with their private key IAllowanceTransfer.PermitSingle permit = IAllowanceTransfer.PermitSingle({ details: IAllowanceTransfer.TokenPermissions({ token: USDC, amount: 10000e6 }), spender: address(router), sigDeadline: block.timestamp + 3600 }); bytes memory signature = userSignature; // Include in command execution bytes memory input = abi.encode(permit, signature); ``` -------------------------------- ### V3SwapRouter: v3SwapExactOutput Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/V3SwapRouter.md Example demonstrating the v3SwapExactOutput function to obtain exactly 100 USDT by sending USDC through WETH. Sets a maximum input amount for slippage protection. ```solidity // Get exactly 100 USDT by sending USDC through WETH bytes memory path = abi.encodePacked( USDT, uint24(3000), WETH, uint24(3000), USDC ); v3SwapExactOutput( recipient, 100e6, // exactly 100 USDT 2000e6, // max 2000 USDC path, userAddress ); ``` -------------------------------- ### Ethereum Mainnet Router Initialization Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Example of initializing the UniversalRouter with parameters specific to the Ethereum Mainnet. Note that stable factory and info addresses are not deployed and are set to zero. ```solidity RouterParameters memory params = RouterParameters({ permit2: 0x000000000022D473030F116dFC111cAA155DB3EF, weth9: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, v2Factory: 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f, // Uniswap V2 v3Factory: 0x1F98431c8aB207c1f50eA2e8b4C64B1dA4E86b3c, // Uniswap V3 v3Deployer: 0x2257f48Cc49e4b3A17D98b8fC7Df60DBeFe6A87, v2InitCodeHash: 0x96e8ac4277198ff8b6f785c46ea216446d1bac20fe2e7cda9e51a185d628f009, v3InitCodeHash: 0xe34f199b19b2b4d1d648202d5f0daa94c7fbb82f0f4e1e2055c4c2cd8f5f7b9, stableFactory: 0x0000000000000000000000000000000000000000, // Not deployed stableInfo: 0x0000000000000000000000000000000000000000, infiVault: 0x0000000000000000000000000000000000000000, // Not deployed infiClPoolManager: 0x0000000000000000000000000000000000000000, infiBinPoolManager: 0x0000000000000000000000000000000000000000 }); ``` -------------------------------- ### Cross-Protocol Swap Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md An example of a cross-protocol swap, executing a V2 swap and then a V3 swap with its output. This operation is atomic, meaning it's all-or-nothing. ```solidity // Example: Swap V2, then swap output via V3, sweep result // Atomic, all-or-nothing execution ``` -------------------------------- ### Get Three-Token Stable Swap Pool Info Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Retrieves information for a three-token stable swap pool. This example shows how to find the index of a specific token within the pool. ```solidity IStableSwapFactory.StableSwapThreePoolPairInfo memory info = factory.getThreePoolPairInfo(USDC, USDT); // Find token index uint256 tokenIndex; if (USDC == info.token0) tokenIndex = 0; else if (USDC == info.token1) tokenIndex = 1; else if (USDC == info.token2) tokenIndex = 2; ``` -------------------------------- ### PermitBatch Usage Example Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Illustrates the creation of a PermitBatch structure, defining an array of TokenPermissions for multiple tokens and specifying the spender and signature deadline. ```solidity IAllowanceTransfer.TokenPermissions[] memory permissions = new IAllowanceTransfer.TokenPermissions[](2); permissions[0] = IAllowanceTransfer.TokenPermissions({ token: USDC, amount: 10000e6 }); permissions[1] = IAllowanceTransfer.TokenPermissions({ token: DAI, amount: 10000e18 }); IAllowanceTransfer.PermitBatch batch = IAllowanceTransfer.PermitBatch({ details: permissions, spender: address(router), sigDeadline: block.timestamp + 3600 }); ``` -------------------------------- ### BSC Testnet Router Initialization Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Example of initializing the UniversalRouter with parameters specific to the BSC Testnet. This includes addresses for WBNB Testnet, factories, and other network-specific contracts. ```solidity RouterParameters memory params = RouterParameters({ permit2: 0x000000000022D473030F116dFC111cAA155DB3EF, weth9: 0xae13d989dac2f0debff460ac112a837c89baa7cd, // WBNB Testnet v2Factory: 0x6725F303b14aFFCCEe25076B76a5A8Ea6dCD6778, v3Factory: 0x1F98431c8aB207c1f50eA2e8b4C64B1dA4E86b3c, v3Deployer: 0x2257f48Cc49e4b3A17D98b8fC7Df60DBeFe6A87, v2InitCodeHash: 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5, v3InitCodeHash: 0xe34f199b19b2b4d1d648202d5f0daa94c7fbb82f0f4e1e2055c4c2cd8f5f7b9, stableFactory: 0xE55e19Fb4F2D85175474b66b9a1f5D8c15DfC61d, stableInfo: 0x895d7c3F64d59Ee41E0843c8e4a76f2C75aADdE2, infiVault: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiClPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiBinPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79 }); ``` -------------------------------- ### Recovering from ExecutionFailed Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/errors.md Example of how to recover from an `ExecutionFailed` error by decoding the error data to get the command index and message. ```solidity try { router.execute(commands, inputs, deadline); } catch (bytes memory reason) { // Decode the error to get commandIndex (uint256 index, bytes memory msg) = abi.decode(reason, (uint256, bytes)); console.log("Command %d failed", index); } ``` -------------------------------- ### BSC Mainnet Router Initialization Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Example of initializing the UniversalRouter with parameters specific to the BSC Mainnet. This includes addresses for WBNB, factories, and other network-specific contracts. ```solidity RouterParameters memory params = RouterParameters({ permit2: 0x000000000022D473030F116dFC111cAA155DB3EF, weth9: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c, // WBNB v2Factory: 0xcA143Ce32Fe78f1f7019d7d551ced3F0D5299d3d, v3Factory: 0x1F98431c8aB207c1f50eA2e8b4C64B1dA4E86b3c, v3Deployer: 0x2257f48Cc49e4b3A17D98b8fC7Df60DBeFe6A87, v2InitCodeHash: 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5, v3InitCodeHash: 0xe34f199b19b2b4d1d648202d5f0daa94c7fbb82f0f4e1e2055c4c2cd8f5f7b9, stableFactory: 0xE55e19Fb4F2D85175474b66b9a1f5D8c15DfC61d, stableInfo: 0x895d7c3F64d59Ee41E0843c8e4a76f2C75aADdE2, infiVault: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiClPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiBinPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79 }); UniversalRouter router = new UniversalRouter(params); ``` -------------------------------- ### Example: Using sortTokens Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Demonstrates the usage of `sortTokens` to consistently order two token addresses. The function returns the addresses sorted from smallest to largest. ```Solidity (address token0, address token1) = UniversalRouterHelper.sortTokens(USDT, USDC); // Returns (USDC, USDT) since USDC < USDT ``` -------------------------------- ### Verify Init Code Hash in Tests Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Provides an example of how to verify the correct init code hash within a test function. It compares an expected hash against the actual hash calculated from the contract's creation code. ```solidity // Verify correct hash in test function testInitCodeHash() public { bytes32 expected = 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5; bytes32 actual = keccak256(type(PancakePair).creationCode); assertEq(actual, expected, "Wrong init code hash"); } ``` -------------------------------- ### Example Usage of _pay Function Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Illustrates how the _pay function is internally called when executing an INFI_SWAP command with a user as the payer, demonstrating the Permit2 routing mechanism. ```Solidity // When executing INFI_SWAP command with user as payer // Internally calls: _pay(USDC, userAddress, 1000e6) // Routes to vault via Permit2 if user is payer ``` -------------------------------- ### Stable Swap for Stablecoins Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md Example of performing a stable swap between stablecoins like USDC and USDT with minimal slippage. This can be achieved through a 2-pool or 3-pool stable swap configuration. ```solidity // USDC ↔ USDT with minimal slippage // Through 2-pool or 3-pool stable swap ``` -------------------------------- ### Initialize and Deploy UniversalRouter Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Demonstrates how to initialize the RouterParameters struct with specific contract addresses and then deploy a new UniversalRouter instance. ```solidity RouterParameters memory params = RouterParameters({ permit2: 0x000000000022D473030F116dFC111cAA155DB3EF, weth9: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, v2Factory: 0xcA143Ce32Fe78f1f7019d7d551ced3F0D5299d3d, v3Factory: 0x1F98431c8aB207c1f50eA2e8b4C64B1dA4E86b3c, v3Deployer: 0x2257f48Cc49e4b3A17D98b8fC7Df60DBeFe6A87, v2InitCodeHash: 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5, v3InitCodeHash: 0xe34f199b19b2b4d1d648202d5f0daa94c7fbb82f0f4e1e2055c4c2cd8f5f7b9, stableFactory: 0xE55e19Fb4F2D85175474b66b9a1f5D8c15DfC61d, stableInfo: 0x895d7c3F64d59Ee41E0843c8e4a76f2C75aADdE2, infiVault: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiClPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiBinPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79 }); UniversalRouter router = new UniversalRouter(params); ``` -------------------------------- ### WETH Integration: Wrap, Swap, Unwrap Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md A three-step command sequence demonstrating WETH integration. It involves wrapping sent ETH to WETH, performing a swap, and then unwrapping the output back to ETH. ```solidity // Wrap sent ETH to WETH, swap it, unwrap output to ETH // Three-step command sequence ``` -------------------------------- ### Wrap and Unwrap Address as Currency Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Demonstrates how to wrap an address into the Currency type and unwrap it back to an address. ```solidity type Currency is address; // Wrap address as Currency Currency token = Currency.wrap(USDC); // Unwrap Currency to address address tokenAddr = Currency.unwrap(token); ``` -------------------------------- ### Get Original Transaction Initiator Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/Dispatcher.md Returns the original transaction initiator, accounting for self-reentrancy. Use this address instead of msg.sender in token transfers. ```Solidity function msgSender() public view override(BaseActionsRouter) returns (address) ``` ```Solidity address user = dispatcher.msgSender(); // Use `user` instead of msg.sender in token transfers ``` -------------------------------- ### Deployment Steps for Universal Router Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md Outlines the sequential steps required for deploying the Universal Router contract. This includes preparing parameters, deploying the contract, verification, and post-deployment configuration. ```solidity 1. Prepare RouterParameters struct 2. Deploy UniversalRouter(params) 3. Verify on blockchain explorer 4. Call acceptOwnership() if deployed via proxy 5. Update factory addresses if needed (via setStableSwap) ``` -------------------------------- ### Initialize Bin Pool Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md This snippet demonstrates initializing a new Bin pool with the INFI_BIN_INITIALIZE_POOL command. It uses a PoolKey and an initial active bin ID. ```Solidity PoolKey memory poolKey = PoolKey({ currency0: Currency.wrap(USDC), currency1: Currency.wrap(USDT), // Stablecoin pair hooks: IHooks(address(0)), poolManager: IBinPoolManager(binPoolManager), fee: 100, // 0.01% for stablecoins parameters: bytes32(0) }); uint24 initialActiveId = 2_700_000; // Example bin ID bytes memory input = abi.encode(poolKey, initialActiveId); router.execute(abi.encodePacked(uint8(0x14)), [input], deadline); ``` -------------------------------- ### Calculate V2 and V3 Init Code Hashes Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Demonstrates how to calculate the init code hashes for V2 Pairs and V3 Pools using `keccak256` on their respective creation codes. These hashes are used for verifying contract deployments. ```solidity // For V2 Pair: bytes32 v2InitCodeHash = keccak256(type(PancakePair).creationCode); // For V3 Pool: bytes32 v3InitCodeHash = keccak256(type(PancakePool).creationCode); ``` -------------------------------- ### Execute Infinity Swap and Wrap ETH Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md This snippet demonstrates how to perform an Infinity swap and then wrap any remaining ETH. It uses the INFI_SWAP and WRAP_ETH commands. ```Solidity bytes memory commands = abi.encodePacked( uint8(0x10), // INFI_SWAP uint8(0x0B) // WRAP_ETH ); bytes[] memory inputs = new bytes[](2); inputs[0] = encodeInfinitySwapAction(...); inputs[1] = abi.encode(recipient, ActionConstants.CONTRACT_BALANCE); router.execute(commands, inputs, deadline); ``` -------------------------------- ### Get Two-Token Stable Swap Pair Info Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Retrieves information for a two-token stable swap pool. Use the returned `swapContract` for swaps and `token0`/`token1` to determine token indices. ```solidity IStableSwapFactory factory = IStableSwapFactory(stableFactory); IStableSwapFactory.StableSwapPairInfo memory info = factory.getPairInfo(USDC, USDT); // Use info.swapContract to perform swaps // Use info.token0 and info.token1 to determine indices ``` -------------------------------- ### INFI_CL_INITIALIZE_POOL (0x13) Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Initializes a new Concentrated Liquidity (CL) pool in Infinity. This command sets up a new pool with specified currencies, fee, and initial price. ```APIDOC ## INFI_CL_INITIALIZE_POOL (0x13) ### Description Initializes a new Concentrated Liquidity (CL) pool in Infinity. This command sets up a new pool with specified currencies, fee, and initial price. ### Method `execute` (from InfinitySwapRouter contract) ### Parameters #### Input Parameters - `command` (bytes1): The command identifier, `0x13` for INFI_CL_INITIALIZE_POOL. - `input` (bytes): Encoded parameters including `poolKey` and `sqrtPriceX96`. #### `poolKey` Structure - `currency0` (Currency): First token (lower address). - `currency1` (Currency): Second token (higher address). - `hooks` (IHooks): Hook contract for custom logic. - `poolManager` (IPoolManager): Pool manager (CL or Bin). - `fee` (uint24): Pool fee in bips (e.g., 3000 for 0.3%). - `parameters` (bytes32): Custom parameters (varies by pool type). #### `sqrtPriceX96` - `uint160`: Initial pool price in Q64.96 format. ### Example ```solidity PoolKey memory poolKey = PoolKey({ currency0: Currency.wrap(USDC), currency1: Currency.wrap(WETH), hooks: IHooks(address(0)), // No hooks poolManager: ICLPoolManager(clPoolManager), // Assuming clPoolManager is defined fee: 3000, // 0.3% parameters: bytes32(0) }); uint160 initialPrice = 2000 << 96; // 2000 WETH per USDC (example) bytes memory input = abi.encode(poolKey, initialPrice); router.execute(abi.encodePacked(uint8(0x13)), [input], deadline); // Assuming router and deadline are defined ``` ### Return Value None (pool is created atomically) ### Throws - Implicitly if pool already exists. - Implicitly if invalid price or parameters. ``` -------------------------------- ### Get Stable Swap Pool Info Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Retrieves pool and token index information for a stable swap pair. Use this to determine the correct indices and contract address for a given stable swap pool. ```Solidity function getStableInfo( address stableSwapFactory, address input, address output, uint256 flag ) internal view returns (uint256 i, uint256 j, address swapContract) ``` -------------------------------- ### Encoding Commands with Flags Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/commands.md Demonstrates how to encode command codes, including the use of the FLAG_ALLOW_REVERT. ```solidity bytes1 cmd = bytes1(uint8(0x04)); // Same command but allow it to fail bytes1 cmd = bytes1(uint8(0x04 | 0x80)); // = 0x84 ``` -------------------------------- ### getAmountInMultihop Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Calculates the required input amount for a multi-hop swap given a desired output amount and a path of tokens. This function iterates through the path in reverse, calling getAmountIn for each hop to determine the necessary input at the start of the path. ```APIDOC ## getAmountInMultihop ### Description Calculates required input for multi-hop exact output swap. ### Signature ```solidity function getAmountInMultihop( address factory, bytes32 initCodeHash, uint256 amountOut, address[] calldata path ) internal view returns (uint256 amount, address pair) ``` ### Parameters #### Path Parameters - **factory** (address) - Required - V2 Factory address - **initCodeHash** (bytes32) - Required - Pair init code hash - **amountOut** (uint256) - Required - Desired final output amount - **path** (address[]) - Required - Token path (e.g., [USDC, WETH, DAI]) ### Returns #### Success Response - **amount** (uint256) - Required input amount (first token) - **pair** (address) - Required - First pair in the route ### Throws - `InvalidPath()` — if path.length < 2 ### Example ```solidity address[] memory path = new address[](3); path[0] = USDC; path[1] = WETH; path[2] = DAI; (uint256 amountIn, address firstPair) = UniversalRouterHelper.getAmountInMultihop( factory, initCodeHash, 100e18, // want 100 DAI path ); ``` ``` -------------------------------- ### Constructor Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Initializes the InfinitySwapRouter contract, setting up references to the Infinity Vault, Concentrated Liquidity Pool Manager, and Bin Pool Manager. ```APIDOC ## Constructor ### Description Initializes the InfinitySwapRouter contract with essential addresses for managing liquidity and pools. ### Parameters #### Path Parameters - **_vault** (address) - Required - Infinity Vault contract address (holds liquidity) - **_clPoolManager** (address) - Required - Concentrated Liquidity Pool Manager address - **_binPoolManager** (address) - Required - Bin Pool Manager address ### Details Initializes parent `InfinityRouter` with pool managers and sets up the vault reference for liquidity interactions. Enables Permit2 payment overrides. ``` -------------------------------- ### Deploy and Test Universal Router Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md Deploys the Universal Router with mainnet parameters and verifies its construction and basic execution capabilities. Ensure `getMainnetParams()` is correctly implemented to provide necessary configuration. ```solidity // test/DeploymentTest.sol function testRouterDeployment() public { RouterParameters memory params = getMainnetParams(); UniversalRouter router = new UniversalRouter(params); // Verify construction succeeded assertNotEq(address(router), address(0)); // Verify can call execute (no params validation in contract) bytes memory commands = ""; bytes[] memory inputs = new bytes[](0); // This should succeed with empty commands router.execute(commands, inputs, block.timestamp + 300); } ``` -------------------------------- ### INFI_BIN_INITIALIZE_POOL (0x14) Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Initializes a new Bin pool in Infinity. This command is similar to CL pool initialization but uses bin-based pricing and is more efficient for certain token pairs. ```APIDOC ## INFI_BIN_INITIALIZE_POOL (0x14) ### Description Initializes a new Bin pool in Infinity. This command is similar to CL pool initialization but uses bin-based pricing and is more efficient for certain token pairs. ### Method `execute` (from InfinitySwapRouter contract) ### Parameters #### Input Parameters - `command` (bytes1): The command identifier, `0x14` for INFI_BIN_INITIALIZE_POOL. - `input` (bytes): Encoded parameters including `poolKey` and `activeId`. #### `poolKey` Structure - `currency0` (Currency): First token (lower address). - `currency1` (Currency): Second token (higher address). - `hooks` (IHooks): Hook contract for custom logic. - `poolManager` (IPoolManager): Pool manager (CL or Bin). - `fee` (uint24): Pool fee in bips (e.g., 100 for 0.01%). - `parameters` (bytes32): Custom parameters (varies by pool type). #### `activeId` - `uint24`: Initial active bin ID. ### Difference from CL Pools - Uses `activeId` instead of `sqrtPriceX96` (bin-based pricing). - Bin pools use discrete price ticks rather than continuous concentrated liquidity. - More efficient for certain token pairs. ### Example ```solidity PoolKey memory poolKey = PoolKey({ currency0: Currency.wrap(USDC), currency1: Currency.wrap(USDT), // Stablecoin pair hooks: IHooks(address(0)), poolManager: IBinPoolManager(binPoolManager), // Assuming binPoolManager is defined fee: 100, // 0.01% for stablecoins parameters: bytes32(0) }); uint24 initialActiveId = 2_700_000; // Example bin ID bytes memory input = abi.encode(poolKey, initialActiveId); router.execute(abi.encodePacked(uint8(0x14)), [input], deadline); // Assuming router and deadline are defined ``` ``` -------------------------------- ### Simple V2 Swap with Sweep Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md Demonstrates a simple V2 swap operation combined with sweeping the output. This uses the V2_SWAP_EXACT_IN command followed by the SWEEP command. ```solidity // Command: Swap USDC for WETH, sweep output // Code: 0x08 (V2_SWAP_EXACT_IN) + 0x04 (SWEEP) ``` -------------------------------- ### Swap with Multiple Token Sources using Permit2 (Solidity) Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/Permit2Payments.md This pattern demonstrates how to use Permit2's batch transfer functionality to atomically pull multiple tokens from a user before executing swaps. It requires defining AllowanceTransferDetails and calling permit2TransferFrom. ```solidity // Use batch Permit2 to pull multiple tokens atomically IAllowanceTransfer.AllowanceTransferDetails[] memory details = ... permit2TransferFrom(details, userAddress); // Then execute swaps with router-held tokens bytes memory commands = abi.encodePacked( uint8(0x08), // V2_SWAP_EXACT_IN uint8(0x00) // V3_SWAP_EXACT_IN ); ``` -------------------------------- ### Initialize Concentrated Liquidity Pool Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/commands.md Initializes a Concentrated Liquidity pool within the Infinity protocol. Requires PoolKey details and a square root price. ```Solidity PoolKey, sqrtPriceX96 ``` -------------------------------- ### Wrap ETH, Swap, and Unwrap Command Sequence Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/commands.md Encodes a sequence to wrap ETH, perform a V2 swap with exact input, and then unwrap WETH. ```solidity bytes memory commands = abi.encodePacked( uint8(0x0B), // WRAP_ETH uint8(0x08), // V2_SWAP_EXACT_IN uint8(0x0C) // UNWRAP_WETH output ); ``` -------------------------------- ### Wrap ETH Before Swap Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/Payments.md This pattern first wraps ETH into WETH using the WRAP_ETH command, then proceeds with a V2 swap using the wrapped WETH. This is useful when interacting with V2 pools that require WETH. ```solidity bytes memory commands = abi.encodePacked( uint8(0x0B), // WRAP_ETH - convert ETH to WETH uint8(0x08) // V2_SWAP_EXACT_IN - swap WETH ); ``` -------------------------------- ### Usage of PoolKey Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Illustrates the creation of a PoolKey instance with specific currency pairs, fee, and other parameters. This key is used in pool initialization commands. ```solidity PoolKey memory key = PoolKey({ currency0: Currency.wrap(address(USDC)), currency1: Currency.wrap(address(WETH)), hooks: IHooks(address(0)), poolManager: ICLPoolManager(clPoolManager), fee: 3000, // 0.3% parameters: bytes32(0) }); // Used in INFI_CL_INITIALIZE_POOL and INFI_BIN_INITIALIZE_POOL commands ``` -------------------------------- ### Configure Private Key for Deployment Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/README.md Set the PRIVATE_KEY environment variable to the private key of the deployer account. The private key must be prefixed with '0x'. This is essential for authorizing the deployment transaction. ```bash // private key need to be prefixed with 0x export PRIVATE_KEY=0x ``` -------------------------------- ### Usage of AllowanceTransferDetails Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/types.md Demonstrates how to initialize and populate an array of AllowanceTransferDetails for batch transfers. This is used before executing router commands. ```solidity IAllowanceTransfer.AllowanceTransferDetails[] memory transfers = new IAllowanceTransfer.AllowanceTransferDetails[](2); transfers[0] = IAllowanceTransfer.AllowanceTransferDetails({ from: userAddress, to: address(this), amount: 1000e6, token: USDC }); transfers[1] = IAllowanceTransfer.AllowanceTransferDetails({ from: userAddress, to: address(this), amount: 10e18, token: DAI }); router.execute(commands, inputs, deadline); ``` -------------------------------- ### Approve and Transfer in Command Sequence (Solidity) Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/Permit2Payments.md This pattern combines user-provided Permit2 signatures with subsequent swap and sweep operations within a single command sequence. It's useful for executing a series of actions atomically. ```solidity bytes memory commands = abi.encodePacked( uint8(0x03), // PERMIT2_PERMIT_BATCH (user provides signature) uint8(0x08), // V2_SWAP_EXACT_IN (uses Permit2 internally) uint8(0x04) // SWEEP output ); ``` -------------------------------- ### Solidity PoolKey with Dynamic Parameters Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Demonstrates how to encode dynamic parameters for a PoolKey in Solidity. This allows for pool-specific configurations beyond standard parameters, such as custom fee structures or pool types. ```solidity bytes32 params = abi.encode( uint8 poolType, uint256 customParam1, uint256 customParam2 ); PoolKey memory poolKey = PoolKey({ ..., parameters: params }); ``` -------------------------------- ### InfinitySwapRouter Constructor Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/InfinitySwapRouter.md Initializes the InfinitySwapRouter contract, setting up references to the Infinity Vault, Concentrated Liquidity Pool Manager, and Bin Pool Manager. ```Solidity constructor( address _vault, address _clPoolManager, address _binPoolManager ) InfinityRouter( IVault(_vault), ICLPoolManager(_clPoolManager), IBinPoolManager(_binPoolManager) ) ``` -------------------------------- ### Constructor Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/StableSwapRouter.md Initializes the StableSwapRouter contract with the addresses of the StableSwapFactory and StableSwapInfo contracts. The caller is set as the owner. ```APIDOC ## Constructor ### Description Initializes the contract with factory and info addresses. Sets `msg.sender` as owner for configuration updates. ### Parameters #### Path Parameters - **_stableSwapFactory** (address) - Required - PancakeSwap Stable Swap Factory contract address - **_stableSwapInfo** (address) - Required - PancakeSwap Stable Swap Info contract address ### Details Initializes the contract with factory and info addresses. Sets `msg.sender` as owner for configuration updates. ``` -------------------------------- ### Deploy Universal Router Contract Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/configuration.md This script deploys the UniversalRouter contract. It requires a PRIVATE_KEY environment variable for broadcasting the transaction. Ensure all contract addresses and init code hashes are correctly configured for your network. ```solidity // script/DeployRouter.s.sol pragma solidity 0.8.26; import "forge-std/Script.sol"; import {UniversalRouter} from "../src/UniversalRouter.sol"; import {RouterParameters} from "../src/base/RouterImmutables.sol"; contract DeployRouter is Script { function run() external { uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); vm.startBroadcast(deployerPrivateKey); RouterParameters memory params = RouterParameters({ permit2: 0x000000000022D473030F116dFC111cAA155DB3EF, weth9: 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c, v2Factory: 0xcA143Ce32Fe78f1f7019d7d551ced3F0D5299d3d, v3Factory: 0x1F98431c8aB207c1f50eA2e8b4C64B1dA4E86b3c, v3Deployer: 0x2257f48Cc49e4b3A17D98b8fC7Df60DBeFe6A87, v2InitCodeHash: 0x00fb7f630766e6a796048ea87d01acd3068e8ff67d078148a3fa3f4a84f69bd5, v3InitCodeHash: 0xe34f199b19b2b4d1d648202d5f0daa94c7fbb82f0f4e1e2055c4c2cd8f5f7b9, stableFactory: 0xE55e19Fb4F2D85175474b66b9a1f5D8c15DfC61d, stableInfo: 0x895d7c3F64d59Ee41E0843c8e4a76f2C75aADdE2, infiVault: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiClPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79, infiBinPoolManager: 0xc31dF97C51e0EeecE5a7f3b11ca1b60DBFf8ED79 }); UniversalRouter router = new UniversalRouter(params); console.log("UniversalRouter deployed at:", address(router)); vm.stopBroadcast(); } } ``` -------------------------------- ### Calculate Multihop Input Amount (V2) Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/UniversalRouterHelper.md Calculates the required input amount for a multi-hop exact output swap using V2 pairs. Ensure the path has at least two tokens. ```solidity function getAmountInMultihop( address factory, bytes32 initCodeHash, uint256 amountOut, address[] calldata path ) internal view returns (uint256 amount, address pair) ``` ```solidity address[] memory path = new address[](3); path[0] = USDC; path[1] = WETH; path[2] = DAI; (uint256 amountIn, address firstPair) = UniversalRouterHelper.getAmountInMultihop( factory, initCodeHash, 100e18, // want 100 DAI path ); ``` -------------------------------- ### Balance Check for Conditional Logic Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/INDEX.md Demonstrates the BALANCE_CHECK_ERC20 command, used to verify a token balance before executing conditional logic. The check can be marked as optional to allow execution to continue even if it fails. ```solidity // Check token balance before executing conditional logic // Mark as optional to continue even if check fails ``` -------------------------------- ### Command Dispatch Flow Overview Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/commands.md Illustrates the order in which the dispatcher processes commands, categorized by their command codes. ```text command < 0x21? ├─ command < 0x10? │ ├─ command < 0x08? │ │ ├─ 0x00: V3_SWAP_EXACT_IN │ │ ├─ 0x01: V3_SWAP_EXACT_OUT │ │ ├─ 0x02: PERMIT2_TRANSFER_FROM │ │ ├─ 0x03: PERMIT2_PERMIT_BATCH │ │ ├─ 0x04: SWEEP │ │ ├─ 0x05: TRANSFER │ │ ├─ 0x06: PAY_PORTION │ │ └─ 0x07: (placeholder) │ └─ 0x08–0x0F: │ ├─ 0x08: V2_SWAP_EXACT_IN │ ├─ 0x09: V2_SWAP_EXACT_OUT │ ├─ 0x0A: PERMIT2_PERMIT │ ├─ 0x0B: WRAP_ETH │ ├─ 0x0C: UNWRAP_WETH │ ├─ 0x0D: PERMIT2_TRANSFER_FROM_BATCH │ ├─ 0x0E: BALANCE_CHECK_ERC20 │ └─ 0x0F: (placeholder) ├─ 0x10–0x14: │ ├─ 0x10: INFI_SWAP │ ├─ 0x11–0x12: (placeholders) │ ├─ 0x13: INFI_CL_INITIALIZE_POOL │ ├─ 0x14: INFI_BIN_INITIALIZE_POOL │ └─ 0x15–0x20: (placeholders) └─ 0x21–0x23: ├─ 0x21: EXECUTE_SUB_PLAN ├─ 0x22: STABLE_SWAP_EXACT_IN ├─ 0x23: STABLE_SWAP_EXACT_OUT └─ 0x24–0x3F: (placeholders) ``` -------------------------------- ### Initialize Bin Pool Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/commands.md Initializes a Bin pool in the Infinity protocol. Uses an activeId (uint24) instead of sqrtPriceX96 for initialization. ```Solidity PoolKey, activeId ``` -------------------------------- ### StableSwapRouter Constructor Source: https://github.com/pancakeswap/infinity-universal-router/blob/main/_autodocs/api-reference/StableSwapRouter.md Initializes the StableSwapRouter contract with the addresses of the Stable Swap Factory and Info contracts. The contract deployer is set as the owner. ```solidity constructor(address _stableSwapFactory, address _stableSwapInfo) Ownable(msg.sender) ```