ETH Price: $3,217.19 (-3.83%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Relay1Gs Wnfs IQ...215898722025-01-09 22:21:472 hrs ago1736461307IN
0xd2700086...47e9F00f2
0.5 ETH0.001507217.83631532
0x00010001215896822025-01-09 21:43:353 hrs ago1736459015IN
0xd2700086...47e9F00f2
0 ETH0.001136057.96806432
Relay1Gs Wnfs IQ...215891392025-01-09 19:54:355 hrs ago1736452475IN
0xd2700086...47e9F00f2
0.1 ETH0.001583610.61962771
0x00010001215885872025-01-09 18:04:117 hrs ago1736445851IN
0xd2700086...47e9F00f2
0 ETH0.0019750913.85294977
Relay1Gs Wnfs IQ...215882732025-01-09 17:00:598 hrs ago1736442059IN
0xd2700086...47e9F00f2
0.1 ETH0.0019513414.06834536
Relay1Gs Wnfs IQ...215877512025-01-09 15:15:479 hrs ago1736435747IN
0xd2700086...47e9F00f2
0.5 ETH0.0015448710.26723953
Relay1Gs Wnfs IQ...215877492025-01-09 15:15:239 hrs ago1736435723IN
0xd2700086...47e9F00f2
0.5 ETH0.001713999.9002994
0x00010001215834992025-01-09 0:59:4724 hrs ago1736384387IN
0xd2700086...47e9F00f2
0 ETH0.000915656.09982654
Relay1Gs Wnfs IQ...215834492025-01-09 0:49:4724 hrs ago1736383787IN
0xd2700086...47e9F00f2
0.5 ETH0.000905965.63125978
0x00010001215834422025-01-09 0:48:2324 hrs ago1736383703IN
0xd2700086...47e9F00f2
0 ETH0.001048515.91179775
Relay1Gs Wnfs IQ...215827292025-01-08 22:24:5926 hrs ago1736375099IN
0xd2700086...47e9F00f2
0.5 ETH0.001899619.87530781
0x00010001215821132025-01-08 20:21:1128 hrs ago1736367671IN
0xd2700086...47e9F00f2
0 ETH0.0025210614.88874674
0x00010001215821112025-01-08 20:20:4728 hrs ago1736367647IN
0xd2700086...47e9F00f2
0 ETH0.0025807314.82100812
0x00010001215821082025-01-08 20:20:1128 hrs ago1736367611IN
0xd2700086...47e9F00f2
0 ETH0.0026231415.06350925
0x00010001215821052025-01-08 20:19:3528 hrs ago1736367575IN
0xd2700086...47e9F00f2
0 ETH0.0033540815.61086547
0x00010001215820922025-01-08 20:16:5928 hrs ago1736367419IN
0xd2700086...47e9F00f2
0 ETH0.0034544718.64895796
Relay1Gs Wnfs IQ...215820392025-01-08 20:06:2329 hrs ago1736366783IN
0xd2700086...47e9F00f2
0.25 ETH0.00301316.86994687
Relay1Gs Wnfs IQ...215820302025-01-08 20:04:3529 hrs ago1736366675IN
0xd2700086...47e9F00f2
0.023 ETH0.0029230716.14725854
Relay1Gs Wnfs IQ...215820282025-01-08 20:04:1129 hrs ago1736366651IN
0xd2700086...47e9F00f2
0.05 ETH0.0029384616.23225445
Relay1Gs Wnfs IQ...215820272025-01-08 20:03:5929 hrs ago1736366639IN
0xd2700086...47e9F00f2
0.05 ETH0.0027821215.36864647
Relay1Gs Wnfs IQ...215820252025-01-08 20:03:3529 hrs ago1736366615IN
0xd2700086...47e9F00f2
0.05 ETH0.0028022915.4800575
Relay1Gs Wnfs IQ...215820242025-01-08 20:03:2329 hrs ago1736366603IN
0xd2700086...47e9F00f2
0.0075 ETH0.0027704113.98307762
0x01010001215763412025-01-08 1:01:472 days ago1736298107IN
0xd2700086...47e9F00f2
0 ETH0.001036068.10170015
0x00010001215674672025-01-06 19:19:593 days ago1736191199IN
0xd2700086...47e9F00f2
0 ETH0.0050546722.79097699
Relay1Gs Wnfs IQ...215674602025-01-06 19:18:353 days ago1736191115IN
0xd2700086...47e9F00f2
0.1 ETH0.0036225624.1578211
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block
From
To
215898722025-01-09 22:21:472 hrs ago1736461307
0xd2700086...47e9F00f2
0.5 ETH
215896822025-01-09 21:43:353 hrs ago1736459015
0xd2700086...47e9F00f2
0.24927737 ETH
215896822025-01-09 21:43:353 hrs ago1736459015
0xd2700086...47e9F00f2
0.24927737 ETH
215891392025-01-09 19:54:355 hrs ago1736452475
0xd2700086...47e9F00f2
0.1 ETH
215885872025-01-09 18:04:117 hrs ago1736445851
0xd2700086...47e9F00f2
0.09253156 ETH
215885872025-01-09 18:04:117 hrs ago1736445851
0xd2700086...47e9F00f2
0.09253156 ETH
215882732025-01-09 17:00:598 hrs ago1736442059
0xd2700086...47e9F00f2
0.1 ETH
215877512025-01-09 15:15:479 hrs ago1736435747
0xd2700086...47e9F00f2
0.5 ETH
215877492025-01-09 15:15:239 hrs ago1736435723
0xd2700086...47e9F00f2
0.5 ETH
215834992025-01-09 0:59:4724 hrs ago1736384387
0xd2700086...47e9F00f2
0.48689503 ETH
215834992025-01-09 0:59:4724 hrs ago1736384387
0xd2700086...47e9F00f2
0.48689503 ETH
215834492025-01-09 0:49:4724 hrs ago1736383787
0xd2700086...47e9F00f2
0.5 ETH
215834422025-01-09 0:48:2324 hrs ago1736383703
0xd2700086...47e9F00f2
0.46330872 ETH
215834422025-01-09 0:48:2324 hrs ago1736383703
0xd2700086...47e9F00f2
0.46330872 ETH
215827292025-01-08 22:24:5926 hrs ago1736375099
0xd2700086...47e9F00f2
0.5 ETH
215821132025-01-08 20:21:1128 hrs ago1736367671
0xd2700086...47e9F00f2
0.86844275 ETH
215821132025-01-08 20:21:1128 hrs ago1736367671
0xd2700086...47e9F00f2
0.86844275 ETH
215821112025-01-08 20:20:4728 hrs ago1736367647
0xd2700086...47e9F00f2
0.8158728 ETH
215821112025-01-08 20:20:4728 hrs ago1736367647
0xd2700086...47e9F00f2
0.8158728 ETH
215821082025-01-08 20:20:1128 hrs ago1736367611
0xd2700086...47e9F00f2
0.17659304 ETH
215821082025-01-08 20:20:1128 hrs ago1736367611
0xd2700086...47e9F00f2
0.17659304 ETH
215820922025-01-08 20:16:5928 hrs ago1736367419
0xd2700086...47e9F00f2
0.18471227 ETH
215820922025-01-08 20:16:5928 hrs ago1736367419
0xd2700086...47e9F00f2
0.18471227 ETH
215820392025-01-08 20:06:2329 hrs ago1736366783
0xd2700086...47e9F00f2
0.25 ETH
215820302025-01-08 20:04:3529 hrs ago1736366675
0xd2700086...47e9F00f2
0.023 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
KekotronRouterV2

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 40000 runs

Other Settings:
paris EvmVersion
File 1 of 16 : KekotronRouterV2.sol
/**
 * Kekotron Router V2
 * 
 * Website: kekotron.io
 * Docs: docs.kekotron.io
 * twitter.com/Kekotron_
 * twitter.com/Nchart_
 */

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {Owned} from "solmate/auth/Owned.sol";
import {KekotronSwapV2} from "./KekotronSwapV2.sol";
import {KekotronSwapTraderJoeV2_1} from "./KekotronSwapTraderJoeV2_1.sol";
import {KekotronSwapV3} from "./KekotronSwapV3.sol";
import {OnlyOwner, TooLittleReceived, InvalidVersion, TokenInCannotBeSameAsTokenOut, InvalidInputAmount} from "./KekotronErrors.sol";
import {Swap, ProtocolData} from "./DataTypes.sol";
import {INITIALIZER, POOL_FEE_MASK} from "./Constants.sol";
import {IERC20} from "./interfaces/IERC20.sol";
import {KekotronLib} from "./KekotronLib.sol";

/**
 * ........            
 *        ..::::::::::::.  .       
 *      .:::::::::::::::.  =+-.    
 *    --::::::::::::::::.  =+++-   
 *    ##*+::::::::::::::.  =+++++
 *   #####:  .::::::::::.  =++++++
 * -######:     .:::::::.  =++++++-
 *  ######:  :.    .::::.  =+++++++
 * #######:  -=-:.    .:.  =+++++++
 * +######:  -=====:.      =++++++=
 * :######:  -========-.   =++++++:
 *  +#####:  -===========-.-+++++= 
 *   =####:  -==============-==+-  
 *    :*##:  -================-.   
 *      :+:  -==============-.     
 *           :==========-:.        
 *              ......
 */

contract KekotronRouterV2 is Owned, KekotronSwapV2, KekotronSwapTraderJoeV2_1, KekotronSwapV3 {
    event FeeUpdated(uint8 fee);
    event FeeReceiverUpdated(address feeReceiver);
    event ProtocolDataUpdated(uint8 protocol, ProtocolData data);
    event AllowedV2CallbackUpdated(bytes4 selector, bool allowed);
    event AllowedV3CallbackUpdated(bytes4 selector, bool allowed);

    address private immutable WRAPPED_NATIVE;
    bytes4 private constant V2_CALLBACK1 = 0x10d1e85c;
    bytes4 private constant V2_CALLBACK2 = 0x84800812;
    bytes4 private constant V2_CALLBACK3 = 0xee22dd87;

    bytes4 private constant V3_CALLBACK1 = 0xfa461e33;
    bytes4 private constant V3_CALLBACK2 = 0x23a69e75;
    bytes4 private constant V3_CALLBACK3 = 0x2c8958f6;

    uint8 public fee = 0; // 100 = 1% - max = 255 = 2.55%
    address public feeReceiver;

    /// @dev Fallback selectors for callbacks, allowing for adding additional protocols in the future
    mapping(bytes4 => bool) public allowedV2Callbacks;
    mapping(bytes4 => bool) public allowedV3Callbacks;

    constructor(address owner_) Owned(owner_) KekotronSwapV2() KekotronSwapTraderJoeV2_1() KekotronSwapV3() {
        (address receiver, address wrappedNative_,) = INITIALIZER.getSetupData();

        WRAPPED_NATIVE = wrappedNative_;
        feeReceiver = receiver;
    }

    modifier onlyOwner() virtual override {
        _requireIsOwner();
        _;
    }

    function updateFee(uint8 newFee) external onlyOwner {
        fee = newFee;

        emit FeeUpdated(newFee);
    }

    function updateFeeReceiver(address newFeeReceiver) external onlyOwner {
        feeReceiver = newFeeReceiver;

        emit FeeReceiverUpdated(newFeeReceiver);
    }

    function withdrawNative() external onlyOwner {
        KekotronLib.safeTransferNative(owner, address(this).balance);
    }

    function withdrawToken(address token) external onlyOwner {
        KekotronLib.safeTransfer(token, owner, IERC20(token).balanceOf(address(this)));
    }

    function updateAllowedV2Callbacks(bytes4 selector, bool allowed) external onlyOwner {
        allowedV2Callbacks[selector] = allowed;

        emit AllowedV2CallbackUpdated(selector, allowed);
    }

    function updatedAllowedV3Callbacks(bytes4 selector, bool allowed) external onlyOwner {
        allowedV3Callbacks[selector] = allowed;

        emit AllowedV3CallbackUpdated(selector, allowed);
    }

    function updateProtocolData(uint8 protocol, ProtocolData memory data) external onlyOwner {
        _updateProtocolData(protocol, data);

        emit ProtocolDataUpdated(protocol, data);
    }

    /**
     * @dev The fallback function is used to handle both callbacks from the pools and swap initiators
     * @dev For swaps, a prefix is added to the calldata to indicate the type of call and certain parameters
     * @dev The prefix is 5 bytes long and is structured as follows:
     * @dev   0: version (1 byte)
     * @dev   1: feeOn (1 byte)
     * @dev   2: protocol (1 byte)
     * @dev   3: poolFee (2 bytes)
     *
     * @dev For callbacks, the selector is checked against the allowed callbacks and the call is forwarded
     * @dev to a callback handler. The callback handler is responsible for decoding the calldata and
     * @dev performing the appropriate actions. For v3 callbacks the msg.sender MUST be a pool launched
     * @dev by the cannonical factory of the protocol.
     *
     * @dev To support new V3 protocols, the owner MUST call updateProtocolData with the new protocol details
     * @dev there can be overlap of protocol selectors between different protocols, so numeric identifiers are
     * @dev used in the calldata prefix to differentiate between them.
     */
    fallback() external payable {
        bytes4 selector = bytes4(msg.data[:4]);

        // First check immutable callbacks
        if (_isV2Callback(selector)) {
            return;
        }

        if (_isV3Callback(selector)) {
            (int256 amount0Delta, int256 amount1Delta, bytes memory data) =
                abi.decode(msg.data[4:], (int256, int256, bytes));
            return _callbackV3(amount0Delta, amount1Delta, data);
        }

        uint8 version;
        uint8 feeOn;
        uint8 protocol;
        uint16 poolFee;

        assembly {
            let data := calldataload(0)
            version := byte(0, data)
            feeOn := byte(1, data)
            protocol := byte(2, data)
            poolFee := shr(216, and(data, POOL_FEE_MASK))
        }

        Swap memory swapData;

        // TOOD: M-03 - Add support for deadline in calldata
        assembly {
            let offset := 0x05
            calldatacopy(add(swapData, 0x0c), offset, 0x14) // pool
            calldatacopy(add(swapData, 0x2c), add(offset, 0x14), 0x14) // tokenIn
            calldatacopy(add(swapData, 0x4c), add(offset, 0x28), 0x14) // tokenOut
            calldatacopy(add(swapData, 0x70), add(offset, 0x3c), 0x10) // amountIn
            calldatacopy(add(swapData, 0x90), add(offset, 0x4c), 0x20) // amountOut
        }

        if (swapData.tokenIn == swapData.tokenOut) {
            revert TokenInCannotBeSameAsTokenOut();
        }

        if (swapData.tokenIn == address(0)) {
            if (msg.value != swapData.amountIn) {
                revert InvalidInputAmount();
            }
        }

        if (version == 0) {
            // v2
            return _swapExactInputV2(swapData, feeReceiver, fee, feeOn, poolFee);
        }

        if (version == 1) {
            // v3
            return _swapExactInputV3(swapData, feeReceiver, fee, feeOn, poolFee, protocol);
        }

        if (version == 2) {
            // Trader Joe v2.1
            return _swapExactInputV2_1(swapData, feeReceiver, fee, feeOn);
        }

        // Fallback to mutable callbacks if no version and no immutable match
        if (allowedV2Callbacks[selector]) {
            return;
        }

        if (allowedV3Callbacks[selector]) {
            (int256 amount0Delta, int256 amount1Delta, bytes memory data) =
                abi.decode(msg.data[4:], (int256, int256, bytes));
            return _callbackV3(amount0Delta, amount1Delta, data);
        }

        revert InvalidVersion();
    }

    function _requireIsOwner() internal view {
        if (msg.sender != owner) {
            revert OnlyOwner();
        }
    }

    function _isV2Callback(bytes4 selector) internal pure returns (bool isCallback) {
        if (selector == V2_CALLBACK1) {
            isCallback = true;
        } else if (selector == V2_CALLBACK2) {
            isCallback = true;
        } else if (selector == V2_CALLBACK3) {
            isCallback = true;
        }
    }

    function _isV3Callback(bytes4 selector) internal pure returns (bool isCallback) {
        if (selector == V3_CALLBACK1) {
            isCallback = true;
        } else if (selector == V3_CALLBACK2) {
            isCallback = true;
        } else if (selector == V3_CALLBACK3) {
            isCallback = true;
        }
    }

    function _wrappedNative()
        internal
        view
        override(KekotronSwapTraderJoeV2_1, KekotronSwapV2, KekotronSwapV3)
        returns (address)
    {
        return WRAPPED_NATIVE;
    }

    receive() external payable {}
}

File 2 of 16 : Owned.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Simple single owner authorization mixin.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/Owned.sol)
abstract contract Owned {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event OwnershipTransferred(address indexed user, address indexed newOwner);

    /*//////////////////////////////////////////////////////////////
                            OWNERSHIP STORAGE
    //////////////////////////////////////////////////////////////*/

    address public owner;

    modifier onlyOwner() virtual {
        require(msg.sender == owner, "UNAUTHORIZED");

        _;
    }

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(address _owner) {
        owner = _owner;

        emit OwnershipTransferred(address(0), _owner);
    }

    /*//////////////////////////////////////////////////////////////
                             OWNERSHIP LOGIC
    //////////////////////////////////////////////////////////////*/

    function transferOwnership(address newOwner) public virtual onlyOwner {
        owner = newOwner;

        emit OwnershipTransferred(msg.sender, newOwner);
    }
}

