Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
SwapRouter
Compiler Version
v0.8.16+commit.07a7930e
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.16; import { ERC20, SafeTransferLib } from "src/base/ERC4626.sol"; import { Multicall } from "src/base/Multicall.sol"; import { IUniswapV2Router02 as IUniswapV2Router } from "src/interfaces/external/IUniswapV2Router02.sol"; import { IUniswapV3Router } from "src/interfaces/external/IUniswapV3Router.sol"; /** * @title Sommelier Swap Router * @notice Provides a universal interface allowing Sommelier contracts to interact with multiple * different exchanges to perform swaps. * @dev Perform multiple swaps using Multicall. * @author crispymangoes, Brian Le */ contract SwapRouter is Multicall { using SafeTransferLib for ERC20; /** * @param UNIV2 Uniswap V2 * @param UNIV3 Uniswap V3 */ enum Exchange { UNIV2, UNIV3 } /** * @notice Get the selector of the function to call in order to perform swap with a given exchange. */ mapping(Exchange => bytes4) public getExchangeSelector; // ========================================== CONSTRUCTOR ========================================== /** * @notice Uniswap V2 swap router contract. */ IUniswapV2Router public immutable uniswapV2Router; // 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D /** * @notice Uniswap V3 swap router contract. */ IUniswapV3Router public immutable uniswapV3Router; // 0xE592427A0AEce92De3Edee1F18E0157C05861564 /** * @param _uniswapV2Router address of the Uniswap V2 swap router contract * @param _uniswapV3Router address of the Uniswap V3 swap router contract */ constructor(IUniswapV2Router _uniswapV2Router, IUniswapV3Router _uniswapV3Router) { // Set up all exchanges. uniswapV2Router = _uniswapV2Router; uniswapV3Router = _uniswapV3Router; // Set up mapping between IDs and selectors. getExchangeSelector[Exchange.UNIV2] = SwapRouter(this).swapWithUniV2.selector; getExchangeSelector[Exchange.UNIV3] = SwapRouter(this).swapWithUniV3.selector; } // ======================================= SWAP OPERATIONS ======================================= /** * @notice Attempted to perform a swap that reverted without a message. */ error SwapRouter__SwapReverted(); /** * @notice Attempted to perform a swap with mismatched assetIn and swap data. * @param actual the address encoded into the swap data * @param expected the address passed in with assetIn */ error SwapRouter__AssetInMisMatch(address actual, address expected); /** * @notice Attempted to perform a swap with mismatched assetOut and swap data. * @param actual the address encoded into the swap data * @param expected the address passed in with assetIn */ error SwapRouter__AssetOutMisMatch(address actual, address expected); /** * @notice Perform a swap using a supported exchange. * @param exchange value dictating which exchange to use to make the swap * @param swapData encoded data used for the swap * @param receiver address to send the received assets to * @return amountOut amount of assets received from the swap */ function swap( Exchange exchange, bytes memory swapData, address receiver, ERC20 assetIn, ERC20 assetOut ) external returns (uint256 amountOut) { // Route swap call to appropriate function using selector. (bool success, bytes memory result) = address(this).delegatecall( abi.encodeWithSelector(getExchangeSelector[exchange], swapData, receiver, assetIn, assetOut) ); if (!success) { // If there is return data, the call reverted with a reason or a custom error so we // bubble up the error message. if (result.length > 0) { assembly { let returndata_size := mload(result) revert(add(32, result), returndata_size) } } else { revert SwapRouter__SwapReverted(); } } amountOut = abi.decode(result, (uint256)); } /** * @notice Perform a swap using Uniswap V2. * @param swapData bytes variable storing the following swap information: * address[] path: array of addresses dictating what swap path to follow * uint256 amount: amount of the first asset in the path to swap * uint256 amountOutMin: the minimum amount of the last asset in the path to receive * @param receiver address to send the received assets to * @return amountOut amount of assets received from the swap */ function swapWithUniV2( bytes memory swapData, address receiver, ERC20 assetIn, ERC20 assetOut ) public returns (uint256 amountOut) { (address[] memory path, uint256 amount, uint256 amountOutMin) = abi.decode( swapData, (address[], uint256, uint256) ); // Check that path matches assetIn and assetOut. if (assetIn != ERC20(path[0])) revert SwapRouter__AssetInMisMatch(path[0], address(assetIn)); if (assetOut != ERC20(path[path.length - 1])) revert SwapRouter__AssetOutMisMatch(path[path.length - 1], address(assetOut)); // Transfer assets to this contract to swap. assetIn.safeTransferFrom(msg.sender, address(this), amount); // Approve assets to be swapped through the router. assetIn.safeApprove(address(uniswapV2Router), amount); // Execute the swap. uint256[] memory amountsOut = uniswapV2Router.swapExactTokensForTokens( amount, amountOutMin, path, receiver, block.timestamp + 60 ); amountOut = amountsOut[amountsOut.length - 1]; _checkApprovalIsZero(assetIn, address(uniswapV2Router)); } /** * @notice Perform a swap using Uniswap V3. * @param swapData bytes variable storing the following swap information * address[] path: array of addresses dictating what swap path to follow * uint24[] poolFees: array of pool fees dictating what swap pools to use * uint256 amount: amount of the first asset in the path to swap * uint256 amountOutMin: the minimum amount of the last asset in the path to receive * @param receiver address to send the received assets to * @return amountOut amount of assets received from the swap */ function swapWithUniV3( bytes memory swapData, address receiver, ERC20 assetIn, ERC20 assetOut ) public returns (uint256 amountOut) { (address[] memory path, uint24[] memory poolFees, uint256 amount, uint256 amountOutMin) = abi.decode( swapData, (address[], uint24[], uint256, uint256) ); // Check that path matches assetIn and assetOut. if (assetIn != ERC20(path[0])) revert SwapRouter__AssetInMisMatch(path[0], address(assetIn)); if (assetOut != ERC20(path[path.length - 1])) revert SwapRouter__AssetOutMisMatch(path[path.length - 1], address(assetOut)); // Transfer assets to this contract to swap. assetIn.safeTransferFrom(msg.sender, address(this), amount); // Approve assets to be swapped through the router. assetIn.safeApprove(address(uniswapV3Router), amount); // Encode swap parameters. bytes memory encodePackedPath = abi.encodePacked(address(assetIn)); for (uint256 i = 1; i < path.length; i++) encodePackedPath = abi.encodePacked(encodePackedPath, poolFees[i - 1], path[i]); // Execute the swap. amountOut = uniswapV3Router.exactInput( IUniswapV3Router.ExactInputParams({ path: encodePackedPath, recipient: receiver, deadline: block.timestamp + 60, amountIn: amount, amountOutMinimum: amountOutMin }) ); _checkApprovalIsZero(assetIn, address(uniswapV3Router)); } // ======================================= HELPER FUNCTIONS ======================================= /** * @notice Emitted when a swap does not use all the assets swap router approved. */ error SwapRouter__UnusedApproval(); /** * @notice Helper function that reverts if the Swap Router has unused approval after a swap is made. */ function _checkApprovalIsZero(ERC20 asset, address spender) internal view { if (asset.allowance(address(this), spender) != 0) revert SwapRouter__UnusedApproval(); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal INITIAL_CHAIN_ID; bytes32 internal INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import { ERC20 } from "src/base/ERC20.sol"; import { SafeTransferLib } from "src/base/SafeTransferLib.sol"; import { Math } from "src/utils/Math.sol"; /// @notice Minimal ERC4626 tokenized Vault implementation. /// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/mixins/ERC4626.sol) abstract contract ERC4626 is ERC20 { using SafeTransferLib for ERC20; using Math for uint256; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares); event Withdraw( address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares ); /*////////////////////////////////////////////////////////////// IMMUTABLES //////////////////////////////////////////////////////////////*/ ERC20 public asset; constructor( ERC20 _asset, string memory _name, string memory _symbol, uint8 _decimals ) ERC20(_name, _symbol, _decimals) { asset = _asset; } /*////////////////////////////////////////////////////////////// DEPOSIT/WITHDRAWAL LOGIC //////////////////////////////////////////////////////////////*/ function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) { // Check for rounding error since we round down in previewDeposit. require((shares = previewDeposit(assets)) != 0, "ZERO_SHARES"); beforeDeposit(assets, shares, receiver); // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(assets, shares, receiver); } function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) { assets = previewMint(shares); // No need to check for rounding error, previewMint rounds up. beforeDeposit(assets, shares, receiver); // Need to transfer before minting or ERC777s could reenter. asset.safeTransferFrom(msg.sender, address(this), assets); _mint(receiver, shares); emit Deposit(msg.sender, receiver, assets, shares); afterDeposit(assets, shares, receiver); } function withdraw( uint256 assets, address receiver, address owner ) public virtual returns (uint256 shares) { shares = previewWithdraw(assets); // No need to check for rounding error, previewWithdraw rounds up. if (msg.sender != owner) { uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; } beforeWithdraw(assets, shares, receiver, owner); _burn(owner, shares); emit Withdraw(msg.sender, receiver, owner, assets, shares); asset.safeTransfer(receiver, assets); afterWithdraw(assets, shares, receiver, owner); } function redeem( uint256 shares, address receiver, address owner ) public virtual returns (uint256 assets) { if (msg.sender != owner) { uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[owner][msg.sender] = allowed - shares; } // Check for rounding error since we round down in previewRedeem. require((assets = previewRedeem(shares)) != 0, "ZERO_ASSETS"); beforeWithdraw(assets, shares, receiver, owner); _burn(owner, shares); emit Withdraw(msg.sender, receiver, owner, assets, shares); asset.safeTransfer(receiver, assets); afterWithdraw(assets, shares, receiver, owner); } /*////////////////////////////////////////////////////////////// ACCOUNTING LOGIC //////////////////////////////////////////////////////////////*/ function totalAssets() public view virtual returns (uint256); function convertToShares(uint256 assets) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets()); } function convertToAssets(uint256 shares) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply); } function previewDeposit(uint256 assets) public view virtual returns (uint256) { return convertToShares(assets); } function previewMint(uint256 shares) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? shares : shares.mulDivUp(totalAssets(), supply); } function previewWithdraw(uint256 assets) public view virtual returns (uint256) { uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero. return supply == 0 ? assets : assets.mulDivUp(supply, totalAssets()); } function previewRedeem(uint256 shares) public view virtual returns (uint256) { return convertToAssets(shares); } /*////////////////////////////////////////////////////////////// DEPOSIT/WITHDRAWAL LIMIT LOGIC //////////////////////////////////////////////////////////////*/ function maxDeposit(address) public view virtual returns (uint256) { return type(uint256).max; } function maxMint(address) public view virtual returns (uint256) { return type(uint256).max; } function maxWithdraw(address owner) public view virtual returns (uint256) { return convertToAssets(balanceOf[owner]); } function maxRedeem(address owner) public view virtual returns (uint256) { return balanceOf[owner]; } /*////////////////////////////////////////////////////////////// INTERNAL HOOKS LOGIC //////////////////////////////////////////////////////////////*/ function beforeDeposit( uint256 assets, uint256 shares, address receiver ) internal virtual {} function afterDeposit( uint256 assets, uint256 shares, address receiver ) internal virtual {} function beforeWithdraw( uint256 assets, uint256 shares, address receiver, address owner ) internal virtual {} function afterWithdraw( uint256 assets, uint256 shares, address receiver, address owner ) internal virtual {} }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; import { IMulticall } from "src/interfaces/IMulticall.sol"; /** * @title Multicall * @notice Enables calling multiple methods in a single call to the contract * From: https://github.com/Uniswap/v3-periphery/blob/1d69caf0d6c8cfeae9acd1f34ead30018d6e6400/contracts/base/Multicall.sol */ abstract contract Multicall is IMulticall { /// @inheritdoc IMulticall function multicall(bytes[] calldata data) public payable override returns (bytes[] memory results) { results = new bytes[](data.length); for (uint256 i = 0; i < data.length; i++) { (bool success, bytes memory result) = address(this).delegatecall(data[i]); if (!success) { // Next 5 lines from https://ethereum.stackexchange.com/a/83577 // solhint-disable-next-line reason-string if (result.length < 68) revert(); assembly { result := add(result, 0x04) } revert(abi.decode(result, (string))); } results[i] = result; } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import { ERC20 } from "src/base/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title Multicall interface /// @notice Enables calling multiple methods in a single call to the contract // From: https://github.com/Uniswap/v3-periphery/contracts/interfaces/IMulticall.sol interface IMulticall { /// @notice Call multiple functions in the current contract and return the data from all of them if they all succeed /// @dev The `msg.value` should not be trusted for any method callable from multicall. /// @param data The encoded function data for each of the calls to make to this contract /// @return results The results from each of the calls passed in via data function multicall(bytes[] calldata data) external payable returns (bytes[] memory results); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity >=0.8.0; interface IUniswapV2Router01 { function factory() external pure returns (address); function WETH() external pure returns (address); function addLiquidity( address tokenA, address tokenB, uint256 amountADesired, uint256 amountBDesired, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns ( uint256 amountA, uint256 amountB, uint256 liquidity ); function addLiquidityETH( address token, uint256 amountTokenDesired, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external payable returns ( uint256 amountToken, uint256 amountETH, uint256 liquidity ); function removeLiquidity( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETH( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountToken, uint256 amountETH); function removeLiquidityWithPermit( address tokenA, address tokenB, uint256 liquidity, uint256 amountAMin, uint256 amountBMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountA, uint256 amountB); function removeLiquidityETHWithPermit( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountToken, uint256 amountETH); function swapExactTokensForTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapTokensForExactTokens( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactETHForTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function swapTokensForExactETH( uint256 amountOut, uint256 amountInMax, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapExactTokensForETH( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external returns (uint256[] memory amounts); function swapETHForExactTokens( uint256 amountOut, address[] calldata path, address to, uint256 deadline ) external payable returns (uint256[] memory amounts); function quote( uint256 amountA, uint256 reserveA, uint256 reserveB ) external pure returns (uint256 amountB); function getAmountOut( uint256 amountIn, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountOut); function getAmountIn( uint256 amountOut, uint256 reserveIn, uint256 reserveOut ) external pure returns (uint256 amountIn); function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts); function getAmountsIn(uint256 amountOut, address[] calldata path) external view returns (uint256[] memory amounts); } interface IUniswapV2Router02 is IUniswapV2Router01 { function removeLiquidityETHSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline ) external returns (uint256 amountETH); function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens( address token, uint256 liquidity, uint256 amountTokenMin, uint256 amountETHMin, address to, uint256 deadline, bool approveMax, uint8 v, bytes32 r, bytes32 s ) external returns (uint256 amountETH); function swapExactTokensForTokensSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; function swapExactETHForTokensSupportingFeeOnTransferTokens( uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external payable; function swapExactTokensForETHSupportingFeeOnTransferTokens( uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to, uint256 deadline ) external; }
// SPDX-License-Identifier: GPL-2.0-or-later pragma solidity >=0.8.0; /// @title Callback for IUniswapV3PoolActions#swap /// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface interface IUniswapV3SwapCallback { /// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap. /// @dev In the implementation you must pay the pool tokens owed for the swap. /// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory. /// amount0Delta and amount1Delta can both be 0 if no tokens were swapped. /// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token0 to the pool. /// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by /// the end of the swap. If positive, the callback must send that amount of token1 to the pool. /// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call function uniswapV3SwapCallback( int256 amount0Delta, int256 amount1Delta, bytes calldata data ) external; } /// @title Router token swapping functionality /// @notice Functions for swapping tokens via Uniswap V3 interface IUniswapV3Router is IUniswapV3SwapCallback { struct ExactInputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; uint160 sqrtPriceLimitX96; } /// @notice Swaps `amountIn` of one token for as much as possible of another token /// @param params The parameters necessary for the swap, encoded as `ExactInputSingleParams` in calldata /// @return amountOut The amount of the received token function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut); struct ExactInputParams { bytes path; address recipient; uint256 deadline; uint256 amountIn; uint256 amountOutMinimum; } /// @notice Swaps `amountIn` of one token for as much as possible of another along the specified path /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactInputParams` in calldata /// @return amountOut The amount of the received token function exactInput(ExactInputParams calldata params) external payable returns (uint256 amountOut); struct ExactOutputSingleParams { address tokenIn; address tokenOut; uint24 fee; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; uint160 sqrtPriceLimitX96; } /// @notice Swaps as little as possible of one token for `amountOut` of another token /// @param params The parameters necessary for the swap, encoded as `ExactOutputSingleParams` in calldata /// @return amountIn The amount of the input token function exactOutputSingle(ExactOutputSingleParams calldata params) external payable returns (uint256 amountIn); struct ExactOutputParams { bytes path; address recipient; uint256 deadline; uint256 amountOut; uint256 amountInMaximum; } /// @notice Swaps as little as possible of one token for `amountOut` of another along the specified path (reversed) /// @param params The parameters necessary for the multi-hop swap, encoded as `ExactOutputParams` in calldata /// @return amountIn The amount of the input token function exactOutput(ExactOutputParams calldata params) external payable returns (uint256 amountIn); }
// SPDX-License-Identifier: Apache-2.0 pragma solidity 0.8.16; library Math { /** * @notice Substract with a floor of 0 for the result. */ function subMinZero(uint256 x, uint256 y) internal pure returns (uint256) { return x > y ? x - y : 0; } /** * @notice Used to change the decimals of precision used for an amount. */ function changeDecimals( uint256 amount, uint8 fromDecimals, uint8 toDecimals ) internal pure returns (uint256) { if (fromDecimals == toDecimals) { return amount; } else if (fromDecimals < toDecimals) { return amount * 10**(toDecimals - fromDecimals); } else { return amount / 10**(fromDecimals - toDecimals); } } // ===================================== OPENZEPPELIN'S MATH ===================================== function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } // ================================= SOLMATE's FIXEDPOINTMATHLIB ================================= uint256 public constant WAD = 1e18; // The scalar of ETH and most ERC20s. function mulWadDown(uint256 x, uint256 y) internal pure returns (uint256) { return mulDivDown(x, y, WAD); // Equivalent to (x * y) / WAD rounded down. } function mulDivDown( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // Divide z by the denominator. z := div(z, denominator) } } function mulDivUp( uint256 x, uint256 y, uint256 denominator ) internal pure returns (uint256 z) { assembly { // Store x * y in z for now. z := mul(x, y) // Equivalent to require(denominator != 0 && (x == 0 || (x * y) / x == y)) if iszero(and(iszero(iszero(denominator)), or(iszero(x), eq(div(z, x), y)))) { revert(0, 0) } // First, divide z - 1 by the denominator and add 1. // We allow z - 1 to underflow if z is 0, because we multiply the // end result by 0 if z is zero, ensuring we return 0 if z is zero. z := mul(iszero(iszero(z)), add(div(sub(z, 1), denominator), 1)) } } }
{ "remappings": [ "@chainlink/=lib/chainlink/", "@compound/=lib/compound-protocol/contracts/", "@ds-test/=lib/forge-std/lib/ds-test/src/", "@ensdomains/=node_modules/@ensdomains/", "@forge-std/=lib/forge-std/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@solmate/=lib/solmate/src/", "@uniswap/v3-core/=lib/v3-core/", "@uniswap/v3-periphery/=lib/v3-periphery/", "@uniswapV3C/=lib/v3-core.git/contracts/", "@uniswapV3P/=lib/v3-periphery.git/contracts/", "chainlink/=lib/chainlink/contracts/src/v0.8/dev/vendor/@arbitrum/nitro-contracts/src/", "compound-protocol/=lib/compound-protocol/", "ds-test/=lib/forge-std/lib/ds-test/src/", "eth-gas-reporter/=node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=node_modules/hardhat/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solmate/=lib/solmate/src/", "v3-core.git/=lib/v3-core.git/contracts/", "v3-periphery.git/=lib/v3-periphery.git/contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "bytecodeHash": "ipfs" }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "london", "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IUniswapV2Router02","name":"_uniswapV2Router","type":"address"},{"internalType":"contract IUniswapV3Router","name":"_uniswapV3Router","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"actual","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"SwapRouter__AssetInMisMatch","type":"error"},{"inputs":[{"internalType":"address","name":"actual","type":"address"},{"internalType":"address","name":"expected","type":"address"}],"name":"SwapRouter__AssetOutMisMatch","type":"error"},{"inputs":[],"name":"SwapRouter__SwapReverted","type":"error"},{"inputs":[],"name":"SwapRouter__UnusedApproval","type":"error"},{"inputs":[{"internalType":"enum SwapRouter.Exchange","name":"","type":"uint8"}],"name":"getExchangeSelector","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"enum SwapRouter.Exchange","name":"exchange","type":"uint8"},{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"contract ERC20","name":"assetIn","type":"address"},{"internalType":"contract ERC20","name":"assetOut","type":"address"}],"name":"swap","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"contract ERC20","name":"assetIn","type":"address"},{"internalType":"contract ERC20","name":"assetOut","type":"address"}],"name":"swapWithUniV2","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"swapData","type":"bytes"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"contract ERC20","name":"assetIn","type":"address"},{"internalType":"contract ERC20","name":"assetOut","type":"address"}],"name":"swapWithUniV3","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"uniswapV2Router","outputs":[{"internalType":"contract IUniswapV2Router02","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"uniswapV3Router","outputs":[{"internalType":"contract IUniswapV3Router","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
60c060405234801561001057600080fd5b506040516115bc3803806115bc83398101604081905261002f916100cd565b6001600160a01b039182166080521660a052600060208190527fad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5805463ffffffff19908116635a0c82791790915560019091527fada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7d8054909116639d453f8d179055610107565b6001600160a01b03811681146100ca57600080fd5b50565b600080604083850312156100e057600080fd5b82516100eb816100b5565b60208401519092506100fc816100b5565b809150509250929050565b60805160a0516114686101546000396000818160d8015281816106ed015281816107c5015261089501526000818160870152818161046201528181610493015261055f01526114686000f3fe6080604052600436106100705760003560e01c80635a0c82791161004e5780635a0c8279146101285780639d453f8d14610148578063a1fbdf3914610168578063ac9650d8146101b157600080fd5b80631694505e146100755780632c76d7a6146100c65780632dfe1690146100fa575b600080fd5b34801561008157600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100d257600080fd5b506100a97f000000000000000000000000000000000000000000000000000000000000000081565b34801561010657600080fd5b5061011a610115366004610ca8565b6101d1565b6040519081526020016100bd565b34801561013457600080fd5b5061011a610143366004610d30565b6102ff565b34801561015457600080fd5b5061011a610163366004610d30565b61058f565b34801561017457600080fd5b50610198610183366004610da5565b60006020819052908152604090205460e01b81565b6040516001600160e01b031990911681526020016100bd565b6101c46101bf366004610dc7565b6108c6565b6040516100bd9190610e8c565b600080803081808a60018111156101ea576101ea610eee565b60018111156101fb576101fb610eee565b815260200190815260200160002060009054906101000a900460e01b8888888860405160240161022e9493929190610f04565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161026c9190610f40565b600060405180830381855af49150503d80600081146102a7576040519150601f19603f3d011682016040523d82523d6000602084013e6102ac565b606091505b5091509150816102df578051156102c65780518082602001fd5b6040516347167cef60e11b815260040160405180910390fd5b808060200190518101906102f39190610f5c565b98975050505050505050565b600080600080878060200190518101906103199190611008565b9250925092508260008151811061033257610332611058565b60200260200101516001600160a01b0316866001600160a01b0316146103a7578260008151811061036557610365611058565b60200260200101518660405163e539288160e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b60405180910390fd5b82600184516103b69190611084565b815181106103c6576103c6611058565b60200260200101516001600160a01b0316856001600160a01b03161461043e5782600184516103f59190611084565b8151811061040557610405611058565b6020026020010151856040516347052b6760e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b6104536001600160a01b038716333085610a1e565b6104876001600160a01b0387167f000000000000000000000000000000000000000000000000000000000000000084610aa8565b60006001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000166338ed17398484878c6104c742603c61109d565b6040518663ffffffff1660e01b81526004016104e79594939291906110b0565b6000604051808303816000875af1158015610506573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261052e9190810190611121565b9050806001825161053f9190611084565b8151811061054f5761054f611058565b60200260200101519450610583877f0000000000000000000000000000000000000000000000000000000000000000610b25565b50505050949350505050565b6000806000806000888060200190518101906105ab91906111b2565b9350935093509350836000815181106105c6576105c6611058565b60200260200101516001600160a01b0316876001600160a01b03161461063257836000815181106105f9576105f9611058565b60200260200101518760405163e539288160e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b83600185516106419190611084565b8151811061065157610651611058565b60200260200101516001600160a01b0316866001600160a01b0316146106c95783600185516106809190611084565b8151811061069057610690611058565b6020026020010151866040516347052b6760e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b6106de6001600160a01b038816333085610a1e565b6107126001600160a01b0388167f000000000000000000000000000000000000000000000000000000000000000084610aa8565b60408051606089901b6bffffffffffffffffffffffff1916602082015281516014818303018152603490910190915260015b85518110156107c257818561075a600184611084565b8151811061076a5761076a611058565b602002602001015187838151811061078457610784611058565b602002602001015160405160200161079e9392919061128d565b604051602081830303815290604052915080806107ba906112d9565b915050610744565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663c04b8d596040518060a001604052808481526020018c6001600160a01b0316815260200142603c61081f919061109d565b8152602001868152602001858152506040518263ffffffff1660e01b815260040161084a91906112f2565b6020604051808303816000875af1158015610869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088d9190610f5c565b95506108b9887f0000000000000000000000000000000000000000000000000000000000000000610b25565b5050505050949350505050565b60608167ffffffffffffffff8111156108e1576108e1610bcb565b60405190808252806020026020018201604052801561091457816020015b60608152602001906001900390816108ff5790505b50905060005b82811015610a17576000803086868581811061093857610938611058565b905060200281019061094a919061134a565b604051610958929190611398565b600060405180830381855af49150503d8060008114610993576040519150601f19603f3d011682016040523d82523d6000602084013e610998565b606091505b5091509150816109e4576044815110156109b157600080fd5b600481019050808060200190518101906109cb91906113a8565b60405162461bcd60e51b815260040161039e919061141f565b808484815181106109f7576109f7611058565b602002602001018190525050508080610a0f906112d9565b91505061091a565b5092915050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610aa15760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b604482015260640161039e565b5050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b1f5760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b604482015260640161039e565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b959190610f5c565b15610bb357604051637404a95160e01b815260040160405180910390fd5b5050565b803560028110610bc657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610c0a57610c0a610bcb565b604052919050565b600067ffffffffffffffff821115610c2c57610c2c610bcb565b50601f01601f191660200190565b600082601f830112610c4b57600080fd5b8135610c5e610c5982610c12565b610be1565b818152846020838601011115610c7357600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114610ca557600080fd5b50565b600080600080600060a08688031215610cc057600080fd5b610cc986610bb7565b9450602086013567ffffffffffffffff811115610ce557600080fd5b610cf188828901610c3a565b9450506040860135610d0281610c90565b92506060860135610d1281610c90565b91506080860135610d2281610c90565b809150509295509295909350565b60008060008060808587031215610d4657600080fd5b843567ffffffffffffffff811115610d5d57600080fd5b610d6987828801610c3a565b9450506020850135610d7a81610c90565b92506040850135610d8a81610c90565b91506060850135610d9a81610c90565b939692955090935050565b600060208284031215610db757600080fd5b610dc082610bb7565b9392505050565b60008060208385031215610dda57600080fd5b823567ffffffffffffffff80821115610df257600080fd5b818501915085601f830112610e0657600080fd5b813581811115610e1557600080fd5b8660208260051b8501011115610e2a57600080fd5b60209290920196919550909350505050565b60005b83811015610e57578181015183820152602001610e3f565b50506000910152565b60008151808452610e78816020860160208601610e3c565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015610ee157603f19888603018452610ecf858351610e60565b94509285019290850190600101610eb3565b5092979650505050505050565b634e487b7160e01b600052602160045260246000fd5b608081526000610f176080830187610e60565b6001600160a01b0395861660208401529385166040830152509216606090920191909152919050565b60008251610f52818460208701610e3c565b9190910192915050565b600060208284031215610f6e57600080fd5b5051919050565b600067ffffffffffffffff821115610f8f57610f8f610bcb565b5060051b60200190565b600082601f830112610faa57600080fd5b81516020610fba610c5983610f75565b82815260059290921b84018101918181019086841115610fd957600080fd5b8286015b84811015610ffd578051610ff081610c90565b8352918301918301610fdd565b509695505050505050565b60008060006060848603121561101d57600080fd5b835167ffffffffffffffff81111561103457600080fd5b61104086828701610f99565b93505060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156110975761109761106e565b92915050565b808201808211156110975761109761106e565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156111005784516001600160a01b0316835293830193918301916001016110db565b50506001600160a01b03969096166060850152505050608001529392505050565b6000602080838503121561113457600080fd5b825167ffffffffffffffff81111561114b57600080fd5b8301601f8101851361115c57600080fd5b805161116a610c5982610f75565b81815260059190911b8201830190838101908783111561118957600080fd5b928401925b828410156111a75783518252928401929084019061118e565b979650505050505050565b600080600080608085870312156111c857600080fd5b845167ffffffffffffffff808211156111e057600080fd5b6111ec88838901610f99565b955060209150818701518181111561120357600080fd5b87019050601f8101881361121657600080fd5b8051611224610c5982610f75565b81815260059190911b8201830190838101908a83111561124357600080fd5b928401925b8284101561127357835162ffffff811681146112645760008081fd5b82529284019290840190611248565b60408a01516060909a0151989b909a509650505050505050565b6000845161129f818460208901610e3c565b60e89490941b6001600160e81b0319169190930190815260609190911b6bffffffffffffffffffffffff1916600382015260170192915050565b6000600182016112eb576112eb61106e565b5060010190565b602081526000825160a0602084015261130e60c0840182610e60565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b6000808335601e1984360301811261136157600080fd5b83018035915067ffffffffffffffff82111561137c57600080fd5b60200191503681900382131561139157600080fd5b9250929050565b8183823760009101908152919050565b6000602082840312156113ba57600080fd5b815167ffffffffffffffff8111156113d157600080fd5b8201601f810184136113e257600080fd5b80516113f0610c5982610c12565b81815285602083850101111561140557600080fd5b611416826020830160208601610e3c565b95945050505050565b602081526000610dc06020830184610e6056fea2646970667358221220d7ec814f57cdb98d279e0fd08bc654057583499820ea222569f8adb86e2ecd3164736f6c634300081000330000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Deployed Bytecode
0x6080604052600436106100705760003560e01c80635a0c82791161004e5780635a0c8279146101285780639d453f8d14610148578063a1fbdf3914610168578063ac9650d8146101b157600080fd5b80631694505e146100755780632c76d7a6146100c65780632dfe1690146100fa575b600080fd5b34801561008157600080fd5b506100a97f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d81565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100d257600080fd5b506100a97f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156481565b34801561010657600080fd5b5061011a610115366004610ca8565b6101d1565b6040519081526020016100bd565b34801561013457600080fd5b5061011a610143366004610d30565b6102ff565b34801561015457600080fd5b5061011a610163366004610d30565b61058f565b34801561017457600080fd5b50610198610183366004610da5565b60006020819052908152604090205460e01b81565b6040516001600160e01b031990911681526020016100bd565b6101c46101bf366004610dc7565b6108c6565b6040516100bd9190610e8c565b600080803081808a60018111156101ea576101ea610eee565b60018111156101fb576101fb610eee565b815260200190815260200160002060009054906101000a900460e01b8888888860405160240161022e9493929190610f04565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b031990941693909317909252905161026c9190610f40565b600060405180830381855af49150503d80600081146102a7576040519150601f19603f3d011682016040523d82523d6000602084013e6102ac565b606091505b5091509150816102df578051156102c65780518082602001fd5b6040516347167cef60e11b815260040160405180910390fd5b808060200190518101906102f39190610f5c565b98975050505050505050565b600080600080878060200190518101906103199190611008565b9250925092508260008151811061033257610332611058565b60200260200101516001600160a01b0316866001600160a01b0316146103a7578260008151811061036557610365611058565b60200260200101518660405163e539288160e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b60405180910390fd5b82600184516103b69190611084565b815181106103c6576103c6611058565b60200260200101516001600160a01b0316856001600160a01b03161461043e5782600184516103f59190611084565b8151811061040557610405611058565b6020026020010151856040516347052b6760e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b6104536001600160a01b038716333085610a1e565b6104876001600160a01b0387167f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d84610aa8565b60006001600160a01b037f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d166338ed17398484878c6104c742603c61109d565b6040518663ffffffff1660e01b81526004016104e79594939291906110b0565b6000604051808303816000875af1158015610506573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261052e9190810190611121565b9050806001825161053f9190611084565b8151811061054f5761054f611058565b60200260200101519450610583877f0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d610b25565b50505050949350505050565b6000806000806000888060200190518101906105ab91906111b2565b9350935093509350836000815181106105c6576105c6611058565b60200260200101516001600160a01b0316876001600160a01b03161461063257836000815181106105f9576105f9611058565b60200260200101518760405163e539288160e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b83600185516106419190611084565b8151811061065157610651611058565b60200260200101516001600160a01b0316866001600160a01b0316146106c95783600185516106809190611084565b8151811061069057610690611058565b6020026020010151866040516347052b6760e01b815260040161039e9291906001600160a01b0392831681529116602082015260400190565b6106de6001600160a01b038816333085610a1e565b6107126001600160a01b0388167f000000000000000000000000e592427a0aece92de3edee1f18e0157c0586156484610aa8565b60408051606089901b6bffffffffffffffffffffffff1916602082015281516014818303018152603490910190915260015b85518110156107c257818561075a600184611084565b8151811061076a5761076a611058565b602002602001015187838151811061078457610784611058565b602002602001015160405160200161079e9392919061128d565b604051602081830303815290604052915080806107ba906112d9565b915050610744565b507f000000000000000000000000e592427a0aece92de3edee1f18e0157c058615646001600160a01b031663c04b8d596040518060a001604052808481526020018c6001600160a01b0316815260200142603c61081f919061109d565b8152602001868152602001858152506040518263ffffffff1660e01b815260040161084a91906112f2565b6020604051808303816000875af1158015610869573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061088d9190610f5c565b95506108b9887f000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564610b25565b5050505050949350505050565b60608167ffffffffffffffff8111156108e1576108e1610bcb565b60405190808252806020026020018201604052801561091457816020015b60608152602001906001900390816108ff5790505b50905060005b82811015610a17576000803086868581811061093857610938611058565b905060200281019061094a919061134a565b604051610958929190611398565b600060405180830381855af49150503d8060008114610993576040519150601f19603f3d011682016040523d82523d6000602084013e610998565b606091505b5091509150816109e4576044815110156109b157600080fd5b600481019050808060200190518101906109cb91906113a8565b60405162461bcd60e51b815260040161039e919061141f565b808484815181106109f7576109f7611058565b602002602001018190525050508080610a0f906112d9565b91505061091a565b5092915050565b60006040516323b872dd60e01b81528460048201528360248201528260448201526020600060648360008a5af13d15601f3d1160016000511416171691505080610aa15760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b604482015260640161039e565b5050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080610b1f5760405162461bcd60e51b815260206004820152600e60248201526d1054141493d59157d1905253115160921b604482015260640161039e565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b03828116602483015283169063dd62ed3e90604401602060405180830381865afa158015610b71573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b959190610f5c565b15610bb357604051637404a95160e01b815260040160405180910390fd5b5050565b803560028110610bc657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715610c0a57610c0a610bcb565b604052919050565b600067ffffffffffffffff821115610c2c57610c2c610bcb565b50601f01601f191660200190565b600082601f830112610c4b57600080fd5b8135610c5e610c5982610c12565b610be1565b818152846020838601011115610c7357600080fd5b816020850160208301376000918101602001919091529392505050565b6001600160a01b0381168114610ca557600080fd5b50565b600080600080600060a08688031215610cc057600080fd5b610cc986610bb7565b9450602086013567ffffffffffffffff811115610ce557600080fd5b610cf188828901610c3a565b9450506040860135610d0281610c90565b92506060860135610d1281610c90565b91506080860135610d2281610c90565b809150509295509295909350565b60008060008060808587031215610d4657600080fd5b843567ffffffffffffffff811115610d5d57600080fd5b610d6987828801610c3a565b9450506020850135610d7a81610c90565b92506040850135610d8a81610c90565b91506060850135610d9a81610c90565b939692955090935050565b600060208284031215610db757600080fd5b610dc082610bb7565b9392505050565b60008060208385031215610dda57600080fd5b823567ffffffffffffffff80821115610df257600080fd5b818501915085601f830112610e0657600080fd5b813581811115610e1557600080fd5b8660208260051b8501011115610e2a57600080fd5b60209290920196919550909350505050565b60005b83811015610e57578181015183820152602001610e3f565b50506000910152565b60008151808452610e78816020860160208601610e3c565b601f01601f19169290920160200192915050565b6000602080830181845280855180835260408601915060408160051b870101925083870160005b82811015610ee157603f19888603018452610ecf858351610e60565b94509285019290850190600101610eb3565b5092979650505050505050565b634e487b7160e01b600052602160045260246000fd5b608081526000610f176080830187610e60565b6001600160a01b0395861660208401529385166040830152509216606090920191909152919050565b60008251610f52818460208701610e3c565b9190910192915050565b600060208284031215610f6e57600080fd5b5051919050565b600067ffffffffffffffff821115610f8f57610f8f610bcb565b5060051b60200190565b600082601f830112610faa57600080fd5b81516020610fba610c5983610f75565b82815260059290921b84018101918181019086841115610fd957600080fd5b8286015b84811015610ffd578051610ff081610c90565b8352918301918301610fdd565b509695505050505050565b60008060006060848603121561101d57600080fd5b835167ffffffffffffffff81111561103457600080fd5b61104086828701610f99565b93505060208401519150604084015190509250925092565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b818103818111156110975761109761106e565b92915050565b808201808211156110975761109761106e565b600060a082018783526020878185015260a0604085015281875180845260c086019150828901935060005b818110156111005784516001600160a01b0316835293830193918301916001016110db565b50506001600160a01b03969096166060850152505050608001529392505050565b6000602080838503121561113457600080fd5b825167ffffffffffffffff81111561114b57600080fd5b8301601f8101851361115c57600080fd5b805161116a610c5982610f75565b81815260059190911b8201830190838101908783111561118957600080fd5b928401925b828410156111a75783518252928401929084019061118e565b979650505050505050565b600080600080608085870312156111c857600080fd5b845167ffffffffffffffff808211156111e057600080fd5b6111ec88838901610f99565b955060209150818701518181111561120357600080fd5b87019050601f8101881361121657600080fd5b8051611224610c5982610f75565b81815260059190911b8201830190838101908a83111561124357600080fd5b928401925b8284101561127357835162ffffff811681146112645760008081fd5b82529284019290840190611248565b60408a01516060909a0151989b909a509650505050505050565b6000845161129f818460208901610e3c565b60e89490941b6001600160e81b0319169190930190815260609190911b6bffffffffffffffffffffffff1916600382015260170192915050565b6000600182016112eb576112eb61106e565b5060010190565b602081526000825160a0602084015261130e60c0840182610e60565b905060018060a01b0360208501511660408401526040840151606084015260608401516080840152608084015160a08401528091505092915050565b6000808335601e1984360301811261136157600080fd5b83018035915067ffffffffffffffff82111561137c57600080fd5b60200191503681900382131561139157600080fd5b9250929050565b8183823760009101908152919050565b6000602082840312156113ba57600080fd5b815167ffffffffffffffff8111156113d157600080fd5b8201601f810184136113e257600080fd5b80516113f0610c5982610c12565b81815285602083850101111561140557600080fd5b611416826020830160208601610e3c565b95945050505050565b602081526000610dc06020830184610e6056fea2646970667358221220d7ec814f57cdb98d279e0fd08bc654057583499820ea222569f8adb86e2ecd3164736f6c63430008100033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
-----Decoded View---------------
Arg [0] : _uniswapV2Router (address): 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D
Arg [1] : _uniswapV3Router (address): 0xE592427A0AEce92De3Edee1F18E0157C05861564
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007a250d5630b4cf539739df2c5dacb4c659f2488d
Arg [1] : 000000000000000000000000e592427a0aece92de3edee1f18e0157c05861564
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.