This is a contract address for Endaoment.
More Info
Private Name Tags
ContractCreator
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 130176817 | 337 days ago | 0.00001 ETH | ||||
| 130176817 | 337 days ago | 0.00001 ETH | ||||
| 130173828 | 337 days ago | 0.00001 ETH | ||||
| 130173828 | 337 days ago | 0.00001 ETH | ||||
| 130173291 | 337 days ago | 0.00001 ETH | ||||
| 130173291 | 337 days ago | 0.00001 ETH | ||||
| 130160642 | 338 days ago | 0.00001 ETH | ||||
| 130160642 | 338 days ago | 0.00001 ETH | ||||
| 130133359 | 338 days ago | 0.00001 ETH | ||||
| 130133359 | 338 days ago | 0.00001 ETH | ||||
| 130133324 | 338 days ago | 0.00001 ETH | ||||
| 130133324 | 338 days ago | 0.00001 ETH | ||||
| 130124874 | 338 days ago | 0.00001 ETH | ||||
| 130124874 | 338 days ago | 0.00001 ETH | ||||
| 127274527 | 404 days ago | 0.0001 ETH | ||||
| 127274527 | 404 days ago | 0.0001 ETH | ||||
| 124678481 | 465 days ago | 0.16 ETH | ||||
| 124678481 | 465 days ago | 0.16 ETH | ||||
| 124115816 | 478 days ago | 0.02 ETH | ||||
| 124115816 | 478 days ago | 0.02 ETH | ||||
| 122087840 | 525 days ago | 0.0059 ETH | ||||
| 122087840 | 525 days ago | 0.0059 ETH | ||||
| 121367103 | 541 days ago | 0.001 ETH | ||||
| 121367103 | 541 days ago | 0.001 ETH | ||||
| 121222167 | 545 days ago | 0.001 ETH |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
AutoRouterWrapper
Compiler Version
v0.8.13+commit.abaa5c0e
Optimization Enabled:
Yes with 9999999 runs
Other Settings:
london EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
//SPDX-License-Identifier: BSD 3-Clause
pragma solidity 0.8.13;
import {ISwapWrapper} from "../interfaces/ISwapWrapper.sol";
import {ISwapRouter} from "../lib/ISwapRouter02.sol";
import {ERC20} from "solmate/tokens/ERC20.sol";
import {IWETH9} from "../lib/IWETH9.sol";
import {SafeTransferLib} from "solmate/utils/SafeTransferLib.sol";
import "../lib/uniswap/Path.sol";
contract AutoRouterWrapper is ISwapWrapper {
using SafeTransferLib for ERC20;
using BytesLib for bytes;
/// @notice A deployed SwapRouter02(1.1.0). See https://docs.uniswap.org/protocol/reference/deployments.
ISwapRouter public immutable swapRouter;
/// @notice WETH contract.
IWETH9 public immutable weth;
/// @notice SwapWrapper name.
string public name;
/// @dev Address we use to represent ETH.
address internal constant eth = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
error TxFailed();
error OnlyMulticallsAllowed();
error PathMismatch();
error UnhandledFunction(bytes4 selector);
error ETHAmountInMismatch();
error TotalAmountMismatch();
error RecipientMismatch(bytes4 selector);
error TokenInMismatch(bytes4 selector);
error TokenOutMismatch(bytes4 selector);
/**
* @param _name SwapWrapper name.
* @param _uniV3SwapRouter Deployed Uniswap v3 SwapRouter.
*/
constructor(string memory _name, address _uniV3SwapRouter) {
name = _name;
swapRouter = ISwapRouter(_uniV3SwapRouter);
weth = IWETH9(swapRouter.WETH9());
}
function swap(address _tokenIn, address _tokenOut, address _recipient, uint256 _amount, bytes calldata _data)
external
payable
returns (uint256)
{
// If token is ETH and value was sent, ensure the value matches the swap input amount.
bool _isInputEth = _tokenIn == eth;
if ((_isInputEth && msg.value != _amount) || (!_isInputEth && msg.value > 0)) {
revert ETHAmountInMismatch();
}
uint256 _prevBalance = getBalance(_tokenOut, _recipient);
if (!_isInputEth) {
// If caller isn't sending ETH, we need to transfer in tokens...
ERC20(_tokenIn).safeTransferFrom(msg.sender, address(this), _amount);
ERC20(_tokenIn).safeApprove(address(swapRouter), 0);
ERC20(_tokenIn).safeApprove(address(swapRouter), _amount);
}
uint256 _totalAmountIn = _validateData(_tokenIn, _tokenOut, _recipient, _data);
// _totalAmountIn has been modified by the various `check...()` methods, and should now sum to _amount
if (_totalAmountIn != _amount) revert TotalAmountMismatch();
(bool _success,) = address(swapRouter).call{value: _isInputEth ? _amount : 0}(_data);
if (!_success) revert TxFailed();
uint256 _amountOut = getBalance(_tokenOut, _recipient) - _prevBalance;
emit WrapperSwapExecuted(_tokenIn, _tokenOut, msg.sender, _recipient, _totalAmountIn, _amountOut);
return _amountOut;
}
function _validateData(address _tokenIn, address _tokenOut, address _recipient, bytes calldata _data)
internal
view
returns (uint256 _totalAmountIn)
{
bytes4 _selector = bytes4(_data[:4]);
// Check that it's the multicall function that's being called.
if (_selector != ISwapRouter.multicall.selector) revert OnlyMulticallsAllowed();
( /*uint256 deadline*/ , bytes[] memory _calls) = abi.decode(_data[4:], (uint256, bytes[]));
uint256 _callsLength = _calls.length;
for (uint256 i = 0; i < _callsLength; i++) {
bytes memory _call = _calls[i];
// Get the selector
_selector = bytes4(_call.slice(0, 4));
// Remove the selector
bytes memory _callWithoutSelector = _call.slice(4, _call.length - 4);
// check TokenIn if it's the first call of a multicall
bool _checkTokenIn = i == 0;
// check TokenOut if it's the last call of a multicall
bool _checkTokenOut = i == _callsLength - 1;
// Check that selector is an approved selector and validate its arguments.
if (_selector == ISwapRouter.exactInputSingle.selector) {
_totalAmountIn += checkExactInputSingle(
_callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
);
} else if (_selector == ISwapRouter.exactInput.selector) {
_totalAmountIn += checkExactInput(
_callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
);
} else if (_selector == ISwapRouter.sweepToken.selector) {
checkSweepToken(_callWithoutSelector, _tokenOut, _recipient);
} else if (_selector == ISwapRouter.swapExactTokensForTokens.selector) {
_totalAmountIn += checkSwapExactTokensForTokens(
_callWithoutSelector, _tokenIn, _tokenOut, _recipient, _checkTokenIn, _checkTokenOut
);
} else if (_selector == ISwapRouter.unwrapWETH9.selector) {
checkUnwrapWETH9(_callWithoutSelector, _recipient);
} else {
revert UnhandledFunction(_selector);
}
}
}
function checkExactInputSingle(
bytes memory _data,
address _tokenInExpected,
address _tokenOutExpected,
address _recipientExpected,
bool _checkTokenIn,
bool _checkTokenOut
) internal view returns (uint256) {
(
address _tokenIn,
address _tokenOut,
/*uint24 _fee*/
,
address _recipient,
uint256 _amountIn,
/*uint256 _amountOutMinimum*/
,
/*uint160 _sqrtPriceLimitX96*/
) = abi.decode(_data, (address, address, uint24, address, uint256, uint256, uint160));
if (_checkTokenIn) {
bool _tokensMatch = checkTokens(_tokenIn, _tokenInExpected);
if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.exactInputSingle.selector);
}
if (_checkTokenOut) {
bool _tokensMatch = checkTokens(_tokenOut, _tokenOutExpected);
if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.exactInputSingle.selector);
}
checkRecipient(_recipient, _recipientExpected, ISwapRouter.exactInputSingle.selector);
return _amountIn;
}
function checkExactInput(
bytes memory _data,
address _tokenInExpected,
address _tokenOutExpected,
address _recipientExpected,
bool _checkTokenIn,
bool _checkTokenOut
) internal view returns (uint256) {
(
bytes memory _path,
address _recipient,
uint256 _amountIn,
/*uint256 amountOutMinimum*/
// First 32 bytes point to the location of dynamic bytes _path
) = abi.decode(_data.slice(32, _data.length - 32), (bytes, address, uint256, uint256));
if (_checkTokenIn) {
(address _tokenA, /*address _tokenB*/,) = Path.decodeFirstPool(_path);
bool _tokensMatch = checkTokens(_tokenA, _tokenInExpected);
if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.exactInput.selector);
}
if (_checkTokenOut) {
( /*address _tokenA*/ , address _tokenB,) = Path.decodeLastPool(_path);
bool _tokensMatch = checkTokens(_tokenB, _tokenOutExpected);
if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.exactInput.selector);
}
checkRecipient(_recipient, _recipientExpected, ISwapRouter.exactInput.selector);
return _amountIn;
}
function checkSweepToken(bytes memory _data, address _tokenOutExpected, address _recipientExpected) internal view {
(address _token, /*uint256 _amountMinimum*/, address _recipient) =
abi.decode(_data, (address, uint256, address));
bool _tokensMatch = checkTokens(_token, _tokenOutExpected);
if (!_tokensMatch) {
revert TokenOutMismatch(ISwapRouter.sweepToken.selector);
}
checkRecipient(_recipient, _recipientExpected, ISwapRouter.sweepToken.selector);
}
function checkSwapExactTokensForTokens(
bytes memory _data,
address _tokenInExpected,
address _tokenOutExpected,
address _recipientExpected,
bool _checkTokenIn,
bool _checkTokenOut
) internal view returns (uint256) {
(
uint256 _amountIn,
/*uint256 amountOutMin*/
,
address[] memory _path,
address _recipient
) = abi.decode(_data, (uint256, uint256, address[], address));
if (_checkTokenIn) {
bool _tokensMatch = checkTokens(_path[0], _tokenInExpected);
if (!_tokensMatch) revert TokenInMismatch(ISwapRouter.swapExactTokensForTokens.selector);
}
if (_checkTokenOut) {
bool _tokensMatch = checkTokens(_path[_path.length - 1], _tokenOutExpected);
if (!_tokensMatch) revert TokenOutMismatch(ISwapRouter.swapExactTokensForTokens.selector);
}
checkRecipient(_recipient, _recipientExpected, ISwapRouter.swapExactTokensForTokens.selector);
return _amountIn;
}
function checkUnwrapWETH9(bytes memory _data, address _recipientExpected) internal pure {
( /*uint256 amountOutMin*/ , address _recipient) = abi.decode(_data, (uint256, address));
checkRecipient(_recipient, _recipientExpected, ISwapRouter.unwrapWETH9.selector);
}
function checkRecipient(address _recipient, address _recipientExpected, bytes4 _selector) internal pure {
if (_selector == ISwapRouter.sweepToken.selector || _selector == ISwapRouter.unwrapWETH9.selector) {
if (_recipient != _recipientExpected) revert RecipientMismatch(_selector);
} else {
// address(2) is a flag for identifying address(this).
// See https://github.com/Uniswap/swap-router-contracts/blob/9dc4a9cce101be984e148e1af6fe605ebcfa658a/contracts/libraries/Constants.sol#L14
if (_recipient != _recipientExpected && _recipient != address(2)) {
revert RecipientMismatch(_selector);
}
}
}
function getBalance(address _tokenOut, address _recipient) internal view returns (uint256) {
if (_tokenOut == address(eth)) {
return address(_recipient).balance;
} else {
return ERC20(_tokenOut).balanceOf(address(_recipient));
}
}
// Return true if two tokens match, OR if _tokenExpected is eth, token must be weth.
function checkTokens(address _token, address _tokenExpected) internal view returns (bool) {
// `TokenIn` should never == eth by the time this check is reached.
return _token == _tokenExpected || (_tokenExpected == eth ? _token == address(weth) : false);
}
/// @notice Required to receive ETH on `weth.withdraw()`
receive() external payable {}
}//SPDX-License-Identifier: BSD 3-Clause
pragma solidity >=0.8.0;
error ETHAmountInMismatch();
/**
* @notice ISwapWrapper is the interface that all swap wrappers should implement.
* This will be used to support swap protocols like Uniswap V2 and V3, Sushiswap, 1inch, etc.
*/
interface ISwapWrapper {
/// @notice Event emitted after a successful swap.
event WrapperSwapExecuted(
address indexed tokenIn,
address indexed tokenOut,
address sender,
address indexed recipient,
uint256 amountIn,
uint256 amountOut
);
/// @notice Name of swap wrapper for UX readability.
function name() external returns (string memory);
/**
* @notice Swap function. Generally we expect the implementer to call some exactAmountIn-like swap method, and so the documentation
* is written with this in mind. However, the method signature is general enough to support exactAmountOut swaps as well.
* @param _tokenIn Token to be swapped (or 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for ETH).
* @param _tokenOut Token to receive (or 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE for ETH).
* @param _recipient Receiver of `_tokenOut`.
* @param _amount Amount of `_tokenIn` that should be swapped.
* @param _data Additional data that the swap wrapper may require to execute the swap.
* @return Amount of _tokenOut received.
*/
function swap(address _tokenIn, address _tokenOut, address _recipient, uint256 _amount, bytes calldata _data)
external
payable
returns (uint256);
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.13;
import "./IUniswapV3SwapCallback.sol";
/// @title Router token swapping functionality
/// @notice Functions for swapping tokens via Uniswap V3
interface ISwapRouter is IUniswapV3SwapCallback {
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
struct ExactInputParams {
bytes path;
address recipient;
uint256 amountIn;
uint256 amountOutMinimum;
}
function exactInput(ExactInputParams memory params) external payable returns (uint256 amountOut);
function exactInputSingle(ExactInputSingleParams calldata params) external payable returns (uint256 amountOut);
function multicall(uint256 deadline, bytes[] calldata data) external payable returns (bytes[] memory);
function sweepToken(address token, uint256 amountMinimum, address recipient) external payable;
function unwrapWETH9WithFee(uint256 amountMinimum, address recipient, uint256 feeBips, address feeRecipient)
external
payable;
function wrapETH(uint256 value) external payable;
function unwrapWETH9(uint256 amountMinimum, address recipient) external payable;
function WETH9() external view returns (address payable);
//V2 Periphery
function swapExactTokensForTokens(uint256 amountIn, uint256 amountOutMin, address[] calldata path, address to)
external
payable
returns (uint256 amountOut);
}// 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/Rari-Capital/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
//////////////////////////////////////////////////////////////*/
bytes32 public constant PERMIT_TYPEHASH =
keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
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 {
bytes32 digest = keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
)
);
address recoveredAddress = ecrecover(digest, 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: BSD-2-Clause
// !! THIS FILE WAS AUTOGENERATED BY abi-to-sol v0.5.2. SEE SOURCE BELOW. !!
pragma solidity 0.8.13;
interface IWETH9 {
function name() external view returns (string memory);
function approve(address guy, uint256 wad) external returns (bool);
function totalSupply() external view returns (uint256);
function transferFrom(address src, address dst, uint256 wad) external returns (bool);
function withdraw(uint256 wad) external;
function decimals() external view returns (uint8);
function balanceOf(address) external view returns (uint256);
function symbol() external view returns (string memory);
function transfer(address dst, uint256 wad) external returns (bool);
function deposit() external payable;
function allowance(address, address) external view returns (uint256);
event Approval(address indexed src, address indexed guy, uint256 wad);
event Transfer(address indexed src, address indexed dst, uint256 wad);
event Deposit(address indexed dst, uint256 wad);
event Withdrawal(address indexed src, uint256 wad);
}
// THIS FILE WAS AUTOGENERATED FROM THE FOLLOWING ABI JSON:
/*
[{"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"guy","type":"address"},{"name":"wad","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"src","type":"address"},{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"wad","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"name":"dst","type":"address"},{"name":"wad","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"name":"","type":"address"},{"name":"","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"guy","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"dst","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"src","type":"address"},{"indexed":false,"name":"wad","type":"uint256"}],"name":"Withdrawal","type":"event"}]*/// 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/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
library SafeTransferLib {
/*///////////////////////////////////////////////////////////////
ETH OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferETH(address to, uint256 amount) internal {
bool callStatus;
assembly {
// Transfer the ETH and store if it succeeded or not.
callStatus := call(gas(), to, amount, 0, 0, 0, 0)
}
require(callStatus, "ETH_TRANSFER_FAILED");
}
/*///////////////////////////////////////////////////////////////
ERC20 OPERATIONS
//////////////////////////////////////////////////////////////*/
function safeTransferFrom(
ERC20 token,
address from,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata to memory piece by piece:
mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "from" argument.
mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
mstore(add(freeMemoryPointer, 68), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.
// Call the token and store if it succeeded or not.
// We use 100 because the calldata length is 4 + 32 * 3.
callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED");
}
function safeTransfer(
ERC20 token,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata to memory piece by piece:
mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.
// Call the token and store if it succeeded or not.
// We use 68 because the calldata length is 4 + 32 * 2.
callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED");
}
function safeApprove(
ERC20 token,
address to,
uint256 amount
) internal {
bool callStatus;
assembly {
// Get a pointer to some free memory.
let freeMemoryPointer := mload(0x40)
// Write the abi-encoded calldata to memory piece by piece:
mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.
// Call the token and store if it succeeded or not.
// We use 68 because the calldata length is 4 + 32 * 2.
callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
}
require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED");
}
/*///////////////////////////////////////////////////////////////
INTERNAL HELPER LOGIC
//////////////////////////////////////////////////////////////*/
function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {
assembly {
// Get how many bytes the call returned.
let returnDataSize := returndatasize()
// If the call reverted:
if iszero(callStatus) {
// Copy the revert message into memory.
returndatacopy(0, 0, returnDataSize)
// Revert with the same message.
revert(0, returnDataSize)
}
switch returnDataSize
case 32 {
// Copy the return data into memory.
returndatacopy(0, 0, returnDataSize)
// Set success to whether it returned true.
success := iszero(iszero(mload(0)))
}
case 0 {
// There was no return data.
success := 1
}
default {
// It returned some malformed input.
success := 0
}
}
}
}// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.6.0;
import "./BytesLib.sol";
/// @title MODIFIED FILE: Functions for manipulating path data for multihop swaps
/// @notice Additional `decodeLastPool` method was added to the orignal file linked below.
/// @notice Link: https://github.com/Uniswap/v3-periphery/blob/b325bb0905d922ae61fcc7df85ee802e8df5e96c/contracts/libraries/Path.sol
library Path {
using BytesLib for bytes;
/// @dev The length of the bytes encoded address
uint256 private constant ADDR_SIZE = 20;
/// @dev The length of the bytes encoded fee
uint256 private constant FEE_SIZE = 3;
/// @dev The offset of a single token address and pool fee
uint256 private constant NEXT_OFFSET = ADDR_SIZE + FEE_SIZE;
/// @dev The offset of an encoded pool key
uint256 private constant POP_OFFSET = NEXT_OFFSET + ADDR_SIZE;
/// @dev The minimum length of an encoding that contains 2 or more pools
uint256 private constant MULTIPLE_POOLS_MIN_LENGTH = POP_OFFSET + NEXT_OFFSET;
/// @notice Returns true iff the path contains two or more pools
/// @param path The encoded swap path
/// @return True if path contains two or more pools, otherwise false
function hasMultiplePools(bytes memory path) internal pure returns (bool) {
return path.length >= MULTIPLE_POOLS_MIN_LENGTH;
}
/// @notice Returns the number of pools in the path
/// @param path The encoded swap path
/// @return The number of pools in the path
function numPools(bytes memory path) internal pure returns (uint256) {
// Ignore the first token address. From then on every fee and token offset indicates a pool.
return ((path.length - ADDR_SIZE) / NEXT_OFFSET);
}
/// @notice Decodes the first pool in path
/// @param path The bytes encoded swap path
/// @return tokenA The first token of the given pool
/// @return tokenB The second token of the given pool
/// @return fee The fee level of the pool
function decodeFirstPool(bytes memory path) internal pure returns (address tokenA, address tokenB, uint24 fee) {
tokenA = path.toAddress(0);
fee = path.toUint24(ADDR_SIZE);
tokenB = path.toAddress(NEXT_OFFSET);
}
/// @notice Gets the segment corresponding to the first pool in the path
/// @param path The bytes encoded swap path
/// @return The segment containing all data necessary to target the first pool in the path
function getFirstPool(bytes memory path) internal pure returns (bytes memory) {
return path.slice(0, POP_OFFSET);
}
/// @notice Skips a token + fee element from the buffer and returns the remainder
/// @param path The swap path
/// @return The remaining token + fee elements in the path
function skipToken(bytes memory path) internal pure returns (bytes memory) {
return path.slice(NEXT_OFFSET, path.length - NEXT_OFFSET);
}
/// @notice Custom method we've added: Decodes the last pool in path
/// @param path The bytes encoded swap path
/// @return tokenA The first token of the given pool
/// @return tokenB The second token of the given pool
/// @return fee The fee level of the pool
function decodeLastPool(bytes memory path) internal pure returns (address tokenA, address tokenB, uint24 fee) {
path = path.slice(path.length - POP_OFFSET, POP_OFFSET);
tokenA = path.toAddress(0);
fee = path.toUint24(ADDR_SIZE);
tokenB = path.toAddress(NEXT_OFFSET);
}
}// Sourced from https://github.com/Uniswap/v3-core/blob/ed88be38ab2032d82bf10ac6f8d03aa631889d48/contracts/interfaces/callback/IUniswapV3SwapCallback.sol
// Modified solidity pragma.
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.8.13;
/// @title Callback for IUniswapV3PoolActions#swap
/// @notice Any contract that calls IUniswapV3PoolActions#swap must implement this interface
interface IUniswapV3SwapCallback {
/// @notice Called to `msg.sender` after executing a swap via IUniswapV3Pool#swap.
/// @dev In the implementation you must pay the pool tokens owed for the swap.
/// The caller of this method must be checked to be a UniswapV3Pool deployed by the canonical UniswapV3Factory.
/// amount0Delta and amount1Delta can both be 0 if no tokens were swapped.
/// @param amount0Delta The amount of token0 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token0 to the pool.
/// @param amount1Delta The amount of token1 that was sent (negative) or must be received (positive) by the pool by
/// the end of the swap. If positive, the callback must send that amount of token1 to the pool.
/// @param data Any data passed through by the caller via the IUniswapV3PoolActions#swap call
function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external;
}// SPDX-License-Identifier: GPL-2.0-or-later /* * @title Solidity Bytes Arrays Utils * @author Gonçalo Sá <[email protected]> * * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity. * The library lets you concatenate, slice and type cast bytes arrays both in memory and storage. * @notice Link: https://github.com/Uniswap/v3-periphery/blob/b325bb0905d922ae61fcc7df85ee802e8df5e96c/contracts/libraries/BytesLib.sol */ pragma solidity >=0.8.0 <0.9.0; library BytesLib { function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) { require(_length + 31 >= _length, "slice_overflow"); require(_bytes.length >= _start + _length, "slice_outOfBounds"); bytes memory tempBytes; assembly { switch iszero(_length) case 0 { // Get a location of some free memory and store it in tempBytes as // Solidity does for memory variables. tempBytes := mload(0x40) // The first word of the slice result is potentially a partial // word read from the original array. To read it, we calculate // the length of that partial word and start copying that many // bytes into the array. The first word we copy will start with // data we don't care about, but the last `lengthmod` bytes will // land at the beginning of the contents of the new array. When // we're done copying, we overwrite the full first word with // the actual length of the slice. let lengthmod := and(_length, 31) // The multiplication in the next line is necessary // because when slicing multiples of 32 bytes (lengthmod == 0) // the following copy loop was copying the origin's length // and then ending prematurely not copying everything it should. let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod))) let end := add(mc, _length) for { // The multiplication in the next line has the same exact purpose // as the one above. let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start) } lt(mc, end) { mc := add(mc, 0x20) cc := add(cc, 0x20) } { mstore(mc, mload(cc)) } mstore(tempBytes, _length) //update free-memory pointer //allocating the array padded to 32 bytes like the compiler does now mstore(0x40, and(add(mc, 31), not(31))) } //if we want a zero-length slice let's just return a zero-length array default { tempBytes := mload(0x40) //zero out the 32 bytes slice we are about to return //we need to do it because Solidity does not garbage collect mstore(tempBytes, 0) mstore(0x40, add(tempBytes, 0x20)) } } return tempBytes; } function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) { require(_bytes.length >= _start + 20, "toAddress_outOfBounds"); address tempAddress; assembly { tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000) } return tempAddress; } function toUint24(bytes memory _bytes, uint256 _start) internal pure returns (uint24) { require(_start + 3 >= _start, "toUint24_overflow"); require(_bytes.length >= _start + 3, "toUint24_outOfBounds"); uint24 tempUint; assembly { tempUint := mload(add(add(_bytes, 0x3), _start)) } return tempUint; } }
{
"remappings": [
"ds-test/=lib/ds-test/src/",
"forge-std/=lib/forge-std/src/",
"murky/=lib/murky/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solmate/=lib/solmate/src/",
"weird-erc20/=lib/solmate/lib/weird-erc20/src/"
],
"optimizer": {
"enabled": true,
"runs": 9999999
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "london",
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"address","name":"_uniV3SwapRouter","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHAmountInMismatch","type":"error"},{"inputs":[],"name":"OnlyMulticallsAllowed","type":"error"},{"inputs":[],"name":"PathMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"RecipientMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"TokenInMismatch","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"TokenOutMismatch","type":"error"},{"inputs":[],"name":"TotalAmountMismatch","type":"error"},{"inputs":[],"name":"TxFailed","type":"error"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"}],"name":"UnhandledFunction","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"WrapperSwapExecuted","type":"event"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenIn","type":"address"},{"internalType":"address","name":"_tokenOut","type":"address"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"swap","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"swapRouter","outputs":[{"internalType":"contract ISwapRouter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH9","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60c06040523480156200001157600080fd5b506040516200217c3803806200217c8339810160408190526200003491620001b7565b815162000049906000906020850190620000d0565b506001600160a01b0381166080819052604080516312a9293f60e21b81529051634aa4a4fc916004808201926020929091908290030181865afa15801562000095573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000bb9190620002a8565b6001600160a01b031660a052506200030b9050565b828054620000de90620002cf565b90600052602060002090601f0160209004810192826200010257600085556200014d565b82601f106200011d57805160ff19168380011785556200014d565b828001600101855582156200014d579182015b828111156200014d57825182559160200191906001019062000130565b506200015b9291506200015f565b5090565b5b808211156200015b576000815560010162000160565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114620001a257600080fd5b50565b8051620001b2816200018c565b919050565b60008060408385031215620001cb57600080fd5b82516001600160401b0380821115620001e357600080fd5b818501915085601f830112620001f857600080fd5b8151818111156200020d576200020d62000176565b604051601f8201601f19908116603f0116810190838211818310171562000238576200023862000176565b816040528281526020935088848487010111156200025557600080fd5b600091505b828210156200027957848201840151818301850152908301906200025a565b828211156200028b5760008484830101525b95506200029d915050858201620001a5565b925050509250929050565b600060208284031215620002bb57600080fd5b8151620002c8816200018c565b9392505050565b600181811c90821680620002e457607f821691505b6020821081036200030557634e487b7160e01b600052602260045260246000fd5b50919050565b60805160a051611e316200034b60003960008181608c015261121801526000818160e50152818161028e015281816102d001526103430152611e316000f3fe6080604052600436106100435760003560e01c806306fdde031461004f5780633fc8cef31461007a578063c31c9c07146100d3578063da1452631461010757600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b50610064610128565b6040516100719190611677565b60405180910390f35b34801561008657600080fd5b506100ae7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610071565b3480156100df57600080fd5b506100ae7f000000000000000000000000000000000000000000000000000000000000000081565b61011a6101153660046116ed565b6101b6565b604051908152602001610071565b60008054610135906117a0565b80601f0160208091040260200160405190810160405280929190818152602001828054610161906117a0565b80156101ae5780601f10610183576101008083540402835291602001916101ae565b820191906000526020600020905b81548152906001019060200180831161019157829003601f168201915b505050505081565b600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148080156101f25750843414155b806102065750801580156102065750600034115b1561023d576040517f61746dbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610249888861049d565b9050816102f55761027273ffffffffffffffffffffffffffffffffffffffff8a16333089610593565b6102b473ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000000000000000000000000000000000000000000006000610682565b6102f573ffffffffffffffffffffffffffffffffffffffff8a167f000000000000000000000000000000000000000000000000000000000000000088610682565b60006103048a8a8a898961074f565b905086811461033f576040517f1ae3648700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1684610384576000610386565b885b88886040516103969291906117f3565b60006040518083038185875af1925050503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b5050905080610413576040517f2b96f51300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000836104208c8c61049d565b61042a9190611832565b604080513381526020810186905290810182905290915073ffffffffffffffffffffffffffffffffffffffff808c16918d8216918f16907fb1b8682cc43fc0063470cc507f616e8f273f9df242d968fe84580a72f2b779619060600160405180910390a49b9a5050505050505050505050565b60007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016104fa575073ffffffffffffffffffffffffffffffffffffffff81163161058d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a9190611849565b90505b92915050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff8416602482015282604482015260008060648360008a5af191505061061081610ac0565b61067b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064015b60405180910390fd5b5050505050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201528260248201526000806044836000895af19150506106e381610ac0565b610749576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610672565b50505050565b60008061075f6004828587611862565b6107689161188c565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f5ae401dc00000000000000000000000000000000000000000000000000000000146107e5576040517f364a674500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f48460048188611862565b81019061080191906119bc565b8051909250905060005b81811015610ab357600083828151811061082757610827611abc565b602002602001015190506108486000600483610b079092919063ffffffff16565b61085190611aeb565b9450600061086f60048084516108679190611832565b849190610b07565b905082156000610880600187611832565b851490507ffb1ba551000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016108ec576108db838f8f8f8686610c81565b6108e5908a611b3b565b9850610a9c565b7f47a7e7c1000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610943576108db838f8f8f8686610dbf565b7f20d54a45000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000089160161099c57610997838e8e610f2f565b610a9c565b7fb8d4bc0d000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016109f3576108db838f8f8f8686610fe5565b7fb6bfb484000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610a4657610997838d61115d565b6040517f9a0778260000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000089166004820152602401610672565b505050508080610aab90611b53565b91505061080b565b5050505095945050505050565b60003d82610ad257806000803e806000fd5b8060208114610aea578015610afb5760009250610b00565b816000803e60005115159250610b00565b600192505b5050919050565b606081610b1581601f611b3b565b1015610b7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610672565b610b878284611b3b565b84511015610bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610672565b606082158015610c105760405191506000825260208201604052610c78565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610c49578051835260209283019201610c31565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008060008a806020019051810190610c9d9190611b9b565b50509450945050935093508615610d17576000610cba858c6111a7565b905080610d15576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b8515610d86576000610d29848b6111a7565b905080610d84576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b610db182897f04e45aaf0000000000000000000000000000000000000000000000000000000061126c565b9a9950505050505050505050565b600080600080610ddf6020808c51610dd79190611832565b8c9190610b07565b806020019051810190610df29190611c2c565b509250925092508515610e78576000610e0a84611439565b505090506000610e1a828c6111a7565b905080610e75576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b8415610ef7576000610e8984611475565b509150506000610e99828b6111a7565b905080610ef4576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b610f2282887fb858183f0000000000000000000000000000000000000000000000000000000061126c565b9998505050505050505050565b60008084806020019051810190610f469190611cc8565b92505091506000610f5783866111a7565b905080610fb2576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fdf2ab5bb000000000000000000000000000000000000000000000000000000006004820152602401610672565b610fdd82857fdf2ab5bb0000000000000000000000000000000000000000000000000000000061126c565b505050505050565b60008060008089806020019051810190610fff9190611d0b565b93509350509250851561108f5760006110328360008151811061102457611024611abc565b60200260200101518b6111a7565b90508061108d576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b84156111245760006110c783600185516110a99190611832565b815181106110b9576110b9611abc565b60200260200101518a6111a7565b905080611122576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b61114f81887f472b43f30000000000000000000000000000000000000000000000000000000061126c565b509098975050505050505050565b6000828060200190518101906111739190611dcb565b91506111a2905081837f49404b7c0000000000000000000000000000000000000000000000000000000061126c565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061058a575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461121657600061058a565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16149392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fdf2ab5bb0000000000000000000000000000000000000000000000000000000014806112fd57507fffffffff0000000000000000000000000000000000000000000000000000000081167f49404b7c00000000000000000000000000000000000000000000000000000000145b1561138b578173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156113de575073ffffffffffffffffffffffffffffffffffffffff8316600214155b156111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b6000808061144784826114c7565b9250611454846014611557565b905061146c61146560036014611b3b565b85906114c7565b91509193909250565b600080806114be6014611489600382611b3b565b6114939190611b3b565b855161149f9190611832565b60146114ac600382611b3b565b6114b69190611b3b565b869190610b07565b93506114478460005b60006114d4826014611b3b565b8351101561153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610672565b5001602001516c01000000000000000000000000900490565b600081611565816003611b3b565b10156115cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f770000000000000000000000000000006044820152606401610672565b6115d8826003611b3b565b83511015611642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610672565b50016003015190565b60005b8381101561166657818101518382015260200161164e565b838111156107495750506000910152565b602081526000825180602084015261169681604085016020870161164b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146116ea57600080fd5b50565b60008060008060008060a0878903121561170657600080fd5b8635611711816116c8565b95506020870135611721816116c8565b94506040870135611731816116c8565b935060608701359250608087013567ffffffffffffffff8082111561175557600080fd5b818901915089601f83011261176957600080fd5b81358181111561177857600080fd5b8a602082850101111561178a57600080fd5b6020830194508093505050509295509295509295565b600181811c908216806117b457607f821691505b6020821081036117ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561184457611844611803565b500390565b60006020828403121561185b57600080fd5b5051919050565b6000808585111561187257600080fd5b8386111561187f57600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156118cc5780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561194a5761194a6118d4565b604052919050565b600067ffffffffffffffff82111561196c5761196c6118d4565b5060051b60200190565b600067ffffffffffffffff821115611990576119906118d4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060408084860312156119d057600080fd5b8335925060208085013567ffffffffffffffff808211156119f057600080fd5b818701915087601f830112611a0457600080fd5b8135611a17611a1282611952565b611903565b81815260059190911b8301840190848101908a831115611a3657600080fd5b8585015b83811015611aaa57803585811115611a525760008081fd5b8601603f81018d13611a645760008081fd5b87810135611a74611a1282611976565b8181528e8b838501011115611a895760008081fd5b818b84018b83013760009181018a0191909152845250918601918601611a3a565b50809750505050505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015611b335780818460040360031b1b83161693505b505050919050565b60008219821115611b4e57611b4e611803565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b8457611b84611803565b5060010190565b8051611b96816116c8565b919050565b600080600080600080600060e0888a031215611bb657600080fd5b8751611bc1816116c8565b6020890151909750611bd2816116c8565b604089015190965062ffffff81168114611beb57600080fd5b6060890151909550611bfc816116c8565b809450506080880151925060a0880151915060c0880151611c1c816116c8565b8091505092959891949750929550565b60008060008060808587031215611c4257600080fd5b845167ffffffffffffffff811115611c5957600080fd5b8501601f81018713611c6a57600080fd5b8051611c78611a1282611976565b818152886020838501011115611c8d57600080fd5b611c9e82602083016020860161164b565b8096505050506020850151611cb2816116c8565b6040860151606090960151949790965092505050565b600080600060608486031215611cdd57600080fd5b8351611ce8816116c8565b602085015160408601519194509250611d00816116c8565b809150509250925092565b60008060008060808587031215611d2157600080fd5b845193506020808601519350604086015167ffffffffffffffff811115611d4757600080fd5b8601601f81018813611d5857600080fd5b8051611d66611a1282611952565b81815260059190911b8201830190838101908a831115611d8557600080fd5b928401925b82841015611dac578351611d9d816116c8565b82529284019290840190611d8a565b8096505050505050611dc060608601611b8b565b905092959194509250565b60008060408385031215611dde57600080fd5b825191506020830151611df0816116c8565b80915050925092905056fea26469706673582212206f1b85be2ca7af517505ed12d9d5b77d7fbee1026625e1a000767ff619b1c1f664736f6c634300080d0033000000000000000000000000000000000000000000000000000000000000004000000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000001a556e6973776170204175746f526f757465722057726170706572000000000000
Deployed Bytecode
0x6080604052600436106100435760003560e01c806306fdde031461004f5780633fc8cef31461007a578063c31c9c07146100d3578063da1452631461010757600080fd5b3661004a57005b600080fd5b34801561005b57600080fd5b50610064610128565b6040516100719190611677565b60405180910390f35b34801561008657600080fd5b506100ae7f000000000000000000000000420000000000000000000000000000000000000681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610071565b3480156100df57600080fd5b506100ae7f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4581565b61011a6101153660046116ed565b6101b6565b604051908152602001610071565b60008054610135906117a0565b80601f0160208091040260200160405190810160405280929190818152602001828054610161906117a0565b80156101ae5780601f10610183576101008083540402835291602001916101ae565b820191906000526020600020905b81548152906001019060200180831161019157829003601f168201915b505050505081565b600073ffffffffffffffffffffffffffffffffffffffff871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee148080156101f25750843414155b806102065750801580156102065750600034115b1561023d576040517f61746dbd00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610249888861049d565b9050816102f55761027273ffffffffffffffffffffffffffffffffffffffff8a16333089610593565b6102b473ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc456000610682565b6102f573ffffffffffffffffffffffffffffffffffffffff8a167f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4588610682565b60006103048a8a8a898961074f565b905086811461033f576040517f1ae3648700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60007f00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc4573ffffffffffffffffffffffffffffffffffffffff1684610384576000610386565b885b88886040516103969291906117f3565b60006040518083038185875af1925050503d80600081146103d3576040519150601f19603f3d011682016040523d82523d6000602084013e6103d8565b606091505b5050905080610413576040517f2b96f51300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000836104208c8c61049d565b61042a9190611832565b604080513381526020810186905290810182905290915073ffffffffffffffffffffffffffffffffffffffff808c16918d8216918f16907fb1b8682cc43fc0063470cc507f616e8f273f9df242d968fe84580a72f2b779619060600160405180910390a49b9a5050505050505050505050565b60007fffffffffffffffffffffffff111111111111111111111111111111111111111273ffffffffffffffffffffffffffffffffffffffff8416016104fa575073ffffffffffffffffffffffffffffffffffffffff81163161058d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83811660048301528416906370a0823190602401602060405180830381865afa158015610566573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058a9190611849565b90505b92915050565b60006040517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8516600482015273ffffffffffffffffffffffffffffffffffffffff8416602482015282604482015260008060648360008a5af191505061061081610ac0565b61067b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5452414e534645525f46524f4d5f4641494c454400000000000000000000000060448201526064015b60405180910390fd5b5050505050565b60006040517f095ea7b300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201528260248201526000806044836000895af19150506106e381610ac0565b610749576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f415050524f56455f4641494c45440000000000000000000000000000000000006044820152606401610672565b50505050565b60008061075f6004828587611862565b6107689161188c565b90507fffffffff0000000000000000000000000000000000000000000000000000000081167f5ae401dc00000000000000000000000000000000000000000000000000000000146107e5576040517f364a674500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006107f48460048188611862565b81019061080191906119bc565b8051909250905060005b81811015610ab357600083828151811061082757610827611abc565b602002602001015190506108486000600483610b079092919063ffffffff16565b61085190611aeb565b9450600061086f60048084516108679190611832565b849190610b07565b905082156000610880600187611832565b851490507ffb1ba551000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016108ec576108db838f8f8f8686610c81565b6108e5908a611b3b565b9850610a9c565b7f47a7e7c1000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610943576108db838f8f8f8686610dbf565b7f20d54a45000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000089160161099c57610997838e8e610f2f565b610a9c565b7fb8d4bc0d000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008916016109f3576108db838f8f8f8686610fe5565b7fb6bfb484000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000891601610a4657610997838d61115d565b6040517f9a0778260000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000089166004820152602401610672565b505050508080610aab90611b53565b91505061080b565b5050505095945050505050565b60003d82610ad257806000803e806000fd5b8060208114610aea578015610afb5760009250610b00565b816000803e60005115159250610b00565b600192505b5050919050565b606081610b1581601f611b3b565b1015610b7d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f736c6963655f6f766572666c6f770000000000000000000000000000000000006044820152606401610672565b610b878284611b3b565b84511015610bf1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f736c6963655f6f75744f66426f756e64730000000000000000000000000000006044820152606401610672565b606082158015610c105760405191506000825260208201604052610c78565b6040519150601f8416801560200281840101858101878315602002848b0101015b81831015610c49578051835260209283019201610c31565b5050858452601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016604052505b50949350505050565b60008060008060008a806020019051810190610c9d9190611b9b565b50509450945050935093508615610d17576000610cba858c6111a7565b905080610d15576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b8515610d86576000610d29848b6111a7565b905080610d84576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f04e45aaf000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b610db182897f04e45aaf0000000000000000000000000000000000000000000000000000000061126c565b9a9950505050505050505050565b600080600080610ddf6020808c51610dd79190611832565b8c9190610b07565b806020019051810190610df29190611c2c565b509250925092508515610e78576000610e0a84611439565b505090506000610e1a828c6111a7565b905080610e75576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b8415610ef7576000610e8984611475565b509150506000610e99828b6111a7565b905080610ef4576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fb858183f000000000000000000000000000000000000000000000000000000006004820152602401610672565b50505b610f2282887fb858183f0000000000000000000000000000000000000000000000000000000061126c565b9998505050505050505050565b60008084806020019051810190610f469190611cc8565b92505091506000610f5783866111a7565b905080610fb2576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527fdf2ab5bb000000000000000000000000000000000000000000000000000000006004820152602401610672565b610fdd82857fdf2ab5bb0000000000000000000000000000000000000000000000000000000061126c565b505050505050565b60008060008089806020019051810190610fff9190611d0b565b93509350509250851561108f5760006110328360008151811061102457611024611abc565b60200260200101518b6111a7565b90508061108d576040517f5c4440c90000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b84156111245760006110c783600185516110a99190611832565b815181106110b9576110b9611abc565b60200260200101518a6111a7565b905080611122576040517f27f5b90d0000000000000000000000000000000000000000000000000000000081527f472b43f3000000000000000000000000000000000000000000000000000000006004820152602401610672565b505b61114f81887f472b43f30000000000000000000000000000000000000000000000000000000061126c565b509098975050505050505050565b6000828060200190518101906111739190611dcb565b91506111a2905081837f49404b7c0000000000000000000000000000000000000000000000000000000061126c565b505050565b60008173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16148061058a575073ffffffffffffffffffffffffffffffffffffffff821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1461121657600061058a565b7f000000000000000000000000420000000000000000000000000000000000000673ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16149392505050565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fdf2ab5bb0000000000000000000000000000000000000000000000000000000014806112fd57507fffffffff0000000000000000000000000000000000000000000000000000000081167f49404b7c00000000000000000000000000000000000000000000000000000000145b1561138b578173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16146111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141580156113de575073ffffffffffffffffffffffffffffffffffffffff8316600214155b156111a2576040517f02a3e6980000000000000000000000000000000000000000000000000000000081527fffffffff0000000000000000000000000000000000000000000000000000000082166004820152602401610672565b6000808061144784826114c7565b9250611454846014611557565b905061146c61146560036014611b3b565b85906114c7565b91509193909250565b600080806114be6014611489600382611b3b565b6114939190611b3b565b855161149f9190611832565b60146114ac600382611b3b565b6114b69190611b3b565b869190610b07565b93506114478460005b60006114d4826014611b3b565b8351101561153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601560248201527f746f416464726573735f6f75744f66426f756e647300000000000000000000006044820152606401610672565b5001602001516c01000000000000000000000000900490565b600081611565816003611b3b565b10156115cd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f746f55696e7432345f6f766572666c6f770000000000000000000000000000006044820152606401610672565b6115d8826003611b3b565b83511015611642576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f746f55696e7432345f6f75744f66426f756e64730000000000000000000000006044820152606401610672565b50016003015190565b60005b8381101561166657818101518382015260200161164e565b838111156107495750506000910152565b602081526000825180602084015261169681604085016020870161164b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b73ffffffffffffffffffffffffffffffffffffffff811681146116ea57600080fd5b50565b60008060008060008060a0878903121561170657600080fd5b8635611711816116c8565b95506020870135611721816116c8565b94506040870135611731816116c8565b935060608701359250608087013567ffffffffffffffff8082111561175557600080fd5b818901915089601f83011261176957600080fd5b81358181111561177857600080fd5b8a602082850101111561178a57600080fd5b6020830194508093505050509295509295509295565b600181811c908216806117b457607f821691505b6020821081036117ed577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b8183823760009101908152919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60008282101561184457611844611803565b500390565b60006020828403121561185b57600080fd5b5051919050565b6000808585111561187257600080fd5b8386111561187f57600080fd5b5050820193919092039150565b7fffffffff0000000000000000000000000000000000000000000000000000000081358181169160048510156118cc5780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff8111828210171561194a5761194a6118d4565b604052919050565b600067ffffffffffffffff82111561196c5761196c6118d4565b5060051b60200190565b600067ffffffffffffffff821115611990576119906118d4565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b60008060408084860312156119d057600080fd5b8335925060208085013567ffffffffffffffff808211156119f057600080fd5b818701915087601f830112611a0457600080fd5b8135611a17611a1282611952565b611903565b81815260059190911b8301840190848101908a831115611a3657600080fd5b8585015b83811015611aaa57803585811115611a525760008081fd5b8601603f81018d13611a645760008081fd5b87810135611a74611a1282611976565b8181528e8b838501011115611a895760008081fd5b818b84018b83013760009181018a0191909152845250918601918601611a3a565b50809750505050505050509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000815160208301517fffffffff0000000000000000000000000000000000000000000000000000000080821693506004831015611b335780818460040360031b1b83161693505b505050919050565b60008219821115611b4e57611b4e611803565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611b8457611b84611803565b5060010190565b8051611b96816116c8565b919050565b600080600080600080600060e0888a031215611bb657600080fd5b8751611bc1816116c8565b6020890151909750611bd2816116c8565b604089015190965062ffffff81168114611beb57600080fd5b6060890151909550611bfc816116c8565b809450506080880151925060a0880151915060c0880151611c1c816116c8565b8091505092959891949750929550565b60008060008060808587031215611c4257600080fd5b845167ffffffffffffffff811115611c5957600080fd5b8501601f81018713611c6a57600080fd5b8051611c78611a1282611976565b818152886020838501011115611c8d57600080fd5b611c9e82602083016020860161164b565b8096505050506020850151611cb2816116c8565b6040860151606090960151949790965092505050565b600080600060608486031215611cdd57600080fd5b8351611ce8816116c8565b602085015160408601519194509250611d00816116c8565b809150509250925092565b60008060008060808587031215611d2157600080fd5b845193506020808601519350604086015167ffffffffffffffff811115611d4757600080fd5b8601601f81018813611d5857600080fd5b8051611d66611a1282611952565b81815260059190911b8201830190838101908a831115611d8557600080fd5b928401925b82841015611dac578351611d9d816116c8565b82529284019290840190611d8a565b8096505050505050611dc060608601611b8b565b905092959194509250565b60008060408385031215611dde57600080fd5b825191506020830151611df0816116c8565b80915050925092905056fea26469706673582212206f1b85be2ca7af517505ed12d9d5b77d7fbee1026625e1a000767ff619b1c1f664736f6c634300080d0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000000000000000000000000000000000000000004000000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45000000000000000000000000000000000000000000000000000000000000001a556e6973776170204175746f526f757465722057726170706572000000000000
-----Decoded View---------------
Arg [0] : _name (string): Uniswap AutoRouter Wrapper
Arg [1] : _uniV3SwapRouter (address): 0x68b3465833fb72A70ecDF485E0e4C7bD8665Fc45
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000040
Arg [1] : 00000000000000000000000068b3465833fb72a70ecdf485e0e4c7bd8665fc45
Arg [2] : 000000000000000000000000000000000000000000000000000000000000001a
Arg [3] : 556e6973776170204175746f526f757465722057726170706572000000000000
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.