File 3 of 16 : KekotronSwapV2.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./interfaces/IPoolV2.sol";
import "./KekotronRouterInitializer.sol";
import "./KekotronLib.sol";
import "./KekotronErrors.sol";
import {Swap} from "./DataTypes.sol";
import {INITIALIZER, MAX_BPS} from "./Constants.sol";

abstract contract KekotronSwapV2 {
    constructor() {}

    function _getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut, uint16 poolFee)
        private
        pure
        returns (uint256)
    {
        if (amountIn == 0) {
            revert InsufficientInputAmount();
        }
        if (reserveIn == 0 || reserveOut == 0) {
            revert InsufficientLiquidity();
        }

        uint256 amountInWithFee = amountIn * (100000 - poolFee) / 100;
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = reserveIn * 1000 + amountInWithFee;

        return numerator / denominator;
    }

    function _swapV2(Swap memory param, address to, uint16 poolFee) private returns (uint256) {
        bool zeroForOne = param.tokenIn < param.tokenOut;

        uint256 amountOut;
        {
            (uint256 reserve0, uint256 reserve1,) = IPoolV2(param.pool).getReserves();
            (uint256 reserveInput, uint256 reserveOutput) = zeroForOne ? (reserve0, reserve1) : (reserve1, reserve0);

            amountOut = _getAmountOut(
                IERC20(param.tokenIn).balanceOf(param.pool) - reserveInput, reserveInput, reserveOutput, poolFee
            );
        }

        (uint256 amount0Out, uint256 amount1Out) = zeroForOne ? (uint256(0), amountOut) : (amountOut, uint256(0));

        uint256 balanceBefore = IERC20(param.tokenOut).balanceOf(to);
        IPoolV2(param.pool).swap(amount0Out, amount1Out, to, new bytes(0));
        uint256 balanceAfter = IERC20(param.tokenOut).balanceOf(to);

        return balanceAfter - balanceBefore;
    }

    function _swapExactNativeForTokensV2(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn, uint16 poolFee)
        private
    {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferNative(feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.depositWrappedNative(_wrappedNative(), param.amountIn);
        KekotronLib.safeTransfer(_wrappedNative(), param.pool, param.amountIn);

        uint256 amountOut = _swapV2(param, feeOut ? address(this) : msg.sender, poolFee);
        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactTokensForNativeV2(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn, uint16 poolFee)
        private
    {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, param.pool, param.amountIn);

        uint256 amountOut = _swapV2(param, address(this), poolFee);

        KekotronLib.withdrawWrappedNative(_wrappedNative(), amountOut);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransferNative(feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        KekotronLib.safeTransferNative(msg.sender, amountOut);
    }

    function _swapExactTokensForTokensV2(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn, uint16 poolFee)
        private
    {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, param.pool, param.amountIn);

        uint256 amountOut = _swapV2(param, feeOut ? address(this) : msg.sender, poolFee);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactInputV2(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn, uint16 poolFee)
        internal
    {
        if (param.tokenIn == address(0)) {
            param.tokenIn = _wrappedNative();
            return _swapExactNativeForTokensV2(param, feeReceiver, fee, feeOn, poolFee);
        }

        if (param.tokenOut == address(0)) {
            param.tokenOut = _wrappedNative();
            return _swapExactTokensForNativeV2(param, feeReceiver, fee, feeOn, poolFee);
        }

        return _swapExactTokensForTokensV2(param, feeReceiver, fee, feeOn, poolFee);
    }

    /// @dev overwritten in top level contract
    function _wrappedNative() internal view virtual returns (address);
}

File 4 of 16 : KekotronSwapTraderJoeV2_1.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./interfaces/IPoolTraderJoeV2_1.sol";
import "./KekotronRouterInitializer.sol";
import "./KekotronLib.sol";
import {TooLittleReceived, TokenInCannotBeSameAsTokenOut} from "./KekotronErrors.sol";
import {Swap} from "./DataTypes.sol";
import {INITIALIZER, MAX_BPS} from "./Constants.sol";

abstract contract KekotronSwapTraderJoeV2_1 {
    constructor() {}

    function _swapV2_1(Swap memory param, address to) private returns (uint256) {
        bool zeroForOne = param.tokenIn < param.tokenOut;

        uint256 balanceBefore = IERC20(param.tokenOut).balanceOf(to);
        IPoolTraderJoeV2_1(param.pool).swap(zeroForOne, to);

        return IERC20(param.tokenOut).balanceOf(to) - balanceBefore;
    }

    function _swapExactNativeForTokensV2_1(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferNative(feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.depositWrappedNative(_wrappedNative(), param.amountIn);
        KekotronLib.safeTransfer(_wrappedNative(), param.pool, param.amountIn);

        uint256 amountOut = _swapV2_1(param, feeOut ? address(this) : msg.sender);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactTokensForNativeV2_1(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, param.pool, param.amountIn);

        uint256 amountOut = _swapV2_1(param, address(this));

        KekotronLib.withdrawWrappedNative(_wrappedNative(), amountOut);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransferNative(feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        KekotronLib.safeTransferNative(msg.sender, amountOut);
    }

    function _swapExactTokensForTokensV2_1(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, param.pool, param.amountIn);

        uint256 amountOut = _swapV2_1(param, feeOut ? address(this) : msg.sender);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactInputV2_1(Swap memory param, address feeReceiver, uint8 fee, uint8 feeOn) internal {
        if (param.tokenIn == address(0)) {
            param.tokenIn = _wrappedNative();
            return _swapExactNativeForTokensV2_1(param, feeReceiver, fee, feeOn);
        }

        if (param.tokenOut == address(0)) {
            param.tokenOut = _wrappedNative();
            return _swapExactTokensForNativeV2_1(param, feeReceiver, fee, feeOn);
        }

        return _swapExactTokensForTokensV2_1(param, feeReceiver, fee, feeOn);
    }

    function _wrappedNative() internal view virtual returns (address);
}

File 5 of 16 : KekotronSwapV3.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import "./interfaces/IAlgebraFactory.sol";
import "./interfaces/IPoolV3.sol";
import "./KekotronRouterInitializer.sol";
import "./KekotronLib.sol";
import {
    TooLittleReceived,
    InvalidCallbackPool,
    InsufficientLiquidity,
    ProtocolDataAlreadySet,
    ProtocolNotFound
} from "./KekotronErrors.sol";
import {Swap} from "./DataTypes.sol";
import {INITIALIZER, MAX_BPS, MIN_SQRT_RATIO, MAX_SQRT_RATIO} from "./Constants.sol";

abstract contract KekotronSwapV3 {
    mapping(uint8 => ProtocolData) private _factories;

    constructor() {
        ProtocolData[] memory protocoldata = INITIALIZER.getProtocolData();

        for (uint8 i = 0; i < protocoldata.length;) {
            _factories[i] = protocoldata[i];
            unchecked {
                ++i;
            }
        }
    }

    /**
     * @notice Returns the factory ID for a given factory address or returns 0 if the factory is not supported
     * @dev    Do not use this on chain, as this function is gas intensive
     */
    function getProtocolNumber(address factory) external view returns (uint8 protocol) {
        bool found;
        for (uint8 i = 0; i < type(uint8).max;) {
            if (factory == _factories[i].factory) {
                protocol = uint8(i);
                found = true;
                break;
            }
            unchecked {
                ++i;
            }
        }
        if (!found) {
            revert ProtocolNotFound();
        }
    }

    /**
     * @notice Allows the owner to update the protocol data for a given protocol
     *
     * @dev    This function is intended to be overridden by the inheriting contract - do not leave unguarded
     *
     * @param  protocol The protocol ID to update
     * @param  data     The new protocol data
     */
    function _updateProtocolData(uint8 protocol, ProtocolData memory data) internal {
        if (_factories[protocol].factory != address(0)) {
            revert ProtocolDataAlreadySet();
        }

        _factories[protocol] = data;
    }

    function _computePool(address tokenIn, address tokenOut, uint24 fee, uint8 protocol)
        private
        view
        returns (address pool)
    {
        address tokenA;
        address tokenB;

        if (tokenIn < tokenOut) {
            tokenA = tokenIn;
            tokenB = tokenOut;
        } else {
            tokenA = tokenOut;
            tokenB = tokenIn;
        }

        ProtocolData memory protocolData = _factories[protocol];

        bytes memory typeData;
        if (protocolData.feeInHash) {
            typeData = abi.encode(tokenA, tokenB, fee);
        } else {
            typeData = abi.encode(tokenA, tokenB);
        }

        pool = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex"ff",
                            protocolData.externalDeployer
                                ? IAlgebraFactory(protocolData.factory).poolDeployer()
                                : protocolData.factory,
                            keccak256(typeData),
                            protocolData.initHash
                        )
                    )
                )
            )
        );
    }

    function _deriveData(Swap memory param, address payer, uint16 poolFee, uint8 protocol)
        private
        pure
        returns (bool, int256, uint160, bytes memory)
    {
        bool zeroForOne = param.tokenIn < param.tokenOut;
        // We shift the fee to save some calldata space in the original call
        uint24 shiftedFee = uint24(poolFee) * 10;

        int256 amountSpecified = int256(param.amountIn);
        uint160 sqrtPriceLimitX96 = (zeroForOne ? MIN_SQRT_RATIO + 1 : MAX_SQRT_RATIO - 1);
        bytes memory data = abi.encode(param.tokenIn, param.tokenOut, shiftedFee, param.amountOut, payer, protocol);

        return (zeroForOne, amountSpecified, sqrtPriceLimitX96, data);
    }

    function _swapV3(Swap memory param, address to, address payer, uint16 poolFee, uint8 protocol)
        private
        returns (uint256)
    {
        (bool zeroForOne, int256 amountSpecified, uint160 sqrtPriceLimitX96, bytes memory data) =
            _deriveData(param, payer, poolFee, protocol);

        (int256 amount0, int256 amount1) =
            IPoolV3(param.pool).swap(to, zeroForOne, amountSpecified, sqrtPriceLimitX96, data);
        uint256 amountOut = uint256(-(zeroForOne ? amount1 : amount0));

        return amountOut;
    }

    function _swapExactNativeForTokensV3(
        Swap memory param,
        address feeReceiver,
        uint8 fee,
        uint8 feeOn,
        uint16 poolFee,
        uint8 protocol
    ) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferNative(feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        KekotronLib.depositWrappedNative(_wrappedNative(), param.amountIn);

        uint256 amountOut = _swapV3(param, feeOut ? address(this) : msg.sender, address(this), poolFee, protocol);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactTokensForNativeV3(
        Swap memory param,
        address feeReceiver,
        uint8 fee,
        uint8 feeOn,
        uint16 poolFee,
        uint8 protocol
    ) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        uint256 amountOut = _swapV3(param, address(this), msg.sender, poolFee, protocol);

        KekotronLib.withdrawWrappedNative(_wrappedNative(), amountOut);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        KekotronLib.safeTransferNative(msg.sender, amountOut);
    }

    function _swapExactTokensForTokensV3(
        Swap memory param,
        address feeReceiver,
        uint8 fee,
        uint8 feeOn,
        uint16 poolFee,
        uint8 protocol
    ) private {
        (bool feeIn, bool feeOut) = fee > 0 ? (feeOn < 1, feeOn > 0) : (false, false);
        uint256 amountFee;

        if (feeIn) {
            amountFee = param.amountIn * fee / MAX_BPS;
            KekotronLib.safeTransferFrom(param.tokenIn, msg.sender, feeReceiver, amountFee);
            param.amountIn -= amountFee;
        }

        uint256 amountOut = _swapV3(param, feeOut ? address(this) : msg.sender, msg.sender, poolFee, protocol);

        if (feeOut) {
            amountFee = amountOut * fee / MAX_BPS;
            amountOut = amountOut - amountFee;
            if (amountFee > 0) {
                KekotronLib.safeTransfer(param.tokenOut, feeReceiver, amountFee);
            }
        }

        if (amountOut < param.amountOut) {
            revert TooLittleReceived();
        }

        if (feeOut) {
            KekotronLib.safeTransfer(param.tokenOut, msg.sender, amountOut);
        }
    }

    function _swapExactInputV3(
        Swap memory param,
        address feeReceiver,
        uint8 fee,
        uint8 feeOn,
        uint16 poolFee,
        uint8 protocol
    ) internal {
        if (param.tokenIn == address(0)) {
            param.tokenIn = _wrappedNative();
            return _swapExactNativeForTokensV3(param, feeReceiver, fee, feeOn, poolFee, protocol);
        }

        if (param.tokenOut == address(0)) {
            param.tokenOut = _wrappedNative();
            return _swapExactTokensForNativeV3(param, feeReceiver, fee, feeOn, poolFee, protocol);
        }

        return _swapExactTokensForTokensV3(param, feeReceiver, fee, feeOn, poolFee, protocol);
    }

    function _callbackV3(int256 amount0Delta, int256 amount1Delta, bytes memory data) internal {
        if (amount0Delta == 0 && amount1Delta == 0) {
            revert InsufficientLiquidity();
        }

        (address tokenIn, address tokenOut, uint24 fee, uint256 limit, address payer, uint8 protocol) =
            abi.decode(data, (address, address, uint24, uint256, address, uint8));

        if (msg.sender != _computePool(tokenIn, tokenOut, fee, protocol)) {
            revert InvalidCallbackPool();
        }

        bool zeroForOne = tokenIn < tokenOut;

        if (uint256(-(zeroForOne ? amount1Delta : amount0Delta)) < limit) {
            revert TooLittleReceived();
        }

        if (payer == address(this)) {
            KekotronLib.safeTransfer(tokenIn, msg.sender, uint256(zeroForOne ? amount0Delta : amount1Delta));
        } else {
            KekotronLib.safeTransferFrom(tokenIn, payer, msg.sender, uint256(zeroForOne ? amount0Delta : amount1Delta));
        }
    }

    function _wrappedNative() internal view virtual returns (address);
}

