Overview
S Balance
0 S
S Value
$0.00More Info
Private Name Tags
ContractCreator
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 Name:
ZapLib
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeTransferLib } from "solmate/utils/SafeTransferLib.sol"; import { SwapParams, AddLiquidityParams } from "contracts/structs/LiquidityStructs.sol"; import { ILiquidityConnector } from "contracts/interfaces/ILiquidityConnector.sol"; import { ConnectorRegistry } from "contracts/ConnectorRegistry.sol"; import { DelegateModule } from "contracts/modules/DelegateModule.sol"; import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol"; import { IZapLib } from "contracts/interfaces/libraries/IZapLib.sol"; import { ISwapLib } from "contracts/interfaces/libraries/ISwapLib.sol"; contract ZapLib is DelegateModule, IZapLib { error LiquidityAmountError(); // 0x4d0ab6b4 ISwapLib public immutable swapLib; ConnectorRegistry public immutable connectorRegistry; constructor(ConnectorRegistry connectorRegistry_, ISwapLib swapLib_) { connectorRegistry = connectorRegistry_; swapLib = swapLib_; } function zapIn( ZapIn memory zap ) external payable { uint256 swapDataLength = zap.swaps.length; for (uint256 i; i < swapDataLength;) { _delegateTo( address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i])) ); unchecked { i++; } } if (zap.addLiquidityParams.lpToken == address(0)) { return; } bool atLeastOneNonZero = false; AddLiquidityParams memory addLiquidityParams = zap.addLiquidityParams; uint256 addLiquidityParamsTokensLength = addLiquidityParams.tokens.length; for (uint256 i; i < addLiquidityParamsTokensLength; i++) { if (addLiquidityParams.tokens[i] == address(0)) { continue; } if (addLiquidityParams.desiredAmounts[i] == 0) { addLiquidityParams.desiredAmounts[i] = IERC20( addLiquidityParams.tokens[i] ).balanceOf(address(this)); } if (addLiquidityParams.desiredAmounts[i] > 0) { atLeastOneNonZero = true; // In case there is USDT or similar dust approval, revoke it SafeTransferLib.safeApprove( addLiquidityParams.tokens[i], addLiquidityParams.router, 0 ); SafeTransferLib.safeApprove( addLiquidityParams.tokens[i], addLiquidityParams.router, addLiquidityParams.desiredAmounts[i] ); } } if (!atLeastOneNonZero) { revert LiquidityAmountError(); } address routerConnector = connectorRegistry.connectorOf(addLiquidityParams.router); _delegateTo( routerConnector, abi.encodeCall( ILiquidityConnector.addLiquidity, (addLiquidityParams) ) ); for (uint256 i; i < addLiquidityParamsTokensLength;) { if (addLiquidityParams.tokens[i] != address(0)) { // Revoke any dust approval in case the amount was estimated SafeTransferLib.safeApprove( addLiquidityParams.tokens[i], addLiquidityParams.router, 0 ); } unchecked { i++; } } } function zapOut( ZapOut memory zap ) external { if (zap.removeLiquidityParams.lpToken != address(0)) { if (zap.removeLiquidityParams.lpAmountIn > 0) { SafeTransferLib.safeApprove( zap.removeLiquidityParams.lpToken, zap.removeLiquidityParams.router, zap.removeLiquidityParams.lpAmountIn ); } address routerConnector = connectorRegistry.connectorOf(zap.removeLiquidityParams.router); _delegateTo( address(routerConnector), abi.encodeCall( ILiquidityConnector.removeLiquidity, zap.removeLiquidityParams ) ); } uint256 swapDataLength = zap.swaps.length; for (uint256 i; i < swapDataLength;) { _delegateTo( address(swapLib), abi.encodeCall(ISwapLib.swap, (zap.swaps[i])) ); unchecked { i++; } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/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 { /*////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ error ETHTransferFailed(); error TransferFromFailed(); error TransferFailed(); error ApproveFailed(); /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; /// @solidity memory-safe-assembly assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } if (!success) revert ETHTransferFailed(); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( address token, address from, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly 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) ) } if (!success) revert TransferFromFailed(); } function safeTransfer( address token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly 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) ) } if (!success) revert TransferFailed(); } function safeApprove( address token, address to, uint256 amount ) internal { bool success; /// @solidity memory-safe-assembly 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) ) } if (!success) revert ApproveFailed(); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; struct AddLiquidityParams { address router; address lpToken; address[] tokens; uint256[] desiredAmounts; uint256[] minAmounts; bytes extraData; } struct RemoveLiquidityParams { address router; address lpToken; address[] tokens; uint256 lpAmountIn; uint256[] minAmountsOut; bytes extraData; } struct SwapParams { address router; uint256 amountIn; uint256 minAmountOut; address tokenIn; bytes extraData; } struct GetAmountOutParams { address router; address lpToken; address tokenIn; address tokenOut; uint256 amountIn; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { AddLiquidityParams, RemoveLiquidityParams, SwapParams, GetAmountOutParams } from "contracts/structs/LiquidityStructs.sol"; interface ILiquidityConnector { function addLiquidity( AddLiquidityParams memory addLiquidityParams ) external payable; function removeLiquidity( RemoveLiquidityParams memory removeLiquidityParams ) external; function swapExactTokensForTokens( SwapParams memory swap ) external payable; function getAmountOut( GetAmountOutParams memory getAmountOutParams ) external view returns (uint256); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; import { Admin } from "contracts/base/Admin.sol"; import { TimelockAdmin } from "contracts/base/TimelockAdmin.sol"; error ConnectorNotRegistered(address target); interface ICustomConnectorRegistry { function connectorOf(address target) external view returns (address); } contract ConnectorRegistry is Admin, TimelockAdmin { event ConnectorChanged(address target, address connector); event CustomRegistryAdded(address registry); event CustomRegistryRemoved(address registry); error ConnectorAlreadySet(address target); error ConnectorNotSet(address target); ICustomConnectorRegistry[] public customRegistries; mapping(ICustomConnectorRegistry => bool) public isCustomRegistry; mapping(address target => address connector) private connectors_; constructor( address admin_, address timelockAdmin_ ) Admin(admin_) TimelockAdmin(timelockAdmin_) { } /// @notice Update connector addresses for a batch of targets. /// @dev Controls which connector contracts are used for the specified /// targets. /// @custom:access Restricted to protocol admin. function setConnectors( address[] calldata targets, address[] calldata connectors ) external onlyAdmin { for (uint256 i; i != targets.length;) { if (connectors_[targets[i]] != address(0)) { revert ConnectorAlreadySet(targets[i]); } connectors_[targets[i]] = connectors[i]; emit ConnectorChanged(targets[i], connectors[i]); unchecked { ++i; } } } function updateConnectors( address[] calldata targets, address[] calldata connectors ) external onlyTimelockAdmin { for (uint256 i; i != targets.length;) { if (connectors_[targets[i]] == address(0)) { revert ConnectorNotSet(targets[i]); } connectors_[targets[i]] = connectors[i]; emit ConnectorChanged(targets[i], connectors[i]); unchecked { ++i; } } } /// @notice Append an address to the custom registries list. /// @custom:access Restricted to protocol admin. function addCustomRegistry(ICustomConnectorRegistry registry) external onlyAdmin { customRegistries.push(registry); isCustomRegistry[registry] = true; emit CustomRegistryAdded(address(registry)); } /// @notice Replace an address in the custom registries list. /// @custom:access Restricted to protocol admin. function updateCustomRegistry( uint256 index, ICustomConnectorRegistry newRegistry ) external onlyTimelockAdmin { address oldRegistry = address(customRegistries[index]); isCustomRegistry[customRegistries[index]] = false; emit CustomRegistryRemoved(oldRegistry); customRegistries[index] = newRegistry; isCustomRegistry[newRegistry] = true; if (address(newRegistry) != address(0)) { emit CustomRegistryAdded(address(newRegistry)); } } function connectorOf(address target) external view returns (address) { address connector = connectors_[target]; if (connector != address(0)) { return connector; } uint256 length = customRegistries.length; for (uint256 i; i != length;) { if (address(customRegistries[i]) != address(0)) { try customRegistries[i].connectorOf(target) returns ( address _connector ) { if (_connector != address(0)) { return _connector; } } catch { // Ignore } } unchecked { ++i; } } revert ConnectorNotRegistered(target); } function hasConnector(address target) external view returns (bool) { if (connectors_[target] != address(0)) { return true; } uint256 length = customRegistries.length; for (uint256 i; i != length;) { if (address(customRegistries[i]) != address(0)) { try customRegistries[i].connectorOf(target) returns ( address _connector ) { if (_connector != address(0)) { return true; } } catch { // Ignore } unchecked { ++i; } } } return false; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; contract DelegateModule { function _delegateTo( address to, bytes memory data ) internal returns (bytes memory) { (bool success, bytes memory result) = to.delegatecall(data); if (!success) { if (result.length == 0) revert(); assembly { revert(add(32, result), mload(result)) } } return result; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { SwapParams, AddLiquidityParams, RemoveLiquidityParams } from "contracts/structs/LiquidityStructs.sol"; struct ZapIn { SwapParams[] swaps; AddLiquidityParams addLiquidityParams; } struct ZapOut { RemoveLiquidityParams removeLiquidityParams; SwapParams[] swaps; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { ZapIn, ZapOut } from "contracts/structs/ZapStructs.sol"; interface IZapLib { function zapIn( ZapIn memory zap ) external payable; function zapOut( ZapOut memory zap ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import { SwapParams } from "contracts/structs/LiquidityStructs.sol"; interface ISwapLib { function swap( SwapParams memory swap ) external payable; function swapMultiple( SwapParams[] memory swaps ) external; }
// 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 immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable 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: MIT pragma solidity ^0.8.17; /// @title Admin contract /// @author vfat.tools /// @notice Provides an administration mechanism allowing restricted functions abstract contract Admin { /// ERRORS /// /// @notice Thrown when the caller is not the admin error NotAdminError(); //0xb5c42b3b /// EVENTS /// /// @notice Emitted when a new admin is set /// @param oldAdmin Address of the old admin /// @param newAdmin Address of the new admin event AdminSet(address oldAdmin, address newAdmin); /// STORAGE /// /// @notice Address of the current admin address public admin; /// MODIFIERS /// /// @dev Restricts a function to the admin modifier onlyAdmin() { if (msg.sender != admin) revert NotAdminError(); _; } /// WRITE FUNCTIONS /// /// @param admin_ Address of the admin constructor(address admin_) { emit AdminSet(admin, admin_); admin = admin_; } /// @notice Sets a new admin /// @param newAdmin Address of the new admin /// @custom:access Restricted to protocol admin. function setAdmin(address newAdmin) external onlyAdmin { emit AdminSet(admin, newAdmin); admin = newAdmin; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.17; /// @title TimelockAdmin contract /// @author vfat.tools /// @notice Provides an timelockAdministration mechanism allowing restricted /// functions abstract contract TimelockAdmin { /// ERRORS /// /// @notice Thrown when the caller is not the timelockAdmin error NotTimelockAdminError(); /// EVENTS /// /// @notice Emitted when a new timelockAdmin is set /// @param oldTimelockAdmin Address of the old timelockAdmin /// @param newTimelockAdmin Address of the new timelockAdmin event TimelockAdminSet(address oldTimelockAdmin, address newTimelockAdmin); /// STORAGE /// /// @notice Address of the current timelockAdmin address public timelockAdmin; /// MODIFIERS /// /// @dev Restricts a function to the timelockAdmin modifier onlyTimelockAdmin() { if (msg.sender != timelockAdmin) revert NotTimelockAdminError(); _; } /// WRITE FUNCTIONS /// /// @param timelockAdmin_ Address of the timelockAdmin constructor(address timelockAdmin_) { emit TimelockAdminSet(timelockAdmin, timelockAdmin_); timelockAdmin = timelockAdmin_; } /// @notice Sets a new timelockAdmin /// @dev Can only be called by the current timelockAdmin /// @param newTimelockAdmin Address of the new timelockAdmin function setTimelockAdmin(address newTimelockAdmin) external onlyTimelockAdmin { emit TimelockAdminSet(timelockAdmin, newTimelockAdmin); timelockAdmin = newTimelockAdmin; } }
{ "remappings": [ "solmate/=lib/solmate/src/", "@openzeppelin/=lib/openzeppelin-contracts/", "@uniswap/v3-periphery/=lib/v3-periphery/", "@uniswap/v3-core/=lib/v3-core/", "@morpho-blue/=lib/morpho-blue/src/", "ds-test/=lib/solmate/lib/ds-test/src/", "forge-std/=lib/forge-std/src/", "morpho-blue/=lib/morpho-blue/", "openzeppelin-contracts/=lib/openzeppelin-contracts/" ], "optimizer": { "enabled": true, "runs": 200 }, "metadata": { "useLiteralContent": false, "bytecodeHash": "ipfs", "appendCBOR": true }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "evmVersion": "paris", "viaIR": false, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract ConnectorRegistry","name":"connectorRegistry_","type":"address"},{"internalType":"contract ISwapLib","name":"swapLib_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ApproveFailed","type":"error"},{"inputs":[],"name":"LiquidityAmountError","type":"error"},{"inputs":[],"name":"connectorRegistry","outputs":[{"internalType":"contract ConnectorRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapLib","outputs":[{"internalType":"contract ISwapLib","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct SwapParams[]","name":"swaps","type":"tuple[]"},{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"lpToken","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256[]","name":"desiredAmounts","type":"uint256[]"},{"internalType":"uint256[]","name":"minAmounts","type":"uint256[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct AddLiquidityParams","name":"addLiquidityParams","type":"tuple"}],"internalType":"struct ZapIn","name":"zap","type":"tuple"}],"name":"zapIn","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"address","name":"lpToken","type":"address"},{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"uint256","name":"lpAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct RemoveLiquidityParams","name":"removeLiquidityParams","type":"tuple"},{"components":[{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct SwapParams[]","name":"swaps","type":"tuple[]"}],"internalType":"struct ZapOut","name":"zap","type":"tuple"}],"name":"zapOut","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405234801561001057600080fd5b506040516110b63803806110b683398101604081905261002f9161005e565b6001600160a01b0391821660a05216608052610098565b6001600160a01b038116811461005b57600080fd5b50565b6000806040838503121561007157600080fd5b825161007c81610046565b602084015190925061008d81610046565b809150509250929050565b60805160a051610fdf6100d76000396000818160c80152818161015a015261053501526000818160780152818161022801526102c50152610fdf6000f3fe60806040526004361061003f5760003560e01c80630e2c0b6e146100445780633faa6e3014610066578063b53c86d2146100b6578063cd5f81a9146100ea575b600080fd5b34801561005057600080fd5b5061006461005f366004610a80565b6100fd565b005b34801561007257600080fd5b5061009a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c257600080fd5b5061009a7f000000000000000000000000000000000000000000000000000000000000000081565b6100646100f8366004610bb1565b6102b2565b8051602001516001600160a01b0316156102125780516060015115610135578051602081015181516060909201516101359290610667565b8051516040516363cd755760e11b81526001600160a01b0391821660048201526000917f0000000000000000000000000000000000000000000000000000000000000000169063c79aeaae90602401602060405180830381865afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c59190610cfe565b905061020f8183600001516040516024016101e09190610de6565b60408051601f198184030181529190526020810180516001600160e01b031663010741f760e61b1790526106c4565b50505b60208101515160005b818110156102ad576102a47f00000000000000000000000000000000000000000000000000000000000000008460200151838151811061025d5761025d610e71565b60200260200101516040516024016102759190610e87565b60408051601f198184030181529190526020810180516001600160e01b03166363471ff960e01b1790526106c4565b5060010161021b565b505050565b80515160005b81811015610303576102fa7f00000000000000000000000000000000000000000000000000000000000000008460000151838151811061025d5761025d610e71565b506001016102b8565b5060208083015101516001600160a01b031661031d575050565b602082015160408101515160009190825b818110156104f25760006001600160a01b03168360400151828151811061035757610357610e71565b60200260200101516001600160a01b031603156104e0578260600151818151811061038457610384610e71565b602002602001015160000361044057826040015181815181106103a9576103a9610e71565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d9190610ed6565b8360600151828151811061043357610433610e71565b6020026020010181815250505b60008360600151828151811061045857610458610e71565b602002602001015111156104e057600193506104978360400151828151811061048357610483610e71565b602002602001015184600001516000610667565b6104e0836040015182815181106104b0576104b0610e71565b60200260200101518460000151856060015184815181106104d3576104d3610e71565b6020026020010151610667565b806104ea81610eef565b91505061032e565b508261051157604051631342adad60e21b815260040160405180910390fd5b81516040516363cd755760e11b81526001600160a01b0391821660048201526000917f0000000000000000000000000000000000000000000000000000000000000000169063c79aeaae90602401602060405180830381865afa15801561057c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a09190610cfe565b90506105e681846040516024016105b79190610f16565b60408051601f198184030181529190526020810180516001600160e01b031663fb986deb60e01b1790526106c4565b5060005b8281101561065e5760006001600160a01b03168460400151828151811061061357610613610e71565b60200260200101516001600160a01b031614610656576106568460400151828151811061064257610642610e71565b602002602001015185600001516000610667565b6001016105ea565b50505050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806106be57604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b6060600080846001600160a01b0316846040516106e19190610f8d565b600060405180830381855af49150503d806000811461071c576040519150601f19603f3d011682016040523d82523d6000602084013e610721565b606091505b50915091508161074157805160000361073957600080fd5b805181602001fd5b949350505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561078257610782610749565b60405290565b6040805190810167ffffffffffffffff8111828210171561078257610782610749565b60405160c0810167ffffffffffffffff8111828210171561078257610782610749565b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f7610749565b604052919050565b6001600160a01b038116811461081457600080fd5b50565b8035610822816107ff565b919050565b600067ffffffffffffffff82111561084157610841610749565b5060051b60200190565b600082601f83011261085c57600080fd5b8135602061087161086c83610827565b6107ce565b82815260059290921b8401810191818101908684111561089057600080fd5b8286015b848110156108b45780356108a7816107ff565b8352918301918301610894565b509695505050505050565b600082601f8301126108d057600080fd5b813560206108e061086c83610827565b82815260059290921b840181019181810190868411156108ff57600080fd5b8286015b848110156108b45780358352918301918301610903565b600082601f83011261092b57600080fd5b813567ffffffffffffffff81111561094557610945610749565b610958601f8201601f19166020016107ce565b81815284602083860101111561096d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261099b57600080fd5b813560206109ab61086c83610827565b82815260059290921b840181019181810190868411156109ca57600080fd5b8286015b848110156108b457803567ffffffffffffffff808211156109ef5760008081fd5b9088019060a0828b03601f1901811315610a095760008081fd5b610a1161075f565b87840135610a1e816107ff565b8082525060408085013589830152606080860135828401526080915081860135610a47816107ff565b90830152918401359183831115610a5e5760008081fd5b610a6c8d8a8588010161091a565b9082015286525050509183019183016109ce565b600060208284031215610a9257600080fd5b813567ffffffffffffffff80821115610aaa57600080fd5b9083019060408286031215610abe57600080fd5b610ac6610788565b823582811115610ad557600080fd5b830160c08188031215610ae757600080fd5b610aef6107ab565b610af882610817565b8152610b0660208301610817565b6020820152604082013584811115610b1d57600080fd5b610b298982850161084b565b60408301525060608201356060820152608082013584811115610b4b57600080fd5b610b57898285016108bf565b60808301525060a082013584811115610b6f57600080fd5b610b7b8982850161091a565b60a083015250825250602083013582811115610b9657600080fd5b610ba28782860161098a565b60208301525095945050505050565b600060208284031215610bc357600080fd5b813567ffffffffffffffff80821115610bdb57600080fd5b9083019060408286031215610bef57600080fd5b610bf7610788565b823582811115610c0657600080fd5b610c128782860161098a565b825250602083013582811115610c2757600080fd5b929092019160c08387031215610c3c57600080fd5b610c446107ab565b610c4d84610817565b8152610c5b60208501610817565b6020820152604084013583811115610c7257600080fd5b610c7e8882870161084b565b604083015250606084013583811115610c9657600080fd5b610ca2888287016108bf565b606083015250608084013583811115610cba57600080fd5b610cc6888287016108bf565b60808301525060a084013583811115610cde57600080fd5b610cea8882870161091a565b60a083015250602082015295945050505050565b600060208284031215610d1057600080fd5b8151610d1b816107ff565b9392505050565b600081518084526020808501945080840160005b83811015610d5b5781516001600160a01b031687529582019590820190600101610d36565b509495945050505050565b600081518084526020808501945080840160005b83811015610d5b57815187529582019590820190600101610d7a565b60005b83811015610db1578181015183820152602001610d99565b50506000910152565b60008151808452610dd2816020860160208601610d96565b601f01601f19169290920160200192915050565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015160c06060840152610e2260e0840182610d22565b9050606084015160808401526080840151601f19808584030160a0860152610e4a8383610d66565b925060a08601519150808584030160c086015250610e688282610dba565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60208152600060018060a01b03808451166020840152602084015160408401526040840151606084015280606085015116608084015250608083015160a08084015261074160c0840182610dba565b600060208284031215610ee857600080fd5b5051919050565b600060018201610f0f57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015160c06060840152610f5260e0840182610d22565b90506060840151601f1980858403016080860152610f708383610d66565b925060808601519150808584030160a0860152610e4a8383610d66565b60008251610f9f818460208701610d96565b919091019291505056fea2646970667358221220efa7f42e8ef06f6b691f74edfedf66f8643f19ae595198c8da5c3d163c92d5c464736f6c634300081300330000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e6000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d
Deployed Bytecode
0x60806040526004361061003f5760003560e01c80630e2c0b6e146100445780633faa6e3014610066578063b53c86d2146100b6578063cd5f81a9146100ea575b600080fd5b34801561005057600080fd5b5061006461005f366004610a80565b6100fd565b005b34801561007257600080fd5b5061009a7f000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d81565b6040516001600160a01b03909116815260200160405180910390f35b3480156100c257600080fd5b5061009a7f0000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e681565b6100646100f8366004610bb1565b6102b2565b8051602001516001600160a01b0316156102125780516060015115610135578051602081015181516060909201516101359290610667565b8051516040516363cd755760e11b81526001600160a01b0391821660048201526000917f0000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e6169063c79aeaae90602401602060405180830381865afa1580156101a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906101c59190610cfe565b905061020f8183600001516040516024016101e09190610de6565b60408051601f198184030181529190526020810180516001600160e01b031663010741f760e61b1790526106c4565b50505b60208101515160005b818110156102ad576102a47f000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d8460200151838151811061025d5761025d610e71565b60200260200101516040516024016102759190610e87565b60408051601f198184030181529190526020810180516001600160e01b03166363471ff960e01b1790526106c4565b5060010161021b565b505050565b80515160005b81811015610303576102fa7f000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d8460000151838151811061025d5761025d610e71565b506001016102b8565b5060208083015101516001600160a01b031661031d575050565b602082015160408101515160009190825b818110156104f25760006001600160a01b03168360400151828151811061035757610357610e71565b60200260200101516001600160a01b031603156104e0578260600151818151811061038457610384610e71565b602002602001015160000361044057826040015181815181106103a9576103a9610e71565b60209081029190910101516040516370a0823160e01b81523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156103f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061041d9190610ed6565b8360600151828151811061043357610433610e71565b6020026020010181815250505b60008360600151828151811061045857610458610e71565b602002602001015111156104e057600193506104978360400151828151811061048357610483610e71565b602002602001015184600001516000610667565b6104e0836040015182815181106104b0576104b0610e71565b60200260200101518460000151856060015184815181106104d3576104d3610e71565b6020026020010151610667565b806104ea81610eef565b91505061032e565b508261051157604051631342adad60e21b815260040160405180910390fd5b81516040516363cd755760e11b81526001600160a01b0391821660048201526000917f0000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e6169063c79aeaae90602401602060405180830381865afa15801561057c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a09190610cfe565b90506105e681846040516024016105b79190610f16565b60408051601f198184030181529190526020810180516001600160e01b031663fb986deb60e01b1790526106c4565b5060005b8281101561065e5760006001600160a01b03168460400151828151811061061357610613610e71565b60200260200101516001600160a01b031614610656576106568460400151828151811061064257610642610e71565b602002602001015185600001516000610667565b6001016105ea565b50505050505050565b600060405163095ea7b360e01b8152836004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806106be57604051633e3f8f7360e01b815260040160405180910390fd5b50505050565b6060600080846001600160a01b0316846040516106e19190610f8d565b600060405180830381855af49150503d806000811461071c576040519150601f19603f3d011682016040523d82523d6000602084013e610721565b606091505b50915091508161074157805160000361073957600080fd5b805181602001fd5b949350505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff8111828210171561078257610782610749565b60405290565b6040805190810167ffffffffffffffff8111828210171561078257610782610749565b60405160c0810167ffffffffffffffff8111828210171561078257610782610749565b604051601f8201601f1916810167ffffffffffffffff811182821017156107f7576107f7610749565b604052919050565b6001600160a01b038116811461081457600080fd5b50565b8035610822816107ff565b919050565b600067ffffffffffffffff82111561084157610841610749565b5060051b60200190565b600082601f83011261085c57600080fd5b8135602061087161086c83610827565b6107ce565b82815260059290921b8401810191818101908684111561089057600080fd5b8286015b848110156108b45780356108a7816107ff565b8352918301918301610894565b509695505050505050565b600082601f8301126108d057600080fd5b813560206108e061086c83610827565b82815260059290921b840181019181810190868411156108ff57600080fd5b8286015b848110156108b45780358352918301918301610903565b600082601f83011261092b57600080fd5b813567ffffffffffffffff81111561094557610945610749565b610958601f8201601f19166020016107ce565b81815284602083860101111561096d57600080fd5b816020850160208301376000918101602001919091529392505050565b600082601f83011261099b57600080fd5b813560206109ab61086c83610827565b82815260059290921b840181019181810190868411156109ca57600080fd5b8286015b848110156108b457803567ffffffffffffffff808211156109ef5760008081fd5b9088019060a0828b03601f1901811315610a095760008081fd5b610a1161075f565b87840135610a1e816107ff565b8082525060408085013589830152606080860135828401526080915081860135610a47816107ff565b90830152918401359183831115610a5e5760008081fd5b610a6c8d8a8588010161091a565b9082015286525050509183019183016109ce565b600060208284031215610a9257600080fd5b813567ffffffffffffffff80821115610aaa57600080fd5b9083019060408286031215610abe57600080fd5b610ac6610788565b823582811115610ad557600080fd5b830160c08188031215610ae757600080fd5b610aef6107ab565b610af882610817565b8152610b0660208301610817565b6020820152604082013584811115610b1d57600080fd5b610b298982850161084b565b60408301525060608201356060820152608082013584811115610b4b57600080fd5b610b57898285016108bf565b60808301525060a082013584811115610b6f57600080fd5b610b7b8982850161091a565b60a083015250825250602083013582811115610b9657600080fd5b610ba28782860161098a565b60208301525095945050505050565b600060208284031215610bc357600080fd5b813567ffffffffffffffff80821115610bdb57600080fd5b9083019060408286031215610bef57600080fd5b610bf7610788565b823582811115610c0657600080fd5b610c128782860161098a565b825250602083013582811115610c2757600080fd5b929092019160c08387031215610c3c57600080fd5b610c446107ab565b610c4d84610817565b8152610c5b60208501610817565b6020820152604084013583811115610c7257600080fd5b610c7e8882870161084b565b604083015250606084013583811115610c9657600080fd5b610ca2888287016108bf565b606083015250608084013583811115610cba57600080fd5b610cc6888287016108bf565b60808301525060a084013583811115610cde57600080fd5b610cea8882870161091a565b60a083015250602082015295945050505050565b600060208284031215610d1057600080fd5b8151610d1b816107ff565b9392505050565b600081518084526020808501945080840160005b83811015610d5b5781516001600160a01b031687529582019590820190600101610d36565b509495945050505050565b600081518084526020808501945080840160005b83811015610d5b57815187529582019590820190600101610d7a565b60005b83811015610db1578181015183820152602001610d99565b50506000910152565b60008151808452610dd2816020860160208601610d96565b601f01601f19169290920160200192915050565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015160c06060840152610e2260e0840182610d22565b9050606084015160808401526080840151601f19808584030160a0860152610e4a8383610d66565b925060a08601519150808584030160c086015250610e688282610dba565b95945050505050565b634e487b7160e01b600052603260045260246000fd5b60208152600060018060a01b03808451166020840152602084015160408401526040840151606084015280606085015116608084015250608083015160a08084015261074160c0840182610dba565b600060208284031215610ee857600080fd5b5051919050565b600060018201610f0f57634e487b7160e01b600052601160045260246000fd5b5060010190565b60208152600060018060a01b0380845116602084015280602085015116604084015250604083015160c06060840152610f5260e0840182610d22565b90506060840151601f1980858403016080860152610f708383610d66565b925060808601519150808584030160a0860152610e4a8383610d66565b60008251610f9f818460208701610d96565b919091019291505056fea2646970667358221220efa7f42e8ef06f6b691f74edfedf66f8643f19ae595198c8da5c3d163c92d5c464736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e6000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d
-----Decoded View---------------
Arg [0] : connectorRegistry_ (address): 0x3575Aa02Ae85D8Cd2AaE6DCaA5D8750cFc9622e6
Arg [1] : swapLib_ (address): 0xb01e431542BAFBac3Fc95057961c92ED8E06E08d
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003575aa02ae85d8cd2aae6dcaa5d8750cfc9622e6
Arg [1] : 000000000000000000000000b01e431542bafbac3fc95057961c92ed8e06e08d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.