Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
SwapFacade
Compiler Version
v0.8.18+commit.87f61d96
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import '@1inch/solidity-utils/contracts/libraries/SafeERC20.sol'; import './features/ContractOnlyEthRecipient.sol'; import './interfaces/ISwapFacade.sol'; import './libs/TokenLibrary.sol'; import './Errors.sol'; import '@openzeppelin/contracts/access/Ownable2Step.sol'; /** * @title SwapFacade * @notice This facade performs minReturn safety checks and holds all approves to ensure safety of all arbitrary calls */ contract SwapFacade is ISwapFacade, Ownable2Step { using SafeERC20 for IERC20; using TokenLibrary for IERC20; address public feeCollector; constructor(address feeCollector_) { if (feeCollector_ == address(0)) { revert AddressCannotBeZero(); } feeCollector = feeCollector_; } /// @notice Performs tokens swap /// @param executor Address of low level executor used to make actual swaps /// @param amount Amount of source tokens user is willing to swap /// @param minReturns Minimal amount of targetToken that user is willing to receive. If not reached transaction reverts /// @param targetTokenTransferInfos instructions on how to transfer tokens to target addresses /// @param deadline Safety parameter against stalled transactions. If deadline reached swap reverts unconditionally /// @param swapDescriptions Descriptions that describe how exactly swaps should be performed /// @param permit Signed permit for spending `amount` of tokens. Optional. May be used instead of manually approving tokens before calling `swap` function swap( ISwapExecutor executor, uint256 amount, MinReturnInfo[] calldata minReturns, ISwapExecutor.TokenTransferInfo[] calldata targetTokenTransferInfos, uint256 deadline, ISwapExecutor.SwapDescription[] calldata swapDescriptions, bytes calldata permit ) external payable override returns (uint256[] memory) { { // solhint-disable-next-line not-rely-on-time if (deadline < block.timestamp) { // solhint-disable-next-line not-rely-on-time revert TransactionExpired(deadline, block.timestamp); } } if (amount == 0) { revert ZeroInput(); } for (uint256 i = 0; i < targetTokenTransferInfos.length; i++) { if (targetTokenTransferInfos[i].recipient == address(0)) { revert ZeroRecipient(); } } if (swapDescriptions.length == 0) { revert EmptySwap(); } uint256 collectedFees; if (msg.value > 0) { if (msg.value != amount) { revert EthValueAmountMismatch(); } else if (permit.length > 0) { revert PermitNotAllowedForEthSwap(); } else if (!TokenLibrary.isEth(swapDescriptions[0].sourceToken)) { revert EthValueSourceTokenMismatch(); } collectedFees = address(feeCollector).balance; } else { if ( swapDescriptions[0].sourceToken.balanceOf(address(executor)) < amount ) { if (permit.length > 0) { SafeERC20.tryPermit( swapDescriptions[0].sourceToken, permit ); } swapDescriptions[0].sourceToken.safeTransferFrom( msg.sender, address(executor), amount ); } collectedFees = swapDescriptions[0].sourceToken.balanceOf( feeCollector ); } uint256[] memory swappedAmounts = _swap( executor, minReturns, targetTokenTransferInfos, swapDescriptions ); if (msg.value > 0) { collectedFees = address(feeCollector).balance - collectedFees; } else { collectedFees = swapDescriptions[0].sourceToken.balanceOf(feeCollector) - collectedFees; } if (swappedAmounts.length != 1) { revert MultiSwapNotAllowed(); } emit Trade( address(swapDescriptions[0].sourceToken), address(minReturns[0].token), amount, swappedAmounts[0], collectedFees ); return swappedAmounts; } /// @notice Performs tokens swap and validates swap success against minReturn value function _swap( ISwapExecutor executor, MinReturnInfo[] calldata minReturns, ISwapExecutor.TokenTransferInfo[] calldata targetTokenTransferInfos, ISwapExecutor.SwapDescription[] calldata swapDescriptions ) private returns (uint256[] memory) { uint256[] memory balancesBeforeSwap = new uint256[](minReturns.length); for (uint256 i = 0; i < minReturns.length; i++) { balancesBeforeSwap[i] = minReturns[i].token.universalBalanceOf( minReturns[i].recipient ); } executor.executeSwap{value: msg.value}( targetTokenTransferInfos, swapDescriptions ); uint256[] memory swappedAmounts = new uint256[](minReturns.length); for (uint256 i = 0; i < minReturns.length; i++) { uint256 balanceBeforeSwap = balancesBeforeSwap[i]; uint256 balanceAfterSwap = minReturns[i].token.universalBalanceOf( minReturns[i].recipient ); uint256 totalSwappedAmount = balanceAfterSwap - balanceBeforeSwap; if (totalSwappedAmount < minReturns[i].amount) { revert MinReturnError(totalSwappedAmount, minReturns[i].amount); } swappedAmounts[i] = totalSwappedAmount; } return swappedAmounts; } function sweep(IERC20 token, address destination) external onlyOwner { token.safeTransfer(destination, IERC20(token).balanceOf(address(this))); } function updateFeeCollector(address newFeeCollector) external onlyOwner { if (newFeeCollector == address(0)) { revert AddressCannotBeZero(); } feeCollector = newFeeCollector; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IDaiLikePermit { function permit( address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPermit2 { struct PermitDetails { // ERC20 token address address token; // the maximum amount allowed to spend uint160 amount; // timestamp at which a spender's token allowances become invalid uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } /// @notice The permit message signed for a single token allownce struct PermitSingle { // the permit data for a single token alownce PermitDetails details; // address permissioned on the allowed tokens address spender; // deadline on the permit signature uint256 sigDeadline; } /// @notice Packed allowance struct PackedAllowance { // amount allowed uint160 amount; // permission expiry uint48 expiration; // an incrementing value indexed per owner,token,and spender for each signature uint48 nonce; } function transferFrom(address user, address spender, uint160 amount, address token) external; function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; function allowance(address user, address token, address spender) external view returns (PackedAllowance memory); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; interface IWETH is IERC20 { event Deposit(address indexed dst, uint256 wad); event Withdrawal(address indexed src, uint256 wad); function deposit() external payable; function withdraw(uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Revert reason forwarder. library RevertReasonForwarder { /// @dev Forwards latest externall call revert. function reRevert() internal pure { // bubble up revert reason from latest external call assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } /// @dev Returns latest external call revert reason. function reReason() internal pure returns (bytes memory reason) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly reason := mload(0x40) let length := returndatasize() mstore(reason, length) returndatacopy(add(reason, 0x20), 0, length) mstore(0x40, add(reason, add(0x20, length))) } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol"; import "../interfaces/IDaiLikePermit.sol"; import "../interfaces/IPermit2.sol"; import "../interfaces/IWETH.sol"; import "../libraries/RevertReasonForwarder.sol"; /** * @title Implements efficient safe methods for ERC20 interface. * @notice Compared to the standard ERC20, this implementation offers several enhancements: * 1. more gas-efficient, providing significant savings in transaction costs. * 2. support for different permit implementations * 3. forceApprove functionality * 4. support for WETH deposit and withdraw */ library SafeERC20 { error SafeTransferFailed(); error SafeTransferFromFailed(); error ForceApproveFailed(); error SafeIncreaseAllowanceFailed(); error SafeDecreaseAllowanceFailed(); error SafePermitBadLength(); error Permit2TransferAmountTooHigh(); // Uniswap Permit2 address address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3; bytes4 private constant _PERMIT_LENGTH_ERROR = 0x68275857; // SafePermitBadLength.selector uint256 private constant _RAW_CALL_GAS_LIMIT = 5000; /** * @notice Fetches the balance of a specific ERC20 token held by an account. * Consumes less gas then regular `ERC20.balanceOf`. * @param token The IERC20 token contract for which the balance will be fetched. * @param account The address of the account whose token balance will be fetched. * @return tokenBalance The balance of the specified ERC20 token held by the account. */ function safeBalanceOf( IERC20 token, address account ) internal view returns(uint256 tokenBalance) { bytes4 selector = IERC20.balanceOf.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0x00, selector) mstore(0x04, account) let success := staticcall(gas(), token, 0x00, 0x24, 0x00, 0x20) tokenBalance := mload(0) if or(iszero(success), lt(returndatasize(), 0x20)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Attempts to safely transfer tokens from one address to another. * @dev If permit2 is true, uses the Permit2 standard; otherwise uses the standard ERC20 transferFrom. * Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. * @param permit2 If true, uses the Permit2 standard for the transfer; otherwise uses the standard ERC20 transferFrom. */ function safeTransferFromUniversal( IERC20 token, address from, address to, uint256 amount, bool permit2 ) internal { if (permit2) { safeTransferFromPermit2(token, from, to, amount); } else { safeTransferFrom(token, from, to, amount); } } /** * @notice Attempts to safely transfer tokens from one address to another using the ERC20 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFrom( IERC20 token, address from, address to, uint256 amount ) internal { bytes4 selector = token.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) success := call(gas(), token, 0, data, 100, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens from one address to another using the Permit2 standard. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param from The address from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param amount The amount of tokens to transfer. */ function safeTransferFromPermit2( IERC20 token, address from, address to, uint256 amount ) internal { if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh(); bytes4 selector = IPermit2.transferFrom.selector; bool success; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), from) mstore(add(data, 0x24), to) mstore(add(data, 0x44), amount) mstore(add(data, 0x64), token) success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0) if success { success := gt(extcodesize(_PERMIT2), 0) } } if (!success) revert SafeTransferFromFailed(); } /** * @notice Attempts to safely transfer tokens to another address. * @dev Either requires `true` in return data, or requires target to be smart-contract and empty return data. * @param token The IERC20 token contract from which the tokens will be transferred. * @param to The address to which the tokens will be transferred. * @param value The amount of tokens to transfer. */ function safeTransfer( IERC20 token, address to, uint256 value ) internal { if (!_makeCall(token, token.transfer.selector, to, value)) { revert SafeTransferFailed(); } } /** * @notice Attempts to approve a spender to spend a certain amount of tokens. * @dev If `approve(from, to, amount)` fails, it tries to set the allowance to zero, and retries the `approve` call. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. */ function forceApprove( IERC20 token, address spender, uint256 value ) internal { if (!_makeCall(token, token.approve.selector, spender, value)) { if ( !_makeCall(token, token.approve.selector, spender, 0) || !_makeCall(token, token.approve.selector, spender, value) ) { revert ForceApproveFailed(); } } } /** * @notice Safely increases the allowance of a spender. * @dev Increases with safe math check. Checks if the increased allowance will overflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to increase the allowance by. */ function safeIncreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed(); forceApprove(token, spender, allowance + value); } /** * @notice Safely decreases the allowance of a spender. * @dev Decreases with safe math check. Checks if the decreased allowance will underflow, if yes, then it reverts the transaction. * Then uses `forceApprove` to increase the allowance. * @param token The IERC20 token contract on which the call will be made. * @param spender The address which will spend the funds. * @param value The amount of tokens to decrease the allowance by. */ function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { uint256 allowance = token.allowance(address(this), spender); if (value > allowance) revert SafeDecreaseAllowanceFailed(); forceApprove(token, spender, allowance - value); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, bytes calldata permit) internal { if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with custom owner and spender parameters. * Permit type is determined automatically based on permit calldata (IERC20Permit, IDaiLikePermit, and IPermit2). * @dev Wraps `tryPermit` function and forwards revert reason if permit fails. * @param token The IERC20 token to execute the permit function on. * @param owner The owner of the tokens for which the permit is made. * @param spender The spender allowed to spend the tokens by the permit. * @param permit The permit data to be used in the function call. */ function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal { if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert(); } /** * @notice Attempts to execute the `permit` function on the provided token with the sender and contract as parameters. * @dev Invokes `tryPermit` with sender as owner and contract as spender. * @param token The IERC20 token to execute the permit function on. * @param permit The permit data to be used in the function call. * @return success Returns true if the permit function was successfully executed, false otherwise. */ function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) { return tryPermit(token, msg.sender, address(this), permit); } /** * @notice The function attempts to call the permit function on a given ERC20 token. * @dev The function is designed to support a variety of permit functions, namely: IERC20Permit, IDaiLikePermit, and IPermit2. * It accommodates both Compact and Full formats of these permit types. * Please note, it is expected that the `expiration` parameter for the compact Permit2 and the `deadline` parameter * for the compact Permit are to be incremented by one before invoking this function. This approach is motivated by * gas efficiency considerations; as the unlimited expiration period is likely to be the most common scenario, and * zeros are cheaper to pass in terms of gas cost. Thus, callers should increment the expiration or deadline by one * before invocation for optimized performance. * @param token The address of the ERC20 token on which to call the permit function. * @param owner The owner of the tokens. This address should have signed the off-chain permit. * @param spender The address which will be approved for transfer of tokens. * @param permit The off-chain permit data, containing different fields depending on the type of permit function. * @return success A boolean indicating whether the permit call was successful. */ function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) { // load function selectors for different permit standards bytes4 permitSelector = IERC20Permit.permit.selector; bytes4 daiPermitSelector = IDaiLikePermit.permit.selector; bytes4 permit2Selector = IPermit2.permit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let ptr := mload(0x40) // Switch case for different permit lengths, indicating different permit standards switch permit.length // Compact IERC20Permit case 100 { mstore(ptr, permitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs) { // stack too deep let deadline := shr(224, calldataload(add(permit.offset, 0x20))) // loads permit.offset 0x20..0x23 let vs := calldataload(add(permit.offset, 0x44)) // loads permit.offset 0x44..0x63 calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // store value = copy permit.offset 0x00..0x19 mstore(add(ptr, 0x64), sub(deadline, 1)) // store deadline = deadline - 1 mstore(add(ptr, 0x84), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // store r = copy permit.offset 0x24..0x43 mstore(add(ptr, 0xc4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // Compact IDaiLikePermit case 72 { mstore(ptr, daiPermitSelector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), spender) // store spender // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs) { // stack too deep let expiry := shr(224, calldataload(add(permit.offset, 0x04))) // loads permit.offset 0x04..0x07 let vs := calldataload(add(permit.offset, 0x28)) // loads permit.offset 0x28..0x47 mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset))) // store nonce = copy permit.offset 0x00..0x03 mstore(add(ptr, 0x64), sub(expiry, 1)) // store expiry = expiry - 1 mstore(add(ptr, 0x84), true) // store allowed = true mstore(add(ptr, 0xa4), add(27, shr(255, vs))) // store v = most significant bit of vs + 27 (27 or 28) calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // store r = copy permit.offset 0x08..0x27 mstore(add(ptr, 0xe4), shr(1, shl(1, vs))) // store s = vs without most significant bit } // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // IERC20Permit case 224 { mstore(ptr, permitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0xe4, 0, 0) } // IDaiLikePermit case 256 { mstore(ptr, daiPermitSelector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s) success := call(gas(), token, 0, ptr, 0x104, 0, 0) } // Compact IPermit2 case 96 { // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs) mstore(ptr, permit2Selector) // store selector mstore(add(ptr, 0x04), owner) // store owner mstore(add(ptr, 0x24), token) // store token calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // store amount = copy permit.offset 0x00..0x13 // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // store expiration = ((permit.offset 0x14..0x17 - 1) & 0xffffffffffff) mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // store nonce = copy permit.offset 0x18..0x1b mstore(add(ptr, 0xa4), spender) // store spender // and(0xffffffffffff, ...) - conversion to uint48 mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // store sigDeadline = ((permit.offset 0x1c..0x1f - 1) & 0xffffffffffff) mstore(add(ptr, 0xe4), 0x100) // store offset = 256 mstore(add(ptr, 0x104), 0x40) // store length = 64 calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // store r = copy permit.offset 0x20..0x3f calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // store vs = copy permit.offset 0x40..0x5f // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // IPermit2 case 352 { mstore(ptr, permit2Selector) calldatacopy(add(ptr, 0x04), permit.offset, permit.length) // copy permit calldata // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature) success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0) } // Unknown default { mstore(ptr, _PERMIT_LENGTH_ERROR) revert(ptr, 4) } } } /** * @dev Executes a low level call to a token contract, making it resistant to reversion and erroneous boolean returns. * @param token The IERC20 token contract on which the call will be made. * @param selector The function signature that is to be called on the token contract. * @param to The address to which the token amount will be transferred. * @param amount The token amount to be transferred. * @return success A boolean indicating if the call was successful. Returns 'true' on success and 'false' on failure. * In case of success but no returned data, validates that the contract code exists. * In case of returned data, ensures that it's a boolean `true`. */ function _makeCall( IERC20 token, bytes4 selector, address to, uint256 amount ) private returns (bool success) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly let data := mload(0x40) mstore(data, selector) mstore(add(data, 0x04), to) mstore(add(data, 0x24), amount) success := call(gas(), token, 0, data, 0x44, 0x0, 0x20) if success { switch returndatasize() case 0 { success := gt(extcodesize(token), 0) } default { success := and(gt(returndatasize(), 31), eq(mload(0), 1)) } } } } /** * @notice Safely deposits a specified amount of Ether into the IWETH contract. Consumes less gas then regular `IWETH.deposit`. * @param weth The IWETH token contract. * @param amount The amount of Ether to deposit into the IWETH contract. */ function safeDeposit(IWETH weth, uint256 amount) internal { if (amount > 0) { bytes4 selector = IWETH.deposit.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) { returndatacopy(0, 0, returndatasize()) revert(0, returndatasize()) } } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract. Consumes less gas then regular `IWETH.withdraw`. * @dev Uses inline assembly to interact with the IWETH contract. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. */ function safeWithdraw(IWETH weth, uint256 amount) internal { bytes4 selector = IWETH.withdraw.selector; assembly ("memory-safe") { // solhint-disable-line no-inline-assembly mstore(0, selector) mstore(4, amount) if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } /** * @notice Safely withdraws a specified amount of wrapped Ether from the IWETH contract to a specified recipient. * Consumes less gas then regular `IWETH.withdraw`. * @param weth The IWETH token contract. * @param amount The amount of wrapped Ether to withdraw from the IWETH contract. * @param to The recipient of the withdrawn Ether. */ function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal { safeWithdraw(weth, amount); if (to != address(this)) { assembly ("memory-safe") { // solhint-disable-line no-inline-assembly if iszero(call(_RAW_CALL_GAS_LIMIT, to, amount, 0, 0, 0, 0)) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; pragma abicoder v1; enum EnumType { SourceTokenInteraction, TargetTokenInteraction, CallType } enum UniswapV3LikeProtocol { Uniswap, Kyber, Maverick, Pancake } error EthValueAmountMismatch(); error EthValueSourceTokenMismatch(); error MinReturnError(uint256, uint256); error EmptySwapOnExecutor(); error EmptySwap(); error ZeroInput(); error ZeroRecipient(); error MultiSwapNotAllowed(); error TransactionExpired(uint256, uint256); error PermitNotAllowedForEthSwap(); error SwapTotalAmountCannotBeZero(); error SwapAmountCannotBeZero(); error DirectEthDepositIsForbidden(); error MStableInvalidSwapType(uint256); error AddressCannotBeZero(); error TransferFromNotAllowed(); error EnumOutOfRangeValue(EnumType, uint256); error BadUniswapV3LikePool(UniswapV3LikeProtocol); error ERC1820InterfactionForbidden();
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; pragma abicoder v1; import '../Errors.sol'; /** * @title ContractOnlyEthRecipient * @notice Base contract that rejects any direct ethereum deposits. This is a failsafe against users who can accidentaly send ether */ abstract contract ContractOnlyEthRecipient { receive() external payable { // solhint-disable-next-line avoid-tx-origin if (msg.sender == tx.origin) { revert DirectEthDepositIsForbidden(); } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /** * @title ISwapExecutor * @notice Interface for executing low level swaps, including all relevant structs and enums */ interface ISwapExecutor { struct TokenTransferInfo { IERC20 token; uint256 exactAmount; address payable recipient; } struct TargetSwapDescription { uint256 tokenRatio; address target; bytes data; // uint8 callType; first 8 bits // uint8 sourceInteraction; next 8 bits // uint32 amountOffset; next 32 bits // address sourceTokenInteractionTarget; last 160 bits uint256 params; } struct SwapDescription { IERC20 sourceToken; TargetSwapDescription[] swaps; } function executeSwap( TokenTransferInfo[] calldata targetTokenTransferInfos, SwapDescription[] calldata swapDescriptions ) external payable; } uint8 constant CALL_TYPE_DIRECT = 0; uint8 constant CALL_TYPE_CALCULATED = 1; uint8 constant SOURCE_TOKEN_INTERACTION_NONE = 0; uint8 constant SOURCE_TOKEN_INTERACTION_TRANSFER = 1; uint8 constant SOURCE_TOKEN_INTERACTION_APPROVE = 2;
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; import './ISwapExecutor.sol'; /** * @title ISwapFacade * @notice Interface for the Facade contract of the aggregator. */ interface ISwapFacade { struct MinReturnInfo { IERC20 token; uint256 amount; address recipient; } event Trade( address srcToken, address dstToken, uint256 srcTokenAmount, uint256 dstTokenAmount, uint256 srcTokenFees ); function swap( ISwapExecutor executor, uint256 amount, MinReturnInfo[] calldata minReturns, ISwapExecutor.TokenTransferInfo[] calldata targetTokenTransferInfos, uint256 deadline, ISwapExecutor.SwapDescription[] calldata swapDescriptions, bytes calldata permit ) external payable returns (uint256[] memory); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.18; pragma abicoder v1; import '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import '@1inch/solidity-utils/contracts/libraries/SafeERC20.sol'; /** * @title TokenLibrary * @notice Library for basic interactions with tokens (such as deposits, withdrawals, transfers) */ library TokenLibrary { using SafeERC20 for IERC20; function isEth(IERC20 token) internal pure returns (bool) { return address(token) == address(0) || address(token) == address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); } function universalBalanceOf( IERC20 token, address account ) internal view returns (uint256) { if (isEth(token)) { return account.balance; } else { return token.balanceOf(account); } } function universalTransfer( IERC20 token, address payable to, uint256 amount ) internal { if (amount == 0) { return; } if (isEth(token)) { to.transfer(amount); } else { token.safeTransfer(to, amount); } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"feeCollector_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AddressCannotBeZero","type":"error"},{"inputs":[],"name":"EmptySwap","type":"error"},{"inputs":[],"name":"EthValueAmountMismatch","type":"error"},{"inputs":[],"name":"EthValueSourceTokenMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"MinReturnError","type":"error"},{"inputs":[],"name":"MultiSwapNotAllowed","type":"error"},{"inputs":[],"name":"PermitNotAllowedForEthSwap","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SafeTransferFromFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"TransactionExpired","type":"error"},{"inputs":[],"name":"ZeroInput","type":"error"},{"inputs":[],"name":"ZeroRecipient","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"srcToken","type":"address"},{"indexed":false,"internalType":"address","name":"dstToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"srcTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"dstTokenAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"srcTokenFees","type":"uint256"}],"name":"Trade","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"feeCollector","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract ISwapExecutor","name":"executor","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"internalType":"struct ISwapFacade.MinReturnInfo[]","name":"minReturns","type":"tuple[]"},{"components":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"uint256","name":"exactAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ISwapExecutor.TokenTransferInfo[]","name":"targetTokenTransferInfos","type":"tuple[]"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"components":[{"internalType":"contract IERC20","name":"sourceToken","type":"address"},{"components":[{"internalType":"uint256","name":"tokenRatio","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"params","type":"uint256"}],"internalType":"struct ISwapExecutor.TargetSwapDescription[]","name":"swaps","type":"tuple[]"}],"internalType":"struct ISwapExecutor.SwapDescription[]","name":"swapDescriptions","type":"tuple[]"},{"internalType":"bytes","name":"permit","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"},{"internalType":"address","name":"destination","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeCollector","type":"address"}],"name":"updateFeeCollector","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60806040523480156200001157600080fd5b50604051620017ad380380620017ad833981016040819052620000349162000107565b6200003f336200008d565b6001600160a01b03811662000067576040516303988b8160e61b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b039290921691909117905562000139565b600180546001600160a01b0319169055620000b481620000b7602090811b620008f217901c565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156200011a57600080fd5b81516001600160a01b03811681146200013257600080fd5b9392505050565b61166480620001496000396000f3fe6080604052600436106100865760003560e01c8063c415b95c11610059578063c415b95c1461010e578063d2c35ce81461012e578063e30c39781461014e578063f0d7bb941461016c578063f2fde38b1461018c57600080fd5b8063715018a61461008b57806379ba5097146100a25780638da5cb5b146100b7578063b8dc491b146100ee575b600080fd5b34801561009757600080fd5b506100a06101ac565b005b3480156100ae57600080fd5b506100a06101c0565b3480156100c357600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100fa57600080fd5b506100a06101093660046110b8565b61023f565b34801561011a57600080fd5b506002546100d1906001600160a01b031681565b34801561013a57600080fd5b506100a06101493660046110f1565b6102ca565b34801561015a57600080fd5b506001546001600160a01b03166100d1565b61017f61017a3660046111f8565b61031b565b6040516100e591906112e7565b34801561019857600080fd5b506100a06101a73660046110f1565b610881565b6101b4610942565b6101be600061099c565b565b60015433906001600160a01b031681146102335760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61023c8161099c565b50565b610247610942565b6040516370a0823160e01b81523060048201526102c69082906001600160a01b038516906370a0823190602401602060405180830381865afa158015610291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b5919061132b565b6001600160a01b03851691906109b5565b5050565b6102d2610942565b6001600160a01b0381166102f9576040516303988b8160e61b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6060428610156103475760405163300249d760e01b81526004810187905242602482015260440161022a565b8a6000036103685760405163af458c0760e01b815260040160405180910390fd5b60005b878110156103d857600089898381811061038757610387611344565b905060600201604001602081019061039f91906110f1565b6001600160a01b0316036103c65760405163d27b444360e01b815260040160405180910390fd5b806103d081611370565b91505061036b565b5060008490036103fb5760405163b494d17560e01b815260040160405180910390fd5b600034156104ad578b34146104235760405163178ee1ed60e21b815260040160405180910390fd5b82156104425760405163283e650d60e01b815260040160405180910390fd5b61047d8686600081811061045857610458611344565b905060200281019061046a9190611389565b6104789060208101906110f1565b6109ea565b61049a57604051632b27b8bb60e01b815260040160405180910390fd5b506002546001600160a01b031631610694565b8b868660008181106104c1576104c1611344565b90506020028101906104d39190611389565b6104e19060208101906110f1565b6001600160a01b03166370a082318f6040518263ffffffff1660e01b815260040161051b91906001600160a01b0391909116815260200190565b602060405180830381865afa158015610538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055c919061132b565b10156105f15782156105a7576105a58686600081811061057e5761057e611344565b90506020028101906105909190611389565b61059e9060208101906110f1565b8585610a24565b505b6105f1338e8e898960008181106105c0576105c0611344565b90506020028101906105d29190611389565b6105e09060208101906110f1565b6001600160a01b0316929190610a3b565b8585600081811061060457610604611344565b90506020028101906106169190611389565b6106249060208101906110f1565b6002546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610691919061132b565b90505b60006106a58e8d8d8d8d8c8c610abf565b905034156106cc576002546106c59083906001600160a01b0316316113a9565b915061077a565b81878760008181106106e0576106e0611344565b90506020028101906106f29190611389565b6107009060208101906110f1565b6002546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061132b565b61077791906113a9565b91505b805160011461079c57604051636676835160e01b815260040160405180910390fd5b7fe0c1b141a85ba7f8df7ded19a02a004b049d9e0a67f9dea87186c07bce3923b0878760008181106107d0576107d0611344565b90506020028101906107e29190611389565b6107f09060208101906110f1565b8d8d600081811061080357610803611344565b61081992602060609092020190810191506110f1565b8f8460008151811061082d5761082d611344565b602090810291909101810151604080516001600160a01b03968716815295909416918501919091529183015260608201526080810184905260a00160405180910390a19d9c50505050505050505050505050565b610889610942565b600180546001600160a01b0383166001600160a01b031990911681179091556108ba6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146101be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161022a565b600180546001600160a01b031916905561023c816108f2565b6109c88363a9059cbb60e01b8484610d77565b6109e55760405163fb7f507960e01b815260040160405180910390fd5b505050565b60006001600160a01b0382161580610a1e57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b6000610a338433308686610dca565b949350505050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af19150508015610a99573d8015610a8f57600160005114601f3d11169150610a97565b6000873b1191505b505b80610ab75760405163f405907160e01b815260040160405180910390fd5b505050505050565b606060008667ffffffffffffffff811115610adc57610adc6113bc565b604051908082528060200260200182016040528015610b05578160200160208202803683370190505b50905060005b87811015610ba657610b77898983818110610b2857610b28611344565b9050606002016040016020810190610b4091906110f1565b8a8a84818110610b5257610b52611344565b610b6892602060609092020190810191506110f1565b6001600160a01b031690611011565b828281518110610b8957610b89611344565b602090810291909101015280610b9e81611370565b915050610b0b565b506040516392b1274560e01b81526001600160a01b038a16906392b12745903490610bdb908a908a908a908a906004016113fb565b6000604051808303818588803b158015610bf457600080fd5b505af1158015610c08573d6000803e3d6000fd5b50600093508a9250505067ffffffffffffffff811115610c2a57610c2a6113bc565b604051908082528060200260200182016040528015610c53578160200160208202803683370190505b50905060005b88811015610d69576000838281518110610c7557610c75611344565b602002602001015190506000610cc08c8c85818110610c9657610c96611344565b9050606002016040016020810190610cae91906110f1565b8d8d86818110610b5257610b52611344565b90506000610cce83836113a9565b90508c8c85818110610ce257610ce2611344565b90506060020160200135811015610d3457808d8d86818110610d0657610d06611344565b9050606002016020013560405163321f864360e11b815260040161022a929190918252602082015260400190565b80858581518110610d4757610d47611344565b6020026020010181815250505050508080610d6190611370565b915050610c59565b509998505050505050505050565b60006040518481528360048201528260248201526020600060448360008a5af19150508015610a33573d8015610db957600160005114601f3d11169150610dc1565b6000863b1191505b50949350505050565b60405160009063d505accf60e01b906323f2ebc360e21b906302b67b5760e41b908560648114610e2d5760488114610e915760e08114610eff576101008114610f1b5760608114610f38576101608114610fdb57636827585760e01b8252600482fd5b848252896004830152886024830152602088013560e01c604489013560208a60448601376001820360648501528060ff1c601b016084850152602060248b0160a48601376001600160ff1b031660c48401525060008060e484828f5af19550611003565b838252896004830152886024830152600488013560e01c6028890135893560e01c6044850152600182036064850152600160848501528060ff1c601b0160a4850152602060088b0160c48601376001600160ff1b031660e48401525060008061010484828f5af19550611003565b8482528688600484013760008060e48460008f5af19550611003565b838252868860048401376000806101048460008f5af19550611003565b8282528960048301528a602483015260148860508401376001601489013560e01c0365ffffffffffff166064830152601888013560e01c60848301528860a48301526001601c89013560e01c0365ffffffffffff1660c483015261010060e4830152604061010483015260208089016101248401376020604089016101448401376000806101648460006e22d473030f116ddee9f6b43ac78ba35af19550611003565b828252868860048401376000806101648460006e22d473030f116ddee9f6b43ac78ba35af195505b505050505095945050505050565b600061101c836109ea565b1561103257506001600160a01b03811631610a1e565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d602081101561109a57600080fd5b50519392505050565b6001600160a01b038116811461023c57600080fd5b600080604083850312156110cb57600080fd5b82356110d6816110a3565b915060208301356110e6816110a3565b809150509250929050565b60006020828403121561110357600080fd5b813561110e816110a3565b9392505050565b8035611120816110a3565b919050565b60008083601f84011261113757600080fd5b50813567ffffffffffffffff81111561114f57600080fd5b60208301915083602060608302850101111561116a57600080fd5b9250929050565b60008083601f84011261118357600080fd5b50813567ffffffffffffffff81111561119b57600080fd5b6020830191508360208260051b850101111561116a57600080fd5b60008083601f8401126111c857600080fd5b50813567ffffffffffffffff8111156111e057600080fd5b60208301915083602082850101111561116a57600080fd5b600080600080600080600080600080600060e08c8e03121561121957600080fd5b6112228c611115565b9a5060208c0135995067ffffffffffffffff8060408e0135111561124557600080fd5b6112558e60408f01358f01611125565b909a50985060608d013581101561126b57600080fd5b61127b8e60608f01358f01611125565b909850965060808d0135955060a08d013581101561129857600080fd5b6112a88e60a08f01358f01611171565b909550935060c08d01358110156112be57600080fd5b506112cf8d60c08e01358e016111b6565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b8181101561131f57835183529284019291840191600101611303565b50909695505050505050565b60006020828403121561133d57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016113825761138261135a565b5060010190565b60008235603e1983360301811261139f57600080fd5b9190910192915050565b81810381811115610a1e57610a1e61135a565b634e487b7160e01b600052604160045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040808252810184905260006060820186825b878110156114645761142082356110a3565b6001600160a01b038235811684526020808401359085015261144560408401356110a3565b604083810135909116908401526060928301929091019060010161140e565b505082810360208401528084825260208201905060208560051b8301018660005b8781101561161f57848303601f19018452603e19368a900381018335126114ab57600080fd5b898335016114b981356110a3565b6001600160a01b03813581168652601e1936839003016020830135126114de57600080fd5b816020830135019150813567ffffffffffffffff808211156114ff57600080fd5b8160051b360360208501131561151457600080fd5b604060208901526040880182815260608901905060608360051b8a0101602086016000609e19883603015b868210156115fb57605f198d85030185528083351261155d57600080fd5b888335016020810135855261157560408201356110a3565b88604082013516602086015260608101358b82360301811261159657600080fd5b8101604081019060200135888111156115ae57600080fd5b8036038213156115bd57600080fd5b608060408801526115d26080880182846113d2565b91505060808201356060870152809550505060208301925060208501945060018201915061153f565b50505080995050505050505050602082019150602084019350600181019050611485565b5090999850505050505050505056fea26469706673582212204fbc7ebf52cb7ab87b88cf1bf0ceb564d3a51205593c2e5b5664743eaaac0a1864736f6c634300081200330000000000000000000000007131ad25bb3fcd2ffb50f2960410cce15fa32dea
Deployed Bytecode
0x6080604052600436106100865760003560e01c8063c415b95c11610059578063c415b95c1461010e578063d2c35ce81461012e578063e30c39781461014e578063f0d7bb941461016c578063f2fde38b1461018c57600080fd5b8063715018a61461008b57806379ba5097146100a25780638da5cb5b146100b7578063b8dc491b146100ee575b600080fd5b34801561009757600080fd5b506100a06101ac565b005b3480156100ae57600080fd5b506100a06101c0565b3480156100c357600080fd5b506000546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100fa57600080fd5b506100a06101093660046110b8565b61023f565b34801561011a57600080fd5b506002546100d1906001600160a01b031681565b34801561013a57600080fd5b506100a06101493660046110f1565b6102ca565b34801561015a57600080fd5b506001546001600160a01b03166100d1565b61017f61017a3660046111f8565b61031b565b6040516100e591906112e7565b34801561019857600080fd5b506100a06101a73660046110f1565b610881565b6101b4610942565b6101be600061099c565b565b60015433906001600160a01b031681146102335760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f7420746865206044820152683732bb9037bbb732b960b91b60648201526084015b60405180910390fd5b61023c8161099c565b50565b610247610942565b6040516370a0823160e01b81523060048201526102c69082906001600160a01b038516906370a0823190602401602060405180830381865afa158015610291573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b5919061132b565b6001600160a01b03851691906109b5565b5050565b6102d2610942565b6001600160a01b0381166102f9576040516303988b8160e61b815260040160405180910390fd5b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6060428610156103475760405163300249d760e01b81526004810187905242602482015260440161022a565b8a6000036103685760405163af458c0760e01b815260040160405180910390fd5b60005b878110156103d857600089898381811061038757610387611344565b905060600201604001602081019061039f91906110f1565b6001600160a01b0316036103c65760405163d27b444360e01b815260040160405180910390fd5b806103d081611370565b91505061036b565b5060008490036103fb5760405163b494d17560e01b815260040160405180910390fd5b600034156104ad578b34146104235760405163178ee1ed60e21b815260040160405180910390fd5b82156104425760405163283e650d60e01b815260040160405180910390fd5b61047d8686600081811061045857610458611344565b905060200281019061046a9190611389565b6104789060208101906110f1565b6109ea565b61049a57604051632b27b8bb60e01b815260040160405180910390fd5b506002546001600160a01b031631610694565b8b868660008181106104c1576104c1611344565b90506020028101906104d39190611389565b6104e19060208101906110f1565b6001600160a01b03166370a082318f6040518263ffffffff1660e01b815260040161051b91906001600160a01b0391909116815260200190565b602060405180830381865afa158015610538573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061055c919061132b565b10156105f15782156105a7576105a58686600081811061057e5761057e611344565b90506020028101906105909190611389565b61059e9060208101906110f1565b8585610a24565b505b6105f1338e8e898960008181106105c0576105c0611344565b90506020028101906105d29190611389565b6105e09060208101906110f1565b6001600160a01b0316929190610a3b565b8585600081811061060457610604611344565b90506020028101906106169190611389565b6106249060208101906110f1565b6002546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa15801561066d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610691919061132b565b90505b60006106a58e8d8d8d8d8c8c610abf565b905034156106cc576002546106c59083906001600160a01b0316316113a9565b915061077a565b81878760008181106106e0576106e0611344565b90506020028101906106f29190611389565b6107009060208101906110f1565b6002546040516370a0823160e01b81526001600160a01b0391821660048201529116906370a0823190602401602060405180830381865afa158015610749573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061076d919061132b565b61077791906113a9565b91505b805160011461079c57604051636676835160e01b815260040160405180910390fd5b7fe0c1b141a85ba7f8df7ded19a02a004b049d9e0a67f9dea87186c07bce3923b0878760008181106107d0576107d0611344565b90506020028101906107e29190611389565b6107f09060208101906110f1565b8d8d600081811061080357610803611344565b61081992602060609092020190810191506110f1565b8f8460008151811061082d5761082d611344565b602090810291909101810151604080516001600160a01b03968716815295909416918501919091529183015260608201526080810184905260a00160405180910390a19d9c50505050505050505050505050565b610889610942565b600180546001600160a01b0383166001600160a01b031990911681179091556108ba6000546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000546001600160a01b031633146101be5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161022a565b600180546001600160a01b031916905561023c816108f2565b6109c88363a9059cbb60e01b8484610d77565b6109e55760405163fb7f507960e01b815260040160405180910390fd5b505050565b60006001600160a01b0382161580610a1e57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b6000610a338433308686610dca565b949350505050565b60006323b872dd60e01b905060006040518281528560048201528460248201528360448201526020600060648360008b5af19150508015610a99573d8015610a8f57600160005114601f3d11169150610a97565b6000873b1191505b505b80610ab75760405163f405907160e01b815260040160405180910390fd5b505050505050565b606060008667ffffffffffffffff811115610adc57610adc6113bc565b604051908082528060200260200182016040528015610b05578160200160208202803683370190505b50905060005b87811015610ba657610b77898983818110610b2857610b28611344565b9050606002016040016020810190610b4091906110f1565b8a8a84818110610b5257610b52611344565b610b6892602060609092020190810191506110f1565b6001600160a01b031690611011565b828281518110610b8957610b89611344565b602090810291909101015280610b9e81611370565b915050610b0b565b506040516392b1274560e01b81526001600160a01b038a16906392b12745903490610bdb908a908a908a908a906004016113fb565b6000604051808303818588803b158015610bf457600080fd5b505af1158015610c08573d6000803e3d6000fd5b50600093508a9250505067ffffffffffffffff811115610c2a57610c2a6113bc565b604051908082528060200260200182016040528015610c53578160200160208202803683370190505b50905060005b88811015610d69576000838281518110610c7557610c75611344565b602002602001015190506000610cc08c8c85818110610c9657610c96611344565b9050606002016040016020810190610cae91906110f1565b8d8d86818110610b5257610b52611344565b90506000610cce83836113a9565b90508c8c85818110610ce257610ce2611344565b90506060020160200135811015610d3457808d8d86818110610d0657610d06611344565b9050606002016020013560405163321f864360e11b815260040161022a929190918252602082015260400190565b80858581518110610d4757610d47611344565b6020026020010181815250505050508080610d6190611370565b915050610c59565b509998505050505050505050565b60006040518481528360048201528260248201526020600060448360008a5af19150508015610a33573d8015610db957600160005114601f3d11169150610dc1565b6000863b1191505b50949350505050565b60405160009063d505accf60e01b906323f2ebc360e21b906302b67b5760e41b908560648114610e2d5760488114610e915760e08114610eff576101008114610f1b5760608114610f38576101608114610fdb57636827585760e01b8252600482fd5b848252896004830152886024830152602088013560e01c604489013560208a60448601376001820360648501528060ff1c601b016084850152602060248b0160a48601376001600160ff1b031660c48401525060008060e484828f5af19550611003565b838252896004830152886024830152600488013560e01c6028890135893560e01c6044850152600182036064850152600160848501528060ff1c601b0160a4850152602060088b0160c48601376001600160ff1b031660e48401525060008061010484828f5af19550611003565b8482528688600484013760008060e48460008f5af19550611003565b838252868860048401376000806101048460008f5af19550611003565b8282528960048301528a602483015260148860508401376001601489013560e01c0365ffffffffffff166064830152601888013560e01c60848301528860a48301526001601c89013560e01c0365ffffffffffff1660c483015261010060e4830152604061010483015260208089016101248401376020604089016101448401376000806101648460006e22d473030f116ddee9f6b43ac78ba35af19550611003565b828252868860048401376000806101648460006e22d473030f116ddee9f6b43ac78ba35af195505b505050505095945050505050565b600061101c836109ea565b1561103257506001600160a01b03811631610a1e565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03168152602001915050602060405180830381865afa158015611084573d6000803e3d6000fd5b505050506040513d602081101561109a57600080fd5b50519392505050565b6001600160a01b038116811461023c57600080fd5b600080604083850312156110cb57600080fd5b82356110d6816110a3565b915060208301356110e6816110a3565b809150509250929050565b60006020828403121561110357600080fd5b813561110e816110a3565b9392505050565b8035611120816110a3565b919050565b60008083601f84011261113757600080fd5b50813567ffffffffffffffff81111561114f57600080fd5b60208301915083602060608302850101111561116a57600080fd5b9250929050565b60008083601f84011261118357600080fd5b50813567ffffffffffffffff81111561119b57600080fd5b6020830191508360208260051b850101111561116a57600080fd5b60008083601f8401126111c857600080fd5b50813567ffffffffffffffff8111156111e057600080fd5b60208301915083602082850101111561116a57600080fd5b600080600080600080600080600080600060e08c8e03121561121957600080fd5b6112228c611115565b9a5060208c0135995067ffffffffffffffff8060408e0135111561124557600080fd5b6112558e60408f01358f01611125565b909a50985060608d013581101561126b57600080fd5b61127b8e60608f01358f01611125565b909850965060808d0135955060a08d013581101561129857600080fd5b6112a88e60a08f01358f01611171565b909550935060c08d01358110156112be57600080fd5b506112cf8d60c08e01358e016111b6565b81935080925050509295989b509295989b9093969950565b6020808252825182820181905260009190848201906040850190845b8181101561131f57835183529284019291840191600101611303565b50909695505050505050565b60006020828403121561133d57600080fd5b5051919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016113825761138261135a565b5060010190565b60008235603e1983360301811261139f57600080fd5b9190910192915050565b81810381811115610a1e57610a1e61135a565b634e487b7160e01b600052604160045260246000fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6040808252810184905260006060820186825b878110156114645761142082356110a3565b6001600160a01b038235811684526020808401359085015261144560408401356110a3565b604083810135909116908401526060928301929091019060010161140e565b505082810360208401528084825260208201905060208560051b8301018660005b8781101561161f57848303601f19018452603e19368a900381018335126114ab57600080fd5b898335016114b981356110a3565b6001600160a01b03813581168652601e1936839003016020830135126114de57600080fd5b816020830135019150813567ffffffffffffffff808211156114ff57600080fd5b8160051b360360208501131561151457600080fd5b604060208901526040880182815260608901905060608360051b8a0101602086016000609e19883603015b868210156115fb57605f198d85030185528083351261155d57600080fd5b888335016020810135855261157560408201356110a3565b88604082013516602086015260608101358b82360301811261159657600080fd5b8101604081019060200135888111156115ae57600080fd5b8036038213156115bd57600080fd5b608060408801526115d26080880182846113d2565b91505060808201356060870152809550505060208301925060208501945060018201915061153f565b50505080995050505050505050602082019150602084019350600181019050611485565b5090999850505050505050505056fea26469706673582212204fbc7ebf52cb7ab87b88cf1bf0ceb564d3a51205593c2e5b5664743eaaac0a1864736f6c63430008120033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007131ad25bb3fcd2ffb50f2960410cce15fa32dea
-----Decoded View---------------
Arg [0] : feeCollector_ (address): 0x7131Ad25bb3fCD2FFB50f2960410cce15Fa32deA
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000007131ad25bb3fcd2ffb50f2960410cce15fa32dea
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
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.