File 6 of 16 : KekotronErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

error OnlyOwner();

error InvalidVersion();

error WrappedNativeCurrencyDeposit();
error WrappedNativeCurrencyWithdraw();
error NativeTransfer();
error TokenTransfer();
error TokenTransferFrom();
error TokenMustBeContract();
error TokenInCannotBeSameAsTokenOut();

error TooLittleReceived();
error InvalidInputAmount();
error InsufficientInputAmount();
error InsufficientLiquidity();
error InvalidCallbackPool();

error ProtocolNotFound();
error ProtocolDataAlreadySet();
error SetupAlreadyComplete();

File 7 of 16 : DataTypes.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

struct Swap {
    address pool;
    address tokenIn;
    address tokenOut;
    uint256 amountIn;
    uint256 amountOut;
}

struct ProtocolData {
    bool feeInHash;
    bool externalDeployer;
    address factory;
    bytes32 initHash;
}

File 8 of 16 : Constants.sol
pragma solidity 0.8.19;

import {KekotronRouterInitializer} from "./KekotronRouterInitializer.sol";

KekotronRouterInitializer constant INITIALIZER =
    KekotronRouterInitializer(address(0x70B973006870a80073CE6d0022a2000000001914));

uint256 constant MAX_BPS = 10_000;
uint160 constant MIN_SQRT_RATIO = 4295128739;
uint160 constant MAX_SQRT_RATIO = 1461446703485210103287273052203988822378723970342;

uint256 constant PUSH_PAYMENT_GAS_LIMIT = 10_000;

