ETH Price: $2,478.13 (-1.70%)

Contract

0xd270008604001e5B00000040100000047e9F00f2
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Relay1Gs Wnfs IQ...206512312024-08-31 21:27:119 hrs ago1725139631IN
0xd2700086...47e9F00f2
0.59 ETH0.000445182.68215059
Relay1Gs Wnfs IQ...206341442024-08-29 12:09:112 days ago1724933351IN
0xd2700086...47e9F00f2
0.15 ETH0.000994115.64156253
0x00010001206341412024-08-29 12:08:352 days ago1724933315IN
0xd2700086...47e9F00f2
0 ETH0.000797956.1451497
Relay1Gs Wnfs IQ...206341222024-08-29 12:04:472 days ago1724933087IN
0xd2700086...47e9F00f2
0.05 ETH0.001142966.40791594
Relay1Gs Wnfs IQ...206341182024-08-29 12:03:592 days ago1724933039IN
0xd2700086...47e9F00f2
0.05 ETH0.001163496.26045689
Relay1Gs Wnfs IQ...206341162024-08-29 12:03:352 days ago1724933015IN
0xd2700086...47e9F00f2
0.05 ETH0.00116596.27341641
Relay1Gs Wnfs IQ...206341142024-08-29 12:03:112 days ago1724932991IN
0xd2700086...47e9F00f2
0.05 ETH0.001124126.04861719
Relay1Gs Wnfs IQ...206341112024-08-29 12:02:352 days ago1724932955IN
0xd2700086...47e9F00f2
0.05 ETH0.001283425.8324489
0x01010003206313442024-08-29 2:44:113 days ago1724899451IN
0xd2700086...47e9F00f2
0 ETH0.000440152.89930845
0x01000003206278352024-08-28 14:58:353 days ago1724857115IN
0xd2700086...47e9F00f2
0.39 ETH0.000819396.1767359
0x01000003206193402024-08-27 10:31:474 days ago1724754707IN
0xd2700086...47e9F00f2
2.2 ETH0.000559783.24108683
0x01010001205943742024-08-23 22:46:118 days ago1724453171IN
0xd2700086...47e9F00f2
0 ETH0.000504553.886289
0x01000001205925262024-08-23 16:34:478 days ago1724430887IN
0xd2700086...47e9F00f2
2 ETH0.000473813.50760256
0x01010003205758612024-08-21 8:39:5910 days ago1724229599IN
0xd2700086...47e9F00f2
0 ETH0.000387282.91059102
0x01000003205292372024-08-14 20:24:3517 days ago1723667075IN
0xd2700086...47e9F00f2
0.0255 ETH0.000838776.32203102
0x00010001205292142024-08-14 20:19:5917 days ago1723666799IN
0xd2700086...47e9F00f2
0 ETH0.000786976.21753533
Relay1Gs Wnfs IQ...205289282024-08-14 19:22:1117 days ago1723663331IN
0xd2700086...47e9F00f2
0.065 ETH0.000772375.12199534
0x00010001205287952024-08-14 18:55:3517 days ago1723661735IN
0xd2700086...47e9F00f2
0 ETH0.000722975.81911506
Relay1Gs Wnfs IQ...205287692024-08-14 18:50:2317 days ago1723661423IN
0xd2700086...47e9F00f2
0.076 ETH0.00082385.86028538
0x00010001205287602024-08-14 18:48:3517 days ago1723661315IN
0xd2700086...47e9F00f2
0 ETH0.000850396.84409252
Relay1Gs Wnfs IQ...205285762024-08-14 18:11:2317 days ago1723659083IN
0xd2700086...47e9F00f2
0.08 ETH0.00089265.91168292
0x00010001205283682024-08-14 17:29:3517 days ago1723656575IN
0xd2700086...47e9F00f2
0 ETH0.001079418.6872008
Relay1Gs Wnfs IQ...205280022024-08-14 16:15:4717 days ago1723652147IN
0xd2700086...47e9F00f2
0.074 ETH0.000913376.04926163
0x00010001205279702024-08-14 16:09:2317 days ago1723651763IN
0xd2700086...47e9F00f2
0 ETH0.000923247.43032665
Relay1Gs Wnfs IQ...205279452024-08-14 16:04:2317 days ago1723651463IN
0xd2700086...47e9F00f2
0.084 ETH0.001236578.79658556
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
206512312024-08-31 21:27:119 hrs ago1725139631
0xd2700086...47e9F00f2
0.59 ETH
206341442024-08-29 12:09:112 days ago1724933351
0xd2700086...47e9F00f2
0.15 ETH
206341412024-08-29 12:08:352 days ago1724933315
0xd2700086...47e9F00f2
0.14536973 ETH
206341412024-08-29 12:08:352 days ago1724933315
0xd2700086...47e9F00f2
0.14536973 ETH
206341222024-08-29 12:04:472 days ago1724933087
0xd2700086...47e9F00f2
0.05 ETH
206341182024-08-29 12:03:592 days ago1724933039
0xd2700086...47e9F00f2
0.05 ETH
206341162024-08-29 12:03:352 days ago1724933015
0xd2700086...47e9F00f2
0.05 ETH
206341142024-08-29 12:03:112 days ago1724932991
0xd2700086...47e9F00f2
0.05 ETH
206341112024-08-29 12:02:352 days ago1724932955
0xd2700086...47e9F00f2
0.05 ETH
206313442024-08-29 2:44:113 days ago1724899451
0xd2700086...47e9F00f2
0.37171346 ETH
206313442024-08-29 2:44:113 days ago1724899451
0xd2700086...47e9F00f2
0.37171346 ETH
206278352024-08-28 14:58:353 days ago1724857115
0xd2700086...47e9F00f2
0.39 ETH
206193402024-08-27 10:31:474 days ago1724754707
0xd2700086...47e9F00f2
2.2 ETH
205943742024-08-23 22:46:118 days ago1724453171
0xd2700086...47e9F00f2
2.37916859 ETH
205943742024-08-23 22:46:118 days ago1724453171
0xd2700086...47e9F00f2
2.37916859 ETH
205925262024-08-23 16:34:478 days ago1724430887
0xd2700086...47e9F00f2
2 ETH
205758612024-08-21 8:39:5910 days ago1724229599
0xd2700086...47e9F00f2
2.17054982 ETH
205758612024-08-21 8:39:5910 days ago1724229599
0xd2700086...47e9F00f2
2.17054982 ETH
205292372024-08-14 20:24:3517 days ago1723667075
0xd2700086...47e9F00f2
0.0255 ETH
205292142024-08-14 20:19:5917 days ago1723666799
0xd2700086...47e9F00f2
0.05956776 ETH
205292142024-08-14 20:19:5917 days ago1723666799
0xd2700086...47e9F00f2
0.05956776 ETH
205289282024-08-14 19:22:1117 days ago1723663331
0xd2700086...47e9F00f2
0.065 ETH
205287952024-08-14 18:55:3517 days ago1723661735
0xd2700086...47e9F00f2
0.06995018 ETH
205287952024-08-14 18:55:3517 days ago1723661735
0xd2700086...47e9F00f2
0.06995018 ETH
205287692024-08-14 18:50:2317 days ago1723661423
0xd2700086...47e9F00f2
0.076 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.