bytes32 constant POOL_FEE_MASK = 0x000000ffff000000000000000000000000000000000000000000000000000000;

File 9 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
    function allowance(address owner, address spender) external view returns (uint256);
    function approve(address spender, uint256 amount) external returns (bool);
    function transfer(address recipient, uint256 amount) external returns (bool);
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
}

File 10 of 16 : KekotronLib.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {IERC20} from "src/interfaces/IERC20.sol";
import {IWETH} from "src/interfaces/IWETH.sol";
import {TokenTransfer, TokenTransferFrom, TokenMustBeContract, NativeTransfer, WrappedNativeCurrencyDeposit, WrappedNativeCurrencyWithdraw} from "./KekotronErrors.sol";
import {PUSH_PAYMENT_GAS_LIMIT} from "./Constants.sol";

library KekotronLib {
    function safeTransfer(address token, address to, uint256 value) internal {
        if (token.code.length == 0) {
            revert TokenMustBeContract();
        }
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
        if (!(success && (data.length == 0 || abi.decode(data, (bool))))) {
            revert TokenTransfer();
        }
    }

    function safeTransferFrom(address token, address from, address to, uint256 value) internal {
        if (token.code.length == 0) {
            revert TokenMustBeContract();
        }
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        if (!(success && (data.length == 0 || abi.decode(data, (bool))))) {
            revert TokenTransferFrom();
        }
    }

    function safeTransferNative(address to, uint256 value) internal {
        (bool success,) = to.call{value: value, gas: PUSH_PAYMENT_GAS_LIMIT}(new bytes(0));
        if (!success) {
            revert NativeTransfer();
        }
    }

    function depositWrappedNative(address wrappedNative, uint256 value) internal {
        (bool success,) = wrappedNative.call{value: value}(new bytes(0));
        if (!success) {
            revert WrappedNativeCurrencyDeposit();
        }
    }

    function withdrawWrappedNative(address wrappedNative, uint256 value) internal {
        (bool success,) = wrappedNative.call(abi.encodeWithSelector(IWETH.withdraw.selector, value));
        if (!success) {
            revert WrappedNativeCurrencyWithdraw();
        }
    }
}

File 11 of 16 : IPoolV2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IPoolV2 {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);
    function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external;
}

File 12 of 16 : KekotronRouterInitializer.sol
/**
 * Kekotron Router V2
 * 
 * Website: kekotron.io
 * Docs: docs.kekotron.io
 * twitter.com/Kekotron_
 * twitter.com/Nchart_
 */

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

import {Owned} from "solmate/auth/Owned.sol";
import {ProtocolData} from "./DataTypes.sol";
import {SetupAlreadyComplete} from "./KekotronErrors.sol";

/**
 * ........            
 *        ..::::::::::::.  .       
 *      .:::::::::::::::.  =+-.    
 *    --::::::::::::::::.  =+++-   
 *    ##*+::::::::::::::.  =+++++
 *   #####:  .::::::::::.  =++++++
 * -######:     .:::::::.  =++++++-
 *  ######:  :.    .::::.  =+++++++
 * #######:  -=-:.    .:.  =+++++++
 * +######:  -=====:.      =++++++=
 * :######:  -========-.   =++++++:
 *  +#####:  -===========-.-+++++= 
 *   =####:  -==============-==+-  
 *    :*##:  -================-.   
 *      :+:  -==============-.     
 *           :==========-:.        
 *              ......
 */

contract KekotronRouterInitializer is Owned {
    event Setup(
        address receiver, 
        address wrappedNative, 
        ProtocolData[] protocolData
    );

    address private receiver;
    address private wrappedNative;
    ProtocolData[] private protocolData;

    constructor(address owner_) Owned(owner_) {}

    function setup(
        address receiver_,
        address wrappedNative_,
        ProtocolData[] calldata protocolData_
    ) external onlyOwner {
        if (protocolData.length > 0) {
            revert SetupAlreadyComplete();
        }
        receiver = receiver_;
        wrappedNative = wrappedNative_;

        uint256 protocolLen = protocolData_.length;

        for (uint256 i = 0; i < protocolLen;) {
            protocolData.push(protocolData_[i]);
            unchecked {
                ++i;
            }
        }
        
        emit Setup(receiver_, wrappedNative_, protocolData_);
    }

    function getWrappedNative() external view returns (address) {
        return wrappedNative;
    }

    function getProtocolData() external view returns (ProtocolData[] memory) {
        return protocolData;
    }

    function getReceiver() external view returns (address) {
        return receiver;
    }

    function getSetupData() external view returns (address, address, ProtocolData[] memory) {
        return (receiver, wrappedNative, protocolData);
    }
}

File 13 of 16 : IPoolTraderJoeV2_1.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IPoolTraderJoeV2_1 {
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1);
    function swap(bool zeroForOne, address to) external;
}

File 14 of 16 : IAlgebraFactory.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity >=0.5.0;

/**
 * @title The interface for the Algebra Factory
 * @dev Credit to Uniswap Labs under GPL-2.0-or-later license:
 * https://github.com/Uniswap/v3-core/tree/main/contracts/interfaces
 */
interface IAlgebraFactory {
    /**
     *  @notice Emitted when the owner of the factory is changed
     *  @param newOwner The owner after the owner was changed
     */
    event Owner(address indexed newOwner);

    /**
     *  @notice Emitted when the vault address is changed
     *  @param newVaultAddress The vault address after the address was changed
     */
    event VaultAddress(address indexed newVaultAddress);

    /**
     *  @notice Emitted when a pool is created
     *  @param token0 The first token of the pool by address sort order
     *  @param token1 The second token of the pool by address sort order
     *  @param pool The address of the created pool
     */
    event Pool(address indexed token0, address indexed token1, address pool);

    /**
     *  @notice Emitted when the farming address is changed
     *  @param newFarmingAddress The farming address after the address was changed
     */
    event FarmingAddress(address indexed newFarmingAddress);

    event FeeConfiguration(
        uint16 alpha1,
        uint16 alpha2,
        uint32 beta1,
        uint32 beta2,
        uint16 gamma1,
        uint16 gamma2,
        uint32 volumeBeta,
        uint16 volumeGamma,
        uint16 baseFee
    );

    /**
     *  @notice Returns the current owner of the factory
     *  @dev Can be changed by the current owner via setOwner
     *  @return The address of the factory owner
     */
    function owner() external view returns (address);

    /**
     *  @notice Returns the current poolDeployerAddress
     *  @return The address of the poolDeployer
     */
    function poolDeployer() external view returns (address);

    /**
     * @dev Is retrieved from the pools to restrict calling
     * certain functions not by a tokenomics contract
     * @return The tokenomics contract address
     */
    function farmingAddress() external view returns (address);

    function vaultAddress() external view returns (address);

    /**
     *  @notice Returns the pool address for a given pair of tokens and a fee, or address 0 if it does not exist
     *  @dev tokenA and tokenB may be passed in either token0/token1 or token1/token0 order
     *  @param tokenA The contract address of either token0 or token1
     *  @param tokenB The contract address of the other token
     *  @return pool The pool address
     */
    function poolByPair(address tokenA, address tokenB) external view returns (address pool);

    /**
     *  @notice Creates a pool for the given two tokens and fee
     *  @param tokenA One of the two tokens in the desired pool
     *  @param tokenB The other of the two tokens in the desired pool
     *  @dev tokenA and tokenB may be passed in either order: token0/token1 or token1/token0. tickSpacing is retrieved
     *  from the fee. The call will revert if the pool already exists, the fee is invalid, or the token arguments
     *  are invalid.
     *  @return pool The address of the newly created pool
     */
    function createPool(address tokenA, address tokenB) external returns (address pool);

    /**
     *  @notice Updates the owner of the factory
     *  @dev Must be called by the current owner
     *  @param _owner The new owner of the factory
     */
    function setOwner(address _owner) external;

    /**
     * @dev updates tokenomics address on the factory
     * @param _farmingAddress The new tokenomics contract address
     */
    function setFarmingAddress(address _farmingAddress) external;

    /**
     * @dev updates vault address on the factory
     * @param _vaultAddress The new vault contract address
     */
    function setVaultAddress(address _vaultAddress) external;

    /**
     * @notice Changes initial fee configuration for new pools
     * @dev changes coefficients for sigmoids: α / (1 + e^( (β-x) / γ))
     * alpha1 + alpha2 + baseFee (max possible fee) must be <= type(uint16).max
     * gammas must be > 0
     * @param alpha1 max value of the first sigmoid
     * @param alpha2 max value of the second sigmoid
     * @param beta1 shift along the x-axis for the first sigmoid
     * @param beta2 shift along the x-axis for the second sigmoid
     * @param gamma1 horizontal stretch factor for the first sigmoid
     * @param gamma2 horizontal stretch factor for the second sigmoid
     * @param volumeBeta shift along the x-axis for the outer volume-sigmoid
     * @param volumeGamma horizontal stretch factor the outer volume-sigmoid
     * @param baseFee minimum possible fee
     */
    function setBaseFeeConfiguration(
        uint16 alpha1,
        uint16 alpha2,
        uint32 beta1,
        uint32 beta2,
        uint16 gamma1,
        uint16 gamma2,
        uint32 volumeBeta,
        uint16 volumeGamma,
        uint16 baseFee
    ) external;
}

File 15 of 16 : IPoolV3.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

interface IPoolV3 {
    function fee() external view returns (uint24);
    function swap(
        address recipient,
        bool zeroForOne,
        int256 amountSpecified,
        uint160 sqrtPriceLimitX96,
        bytes calldata data
    ) external returns (int256 amount0, int256 amount1);
}

File 16 of 16 : IWETH.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

interface IWETH {
    function deposit() external payable;
    function withdraw(uint256 amount) external;
}

Settings
{
  "remappings": [
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "forge-std/=lib/forge-std/src/",
    "foundry-huff/=lib/foundry-huff/src/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/solmate/src/",
    "lib/forge-std:ds-test/=lib/forge-std/lib/ds-test/src/",
    "lib/solady:ds-test/=lib/solady/lib/ds-test/src/",
    "lib/solady:forge-std/=lib/solady/test/utils/forge-std/",
    "lib/solmate:ds-test/=lib/solmate/lib/ds-test/src/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 40000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InsufficientInputAmount","type":"error"},{"inputs":[],"name":"InsufficientLiquidity","type":"error"},{"inputs":[],"name":"InvalidCallbackPool","type":"error"},{"inputs":[],"name":"InvalidInputAmount","type":"error"},{"inputs":[],"name":"InvalidVersion","type":"error"},{"inputs":[],"name":"NativeTransfer","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"ProtocolDataAlreadySet","type":"error"},{"inputs":[],"name":"ProtocolNotFound","type":"error"},{"inputs":[],"name":"TokenInCannotBeSameAsTokenOut","type":"error"},{"inputs":[],"name":"TokenMustBeContract","type":"error"},{"inputs":[],"name":"TokenTransfer","type":"error"},{"inputs":[],"name":"TokenTransferFrom","type":"error"},{"inputs":[],"name":"TooLittleReceived","type":"error"},{"inputs":[],"name":"WrappedNativeCurrencyDeposit","type":"error"},{"inputs":[],"name":"WrappedNativeCurrencyWithdraw","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"AllowedV2CallbackUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes4","name":"selector","type":"bytes4"},{"indexed":false,"internalType":"bool","name":"allowed","type":"bool"}],"name":"AllowedV3CallbackUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"feeReceiver","type":"address"}],"name":"FeeReceiverUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"fee","type":"uint8"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"protocol","type":"uint8"},{"components":[{"internalType":"bool","name":"feeInHash","type":"bool"},{"internalType":"bool","name":"externalDeployer","type":"bool"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"bytes32","name":"initHash","type":"bytes32"}],"indexed":false,"internalType":"struct ProtocolData","name":"data","type":"tuple"}],"name":"ProtocolDataUpdated","type":"event"},{"stateMutability":"payable","type":"fallback"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"allowedV2Callbacks","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"name":"allowedV3Callbacks","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"fee","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeReceiver","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"factory","type":"address"}],"name":"getProtocolNumber","outputs":[{"internalType":"uint8","name":"protocol","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"updateAllowedV2Callbacks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"newFee","type":"uint8"}],"name":"updateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFeeReceiver","type":"address"}],"name":"updateFeeReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint8","name":"protocol","type":"uint8"},{"components":[{"internalType":"bool","name":"feeInHash","type":"bool"},{"internalType":"bool","name":"externalDeployer","type":"bool"},{"internalType":"address","name":"factory","type":"address"},{"internalType":"bytes32","name":"initHash","type":"bytes32"}],"internalType":"struct ProtocolData","name":"data","type":"tuple"}],"name":"updateProtocolData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bool","name":"allowed","type":"bool"}],"name":"updatedAllowedV3Callbacks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a06040526002805460ff191690553480156200001b57600080fd5b5060405162003a7138038062003a718339810160408190526200003e9162000282565b600080546001600160a01b0319166001600160a01b03831690811782556040518392907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a35060007370b973006870a80073ce6d0022a20000000019146001600160a01b0316632d94bffe6040518163ffffffff1660e01b8152600401600060405180830381865afa158015620000dc573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526200010691908101906200040a565b905060005b81518160ff161015620001ae57818160ff16815181106200013057620001306200044a565b60209081029190910181015160ff8316600090815260018084526040918290208351815495850151938501516001600160a01b0316620100000262010000600160b01b03199415156101000261ff00199215159290921661ffff1990971696909617179290921693909317815560609091015190820155016200010b565b50506000807370b973006870a80073ce6d0022a20000000019146001600160a01b031663106db7a26040518163ffffffff1660e01b8152600401600060405180830381865afa15801562000206573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405262000230919081019062000460565b506001600160a01b03908116608052600280549190921661010002610100600160a81b031990911617905550620004c6915050565b80516001600160a01b03811681146200027d57600080fd5b919050565b6000602082840312156200029557600080fd5b620002a08262000265565b9392505050565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b0381118282101715620002e257620002e2620002a7565b60405290565b604051601f8201601f191681016001600160401b0381118282101715620003135762000313620002a7565b604052919050565b805180151581146200027d57600080fd5b600082601f8301126200033e57600080fd5b815160206001600160401b038211156200035c576200035c620002a7565b6200036c818360051b01620002e8565b82815260079290921b840181019181810190868411156200038c57600080fd5b8286015b84811015620003ff5760808189031215620003ab5760008081fd5b620003b5620002bd565b620003c0826200031b565b8152620003cf8583016200031b565b858201526040620003e281840162000265565b908201526060828101519082015283529183019160800162000390565b509695505050505050565b6000602082840312156200041d57600080fd5b81516001600160401b038111156200043457600080fd5b62000442848285016200032c565b949350505050565b634e487b7160e01b600052603260045260246000fd5b6000806000606084860312156200047657600080fd5b620004818462000265565b9250620004916020850162000265565b60408501519092506001600160401b03811115620004ae57600080fd5b620004bc868287016200032c565b9150509250925092565b6080516135346200053d600039600081816109e501528181610a5201528181610ace01528181610b3c01528181610bbb01528181610c270152818161173701528181611765015281816118f101528181611aa601528181611c1101528181611dcc01528181611dfa0152611f8201526135346000f3fe6080604052600436106100e15760003560e01c8063b4fc4ce81161007f578063cb032abb11610059578063cb032abb1461059a578063cbf104e6146105ca578063ddca3f43146105fc578063f2fde38b14610616576100e8565b8063b4fc4ce81461053a578063c269062a1461055a578063c69bebe41461057a576100e8565b806389476069116100bb57806389476069146104765780638da5cb5b14610496578063949c09b8146104e8578063b3f0067414610508576100e8565b806309d8ad7e146103fc57806350431ce41461041c578063804c13a514610431576100e8565b366100e857005b60006100f76004823681612d7f565b61010091612da9565b905061010b81610636565b1561011257005b61011b8161072c565b1561015157600080806101313660048184612d7f565b81019061013e9190612e6f565b92509250925061014f838383610821565b005b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281359182901a91600181901a91600282901a9160d81c61ffff16906005601481600c8401376014808201602c840137601460288201604c8401376010603c820160708401376020604c8201609084013750806040015173ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff1603610239576040517f3e9e6adf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015173ffffffffffffffffffffffffffffffffffffffff166102955780606001513414610295576040517f340dabef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460ff166000036102cf5760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff1687866109c4565b8460ff1660010361030a5760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff16878688610aad565b8460ff166002036103435760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff1687610b9a565b7fffffffff00000000000000000000000000000000000000000000000000000000861660009081526003602052604090205460ff161561037f57005b7fffffffff00000000000000000000000000000000000000000000000000000000861660009081526004602052604090205460ff16156103ca57600080806101313660048184612d7f565b6040517fa9146eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34801561040857600080fd5b5061014f610417366004612f73565b610c7f565b34801561042857600080fd5b5061014f610d22565b34801561043d57600080fd5b5061046161044c366004612faa565b60046020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561048257600080fd5b5061014f610491366004612fee565b610d4f565b3480156104a257600080fd5b506000546104c39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161046d565b3480156104f457600080fd5b5061014f61050336600461301a565b610df5565b34801561051457600080fd5b506002546104c390610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561054657600080fd5b5061014f610555366004612f73565b610e64565b34801561056657600080fd5b5061014f610575366004613037565b610eff565b34801561058657600080fd5b5061014f610595366004612fee565b610f86565b3480156105a657600080fd5b506104616105b5366004612faa565b60036020526000908152604090205460ff1681565b3480156105d657600080fd5b506105ea6105e5366004612fee565b611008565b60405160ff909116815260200161046d565b34801561060857600080fd5b506002546105ea9060ff1681565b34801561062257600080fd5b5061014f610631366004612fee565b6110a4565b60007fef2e17a4000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161068957506001919050565b7f7b7ff7ee000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016106da57506001919050565b7f11dd2279000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610727575060015b919050565b60007f05b9e1cd000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161077f57506001919050565b7fdc59618b000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016107d057506001919050565b7fd376a70a000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161072757506001919050565b8215801561082d575081155b15610864576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806000808680602001905181019061088191906130f8565b9550955095509550955095506108998686868461111c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108fd576040517ffe5f21b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808616908716108381610925578a610927565b895b610930906131ac565b1015610968576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff8416036109a15761099c873383610995578b6113a3565b8c5b6113a3565b6109b8565b6109b8878433846109b2578c61152d565b8d61152d565b50505050505050505050565b602085015173ffffffffffffffffffffffffffffffffffffffff16610a31577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020860152610a2c85858585856116bf565b610aa6565b604085015173ffffffffffffffffffffffffffffffffffffffff16610a99577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166040860152610a2c858585858561184c565b610aa6858585858561199d565b5050505050565b602086015173ffffffffffffffffffffffffffffffffffffffff16610b1b577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020870152610b16868686868686611a2e565b610b92565b604086015173ffffffffffffffffffffffffffffffffffffffff16610b84577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166040870152610b16868686868686611b82565b610b92868686868686611cc0565b505050505050565b602084015173ffffffffffffffffffffffffffffffffffffffff16610c06577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166020850152610c0184848484611d54565b610c79565b604084015173ffffffffffffffffffffffffffffffffffffffff16610c6d577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166040850152610c0184848484611ede565b610c798484848461202c565b50505050565b610c876120bd565b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f9f4d014371fee791ded92725ec4823e0c4ad2b1f780340daa6eadc79be0c645b91015b60405180910390a15050565b610d2a6120bd565b600054610d4d9073ffffffffffffffffffffffffffffffffffffffff164761210e565b565b610d576120bd565b6000546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610df291839173ffffffffffffffffffffffffffffffffffffffff918216918316906370a0823190602401602060405180830381865afa158015610dce573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099791906131e4565b50565b610dfd6120bd565b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff83169081179091556040519081527f3417887ae5fbc941092ff601511bc0f4e3f14ae835bb881189b4c8148c651269906020015b60405180910390a150565b610e6c6120bd565b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527fb8b8f038e8f3a4d23cf98334650d6e922a82dd51bec266d9b41ccbe872df81fb9101610d16565b610f076120bd565b610f1182826121ca565b6040805160ff84168152825115156020808301919091528301511515818301529082015173ffffffffffffffffffffffffffffffffffffffff1660608083019190915282015160808201527fed14c0f5b34ddd2bbe53d7afe83b0881c8f62a3c7393013ea4cf80f80ceb68589060a001610d16565b610f8e6120bd565b600280547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f27aae5db36d94179909d019ae0b1ac7c16d96d953148f63c0f6a0a9c8ead79ee90602001610e59565b60008060005b60ff81811610156110665760ff811660009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff6201000090910481169085160361105e5780925060019150611066565b60010161100e565b508061109e576040517f924ce2f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b6110ac6120bd565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60008060008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16101561115f575085905084611165565b50849050855b60ff84811660009081526001602081815260409283902083516080810185528154808716158015835261010082049097161515938201939093526201000090920473ffffffffffffffffffffffffffffffffffffffff16938201939093529101546060808301919091529091611223576040805173ffffffffffffffffffffffffffffffffffffffff808716602083015285169181019190915262ffffff88166060820152608001604051602081830303815290604052905061125d565b506040805173ffffffffffffffffffffffffffffffffffffffff858116602083015284168183015281518082038301815260609091019091525b81602001516112705781604001516112e3565b816040015173ffffffffffffffffffffffffffffffffffffffff16633119049a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e391906131fd565b81805190602001208360600151604051602001611360939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209998505050505050505050565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036113f4576040517f190eff8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052915160009283929087169161148b919061323e565b6000604051808303816000865af19150503d80600081146114c8576040519150601f19603f3d011682016040523d82523d6000602084013e6114cd565b606091505b50915091508180156114f75750805115806114f75750808060200190518101906114f7919061325a565b610aa6576040517feb2cf4fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff163b60000361157e576040517f190eff8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161161d919061323e565b6000604051808303816000865af19150503d806000811461165a576040519150601f19603f3d011682016040523d82523d6000602084013e61165f565b606091505b5091509150818015611689575080511580611689575080806020019051810190611689919061325a565b610b92576040517f6e89eca500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008560ff16116116d5576000806116e4565b60018460ff161060008560ff16115b9150915060008215611732576127108660ff1689606001516117069190613277565b611710919061328e565b905061171c878261210e565b808860600181815161172e91906132c9565b9052505b6117607f000000000000000000000000000000000000000000000000000000000000000089606001516122f9565b6117907f0000000000000000000000000000000000000000000000000000000000000000895160608b01516113a3565b60006117a989846117a157336117a3565b305b876123ad565b905082156117ee576127106117c160ff891683613277565b6117cb919061328e565b91506117d782826132c9565b905081156117ee576117ee896040015189846113a3565b886080015181101561182c576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821561184157611841896040015133836113a3565b505050505050505050565b60008060008560ff161161186257600080611871565b60018460ff161060008560ff16115b91509150600082156118c5576127108660ff1689606001516118939190613277565b61189d919061328e565b90506118af886020015133898461152d565b80886060018181516118c191906132c9565b9052505b6118dd8860200151338a600001518b6060015161152d565b60006118ea8930876123ad565b90506119177f00000000000000000000000000000000000000000000000000000000000000005b82612757565b82156119555761271061192d60ff891683613277565b611937919061328e565b915061194382826132c9565b9050811561195557611955888361210e565b8860800151811015611993576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611841338261210e565b60008060008560ff16116119b3576000806119c2565b60018460ff161060008560ff16115b9150915060008215611a16576127108660ff1689606001516119e49190613277565b6119ee919061328e565b9050611a00886020015133898461152d565b8088606001818151611a1291906132c9565b9052505b6117908860200151338a600001518b6060015161152d565b60008060008660ff1611611a4457600080611a53565b60018560ff161060008660ff16115b9150915060008215611aa1576127108760ff168a60600151611a759190613277565b611a7f919061328e565b9050611a8b888261210e565b8089606001818151611a9d91906132c9565b9052505b611acf7f00000000000000000000000000000000000000000000000000000000000000008a606001516122f9565b6000611aea8a84611ae05733611ae2565b305b308989612891565b90508215611b2f57612710611b0260ff8a1683613277565b611b0c919061328e565b9150611b1882826132c9565b90508115611b2f57611b2f8a604001518a846113a3565b8960800151811015611b6d576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156109b8576109b88a6040015133836113a3565b60008060008660ff1611611b9857600080611ba7565b60018560ff161060008660ff16115b9150915060008215611bfb576127108760ff168a60600151611bc99190613277565b611bd3919061328e565b9050611be58960200151338a8461152d565b8089606001818151611bf791906132c9565b9052505b6000611c0a8a30338989612891565b9050611c357f0000000000000000000000000000000000000000000000000000000000000000611911565b8215611c7857612710611c4b60ff8a1683613277565b611c55919061328e565b9150611c6182826132c9565b90508115611c7857611c788a604001518a846113a3565b8960800151811015611cb6576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109b8338261210e565b60008060008660ff1611611cd657600080611ce5565b60018560ff161060008660ff16115b9150915060008215611d39576127108760ff168a60600151611d079190613277565b611d11919061328e565b9050611d238960200151338a8461152d565b8089606001818151611d3591906132c9565b9052505b6000611aea8a84611d4a5733611d4c565b305b338989612891565b60008060008460ff1611611d6a57600080611d79565b60018360ff161060008460ff16115b9150915060008215611dc7576127108560ff168860600151611d9b9190613277565b611da5919061328e565b9050611db1868261210e565b8087606001818151611dc391906132c9565b9052505b611df57f000000000000000000000000000000000000000000000000000000000000000088606001516122f9565b611e257f0000000000000000000000000000000000000000000000000000000000000000885160608a01516113a3565b6000611e3c8884611e365733612964565b30612964565b90508215611e8157612710611e5460ff881683613277565b611e5e919061328e565b9150611e6a82826132c9565b90508115611e8157611e81886040015188846113a3565b8760800151811015611ebf576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215611ed457611ed4886040015133836113a3565b5050505050505050565b60008060008460ff1611611ef457600080611f03565b60018360ff161060008460ff16115b9150915060008215611f57576127108560ff168860600151611f259190613277565b611f2f919061328e565b9050611f41876020015133888461152d565b8087606001818151611f5391906132c9565b9052505b611f6f87602001513389600001518a6060015161152d565b6000611f7b8830612964565b9050611fa67f0000000000000000000000000000000000000000000000000000000000000000611911565b8215611fe457612710611fbc60ff881683613277565b611fc6919061328e565b9150611fd282826132c9565b90508115611fe457611fe4878361210e565b8760800151811015612022576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ed4338261210e565b60008060008460ff161161204257600080612051565b60018360ff161060008460ff16115b91509150600082156120a5576127108560ff1688606001516120739190613277565b61207d919061328e565b905061208f876020015133888461152d565b80876060018181516120a191906132c9565b9052505b611e2587602001513389600001518a6060015161152d565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d4d576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201928390529173ffffffffffffffffffffffffffffffffffffffff8516916127109185916121479161323e565b600060405180830381858888f193505050503d8060008114612185576040519150601f19603f3d011682016040523d82523d6000602084013e61218a565b606091505b50509050806121c5576040517f1597afd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60ff821660009081526001602052604090205462010000900473ffffffffffffffffffffffffffffffffffffffff1615612230576040517f40e60c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff90911660009081526001602081815260409283902084518154928601519486015173ffffffffffffffffffffffffffffffffffffffff1662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff951515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171793909316178255606090920151910155565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff8416908390604051612330919061323e565b60006040518083038185875af1925050503d806000811461236d576040519150601f19603f3d011682016040523d82523d6000602084013e612372565b606091505b50509050806121c5576040517f96f32d3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080846040015173ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161090506000806000876000015173ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561243d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246191906132fa565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff16915060008085612495578284612498565b83835b60208c01518c516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015293955091935061254e928592909116906370a0823190602401602060405180830381865afa158015612518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253c91906131e4565b61254691906132c9565b83838b612b41565b9450505050506000808361256457826000612568565b6000835b6040808b015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015293955091935060009216906370a0823190602401602060405180830381865afa1580156125e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260591906131e4565b895190915073ffffffffffffffffffffffffffffffffffffffff1663022c0d9f84848b60006040519080825280601f01601f191660200182016040528015612654576020820181803683370190505b506040518563ffffffff1660e01b81526004016126749493929190613394565b600060405180830381600087803b15801561268e57600080fd5b505af11580156126a2573d6000803e3d6000fd5b5050505060408981015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116600483015260009216906370a0823190602401602060405180830381865afa158015612719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273d91906131e4565b905061274982826132c9565b9a9950505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d60e01b8360405160240161278b91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612814919061323e565b6000604051808303816000865af19150503d8060008114612851576040519150601f19603f3d011682016040523d82523d6000602084013e612856565b606091505b50509050806121c5576040517fdac2c51d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008060006128a58a898989612c2e565b93509350935093506000808b6000015173ffffffffffffffffffffffffffffffffffffffff1663128acb088c888888886040518663ffffffff1660e01b81526004016128f59594939291906133d9565b60408051808303816000875af1158015612913573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612937919061342b565b91509150600086612948578261294a565b815b612953906131ac565b9d9c50505050505050505050505050565b604082810151602084015191517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600093811692169182119183916370a0823190602401602060405180830381865afa1580156129e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0891906131e4565b85516040517f53c059a0000000000000000000000000000000000000000000000000000000008152841515600482015273ffffffffffffffffffffffffffffffffffffffff87811660248301529293509116906353c059a090604401600060405180830381600087803b158015612a7e57600080fd5b505af1158015612a92573d6000803e3d6000fd5b5050505060408581015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152839216906370a0823190602401602060405180830381865afa158015612b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2c91906131e4565b612b3691906132c9565b925050505b92915050565b600084600003612b7d576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580612b88575082155b15612bbf576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006064612bd461ffff8516620186a061344f565b612be39062ffffff1688613277565b612bed919061328e565b90506000612bfb8583613277565b9050600082612c0c886103e8613277565b612c169190613472565b9050612c22818361328e565b98975050505050505050565b600080600060606000886040015173ffffffffffffffffffffffffffffffffffffffff16896020015173ffffffffffffffffffffffffffffffffffffffff1610905060008761ffff16600a612c839190613485565b60608b0151909150600083612cb657612cb1600173fffd8963efd1fc6a506488495d951d5263988d266134a4565b612cc6565b612cc66401000276a360016134d1565b905060008c602001518d60400151858f608001518f8e604051602001612d3c9695949392919073ffffffffffffffffffffffffffffffffffffffff9687168152948616602086015262ffffff9390931660408501526060840191909152909216608082015260ff9190911660a082015260c00190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052949d929c50909a509298509650505050505050565b60008085851115612d8f57600080fd5b83861115612d9c57600080fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015612de95780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612e6757612e67612df1565b604052919050565b600080600060608486031215612e8457600080fd5b833592506020808501359250604085013567ffffffffffffffff80821115612eab57600080fd5b818701915087601f830112612ebf57600080fd5b813581811115612ed157612ed1612df1565b612f01847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612e20565b91508082528884828501011115612f1757600080fd5b80848401858401376000848284010152508093505050509250925092565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461072757600080fd5b8015158114610df257600080fd5b60008060408385031215612f8657600080fd5b612f8f83612f35565b91506020830135612f9f81612f65565b809150509250929050565b600060208284031215612fbc57600080fd5b612fc582612f35565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610df257600080fd5b60006020828403121561300057600080fd5b8135612fc581612fcc565b60ff81168114610df257600080fd5b60006020828403121561302c57600080fd5b8135612fc58161300b565b60008082840360a081121561304b57600080fd5b83356130568161300b565b925060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561308857600080fd5b506040516080810181811067ffffffffffffffff821117156130ac576130ac612df1565b60405260208401356130bd81612f65565b815260408401356130cd81612f65565b602082015260608401356130e081612fcc565b60408201526080939093013560608401525092909150565b60008060008060008060c0878903121561311157600080fd5b865161311c81612fcc565b602088015190965061312d81612fcc565b604088015190955062ffffff8116811461314657600080fd5b60608801516080890151919550935061315e81612fcc565b60a088015190925061316f8161300b565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007f800000000000000000000000000000000000000000000000000000000000000082036131dd576131dd61317d565b5060000390565b6000602082840312156131f657600080fd5b5051919050565b60006020828403121561320f57600080fd5b8151612fc581612fcc565b60005b8381101561323557818101518382015260200161321d565b50506000910152565b6000825161325081846020870161321a565b9190910192915050565b60006020828403121561326c57600080fd5b8151612fc581612f65565b8082028115828204841417612b3b57612b3b61317d565b6000826132c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115612b3b57612b3b61317d565b80516dffffffffffffffffffffffffffff8116811461072757600080fd5b60008060006060848603121561330f57600080fd5b613318846132dc565b9250613326602085016132dc565b9150604084015163ffffffff8116811461333f57600080fd5b809150509250925092565b6000815180845261336281602086016020860161321a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006133cf608083018461334a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261342060a083018461334a565b979650505050505050565b6000806040838503121561343e57600080fd5b505080516020909101519092909150565b62ffffff82811682821603908082111561346b5761346b61317d565b5092915050565b80820180821115612b3b57612b3b61317d565b62ffffff818116838216028082169190828114612de957612de961317d565b73ffffffffffffffffffffffffffffffffffffffff82811682821603908082111561346b5761346b61317d565b73ffffffffffffffffffffffffffffffffffffffff81811683821601908082111561346b5761346b61317d56fea26469706673582212205cff4c10db6e5faa041e3a716efbb9fb22ee01c7aea5a7a49d21275f152274da64736f6c63430008130033000000000000000000000000ae010a324281de301d1bfb2611ef8873d8843622

Deployed Bytecode

0x6080604052600436106100e15760003560e01c8063b4fc4ce81161007f578063cb032abb11610059578063cb032abb1461059a578063cbf104e6146105ca578063ddca3f43146105fc578063f2fde38b14610616576100e8565b8063b4fc4ce81461053a578063c269062a1461055a578063c69bebe41461057a576100e8565b806389476069116100bb57806389476069146104765780638da5cb5b14610496578063949c09b8146104e8578063b3f0067414610508576100e8565b806309d8ad7e146103fc57806350431ce41461041c578063804c13a514610431576100e8565b366100e857005b60006100f76004823681612d7f565b61010091612da9565b905061010b81610636565b1561011257005b61011b8161072c565b1561015157600080806101313660048184612d7f565b81019061013e9190612e6f565b92509250925061014f838383610821565b005b6040805160a081018252600080825260208201819052918101829052606081018290526080810182905281359182901a91600181901a91600282901a9160d81c61ffff16906005601481600c8401376014808201602c840137601460288201604c8401376010603c820160708401376020604c8201609084013750806040015173ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff1603610239576040517f3e9e6adf00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b602081015173ffffffffffffffffffffffffffffffffffffffff166102955780606001513414610295576040517f340dabef00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8460ff166000036102cf5760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff1687866109c4565b8460ff1660010361030a5760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff16878688610aad565b8460ff166002036103435760025461014f90829073ffffffffffffffffffffffffffffffffffffffff6101008204169060ff1687610b9a565b7fffffffff00000000000000000000000000000000000000000000000000000000861660009081526003602052604090205460ff161561037f57005b7fffffffff00000000000000000000000000000000000000000000000000000000861660009081526004602052604090205460ff16156103ca57600080806101313660048184612d7f565b6040517fa9146eeb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b34801561040857600080fd5b5061014f610417366004612f73565b610c7f565b34801561042857600080fd5b5061014f610d22565b34801561043d57600080fd5b5061046161044c366004612faa565b60046020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b34801561048257600080fd5b5061014f610491366004612fee565b610d4f565b3480156104a257600080fd5b506000546104c39073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff909116815260200161046d565b3480156104f457600080fd5b5061014f61050336600461301a565b610df5565b34801561051457600080fd5b506002546104c390610100900473ffffffffffffffffffffffffffffffffffffffff1681565b34801561054657600080fd5b5061014f610555366004612f73565b610e64565b34801561056657600080fd5b5061014f610575366004613037565b610eff565b34801561058657600080fd5b5061014f610595366004612fee565b610f86565b3480156105a657600080fd5b506104616105b5366004612faa565b60036020526000908152604090205460ff1681565b3480156105d657600080fd5b506105ea6105e5366004612fee565b611008565b60405160ff909116815260200161046d565b34801561060857600080fd5b506002546105ea9060ff1681565b34801561062257600080fd5b5061014f610631366004612fee565b6110a4565b60007fef2e17a4000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161068957506001919050565b7f7b7ff7ee000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016106da57506001919050565b7f11dd2279000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831601610727575060015b919050565b60007f05b9e1cd000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161077f57506001919050565b7fdc59618b000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316016107d057506001919050565b7fd376a70a000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000083160161072757506001919050565b8215801561082d575081155b15610864576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000806000806000808680602001905181019061088191906130f8565b9550955095509550955095506108998686868461111c565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108fd576040517ffe5f21b100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff808616908716108381610925578a610927565b895b610930906131ac565b1015610968576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b3073ffffffffffffffffffffffffffffffffffffffff8416036109a15761099c873383610995578b6113a3565b8c5b6113a3565b6109b8565b6109b8878433846109b2578c61152d565b8d61152d565b50505050505050505050565b602085015173ffffffffffffffffffffffffffffffffffffffff16610a31577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166020860152610a2c85858585856116bf565b610aa6565b604085015173ffffffffffffffffffffffffffffffffffffffff16610a99577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166040860152610a2c858585858561184c565b610aa6858585858561199d565b5050505050565b602086015173ffffffffffffffffffffffffffffffffffffffff16610b1b577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166020870152610b16868686868686611a2e565b610b92565b604086015173ffffffffffffffffffffffffffffffffffffffff16610b84577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166040870152610b16868686868686611b82565b610b92868686868686611cc0565b505050505050565b602084015173ffffffffffffffffffffffffffffffffffffffff16610c06577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166020850152610c0184848484611d54565b610c79565b604084015173ffffffffffffffffffffffffffffffffffffffff16610c6d577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166040850152610c0184848484611ede565b610c798484848461202c565b50505050565b610c876120bd565b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527f9f4d014371fee791ded92725ec4823e0c4ad2b1f780340daa6eadc79be0c645b91015b60405180910390a15050565b610d2a6120bd565b600054610d4d9073ffffffffffffffffffffffffffffffffffffffff164761210e565b565b610d576120bd565b6000546040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152610df291839173ffffffffffffffffffffffffffffffffffffffff918216918316906370a0823190602401602060405180830381865afa158015610dce573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099791906131e4565b50565b610dfd6120bd565b600280547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660ff83169081179091556040519081527f3417887ae5fbc941092ff601511bc0f4e3f14ae835bb881189b4c8148c651269906020015b60405180910390a150565b610e6c6120bd565b7fffffffff00000000000000000000000000000000000000000000000000000000821660008181526004602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00168515159081179091558251938452908301527fb8b8f038e8f3a4d23cf98334650d6e922a82dd51bec266d9b41ccbe872df81fb9101610d16565b610f076120bd565b610f1182826121ca565b6040805160ff84168152825115156020808301919091528301511515818301529082015173ffffffffffffffffffffffffffffffffffffffff1660608083019190915282015160808201527fed14c0f5b34ddd2bbe53d7afe83b0881c8f62a3c7393013ea4cf80f80ceb68589060a001610d16565b610f8e6120bd565b600280547fffffffffffffffffffffff0000000000000000000000000000000000000000ff1661010073ffffffffffffffffffffffffffffffffffffffff8416908102919091179091556040519081527f27aae5db36d94179909d019ae0b1ac7c16d96d953148f63c0f6a0a9c8ead79ee90602001610e59565b60008060005b60ff81811610156110665760ff811660009081526001602052604090205473ffffffffffffffffffffffffffffffffffffffff6201000090910481169085160361105e5780925060019150611066565b60010161100e565b508061109e576040517f924ce2f500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50919050565b6110ac6120bd565b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff83169081178255604051909133917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a350565b60008060008573ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff16101561115f575085905084611165565b50849050855b60ff84811660009081526001602081815260409283902083516080810185528154808716158015835261010082049097161515938201939093526201000090920473ffffffffffffffffffffffffffffffffffffffff16938201939093529101546060808301919091529091611223576040805173ffffffffffffffffffffffffffffffffffffffff808716602083015285169181019190915262ffffff88166060820152608001604051602081830303815290604052905061125d565b506040805173ffffffffffffffffffffffffffffffffffffffff858116602083015284168183015281518082038301815260609091019091525b81602001516112705781604001516112e3565b816040015173ffffffffffffffffffffffffffffffffffffffff16633119049a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156112bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112e391906131fd565b81805190602001208360600151604051602001611360939291907fff00000000000000000000000000000000000000000000000000000000000000815260609390931b7fffffffffffffffffffffffffffffffffffffffff0000000000000000000000001660018401526015830191909152603582015260550190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815291905280516020909101209998505050505050505050565b8273ffffffffffffffffffffffffffffffffffffffff163b6000036113f4576040517f190eff8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052915160009283929087169161148b919061323e565b6000604051808303816000865af19150503d80600081146114c8576040519150601f19603f3d011682016040523d82523d6000602084013e6114cd565b606091505b50915091508180156114f75750805115806114f75750808060200190518101906114f7919061325a565b610aa6576040517feb2cf4fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8373ffffffffffffffffffffffffffffffffffffffff163b60000361157e576040517f190eff8800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff85811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd00000000000000000000000000000000000000000000000000000000179052915160009283929088169161161d919061323e565b6000604051808303816000865af19150503d806000811461165a576040519150601f19603f3d011682016040523d82523d6000602084013e61165f565b606091505b5091509150818015611689575080511580611689575080806020019051810190611689919061325a565b610b92576040517f6e89eca500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008560ff16116116d5576000806116e4565b60018460ff161060008560ff16115b9150915060008215611732576127108660ff1689606001516117069190613277565b611710919061328e565b905061171c878261210e565b808860600181815161172e91906132c9565b9052505b6117607f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc289606001516122f9565b6117907f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2895160608b01516113a3565b60006117a989846117a157336117a3565b305b876123ad565b905082156117ee576127106117c160ff891683613277565b6117cb919061328e565b91506117d782826132c9565b905081156117ee576117ee896040015189846113a3565b886080015181101561182c576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b821561184157611841896040015133836113a3565b505050505050505050565b60008060008560ff161161186257600080611871565b60018460ff161060008560ff16115b91509150600082156118c5576127108660ff1689606001516118939190613277565b61189d919061328e565b90506118af886020015133898461152d565b80886060018181516118c191906132c9565b9052505b6118dd8860200151338a600001518b6060015161152d565b60006118ea8930876123ad565b90506119177f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc25b82612757565b82156119555761271061192d60ff891683613277565b611937919061328e565b915061194382826132c9565b9050811561195557611955888361210e565b8860800151811015611993576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611841338261210e565b60008060008560ff16116119b3576000806119c2565b60018460ff161060008560ff16115b9150915060008215611a16576127108660ff1689606001516119e49190613277565b6119ee919061328e565b9050611a00886020015133898461152d565b8088606001818151611a1291906132c9565b9052505b6117908860200151338a600001518b6060015161152d565b60008060008660ff1611611a4457600080611a53565b60018560ff161060008660ff16115b9150915060008215611aa1576127108760ff168a60600151611a759190613277565b611a7f919061328e565b9050611a8b888261210e565b8089606001818151611a9d91906132c9565b9052505b611acf7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc28a606001516122f9565b6000611aea8a84611ae05733611ae2565b305b308989612891565b90508215611b2f57612710611b0260ff8a1683613277565b611b0c919061328e565b9150611b1882826132c9565b90508115611b2f57611b2f8a604001518a846113a3565b8960800151811015611b6d576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b82156109b8576109b88a6040015133836113a3565b60008060008660ff1611611b9857600080611ba7565b60018560ff161060008660ff16115b9150915060008215611bfb576127108760ff168a60600151611bc99190613277565b611bd3919061328e565b9050611be58960200151338a8461152d565b8089606001818151611bf791906132c9565b9052505b6000611c0a8a30338989612891565b9050611c357f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611911565b8215611c7857612710611c4b60ff8a1683613277565b611c55919061328e565b9150611c6182826132c9565b90508115611c7857611c788a604001518a846113a3565b8960800151811015611cb6576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6109b8338261210e565b60008060008660ff1611611cd657600080611ce5565b60018560ff161060008660ff16115b9150915060008215611d39576127108760ff168a60600151611d079190613277565b611d11919061328e565b9050611d238960200151338a8461152d565b8089606001818151611d3591906132c9565b9052505b6000611aea8a84611d4a5733611d4c565b305b338989612891565b60008060008460ff1611611d6a57600080611d79565b60018360ff161060008460ff16115b9150915060008215611dc7576127108560ff168860600151611d9b9190613277565b611da5919061328e565b9050611db1868261210e565b8087606001818151611dc391906132c9565b9052505b611df57f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc288606001516122f9565b611e257f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2885160608a01516113a3565b6000611e3c8884611e365733612964565b30612964565b90508215611e8157612710611e5460ff881683613277565b611e5e919061328e565b9150611e6a82826132c9565b90508115611e8157611e81886040015188846113a3565b8760800151811015611ebf576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8215611ed457611ed4886040015133836113a3565b5050505050505050565b60008060008460ff1611611ef457600080611f03565b60018360ff161060008460ff16115b9150915060008215611f57576127108560ff168860600151611f259190613277565b611f2f919061328e565b9050611f41876020015133888461152d565b8087606001818151611f5391906132c9565b9052505b611f6f87602001513389600001518a6060015161152d565b6000611f7b8830612964565b9050611fa67f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611911565b8215611fe457612710611fbc60ff881683613277565b611fc6919061328e565b9150611fd282826132c9565b90508115611fe457611fe4878361210e565b8760800151811015612022576040517fc9f52c7100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b611ed4338261210e565b60008060008460ff161161204257600080612051565b60018360ff161060008460ff16115b91509150600082156120a5576127108560ff1688606001516120739190613277565b61207d919061328e565b905061208f876020015133888461152d565b80876060018181516120a191906132c9565b9052505b611e2587602001513389600001518a6060015161152d565b60005473ffffffffffffffffffffffffffffffffffffffff163314610d4d576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051600080825260208201928390529173ffffffffffffffffffffffffffffffffffffffff8516916127109185916121479161323e565b600060405180830381858888f193505050503d8060008114612185576040519150601f19603f3d011682016040523d82523d6000602084013e61218a565b606091505b50509050806121c5576040517f1597afd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b60ff821660009081526001602052604090205462010000900473ffffffffffffffffffffffffffffffffffffffff1615612230576040517f40e60c7700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60ff90911660009081526001602081815260409283902084518154928601519486015173ffffffffffffffffffffffffffffffffffffffff1662010000027fffffffffffffffffffff0000000000000000000000000000000000000000ffff951515610100027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff921515929092167fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0000909416939093171793909316178255606090920151910155565b6040805160008082526020820190925273ffffffffffffffffffffffffffffffffffffffff8416908390604051612330919061323e565b60006040518083038185875af1925050503d806000811461236d576040519150601f19603f3d011682016040523d82523d6000602084013e612372565b606091505b50509050806121c5576040517f96f32d3000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080846040015173ffffffffffffffffffffffffffffffffffffffff16856020015173ffffffffffffffffffffffffffffffffffffffff161090506000806000876000015173ffffffffffffffffffffffffffffffffffffffff16630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa15801561243d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061246191906132fa565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff16915060008085612495578284612498565b83835b60208c01518c516040517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015293955091935061254e928592909116906370a0823190602401602060405180830381865afa158015612518573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253c91906131e4565b61254691906132c9565b83838b612b41565b9450505050506000808361256457826000612568565b6000835b6040808b015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8b8116600483015293955091935060009216906370a0823190602401602060405180830381865afa1580156125e1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061260591906131e4565b895190915073ffffffffffffffffffffffffffffffffffffffff1663022c0d9f84848b60006040519080825280601f01601f191660200182016040528015612654576020820181803683370190505b506040518563ffffffff1660e01b81526004016126749493929190613394565b600060405180830381600087803b15801561268e57600080fd5b505af11580156126a2573d6000803e3d6000fd5b5050505060408981015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a8116600483015260009216906370a0823190602401602060405180830381865afa158015612719573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061273d91906131e4565b905061274982826132c9565b9a9950505050505050505050565b60008273ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d60e01b8360405160240161278b91815260200190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff00000000000000000000000000000000000000000000000000000000909416939093179092529051612814919061323e565b6000604051808303816000865af19150503d8060008114612851576040519150601f19603f3d011682016040523d82523d6000602084013e612856565b606091505b50509050806121c5576040517fdac2c51d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008060008060006128a58a898989612c2e565b93509350935093506000808b6000015173ffffffffffffffffffffffffffffffffffffffff1663128acb088c888888886040518663ffffffff1660e01b81526004016128f59594939291906133d9565b60408051808303816000875af1158015612913573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612937919061342b565b91509150600086612948578261294a565b815b612953906131ac565b9d9c50505050505050505050505050565b604082810151602084015191517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8481166004830152600093811692169182119183916370a0823190602401602060405180830381865afa1580156129e4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a0891906131e4565b85516040517f53c059a0000000000000000000000000000000000000000000000000000000008152841515600482015273ffffffffffffffffffffffffffffffffffffffff87811660248301529293509116906353c059a090604401600060405180830381600087803b158015612a7e57600080fd5b505af1158015612a92573d6000803e3d6000fd5b5050505060408581015190517f70a0823100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8681166004830152839216906370a0823190602401602060405180830381865afa158015612b08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612b2c91906131e4565b612b3691906132c9565b925050505b92915050565b600084600003612b7d576040517f098fb56100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580612b88575082155b15612bbf576040517fbb55fd2700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006064612bd461ffff8516620186a061344f565b612be39062ffffff1688613277565b612bed919061328e565b90506000612bfb8583613277565b9050600082612c0c886103e8613277565b612c169190613472565b9050612c22818361328e565b98975050505050505050565b600080600060606000886040015173ffffffffffffffffffffffffffffffffffffffff16896020015173ffffffffffffffffffffffffffffffffffffffff1610905060008761ffff16600a612c839190613485565b60608b0151909150600083612cb657612cb1600173fffd8963efd1fc6a506488495d951d5263988d266134a4565b612cc6565b612cc66401000276a360016134d1565b905060008c602001518d60400151858f608001518f8e604051602001612d3c9695949392919073ffffffffffffffffffffffffffffffffffffffff9687168152948616602086015262ffffff9390931660408501526060840191909152909216608082015260ff9190911660a082015260c00190565b604080518083037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0018152919052949d929c50909a509298509650505050505050565b60008085851115612d8f57600080fd5b83861115612d9c57600080fd5b5050820193919092039150565b7fffffffff000000000000000000000000000000000000000000000000000000008135818116916004851015612de95780818660040360031b1b83161692505b505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612e6757612e67612df1565b604052919050565b600080600060608486031215612e8457600080fd5b833592506020808501359250604085013567ffffffffffffffff80821115612eab57600080fd5b818701915087601f830112612ebf57600080fd5b813581811115612ed157612ed1612df1565b612f01847fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f84011601612e20565b91508082528884828501011115612f1757600080fd5b80848401858401376000848284010152508093505050509250925092565b80357fffffffff000000000000000000000000000000000000000000000000000000008116811461072757600080fd5b8015158114610df257600080fd5b60008060408385031215612f8657600080fd5b612f8f83612f35565b91506020830135612f9f81612f65565b809150509250929050565b600060208284031215612fbc57600080fd5b612fc582612f35565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff81168114610df257600080fd5b60006020828403121561300057600080fd5b8135612fc581612fcc565b60ff81168114610df257600080fd5b60006020828403121561302c57600080fd5b8135612fc58161300b565b60008082840360a081121561304b57600080fd5b83356130568161300b565b925060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08201121561308857600080fd5b506040516080810181811067ffffffffffffffff821117156130ac576130ac612df1565b60405260208401356130bd81612f65565b815260408401356130cd81612f65565b602082015260608401356130e081612fcc565b60408201526080939093013560608401525092909150565b60008060008060008060c0878903121561311157600080fd5b865161311c81612fcc565b602088015190965061312d81612fcc565b604088015190955062ffffff8116811461314657600080fd5b60608801516080890151919550935061315e81612fcc565b60a088015190925061316f8161300b565b809150509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007f800000000000000000000000000000000000000000000000000000000000000082036131dd576131dd61317d565b5060000390565b6000602082840312156131f657600080fd5b5051919050565b60006020828403121561320f57600080fd5b8151612fc581612fcc565b60005b8381101561323557818101518382015260200161321d565b50506000910152565b6000825161325081846020870161321a565b9190910192915050565b60006020828403121561326c57600080fd5b8151612fc581612f65565b8082028115828204841417612b3b57612b3b61317d565b6000826132c4577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b81810381811115612b3b57612b3b61317d565b80516dffffffffffffffffffffffffffff8116811461072757600080fd5b60008060006060848603121561330f57600080fd5b613318846132dc565b9250613326602085016132dc565b9150604084015163ffffffff8116811461333f57600080fd5b809150509250925092565b6000815180845261336281602086016020860161321a565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b84815283602082015273ffffffffffffffffffffffffffffffffffffffff831660408201526080606082015260006133cf608083018461334a565b9695505050505050565b600073ffffffffffffffffffffffffffffffffffffffff8088168352861515602084015285604084015280851660608401525060a0608083015261342060a083018461334a565b979650505050505050565b6000806040838503121561343e57600080fd5b505080516020909101519092909150565b62ffffff82811682821603908082111561346b5761346b61317d565b5092915050565b80820180821115612b3b57612b3b61317d565b62ffffff818116838216028082169190828114612de957612de961317d565b73ffffffffffffffffffffffffffffffffffffffff82811682821603908082111561346b5761346b61317d565b73ffffffffffffffffffffffffffffffffffffffff81811683821601908082111561346b5761346b61317d56fea26469706673582212205cff4c10db6e5faa041e3a716efbb9fb22ee01c7aea5a7a49d21275f152274da64736f6c63430008130033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000ae010a324281de301d1bfb2611ef8873d8843622

-----Decoded View---------------
Arg [0] : owner_ (address): 0xAE010A324281De301D1bFB2611EF8873D8843622

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000ae010a324281de301d1bfb2611ef8873d8843622


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.