ETH Price: $3,259.52 (-2.23%)
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Approve198742832024-05-15 8:48:11252 days ago1715762891IN
0xe219a14e...DA154E8Eb
0 ETH0.000148335.6462728
Approve198742822024-05-15 8:47:59252 days ago1715762879IN
0xe219a14e...DA154E8Eb
0 ETH0.000155385.91452077
Approve196202112024-04-09 19:37:11288 days ago1712691431IN
0xe219a14e...DA154E8Eb
0 ETH0.0005889222.41720242
Approve196202112024-04-09 19:37:11288 days ago1712691431IN
0xe219a14e...DA154E8Eb
0 ETH0.0005440822.41720242
Approve170221042023-04-11 3:07:23652 days ago1681182443IN
0xe219a14e...DA154E8Eb
0 ETH0.0012454326.75194698
Approve169028892023-03-25 7:07:23669 days ago1679728043IN
0xe219a14e...DA154E8Eb
0 ETH0.0006373813.69100988
Transfer166854712023-02-22 17:30:35700 days ago1677087035IN
0xe219a14e...DA154E8Eb
0 ETH0.0019430741.56754427
Approve166287892023-02-14 18:30:59708 days ago1676399459IN
0xe219a14e...DA154E8Eb
0 ETH0.0011675825.0796623
Approve165894082023-02-09 6:27:47713 days ago1675924067IN
0xe219a14e...DA154E8Eb
0 ETH0.0009907821.28204292
Approve165397112023-02-02 7:44:47720 days ago1675323887IN
0xe219a14e...DA154E8Eb
0 ETH0.0007392815.87990019
Approve164906792023-01-26 11:25:59727 days ago1674732359IN
0xe219a14e...DA154E8Eb
0 ETH0.0006155713.22263329
Approve164565502023-01-21 17:04:11732 days ago1674320651IN
0xe219a14e...DA154E8Eb
0 ETH0.0014157230.40965321
Approve164496672023-01-20 17:59:47733 days ago1674237587IN
0xe219a14e...DA154E8Eb
0 ETH0.0012558926.97648555
Approve164360622023-01-18 20:25:11735 days ago1674073511IN
0xe219a14e...DA154E8Eb
0 ETH0.0011908425.57934006
Approve164312462023-01-18 4:17:35735 days ago1674015455IN
0xe219a14e...DA154E8Eb
0 ETH0.0009456620.31280047
Approve164267112023-01-17 13:06:35736 days ago1673960795IN
0xe219a14e...DA154E8Eb
0 ETH0.0010407422.35525
Approve164257892023-01-17 10:01:35736 days ago1673949695IN
0xe219a14e...DA154E8Eb
0 ETH0.000809717.39235383
Approve164230912023-01-17 1:00:11736 days ago1673917211IN
0xe219a14e...DA154E8Eb
0 ETH0.0012402226.64008618
Approve164212592023-01-16 18:51:35737 days ago1673895095IN
0xe219a14e...DA154E8Eb
0 ETH0.0009264219.89959345
Approve164210592023-01-16 18:11:23737 days ago1673892683IN
0xe219a14e...DA154E8Eb
0 ETH0.0014651531.47156557
Approve164169482023-01-16 4:24:47737 days ago1673843087IN
0xe219a14e...DA154E8Eb
0 ETH0.0008908619.13568876
Approve163850832023-01-11 17:32:59742 days ago1673458379IN
0xe219a14e...DA154E8Eb
0 ETH0.0017514637.62139457

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block
From
To
161810302022-12-14 6:04:11770 days ago1670997851  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
NomiswapStablePair

Compiler Version
v0.8.15+commit.e14f2714

Optimization Enabled:
Yes with 999999 runs

Other Settings:
default evmVersion
File 1 of 16 : NomiswapStablePair.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity =0.8.15;

import "./interfaces/INomiswapStablePair.sol";
import "./interfaces/INomiswapCallee.sol";
import "./interfaces/INomiswapFactory.sol";
import "./NomiswapStableERC20.sol";
import "./libraries/MathUtils.sol";
import "./libraries/UQ112x112.sol";
import "./util/FactoryGuard.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

contract NomiswapStablePair is INomiswapStablePair, NomiswapStableERC20, ReentrancyGuard, FactoryGuard {
    using MathUtils for uint256;

    uint256 public constant MINIMUM_LIQUIDITY = 10**3;

    uint256 public constant MAX_FEE = 2**32 - 1; // @dev 100% (max of uint32).
    uint256 private constant A_PRECISION = 100;

    uint256 private constant MAX_A = 10 ** 6;
    uint256 private constant MAX_A_CHANGE = 100;
    uint256 private constant MIN_RAMP_TIME = 86400;

    uint256 private constant Q112 = 2**112;
    uint256 private constant MAX_LOOP_LIMIT = 256;

    address public immutable token0;
    address public immutable token1;

    uint112 private reserve0;           // uses single storage slot, accessible via getReserves
    uint112 private reserve1;           // uses single storage slot, accessible via getReserves
    uint32  private blockTimestampLast; // uses single storage slot, accessible via getReserves

    uint128 public adminFee = 1;
    uint128 public devFee = uint128(Q112*(10-7)/uint(7)); // 70% (1/0.7-1)

    uint128 public immutable token0PrecisionMultiplier; // uses single storage slot
    uint128 public immutable token1PrecisionMultiplier; // uses single storage slot

    uint32 initialA = uint32(85 * A_PRECISION); // uses single storage slot
    uint32 futureA = initialA; // uses single storage slot
    uint40 initialATime; // uses single storage slot
    uint40 futureATime; // uses single storage slot
    uint32 public swapFee = 4294968; // 0.1% default

    constructor(address _token0, address _token1) FactoryGuard(msg.sender) {
        futureATime = uint40(block.timestamp);
        token0 = _token0;
        token1 = _token1;
        uint8 decimals0 = IERC20Metadata(_token0).decimals();
        require(decimals0 <= 18, 'NomiswapStablePair: unsupported token');
        token0PrecisionMultiplier = uint128(10)**(18 - decimals0);
        uint8 decimals1 = IERC20Metadata(_token1).decimals();
        require(decimals1 <= 18, 'NomiswapStablePair: unsupported token');
        token1PrecisionMultiplier = uint128(10)**(18 - decimals1);
    }

    function symbol() external view returns (string memory) {
        return string.concat(
            symbolPrefix,
            "-",
            IERC20Metadata(token0).symbol(),
            "-",
            IERC20Metadata(token1).symbol()
        );
    }

    function setSwapFee(uint32 _swapFee) override external onlyFactory {
        require(_swapFee <= MAX_FEE, 'NomiswapStablePair: FORBIDDEN_FEE');
        swapFee = _swapFee;
    }

    function setDevFee(uint128 _devFee) override external onlyFactory {
        require(_devFee != 0, "NomiswapStablePair: dev fee 0");
        devFee = _devFee;
    }

    // this low-level function should be called from a contract which performs important safety checks
    function mint(address to) override external nonReentrant returns (uint liquidity) {
        (uint112 _reserve0, uint112 _reserve1,) = getReserves(); // gas savings
        uint balance0 = IERC20(token0).balanceOf(address(this));
        uint balance1 = IERC20(token1).balanceOf(address(this));

        _mintFee();
        uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        uint amount0 = balance0 - _reserve0;
        uint amount1 = balance1 - _reserve1;

        if (_totalSupply == 0) {
            uint A = getA();
            uint dBalance = _computeLiquidity(balance0, balance1, A);
            liquidity = dBalance - MINIMUM_LIQUIDITY;
            _mint(address(0), MINIMUM_LIQUIDITY); // permanently lock the first MINIMUM_LIQUIDITY tokens
        } else {
            liquidity = MathUtils.min(amount0 * _totalSupply / _reserve0, amount1 * _totalSupply / _reserve1);
        }

        require(liquidity > 0, 'Nomiswap: INSUFFICIENT_LIQUIDITY_MINTED');
        _mint(to, liquidity);

        _update(balance0, balance1);
        emit Mint(msg.sender, amount0, amount1);
    }

    // this low-level function should be called from a contract which performs important safety checks
    function burn(address to) override external nonReentrant returns (uint amount0, uint amount1) {
        address _token0 = token0;                                // gas savings
        address _token1 = token1;                                // gas savings
        uint balance0 = IERC20(_token0).balanceOf(address(this));
        uint balance1 = IERC20(_token1).balanceOf(address(this));
        uint liquidity = balanceOf[address(this)];

        _mintFee();
        uint _totalSupply = totalSupply; // gas savings, must be defined here since totalSupply can update in _mintFee
        amount0 = liquidity * balance0 / _totalSupply; // using balances ensures pro-rata distribution
        amount1 = liquidity * balance1 / _totalSupply; // using balances ensures pro-rata distribution
        require(amount0 > 0 && amount1 > 0, 'Nomiswap: INSUFFICIENT_LIQUIDITY_BURNED');
        _burn(address(this), liquidity);
        SafeERC20.safeTransfer(IERC20(_token0), to, amount0);
        SafeERC20.safeTransfer(IERC20(_token1), to, amount1);
        balance0 = IERC20(_token0).balanceOf(address(this));
        balance1 = IERC20(_token1).balanceOf(address(this));

        _update(balance0, balance1);
        emit Burn(msg.sender, amount0, amount1, to);
    }

    // this low-level function should be called from a contract which performs important safety checks
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) override external nonReentrant {
        require(amount0Out > 0 || amount1Out > 0, 'Nomiswap: INSUFFICIENT_OUTPUT_AMOUNT');
        (uint _reserve0, uint _reserve1,) = getReserves(); // gas savings
        require(amount0Out < _reserve0 && amount1Out < _reserve1, 'Nomiswap: INSUFFICIENT_LIQUIDITY');

        uint balance0;
        uint balance1;
        { // scope for _token{0,1}, avoids stack too deep errors
            address _token0 = token0;
            address _token1 = token1;
            require(to != _token0 && to != _token1, 'Nomiswap: INVALID_TO');
            if (amount0Out > 0) SafeERC20.safeTransfer(IERC20(_token0), to, amount0Out); // optimistically transfer tokens
            if (amount1Out > 0) SafeERC20.safeTransfer(IERC20(_token1), to, amount1Out); // optimistically transfer tokens
            if (data.length > 0) INomiswapCallee(to).nomiswapCall(msg.sender, amount0Out, amount1Out, data);
            balance0 = IERC20(_token0).balanceOf(address(this));
            balance1 = IERC20(_token1).balanceOf(address(this));
        }
        uint amount0In = balance0 > _reserve0 - amount0Out ? balance0 - (_reserve0 - amount0Out) : 0;
        uint amount1In = balance1 > _reserve1 - amount1Out ? balance1 - (_reserve1 - amount1Out) : 0;
        require(amount0In > 0 || amount1In > 0, 'Nomiswap: INSUFFICIENT_INPUT_AMOUNT');
        { // scope for reserve{0,1}Adjusted, avoids stack too deep errors

            uint256 A = getA();
            uint _swapFee = swapFee;
            uint _token0PrecisionMultiplier = token0PrecisionMultiplier;
            uint _token1PrecisionMultiplier = token1PrecisionMultiplier;
            uint balance0Adjusted = (balance0 * MAX_FEE - amount0In * _swapFee) * _token0PrecisionMultiplier / MAX_FEE;
            uint balance1Adjusted = (balance1 * MAX_FEE - amount1In * _swapFee) * _token1PrecisionMultiplier / MAX_FEE;
            uint256 dBalance = _computeLiquidityFromAdjustedBalances(balance0Adjusted, balance1Adjusted, A);

            uint256 adjustedReserve0 = _reserve0 * _token0PrecisionMultiplier;
            uint256 adjustedReserve1 = _reserve1 * _token1PrecisionMultiplier;
            uint256 dReserves = _computeLiquidityFromAdjustedBalances(adjustedReserve0, adjustedReserve1, A);

            require(dBalance >= dReserves, 'Nomiswap: D');

            uint256 dTotal = _computeLiquidity(balance0, balance1, A);
            uint numerator = totalSupply * (dTotal - dReserves);
            uint denominator = (dTotal * devFee/Q112) + dReserves;
            adminFee += uint128(numerator / denominator);
        }

        _update(balance0, balance1);
        emit Swap(msg.sender, amount0In, amount1In, amount0Out, amount1Out, to);
    }

    // force balances to match reserves
    function skim(address to) override external nonReentrant {
        address _token0 = token0; // gas savings
        address _token1 = token1; // gas savings
        SafeERC20.safeTransfer(IERC20(_token0), to, IERC20(_token0).balanceOf(address(this)) - reserve0);
        SafeERC20.safeTransfer(IERC20(_token1), to, IERC20(_token1).balanceOf(address(this)) - reserve1);
    }

    // force reserves to match balances
    function sync() override external nonReentrant {
        _update(IERC20(token0).balanceOf(address(this)), IERC20(token1).balanceOf(address(this)));
    }

    function rampA(uint32 _futureA, uint40 _futureTime) override external nonReentrant onlyFactory {
        require(block.timestamp >= initialATime + MIN_RAMP_TIME, 'NomiswapStablePair: INVALID_TIME');
        require(_futureTime >= block.timestamp + MIN_RAMP_TIME, 'NomiswapStablePair: INVALID_FUTURE_TIME');

        uint32 _initialA = uint32(getA());

        require(_futureA > 0 && _futureA < MAX_A * A_PRECISION);

        if (_futureA < _initialA) {
            require(_futureA * MAX_A_CHANGE >= _initialA);
        } else {
            require(_futureA <= _initialA * MAX_A_CHANGE);
        }

        initialA = _initialA;
        futureA = _futureA;
        initialATime = uint40(block.timestamp);
        futureATime = _futureTime;

        emit RampA(_initialA, _futureA, block.timestamp, _futureTime);
    }

    function stopRampA() override external nonReentrant onlyFactory {
        uint32 currentA = uint32(getA());

        initialA = currentA;
        futureA = currentA;
        initialATime = uint40(block.timestamp);
        futureATime = uint40(block.timestamp);

        emit StopRampA(currentA, block.timestamp);
    }

    function getAmountIn(address tokenIn, uint256 amountOut) external view override returns (uint256 finalAmountIn) {
        (uint256 _reserve0, uint256 _reserve1, ) = getReserves();

        uint256 _token0PrecisionMultiplier = token0PrecisionMultiplier;
        uint256 _token1PrecisionMultiplier = token1PrecisionMultiplier;
        uint256 adjustedReserve0 = _reserve0 * _token0PrecisionMultiplier;
        uint256 adjustedReserve1 = _reserve1 * _token1PrecisionMultiplier;
        uint256 A = getA();
        uint256 d = _computeLiquidityFromAdjustedBalances(adjustedReserve0, adjustedReserve1, A);

        if (tokenIn == token0) {
            uint256 x = adjustedReserve1 - amountOut * _token1PrecisionMultiplier;
            uint256 y = _getY(x, d, A);
            uint256 dy = (y - adjustedReserve0).divRoundUp(_token0PrecisionMultiplier);
            finalAmountIn = (dy * MAX_FEE).divRoundUp(MAX_FEE - swapFee);
        } else {
            require(tokenIn == token1, "INVALID_INPUT_TOKEN");
            uint256 x = adjustedReserve0 - amountOut * _token0PrecisionMultiplier;
            uint256 y = _getY(x, d, A);
            uint256 dy = (y - adjustedReserve1).divRoundUp(_token1PrecisionMultiplier);
            finalAmountIn = (dy * MAX_FEE).divRoundUp(MAX_FEE - swapFee);
        }
    }

    function getAmountOut(address tokenIn, uint256 amountIn) external view override returns (uint256 finalAmountOut) {
        (uint256 _reserve0, uint256 _reserve1, ) = getReserves();

        uint256 _token0PrecisionMultiplier = token0PrecisionMultiplier;
        uint256 _token1PrecisionMultiplier = token1PrecisionMultiplier;
        uint256 feeDeductedAmountIn = (amountIn * MAX_FEE - amountIn * swapFee) / MAX_FEE;
        uint256 adjustedReserve0 = _reserve0 * _token0PrecisionMultiplier;
        uint256 adjustedReserve1 = _reserve1 * _token1PrecisionMultiplier;
        uint256 A = getA();
        uint256 d = _computeLiquidityFromAdjustedBalances(adjustedReserve0, adjustedReserve1, A);

        if (tokenIn == token0) {
            uint256 x = adjustedReserve0 + feeDeductedAmountIn * _token0PrecisionMultiplier;
            uint256 y = _getY(x, d, A);
            finalAmountOut = (adjustedReserve1 - y) / _token1PrecisionMultiplier;
        } else {
            require(tokenIn == token1, "INVALID_INPUT_TOKEN");
            uint256 x = adjustedReserve1 + feeDeductedAmountIn * _token1PrecisionMultiplier;
            uint256 y = _getY(x, d, A);
            finalAmountOut = (adjustedReserve0 - y) / _token0PrecisionMultiplier;
        }
    }

    function getReserves() override public view returns (uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast) {
        _reserve0 = reserve0;
        _reserve1 = reserve1;
        _blockTimestampLast = blockTimestampLast;
    }

    function factory() override public view returns (address) {
        return _factory;
    }

    function getA() override public view returns (uint256) {
        uint256 t1  = futureATime;
        uint256 A1  = futureA;

        if (block.timestamp < t1) {
            uint256 A0 = initialA;
            uint256 t0 = initialATime;
            // Expressions in uint32 cannot have negative numbers, thus "if"
            if (A1 > A0) {
                return A0 + (block.timestamp - t0) * (A1 - A0) / (t1 - t0);
            } else {
                return A0 - (block.timestamp - t0) * (A0 - A1) / (t1 - t0);
            }
        } else {
            // when t1 == 0 or block.timestamp >= t1
            return A1;
        }
    }

    function _computeLiquidity(uint256 _reserve0, uint256 _reserve1, uint256 A) private view returns (uint256 liquidity) {
        uint256 adjustedReserve0 = _reserve0 * token0PrecisionMultiplier;
        uint256 adjustedReserve1 = _reserve1 * token1PrecisionMultiplier;
        liquidity = _computeLiquidityFromAdjustedBalances(adjustedReserve0, adjustedReserve1, A);
    }

    function _update(uint balance0, uint balance1) private {
        require(balance0 <= type(uint112).max && balance1 <= type(uint112).max, 'Nomiswap: OVERFLOW');
        uint32 blockTimestamp = uint32(block.timestamp % 2**32);
        reserve0 = uint112(balance0);
        reserve1 = uint112(balance1);
        blockTimestampLast = blockTimestamp;
        emit Sync(reserve0, reserve1);
    }

    // if fee is on, mint liquidity equivalent to 1/6th of the growth in sqrt(k)
    function _mintFee() private {
        address feeTo = INomiswapFactory(factory()).feeTo();
        bool feeOn = feeTo != address(0);
        uint _adminFee = adminFee; // gas savings
        if (feeOn) {
            if (_adminFee > 1) {
                _mint(feeTo, _adminFee - 1);
                adminFee = 1;
            }
        } else if (_adminFee > 1) {
            adminFee = 1;
        }
    }

    function _computeLiquidityFromAdjustedBalances(uint256 xp0, uint256 xp1, uint256 A) private pure returns (uint256 d) {
        uint256 x = xp0 < xp1 ? xp0 : xp1;
        uint256 y = xp0 < xp1 ? xp1 : xp0;
        uint256 s = x + y;
        if (s == 0) {
            return 0;
        }

        uint256 N_A = 16 * A;
        uint256 numeratorP = N_A * s * y;
        uint256 denominatorP = (N_A - 4 * A_PRECISION) * y;

        uint256 prevD;
        d = s;
        for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {
            prevD = d;
            uint256 N_D = A_PRECISION * d * d / x;
            d = (2 * d * N_D + numeratorP) / (3 * N_D + denominatorP);
            if (d.within1(prevD)) {
                break;
            }
        }
    }

    function _getY(uint256 x, uint256 d, uint256 A) private pure returns (uint256 y) {
        uint256 yPrev;
        y = d;
        uint256 N_A = A * 4;
        uint256 numeratorP = A_PRECISION * d * d / x * d / 4;
        unchecked {
            uint256 denominatorP = N_A * (x - d) + d * A_PRECISION; // underflow is possible and desired

            // @dev Iterative approximation.
            for (uint256 i = 0; i < MAX_LOOP_LIMIT; i++) {
                yPrev = y;
                uint256 N_Y = N_A * y;
                y = (N_Y * y + numeratorP).divRoundUp((2 * N_Y + denominatorP));
                if (y.within1(yPrev)) {
                    break;
                }
            }
        }
    }

}

File 2 of 16 : FactoryGuard.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity =0.8.15;

contract FactoryGuard {

    address immutable internal _factory;
    modifier onlyFactory() {
        require(msg.sender == _factory, 'Nomiswap: FORBIDDEN');
        _;
    }

    constructor(address factory) {
        _factory = factory;
    }

}

File 3 of 16 : UQ112x112.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity =0.8.15;

// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))

// range: [0, 2**112 - 1]
// resolution: 1 / 2**112

library UQ112x112 {
    uint224 constant Q112 = 2**112;

    // encode a uint112 as a UQ112x112
    function encode(uint112 y) internal pure returns (uint224 z) {
        z = uint224(y) * Q112; // never overflows
    }

    // divide a UQ112x112 by a uint112, returning a UQ112x112
    function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
        z = x / uint224(y);
    }
}

File 4 of 16 : MathUtils.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity =0.8.15;

/// @notice A library that contains functions for calculating differences between two uint256.
/// @author Adapted from https://github.com/saddle-finance/saddle-contract/blob/master/contracts/MathUtils.sol.
library MathUtils {
    /// @notice Compares a and b and returns 'true' if the difference between a and b
    /// is less than 1 or equal to each other.
    /// @param a uint256 to compare with.
    /// @param b uint256 to compare with.
    function within1(uint256 a, uint256 b) internal pure returns (bool) {
        unchecked {
            if (a > b) {
                return a - b <= 1;
            }
            return b - a <= 1;
        }
    }

    function divRoundUp(uint numerator, uint denumerator) internal pure returns (uint) {
        return (numerator + denumerator - 1) / denumerator;
    }

    function min(uint x, uint y) internal pure returns (uint z) {
        z = x < y ? x : y;
    }

}

File 5 of 16 : INomiswapStablePair.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

import "./INomiswapPair.sol";
pragma experimental ABIEncoderV2;

interface INomiswapStablePair is INomiswapPair {

    event RampA(uint256 oldA, uint256 newA, uint256 initialTime, uint256 futureTime);
    event StopRampA(uint256 A, uint256 t);

    function devFee() external view returns (uint128);

//    function burnSingle(address tokenOut, address recipient) external returns (uint256 amountOut);

    function getA() external view returns (uint256);

    function setSwapFee(uint32) external;
    function setDevFee(uint128) external;

    function rampA(uint32 _futureA, uint40 _futureTime) external;
    function stopRampA() external;

    function getAmountIn(address tokenIn, uint256 amountOut) external view returns (uint256);
    function getAmountOut(address tokenIn, uint256 amountIn) external view returns (uint256);

}

File 6 of 16 : INomiswapPair.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

import "./INomiswapERC20.sol";

interface INomiswapPair is INomiswapERC20 {

    event Mint(address indexed sender, uint amount0, uint amount1);
    event Burn(address indexed sender, uint amount0, uint amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint amount0In,
        uint amount1In,
        uint amount0Out,
        uint amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint);
    function factory() external view returns (address);
    function token0() external view returns (address);
    function token1() external view returns (address);
    function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast);

    function swapFee() external view returns (uint32);

    function mint(address to) external returns (uint liquidity);
    function burn(address to) external returns (uint amount0, uint amount1);
    function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external;
    function skim(address to) external;
    function sync() external;

}

File 7 of 16 : INomiswapFactory.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.5.0;

interface INomiswapFactory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint);

    function feeTo() external view returns (address);
    function feeToSetter() external view returns (address);
    function INIT_CODE_HASH() external view returns (bytes32);

    function getPair(address tokenA, address tokenB) external view returns (address pair);
    function allPairs(uint) external view returns (address pair);
    function allPairsLength() external view returns (uint);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;
    function setFeeToSetter(address) external;
    function setSwapFee(address pair, uint32 swapFee) external;
}

File 8 of 16 : INomiswapERC20.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";

interface INomiswapERC20 is IERC20Metadata {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
    function PERMIT_TYPEHASH() external pure returns (bytes32);
    function nonces(address owner) external view returns (uint);

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external;
}

File 9 of 16 : INomiswapCallee.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.5.0;

interface INomiswapCallee {
    function nomiswapCall(address sender, uint amount0, uint amount1, bytes calldata data) external;
}

File 10 of 16 : NomiswapStableERC20.sol
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity =0.8.15;

import "./interfaces/INomiswapERC20.sol";

abstract contract NomiswapStableERC20 is INomiswapERC20 {

    uint256 constant MAX_UINT = type(uint256).max; // 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

    string public constant name = 'Nomiswap stable LPs';
    string internal constant symbolPrefix = 'NMX-SLP';
    uint8 public constant decimals = 18;
    uint  public totalSupply;
    mapping(address => uint) public balanceOf;
    mapping(address => mapping(address => uint)) public allowance;

    bytes32 public immutable DOMAIN_SEPARATOR;
    // keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
    bytes32 public constant PERMIT_TYPEHASH = 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
    mapping(address => uint) public nonces;

    constructor() {
        uint chainId = block.chainid;

        DOMAIN_SEPARATOR = keccak256(
            abi.encode(
                keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'),
                keccak256(bytes(name)),
                keccak256(bytes('1')),
                chainId,
                address(this)
            )
        );
    }

    function _mint(address to, uint value) internal {
        totalSupply = totalSupply + value;
        balanceOf[to] = balanceOf[to] + value;
        emit Transfer(address(0), to, value);
    }

    function _burn(address from, uint value) internal {
        balanceOf[from] = balanceOf[from] - value;
        totalSupply = totalSupply - value;
        emit Transfer(from, address(0), value);
    }

    function _approve(address owner, address spender, uint value) private {
        allowance[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    function _transfer(address from, address to, uint value) private {
        balanceOf[from] = balanceOf[from] - value;
        balanceOf[to] = balanceOf[to] + value;
        emit Transfer(from, to, value);
    }

    function approve(address spender, uint value) external returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        _approve(msg.sender, spender, allowance[msg.sender][spender] + addedValue);
        return true;
    }

    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        uint256 currentAllowance = allowance[msg.sender][spender];
        require(currentAllowance >= subtractedValue, "NomiswapStableERC20: decreased allowance below zero");
        _approve(msg.sender, spender, currentAllowance - subtractedValue);
        return true;
    }

    function transfer(address to, uint value) external returns (bool) {
        _transfer(msg.sender, to, value);
        return true;
    }

    function transferFrom(address from, address to, uint value) external returns (bool) {
        if (allowance[from][msg.sender] != MAX_UINT) {
            allowance[from][msg.sender] = allowance[from][msg.sender] - value;
        }
        _transfer(from, to, value);
        return true;
    }

    function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
        require(deadline >= block.timestamp, 'Nomiswap: EXPIRED');
        bytes32 digest = keccak256(
            abi.encodePacked(
                '\x19\x01',
                DOMAIN_SEPARATOR,
                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
            )
        );
        address recoveredAddress = ecrecover(digest, v, r, s);
        require(recoveredAddress != address(0) && recoveredAddress == owner, 'Nomiswap: INVALID_SIGNATURE');
        _approve(owner, spender, value);
    }

}

File 11 of 16 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

File 12 of 16 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/draft-IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 value
    ) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 newAllowance = token.allowance(address(this), spender) + value;
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            uint256 newAllowance = oldAllowance - value;
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
        }
    }

    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) {
            // Return data is optional
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 13 of 16 : draft-IERC20Permit.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 14 of 16 : IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

File 15 of 16 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 16 of 16 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

Settings
{
  "remappings": [],
  "optimizer": {
    "enabled": true,
    "runs": 999999
  },
  "evmVersion": "istanbul",
  "libraries": {},
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_token0","type":"address"},{"internalType":"address","name":"_token1","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Burn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1","type":"uint256"}],"name":"Mint","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newA","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"initialTime","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"futureTime","type":"uint256"}],"name":"RampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"A","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"t","type":"uint256"}],"name":"StopRampA","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount0In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1In","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount0Out","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount1Out","type":"uint256"},{"indexed":true,"internalType":"address","name":"to","type":"address"}],"name":"Swap","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint112","name":"reserve0","type":"uint112"},{"indexed":false,"internalType":"uint112","name":"reserve1","type":"uint112"}],"name":"Sync","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINIMUM_LIQUIDITY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"adminFee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"burn","outputs":[{"internalType":"uint256","name":"amount0","type":"uint256"},{"internalType":"uint256","name":"amount1","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"devFee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getA","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"finalAmountIn","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"finalAmountOut","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getReserves","outputs":[{"internalType":"uint112","name":"_reserve0","type":"uint112"},{"internalType":"uint112","name":"_reserve1","type":"uint112"},{"internalType":"uint32","name":"_blockTimestampLast","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"mint","outputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_futureA","type":"uint32"},{"internalType":"uint40","name":"_futureTime","type":"uint40"}],"name":"rampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_devFee","type":"uint128"}],"name":"setDevFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_swapFee","type":"uint32"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"}],"name":"skim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stopRampA","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount0Out","type":"uint256"},{"internalType":"uint256","name":"amount1Out","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"swap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapFee","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sync","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token0","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token0PrecisionMultiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token1PrecisionMultiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]

610140604052600680546001600160801b031916600117905560076200002b600160701b6003620003f6565b62000037919062000418565b600680546001600160801b03928316600160801b0292169190911790556200006260646055620003f6565b600780546001600160401b03191663ffffffff92909216918217640100000000929092029190911763ffffffff60901b19166208312760931b179055348015620000ab57600080fd5b5060405162004b4838038062004b48833981016040819052620000ce9162000458565b604080518082018252601381527f4e6f6d697377617020737461626c65204c5073000000000000000000000000006020918201528151808301835260018152603160f81b9082015281517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f918101919091527f22155260db1abf6474eb894108f4b66f54f6b4a9c481b6e3e789468ed505cc97918101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6606082015246608082018190523060a0830152339160c00160408051808303601f190181528282528051602091820120608052600160049081556001600160a01b0395861660a0526007805464ffffffffff60681b19166d01000000000000000000000000004264ffffffffff160217905587861660c081905295871660e05263313ce56760e01b84529151600095945063313ce5679383810193908290030181865afa1580156200023f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000265919062000490565b905060128160ff161115620002be5760405162461bcd60e51b8152602060048201526025602482015260008051602062004b288339815191526044820152643a37b5b2b760d91b60648201526084015b60405180910390fd5b620002cb816012620004bc565b620002d890600a62000622565b6001600160801b0316610100816001600160801b0316815250506000826001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801562000333573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000359919062000490565b905060128160ff161115620003ae5760405162461bcd60e51b8152602060048201526025602482015260008051602062004b288339815191526044820152643a37b5b2b760d91b6064820152608401620002b5565b620003bb816012620004bc565b620003c890600a62000622565b6001600160801b031661012052506200063c92505050565b634e487b7160e01b600052601160045260246000fd5b6000816000190483118215151615620004135762000413620003e0565b500290565b6000826200043657634e487b7160e01b600052601260045260246000fd5b500490565b80516001600160a01b03811681146200045357600080fd5b919050565b600080604083850312156200046c57600080fd5b62000477836200043b565b915062000487602084016200043b565b90509250929050565b600060208284031215620004a357600080fd5b815160ff81168114620004b557600080fd5b9392505050565b600060ff821660ff841680821015620004d957620004d9620003e0565b90039392505050565b600181815b8085111562000529576001600160801b038290048211156200050d576200050d620003e0565b808516156200051b57918102915b93841c9390800290620004e7565b509250929050565b60008262000542575060016200061c565b8162000551575060006200061c565b81600181146200056a57600281146200057557620005b0565b60019150506200061c565b60ff841115620005895762000589620003e0565b6001841b91506001600160801b03821115620005a957620005a9620003e0565b506200061c565b5060208310610133831016604e8410600b8410161715620005ef575081810a6001600160801b03811115620005e957620005e9620003e0565b6200061c565b620005fb8383620004e2565b6001600160801b03819004821115620006185762000618620003e0565b0290505b92915050565b6000620004b560ff84166001600160801b03841662000531565b60805160a05160c05160e05161010051610120516143ca6200075e6000396000818161049001528181610d150152818161130e01528181612739015261330101526000818161063701528181610cf1015281816112ea0152818161271501526132c10152600081816106bd0152818161090201528181611441015281816116d701528181611cf901528181612198015281816123a50152818161287c0152612fca01526000818161038c015281816108e1015281816113670152818161162301528181611cd7015281816120e701528181612383015281816127e40152612f1c015260008181610679015281816110050152818161193a015281816124ff01528181612d7401526136df0152600081816104560152612ae901526143ca6000f3fe608060405234801561001057600080fd5b50600436106102925760003560e01c80637ecebe0011610160578063bc25cf77116100d8578063d46300fd1161008c578063d6d788c311610071578063d6d788c3146106fa578063dd62ed3e1461070d578063fff6cae91461073857600080fd5b8063d46300fd146106df578063d505accf146106e757600080fd5b8063c4db7fa0116100bd578063c4db7fa01461069d578063ca706bcf146106a5578063d21220a7146106b857600080fd5b8063bc25cf7714610664578063c45a01551461067757600080fd5b8063a457c2d71161012f578063ba9a7a5611610114578063ba9a7a5614610629578063baa8c7cb14610632578063bc063e1a1461065957600080fd5b8063a457c2d714610603578063a9059cbb1461061657600080fd5b80637ecebe001461059757806389afcb44146105b757806395d89b41146105df578063a0be06f9146105e757600080fd5b8063313ce5671161020e578063632db21c116101c25780636a627842116101a75780636a6278421461055157806370a082311461056457806373c48bb51461058457600080fd5b8063632db21c1461050e5780636827e7641461052157600080fd5b806339509351116101f357806339509351146104785780634e25dc471461048b57806354cf2aeb146104d357600080fd5b8063313ce567146104375780633644e5151461045157600080fd5b80630dfe16811161026557806318160ddd1161024a57806318160ddd146103e657806323b872dd146103fd57806330adf81f1461041057600080fd5b80630dfe168114610387578063111f8ef3146103d357600080fd5b8063022c0d9f1461029757806306fdde03146102ac5780630902f1ac146102fe578063095ea7b314610364575b600080fd5b6102aa6102a5366004613cfd565b610740565b005b6102e86040518060400160405280601381526020017f4e6f6d697377617020737461626c65204c50730000000000000000000000000081525081565b6040516102f59190613dc3565b60405180910390f35b600554604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016102f5565b610377610372366004613e14565b610fd6565b60405190151581526020016102f5565b6103ae7f000000000000000000000000000000000000000000000000000000000000000081565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b6102aa6103e1366004613e40565b610fed565b6103ef60005481565b6040519081526020016102f5565b61037761040b366004613e72565b61113d565b6103ef7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61043f601281565b60405160ff90911681526020016102f5565b6103ef7f000000000000000000000000000000000000000000000000000000000000000081565b610377610486366004613e14565b611218565b6104b27f000000000000000000000000000000000000000000000000000000000000000081565b6040516fffffffffffffffffffffffffffffffff90911681526020016102f5565b6007546104f9907201000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103ef61051c366004613e14565b611261565b6006546104b29070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6103ef61055f366004613eb3565b611571565b6103ef610572366004613eb3565b60016020526000908152604090205481565b6102aa610592366004613ee4565b61191a565b6103ef6105a5366004613eb3565b60036020526000908152604090205481565b6105ca6105c5366004613eb3565b611c9e565b604080519283526020830191909152016102f5565b6102e86120ad565b6006546104b2906fffffffffffffffffffffffffffffffff1681565b610377610611366004613e14565b61226d565b610377610624366004613e14565b61233d565b6103ef6103e881565b6104b27f000000000000000000000000000000000000000000000000000000000000000081565b6103ef63ffffffff81565b6102aa610672366004613eb3565b61234a565b7f00000000000000000000000000000000000000000000000000000000000000006103ae565b6102aa6124df565b6103ef6106b3366004613e14565b612688565b6103ae7f000000000000000000000000000000000000000000000000000000000000000081565b6103ef61297a565b6102aa6106f5366004613f25565b612a56565b6102aa610708366004613f9c565b612d5c565b6103ef61071b366004613fb7565b600260209081526000928352604080842090915290825290205481565b6102aa612ee2565b610748613059565b60008511806107575750600084115b6107e7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4e6f6d69737761703a20494e53554646494349454e545f4f55545055545f414d60448201527f4f554e540000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000806108436005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150818710801561087657508086105b6108dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201526064016107de565b6000807f00000000000000000000000000000000000000000000000000000000000000007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff8981169083161480159061097657508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b6109dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f6d69737761703a20494e56414c49445f544f00000000000000000000000060448201526064016107de565b8a156109ed576109ed828a8d6130cc565b89156109fe576109fe818a8c6130cc565b8615610a91576040517f2210968200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690632210968290610a5e9033908f908f908e908e90600401613fe5565b600060405180830381600087803b158015610a7857600080fd5b505af1158015610a8c573d6000803e3d6000fd5b505050505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1f919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290945073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb0919061405d565b9250505060008985610bc291906140a5565b8311610bcf576000610be3565b610bd98a866140a5565b610be390846140a5565b90506000610bf18a866140a5565b8311610bfe576000610c12565b610c088a866140a5565b610c1290846140a5565b90506000821180610c235750600081115b610caf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4e6f6d69737761703a20494e53554646494349454e545f494e5055545f414d4f60448201527f554e54000000000000000000000000000000000000000000000000000000000060648201526084016107de565b6000610cb961297a565b60075490915063ffffffff72010000000000000000000000000000000000009091048116906fffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116917f00000000000000000000000000000000000000000000000000000000000000009091169060009083610d46868a6140bc565b610d5463ffffffff8d6140bc565b610d5e91906140a5565b610d6891906140bc565b610d729190614128565b9050600063ffffffff83610d86878a6140bc565b610d9463ffffffff8d6140bc565b610d9e91906140a5565b610da891906140bc565b610db29190614128565b90506000610dc183838961315e565b90506000610dcf868f6140bc565b90506000610ddd868f6140bc565b90506000610dec83838c61315e565b905080841015610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e6f6d69737761703a204400000000000000000000000000000000000000000060448201526064016107de565b6000610e658f8f8d6132a8565b90506000610e7383836140a5565b600054610e8091906140bc565b60065490915060009084906e01000000000000000000000000000090610ecc9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16866140bc565b610ed69190614128565b610ee0919061413c565b9050610eec8183614128565b60068054600090610f109084906fffffffffffffffffffffffffffffffff16614154565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050505050505050505050505050610f5d848461333e565b60408051838152602081018390529081018c9052606081018b905273ffffffffffffffffffffffffffffffffffffffff8a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a3505050505050610fcf6001600455565b5050505050565b6000610fe33384846134d1565b5060015b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461108c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b806fffffffffffffffffffffffffffffffff16600003611108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e6f6d6973776170537461626c65506169723a2064657620666565203000000060448201526064016107de565b600680546fffffffffffffffffffffffffffffffff928316700100000000000000000000000000000000029216919091179055565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146112025773ffffffffffffffffffffffffffffffffffffffff841660009081526002602090815260408083203384529091529020546111d09083906140a5565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b61120d848484613540565b5060015b9392505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091610fe391859061125c90869061413c565b6134d1565b60008060006112bf6005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506dffffffffffffffffffffffffffff91821693501690506fffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116907f000000000000000000000000000000000000000000000000000000000000000016600061133a83866140bc565b9050600061134883866140bc565b9050600061135461297a565b9050600061136384848461315e565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff160361143f5760006113c4868c6140bc565b6113ce90856140a5565b905060006113dd82848661360f565b905060006113f5896113ef89856140a5565b906136b8565b600754909150611435906114279063ffffffff72010000000000000000000000000000000000009091048116906140a5565b6113ef63ffffffff846140bc565b9b50505050611563565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff16146114f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f494e5055545f544f4b454e0000000000000000000000000060448201526064016107de565b6000611500878c6140bc565b61150a90866140a5565b9050600061151982848661360f565b9050600061152b886113ef88856140a5565b60075490915061155d906114279063ffffffff72010000000000000000000000000000000000009091048116906140a5565b9b505050505b505050505050505092915050565b600061157b613059565b6000806115d76005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919350915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561166a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168e919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190602401602060405180830381865afa15801561171e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611742919061405d565b905061174c6136db565b600080549061176b6dffffffffffffffffffffffffffff8716856140a5565b905060006117896dffffffffffffffffffffffffffff8716856140a5565b9050826000036117d057600061179d61297a565b905060006117ac8787846132a8565b90506117ba6103e8826140a5565b99506117c960006103e861382a565b5050611825565b6118226dffffffffffffffffffffffffffff88166117ee85856140bc565b6117f89190614128565b6dffffffffffffffffffffffffffff881661181386856140bc565b61181d9190614128565b6138d5565b97505b600088116118b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201527f5f4d494e5445440000000000000000000000000000000000000000000000000060648201526084016107de565b6118bf898961382a565b6118c9858561333e565b604080518381526020810183905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a2505050505050506119156001600455565b919050565b611922613059565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016146119c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b6007546119e590620151809068010000000000000000900464ffffffffff1661413c565b421015611a4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f6d6973776170537461626c65506169723a20494e56414c49445f54494d4560448201526064016107de565b611a5b620151804261413c565b8164ffffffffff161015611af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d6973776170537461626c65506169723a20494e56414c49445f4655545560448201527f52455f54494d450000000000000000000000000000000000000000000000000060648201526084016107de565b6000611afb61297a565b905060008363ffffffff16118015611b255750611b1c6064620f42406140bc565b8363ffffffff16105b611b2e57600080fd5b8063ffffffff168363ffffffff161015611b6c578063ffffffff1660648463ffffffff16611b5c91906140bc565b1015611b6757600080fd5b611b8f565b611b7d606463ffffffff83166140bc565b8363ffffffff161115611b8f57600080fd5b6007805463ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217640100000000918716918202177fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff16680100000000000000004264ffffffffff818116929092027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff16929092176d0100000000000000000000000000918816918202179094556040805193845260208401929092529082015260608101919091527fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c2549060800160405180910390a150611c9a6001600455565b5050565b600080611ca9613059565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f0000000000000000000000000000000000000000000000000000000000000000907f00000000000000000000000000000000000000000000000000000000000000009060009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611d5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7e919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e12919061405d565b30600090815260016020526040902054909150611e2d6136db565b60005480611e3b85846140bc565b611e459190614128565b975080611e5284846140bc565b611e5c9190614128565b9650600088118015611e6e5750600087115b611efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201527f5f4255524e45440000000000000000000000000000000000000000000000000060648201526084016107de565b611f0430836138eb565b611f0f868a8a6130cc565b611f1a858a896130cc565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015611f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa8919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290945073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612039919061405d565b9250612045848461333e565b604080518981526020810189905273ffffffffffffffffffffffffffffffffffffffff8b169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050506120a86001600455565b915091565b60606040518060400160405280600781526020017f4e4d582d534c50000000000000000000000000000000000000000000000000008152507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612150573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261219691908101906141b7565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612201573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261224791908101906141b7565b60405160200161225993929190614277565b604051602081830303815290604052905090565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120548281101561232e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4e6f6d6973776170537461626c6545524332303a20646563726561736564206160448201527f6c6c6f77616e63652062656c6f77207a65726f0000000000000000000000000060648201526084016107de565b61120d338561125c86856140a5565b6000610fe3338484613540565b612352613059565b6005546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f0000000000000000000000000000000000000000000000000000000000000000917f00000000000000000000000000000000000000000000000000000000000000009161245091849186916dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8416906370a08231906024015b602060405180830381865afa15801561241d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612441919061405d565b61244b91906140a5565b6130cc565b6005546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526124d091839186916e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401612400565b50506124dc6001600455565b50565b6124e7613059565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b600061259061297a565b600780547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001663ffffffff83169081176401000000008202177fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff16680100000000000000004264ffffffffff81169182027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff16929092176d010000000000000000000000000091909102179092556040805191825260208201929092529192507f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc201938910160405180910390a1506126866001600455565b565b60008060006126e66005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506007546dffffffffffffffffffffffffffff9283169450911691506fffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116917f00000000000000000000000000000000000000000000000000000000000000009091169060009063ffffffff9061278790720100000000000000000000000000000000000090048216896140bc565b61279563ffffffff8a6140bc565b61279f91906140a5565b6127a99190614128565b905060006127b784876140bc565b905060006127c584876140bc565b905060006127d161297a565b905060006127e084848461315e565b90507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361287a57600061284188876140bc565b61284b908661413c565b9050600061285a82848661360f565b90508761286782876140a5565b6128719190614128565b9b50505061296b565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff161461292f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f494e5055545f544f4b454e0000000000000000000000000060448201526064016107de565b600061293b87876140bc565b612945908561413c565b9050600061295482848661360f565b90508861296182886140a5565b61155d9190614128565b50505050505050505092915050565b6007546000906d0100000000000000000000000000810464ffffffffff1690640100000000900463ffffffff1642821115610fe75760075463ffffffff81169068010000000000000000900464ffffffffff1681831115612a1a576129df81856140a5565b6129e983856140a5565b6129f383426140a5565b6129fd91906140bc565b612a079190614128565b612a11908361413c565b94505050505090565b612a2481856140a5565b612a2e84846140a5565b612a3883426140a5565b612a4291906140bc565b612a4c9190614128565b612a1190836140a5565b42841015612ac0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e6f6d69737761703a204558504952454400000000000000000000000000000060448201526064016107de565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260036020526040812080547f0000000000000000000000000000000000000000000000000000000000000000917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187612b3b836142ed565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001612bdc9291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612c65573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612ce057508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e6f6d69737761703a20494e56414c49445f5349474e4154555245000000000060448201526064016107de565b612d518989896134d1565b505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614612dfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b63ffffffff8163ffffffff161115612e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4e6f6d6973776170537461626c65506169723a20464f5242494444454e5f464560448201527f450000000000000000000000000000000000000000000000000000000000000060648201526084016107de565b6007805463ffffffff9092167201000000000000000000000000000000000000027fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff909216919091179055565b612eea613059565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015261304f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9c919061405d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015613026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304a919061405d565b61333e565b6126866001600455565b6002600454036130c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107de565b6002600455565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261315990849061399e565b505050565b60008083851061316e5783613170565b845b905060008486106131815785613183565b845b90506000613191828461413c565b9050806000036131a75760009350505050611211565b60006131b48660106140bc565b90506000836131c384846140bc565b6131cd91906140bc565b90506000846131de606460046140bc565b6131e890856140a5565b6131f291906140bc565b9050600084975060005b61010081101561329957889150600088836132188160646140bc565b61322291906140bc565b61322c9190614128565b90508361323a8260036140bc565b613244919061413c565b85826132518d60026140bc565b61325b91906140bc565b613265919061413c565b61326f9190614128565b995061327b8a84613aaa565b156132865750613299565b5080613291816142ed565b9150506131fc565b50505050505050509392505050565b6000806132e76fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016866140bc565b905060006133276fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016866140bc565b905061333482828661315e565b9695505050505050565b6dffffffffffffffffffffffffffff821180159061336a57506dffffffffffffffffffffffffffff8111155b6133d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e6f6d69737761703a204f564552464c4f57000000000000000000000000000060448201526064016107de565b60006133e164010000000042614325565b6005805463ffffffff83167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8781166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168a83161794909417918216831794859055604080519382169282169290921783529290930490911660208201529192507f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020546135719082906140a5565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526001602052604080822093909355908416815220546135ae90829061413c565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906135339085815260200190565b8160008061361e8460046140bc565b9050600060048688816136328160646140bc565b61363c91906140bc565b6136469190614128565b61365091906140bc565b61365a9190614128565b90508587038202606487020160005b6101008110156136ac5785945083850261368c81870285016002830285016136b8565b96506136988787613aaa565b156136a357506136ac565b50600101613669565b50505050509392505050565b60008160016136c7828661413c565b6136d191906140a5565b6112119190614128565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015613748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376c9190614339565b60065490915073ffffffffffffffffffffffffffffffffffffffff8216158015916fffffffffffffffffffffffffffffffff16906137f1576001811115613159576137c1836137bc6001846140a5565b61382a565b600680547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001179055505050565b600181111561315957600680547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001179055505050565b80600054613838919061413c565b600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602052604090205461386b90829061413c565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138c99085815260200190565b60405180910390a35050565b60008183106138e45781611211565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205461391c9082906140a5565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040812091909155546139519082906140a5565b600090815560405182815273ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016138c9565b6000613a00826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613acc9092919063ffffffff16565b8051909150156131595780806020019051810190613a1e9190614356565b613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107de565b600081831115613ac1575060018183031115610fe7565b506001919003111590565b6060613adb8484600085613ae3565b949350505050565b606082471015613b75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107de565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613b9e9190614378565b60006040518083038185875af1925050503d8060008114613bdb576040519150601f19603f3d011682016040523d82523d6000602084013e613be0565b606091505b5091509150613bf187838387613bfc565b979650505050505050565b60608315613c92578251600003613c8b5773ffffffffffffffffffffffffffffffffffffffff85163b613c8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107de565b5081613adb565b613adb8383815115613ca75781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107de9190613dc3565b73ffffffffffffffffffffffffffffffffffffffff811681146124dc57600080fd5b600080600080600060808688031215613d1557600080fd5b85359450602086013593506040860135613d2e81613cdb565b9250606086013567ffffffffffffffff80821115613d4b57600080fd5b818801915088601f830112613d5f57600080fd5b813581811115613d6e57600080fd5b896020828501011115613d8057600080fd5b9699959850939650602001949392505050565b60005b83811015613dae578181015183820152602001613d96565b83811115613dbd576000848401525b50505050565b6020815260008251806020840152613de2816040850160208701613d93565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215613e2757600080fd5b8235613e3281613cdb565b946020939093013593505050565b600060208284031215613e5257600080fd5b81356fffffffffffffffffffffffffffffffff8116811461121157600080fd5b600080600060608486031215613e8757600080fd5b8335613e9281613cdb565b92506020840135613ea281613cdb565b929592945050506040919091013590565b600060208284031215613ec557600080fd5b813561121181613cdb565b803563ffffffff8116811461191557600080fd5b60008060408385031215613ef757600080fd5b613f0083613ed0565b9150602083013564ffffffffff81168114613f1a57600080fd5b809150509250929050565b600080600080600080600060e0888a031215613f4057600080fd5b8735613f4b81613cdb565b96506020880135613f5b81613cdb565b95506040880135945060608801359350608088013560ff81168114613f7f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600060208284031215613fae57600080fd5b61121182613ed0565b60008060408385031215613fca57600080fd5b8235613fd581613cdb565b91506020830135613f1a81613cdb565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101949350505050565b60006020828403121561406f57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156140b7576140b7614076565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156140f4576140f4614076565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614137576141376140f9565b500490565b6000821982111561414f5761414f614076565b500190565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561417f5761417f614076565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156141c957600080fd5b815167ffffffffffffffff808211156141e157600080fd5b818401915084601f8301126141f557600080fd5b81518181111561420757614207614188565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561424d5761424d614188565b8160405282815287602084870101111561426657600080fd5b613bf1836020830160208801613d93565b60008451614289818460208901613d93565b80830190507f2d0000000000000000000000000000000000000000000000000000000000000080825285516142c5816001850160208a01613d93565b600192019182015283516142e0816002840160208801613d93565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361431e5761431e614076565b5060010190565b600082614334576143346140f9565b500690565b60006020828403121561434b57600080fd5b815161121181613cdb565b60006020828403121561436857600080fd5b8151801515811461121157600080fd5b6000825161438a818460208701613d93565b919091019291505056fea26469706673582212209c0499a9d8420b24d33a3a218c42e9fca62cc10ba6a9137b9775a622c5d2247264736f6c634300080f00334e6f6d6973776170537461626c65506169723a20756e737570706f7274656420000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106102925760003560e01c80637ecebe0011610160578063bc25cf77116100d8578063d46300fd1161008c578063d6d788c311610071578063d6d788c3146106fa578063dd62ed3e1461070d578063fff6cae91461073857600080fd5b8063d46300fd146106df578063d505accf146106e757600080fd5b8063c4db7fa0116100bd578063c4db7fa01461069d578063ca706bcf146106a5578063d21220a7146106b857600080fd5b8063bc25cf7714610664578063c45a01551461067757600080fd5b8063a457c2d71161012f578063ba9a7a5611610114578063ba9a7a5614610629578063baa8c7cb14610632578063bc063e1a1461065957600080fd5b8063a457c2d714610603578063a9059cbb1461061657600080fd5b80637ecebe001461059757806389afcb44146105b757806395d89b41146105df578063a0be06f9146105e757600080fd5b8063313ce5671161020e578063632db21c116101c25780636a627842116101a75780636a6278421461055157806370a082311461056457806373c48bb51461058457600080fd5b8063632db21c1461050e5780636827e7641461052157600080fd5b806339509351116101f357806339509351146104785780634e25dc471461048b57806354cf2aeb146104d357600080fd5b8063313ce567146104375780633644e5151461045157600080fd5b80630dfe16811161026557806318160ddd1161024a57806318160ddd146103e657806323b872dd146103fd57806330adf81f1461041057600080fd5b80630dfe168114610387578063111f8ef3146103d357600080fd5b8063022c0d9f1461029757806306fdde03146102ac5780630902f1ac146102fe578063095ea7b314610364575b600080fd5b6102aa6102a5366004613cfd565b610740565b005b6102e86040518060400160405280601381526020017f4e6f6d697377617020737461626c65204c50730000000000000000000000000081525081565b6040516102f59190613dc3565b60405180910390f35b600554604080516dffffffffffffffffffffffffffff80841682526e01000000000000000000000000000084041660208201527c010000000000000000000000000000000000000000000000000000000090920463ffffffff16908201526060016102f5565b610377610372366004613e14565b610fd6565b60405190151581526020016102f5565b6103ae7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016102f5565b6102aa6103e1366004613e40565b610fed565b6103ef60005481565b6040519081526020016102f5565b61037761040b366004613e72565b61113d565b6103ef7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b61043f601281565b60405160ff90911681526020016102f5565b6103ef7f2abab4249609e699c123826ac59be2ca97b30e5ed633abefb30e60668584a78681565b610377610486366004613e14565b611218565b6104b27f000000000000000000000000000000000000000000000000000000e8d4a5100081565b6040516fffffffffffffffffffffffffffffffff90911681526020016102f5565b6007546104f9907201000000000000000000000000000000000000900463ffffffff1681565b60405163ffffffff90911681526020016102f5565b6103ef61051c366004613e14565b611261565b6006546104b29070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6103ef61055f366004613eb3565b611571565b6103ef610572366004613eb3565b60016020526000908152604090205481565b6102aa610592366004613ee4565b61191a565b6103ef6105a5366004613eb3565b60036020526000908152604090205481565b6105ca6105c5366004613eb3565b611c9e565b604080519283526020830191909152016102f5565b6102e86120ad565b6006546104b2906fffffffffffffffffffffffffffffffff1681565b610377610611366004613e14565b61226d565b610377610624366004613e14565b61233d565b6103ef6103e881565b6104b27f000000000000000000000000000000000000000000000000000000e8d4a5100081565b6103ef63ffffffff81565b6102aa610672366004613eb3565b61234a565b7f000000000000000000000000818339b4e536e707f14980219037c5046b049dd46103ae565b6102aa6124df565b6103ef6106b3366004613e14565b612688565b6103ae7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec781565b6103ef61297a565b6102aa6106f5366004613f25565b612a56565b6102aa610708366004613f9c565b612d5c565b6103ef61071b366004613fb7565b600260209081526000928352604080842090915290825290205481565b6102aa612ee2565b610748613059565b60008511806107575750600084115b6107e7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f4e6f6d69737761703a20494e53554646494349454e545f4f55545055545f414d60448201527f4f554e540000000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000806108436005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506dffffffffffffffffffffffffffff1691506dffffffffffffffffffffffffffff169150818710801561087657508086105b6108dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201526064016107de565b6000807f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb487f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff8981169083161480159061097657508073ffffffffffffffffffffffffffffffffffffffff168973ffffffffffffffffffffffffffffffffffffffff1614155b6109dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f4e6f6d69737761703a20494e56414c49445f544f00000000000000000000000060448201526064016107de565b8a156109ed576109ed828a8d6130cc565b89156109fe576109fe818a8c6130cc565b8615610a91576040517f2210968200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8a1690632210968290610a5e9033908f908f908e908e90600401613fe5565b600060405180830381600087803b158015610a7857600080fd5b505af1158015610a8c573d6000803e3d6000fd5b505050505b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8316906370a0823190602401602060405180830381865afa158015610afb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1f919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290945073ffffffffffffffffffffffffffffffffffffffff8216906370a0823190602401602060405180830381865afa158015610b8c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb0919061405d565b9250505060008985610bc291906140a5565b8311610bcf576000610be3565b610bd98a866140a5565b610be390846140a5565b90506000610bf18a866140a5565b8311610bfe576000610c12565b610c088a866140a5565b610c1290846140a5565b90506000821180610c235750600081115b610caf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f4e6f6d69737761703a20494e53554646494349454e545f494e5055545f414d4f60448201527f554e54000000000000000000000000000000000000000000000000000000000060648201526084016107de565b6000610cb961297a565b60075490915063ffffffff72010000000000000000000000000000000000009091048116906fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000e8d4a510008116917f000000000000000000000000000000000000000000000000000000e8d4a510009091169060009083610d46868a6140bc565b610d5463ffffffff8d6140bc565b610d5e91906140a5565b610d6891906140bc565b610d729190614128565b9050600063ffffffff83610d86878a6140bc565b610d9463ffffffff8d6140bc565b610d9e91906140a5565b610da891906140bc565b610db29190614128565b90506000610dc183838961315e565b90506000610dcf868f6140bc565b90506000610ddd868f6140bc565b90506000610dec83838c61315e565b905080841015610e58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4e6f6d69737761703a204400000000000000000000000000000000000000000060448201526064016107de565b6000610e658f8f8d6132a8565b90506000610e7383836140a5565b600054610e8091906140bc565b60065490915060009084906e01000000000000000000000000000090610ecc9070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff16866140bc565b610ed69190614128565b610ee0919061413c565b9050610eec8183614128565b60068054600090610f109084906fffffffffffffffffffffffffffffffff16614154565b92506101000a8154816fffffffffffffffffffffffffffffffff02191690836fffffffffffffffffffffffffffffffff16021790555050505050505050505050505050610f5d848461333e565b60408051838152602081018390529081018c9052606081018b905273ffffffffffffffffffffffffffffffffffffffff8a169033907fd78ad95fa46c994b6551d0da85fc275fe613ce37657fb8d5e3d130840159d8229060800160405180910390a3505050505050610fcf6001600455565b5050505050565b6000610fe33384846134d1565b5060015b92915050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000818339b4e536e707f14980219037c5046b049dd4161461108c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b806fffffffffffffffffffffffffffffffff16600003611108576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f4e6f6d6973776170537461626c65506169723a2064657620666565203000000060448201526064016107de565b600680546fffffffffffffffffffffffffffffffff928316700100000000000000000000000000000000029216919091179055565b73ffffffffffffffffffffffffffffffffffffffff831660009081526002602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff146112025773ffffffffffffffffffffffffffffffffffffffff841660009081526002602090815260408083203384529091529020546111d09083906140a5565b73ffffffffffffffffffffffffffffffffffffffff851660009081526002602090815260408083203384529091529020555b61120d848484613540565b5060015b9392505050565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091610fe391859061125c90869061413c565b6134d1565b60008060006112bf6005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506dffffffffffffffffffffffffffff91821693501690506fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000e8d4a510008116907f000000000000000000000000000000000000000000000000000000e8d4a5100016600061133a83866140bc565b9050600061134883866140bc565b9050600061135461297a565b9050600061136384848461315e565b90507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4873ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff160361143f5760006113c4868c6140bc565b6113ce90856140a5565b905060006113dd82848661360f565b905060006113f5896113ef89856140a5565b906136b8565b600754909150611435906114279063ffffffff72010000000000000000000000000000000000009091048116906140a5565b6113ef63ffffffff846140bc565b9b50505050611563565b7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff168b73ffffffffffffffffffffffffffffffffffffffff16146114f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f494e5055545f544f4b454e0000000000000000000000000060448201526064016107de565b6000611500878c6140bc565b61150a90866140a5565b9050600061151982848661360f565b9050600061152b886113ef88856140a5565b60075490915061155d906114279063ffffffff72010000000000000000000000000000000000009091048116906140a5565b9b505050505b505050505050505092915050565b600061157b613059565b6000806115d76005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152919350915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4816906370a0823190602401602060405180830381865afa15801561166a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061168e919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec716906370a0823190602401602060405180830381865afa15801561171e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611742919061405d565b905061174c6136db565b600080549061176b6dffffffffffffffffffffffffffff8716856140a5565b905060006117896dffffffffffffffffffffffffffff8716856140a5565b9050826000036117d057600061179d61297a565b905060006117ac8787846132a8565b90506117ba6103e8826140a5565b99506117c960006103e861382a565b5050611825565b6118226dffffffffffffffffffffffffffff88166117ee85856140bc565b6117f89190614128565b6dffffffffffffffffffffffffffff881661181386856140bc565b61181d9190614128565b6138d5565b97505b600088116118b5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201527f5f4d494e5445440000000000000000000000000000000000000000000000000060648201526084016107de565b6118bf898961382a565b6118c9858561333e565b604080518381526020810183905233917f4c209b5fc8ad50758f13e2e1088ba56a560dff690a1c6fef26394f4c03821c4f910160405180910390a2505050505050506119156001600455565b919050565b611922613059565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000818339b4e536e707f14980219037c5046b049dd416146119c1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b6007546119e590620151809068010000000000000000900464ffffffffff1661413c565b421015611a4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4e6f6d6973776170537461626c65506169723a20494e56414c49445f54494d4560448201526064016107de565b611a5b620151804261413c565b8164ffffffffff161015611af1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d6973776170537461626c65506169723a20494e56414c49445f4655545560448201527f52455f54494d450000000000000000000000000000000000000000000000000060648201526084016107de565b6000611afb61297a565b905060008363ffffffff16118015611b255750611b1c6064620f42406140bc565b8363ffffffff16105b611b2e57600080fd5b8063ffffffff168363ffffffff161015611b6c578063ffffffff1660648463ffffffff16611b5c91906140bc565b1015611b6757600080fd5b611b8f565b611b7d606463ffffffff83166140bc565b8363ffffffff161115611b8f57600080fd5b6007805463ffffffff8381167fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000009092168217640100000000918716918202177fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff16680100000000000000004264ffffffffff818116929092027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff16929092176d0100000000000000000000000000918816918202179094556040805193845260208401929092529082015260608101919091527fa2b71ec6df949300b59aab36b55e189697b750119dd349fcfa8c0f779e83c2549060800160405180910390a150611c9a6001600455565b5050565b600080611ca9613059565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48907f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec79060009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611d5a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d7e919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290915060009073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401602060405180830381865afa158015611dee573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e12919061405d565b30600090815260016020526040902054909150611e2d6136db565b60005480611e3b85846140bc565b611e459190614128565b975080611e5284846140bc565b611e5c9190614128565b9650600088118015611e6e5750600087115b611efa576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4e6f6d69737761703a20494e53554646494349454e545f4c495155494449545960448201527f5f4255524e45440000000000000000000000000000000000000000000000000060648201526084016107de565b611f0430836138eb565b611f0f868a8a6130cc565b611f1a858a896130cc565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8716906370a0823190602401602060405180830381865afa158015611f84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fa8919061405d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015290945073ffffffffffffffffffffffffffffffffffffffff8616906370a0823190602401602060405180830381865afa158015612015573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612039919061405d565b9250612045848461333e565b604080518981526020810189905273ffffffffffffffffffffffffffffffffffffffff8b169133917fdccd412f0b1252819cb1fd330b93224ca42612892bb3f4f789976e6d81936496910160405180910390a35050505050506120a86001600455565b915091565b60606040518060400160405280600781526020017f4e4d582d534c50000000000000000000000000000000000000000000000000008152507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4873ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612150573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261219691908101906141b7565b7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff166395d89b416040518163ffffffff1660e01b8152600401600060405180830381865afa158015612201573d6000803e3d6000fd5b505050506040513d6000823e601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820160405261224791908101906141b7565b60405160200161225993929190614277565b604051602081830303815290604052905090565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120548281101561232e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603360248201527f4e6f6d6973776170537461626c6545524332303a20646563726561736564206160448201527f6c6c6f77616e63652062656c6f77207a65726f0000000000000000000000000060648201526084016107de565b61120d338561125c86856140a5565b6000610fe3338484613540565b612352613059565b6005546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48917f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec79161245091849186916dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8416906370a08231906024015b602060405180830381865afa15801561241d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612441919061405d565b61244b91906140a5565b6130cc565b6005546040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526124d091839186916e01000000000000000000000000000090046dffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff8416906370a0823190602401612400565b50506124dc6001600455565b50565b6124e7613059565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000818339b4e536e707f14980219037c5046b049dd41614612586576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b600061259061297a565b600780547fffffffffffffffffffffffffffffffffffffffffffffffff00000000000000001663ffffffff83169081176401000000008202177fffffffffffffffffffffffffffff00000000000000000000ffffffffffffffff16680100000000000000004264ffffffffff81169182027fffffffffffffffffffffffffffff0000000000ffffffffffffffffffffffffff16929092176d010000000000000000000000000091909102179092556040805191825260208201929092529192507f46e22fb3709ad289f62ce63d469248536dbc78d82b84a3d7e74ad606dc201938910160405180910390a1506126866001600455565b565b60008060006126e66005546dffffffffffffffffffffffffffff808216926e01000000000000000000000000000083049091169163ffffffff7c01000000000000000000000000000000000000000000000000000000009091041690565b506007546dffffffffffffffffffffffffffff9283169450911691506fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000e8d4a510008116917f000000000000000000000000000000000000000000000000000000e8d4a510009091169060009063ffffffff9061278790720100000000000000000000000000000000000090048216896140bc565b61279563ffffffff8a6140bc565b61279f91906140a5565b6127a99190614128565b905060006127b784876140bc565b905060006127c584876140bc565b905060006127d161297a565b905060006127e084848461315e565b90507f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4873ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361287a57600061284188876140bc565b61284b908661413c565b9050600061285a82848661360f565b90508761286782876140a5565b6128719190614128565b9b50505061296b565b7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff161461292f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f494e56414c49445f494e5055545f544f4b454e0000000000000000000000000060448201526064016107de565b600061293b87876140bc565b612945908561413c565b9050600061295482848661360f565b90508861296182886140a5565b61155d9190614128565b50505050505050505092915050565b6007546000906d0100000000000000000000000000810464ffffffffff1690640100000000900463ffffffff1642821115610fe75760075463ffffffff81169068010000000000000000900464ffffffffff1681831115612a1a576129df81856140a5565b6129e983856140a5565b6129f383426140a5565b6129fd91906140bc565b612a079190614128565b612a11908361413c565b94505050505090565b612a2481856140a5565b612a2e84846140a5565b612a3883426140a5565b612a4291906140bc565b612a4c9190614128565b612a1190836140a5565b42841015612ac0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4e6f6d69737761703a204558504952454400000000000000000000000000000060448201526064016107de565b73ffffffffffffffffffffffffffffffffffffffff8716600090815260036020526040812080547f2abab4249609e699c123826ac59be2ca97b30e5ed633abefb30e60668584a786917f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9918b918b918b9187612b3b836142ed565b9091555060408051602081019690965273ffffffffffffffffffffffffffffffffffffffff94851690860152929091166060840152608083015260a082015260c0810187905260e00160405160208183030381529060405280519060200120604051602001612bdc9291907f190100000000000000000000000000000000000000000000000000000000000081526002810192909252602282015260420190565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120600080855291840180845281905260ff88169284019290925260608301869052608083018590529092509060019060a0016020604051602081039080840390855afa158015612c65573d6000803e3d6000fd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff811615801590612ce057508873ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b612d46576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601b60248201527f4e6f6d69737761703a20494e56414c49445f5349474e4154555245000000000060448201526064016107de565b612d518989896134d1565b505050505050505050565b3373ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000818339b4e536e707f14980219037c5046b049dd41614612dfb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601360248201527f4e6f6d69737761703a20464f5242494444454e0000000000000000000000000060448201526064016107de565b63ffffffff8163ffffffff161115612e95576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f4e6f6d6973776170537461626c65506169723a20464f5242494444454e5f464560448201527f450000000000000000000000000000000000000000000000000000000000000060648201526084016107de565b6007805463ffffffff9092167201000000000000000000000000000000000000027fffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffff909216919091179055565b612eea613059565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015261304f907f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4873ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015612f78573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f9c919061405d565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015613026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061304a919061405d565b61333e565b6126866001600455565b6002600454036130c5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016107de565b6002600455565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb0000000000000000000000000000000000000000000000000000000017905261315990849061399e565b505050565b60008083851061316e5783613170565b845b905060008486106131815785613183565b845b90506000613191828461413c565b9050806000036131a75760009350505050611211565b60006131b48660106140bc565b90506000836131c384846140bc565b6131cd91906140bc565b90506000846131de606460046140bc565b6131e890856140a5565b6131f291906140bc565b9050600084975060005b61010081101561329957889150600088836132188160646140bc565b61322291906140bc565b61322c9190614128565b90508361323a8260036140bc565b613244919061413c565b85826132518d60026140bc565b61325b91906140bc565b613265919061413c565b61326f9190614128565b995061327b8a84613aaa565b156132865750613299565b5080613291816142ed565b9150506131fc565b50505050505050509392505050565b6000806132e76fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000e8d4a5100016866140bc565b905060006133276fffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000e8d4a5100016866140bc565b905061333482828661315e565b9695505050505050565b6dffffffffffffffffffffffffffff821180159061336a57506dffffffffffffffffffffffffffff8111155b6133d0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f4e6f6d69737761703a204f564552464c4f57000000000000000000000000000060448201526064016107de565b60006133e164010000000042614325565b6005805463ffffffff83167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff6dffffffffffffffffffffffffffff8781166e0100000000000000000000000000009081027fffffffff000000000000000000000000000000000000000000000000000000009095168a83161794909417918216831794859055604080519382169282169290921783529290930490911660208201529192507f1c411e9a96e071241c2f21f7726b17ae89e3cab4c78be50e062b03a9fffbbad1910160405180910390a1505050565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600160205260409020546135719082906140a5565b73ffffffffffffffffffffffffffffffffffffffff80851660009081526001602052604080822093909355908416815220546135ae90829061413c565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906135339085815260200190565b8160008061361e8460046140bc565b9050600060048688816136328160646140bc565b61363c91906140bc565b6136469190614128565b61365091906140bc565b61365a9190614128565b90508587038202606487020160005b6101008110156136ac5785945083850261368c81870285016002830285016136b8565b96506136988787613aaa565b156136a357506136ac565b50600101613669565b50505050509392505050565b60008160016136c7828661413c565b6136d191906140a5565b6112119190614128565b60007f000000000000000000000000818339b4e536e707f14980219037c5046b049dd473ffffffffffffffffffffffffffffffffffffffff1663017e7e586040518163ffffffff1660e01b8152600401602060405180830381865afa158015613748573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061376c9190614339565b60065490915073ffffffffffffffffffffffffffffffffffffffff8216158015916fffffffffffffffffffffffffffffffff16906137f1576001811115613159576137c1836137bc6001846140a5565b61382a565b600680547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001179055505050565b600181111561315957600680547fffffffffffffffffffffffffffffffff00000000000000000000000000000000166001179055505050565b80600054613838919061413c565b600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602052604090205461386b90829061413c565b73ffffffffffffffffffffffffffffffffffffffff83166000818152600160205260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906138c99085815260200190565b60405180910390a35050565b60008183106138e45781611211565b5090919050565b73ffffffffffffffffffffffffffffffffffffffff821660009081526001602052604090205461391c9082906140a5565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040812091909155546139519082906140a5565b600090815560405182815273ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906020016138c9565b6000613a00826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16613acc9092919063ffffffff16565b8051909150156131595780806020019051810190613a1e9190614356565b613159576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016107de565b600081831115613ac1575060018183031115610fe7565b506001919003111590565b6060613adb8484600085613ae3565b949350505050565b606082471015613b75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016107de565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051613b9e9190614378565b60006040518083038185875af1925050503d8060008114613bdb576040519150601f19603f3d011682016040523d82523d6000602084013e613be0565b606091505b5091509150613bf187838387613bfc565b979650505050505050565b60608315613c92578251600003613c8b5773ffffffffffffffffffffffffffffffffffffffff85163b613c8b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016107de565b5081613adb565b613adb8383815115613ca75781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107de9190613dc3565b73ffffffffffffffffffffffffffffffffffffffff811681146124dc57600080fd5b600080600080600060808688031215613d1557600080fd5b85359450602086013593506040860135613d2e81613cdb565b9250606086013567ffffffffffffffff80821115613d4b57600080fd5b818801915088601f830112613d5f57600080fd5b813581811115613d6e57600080fd5b896020828501011115613d8057600080fd5b9699959850939650602001949392505050565b60005b83811015613dae578181015183820152602001613d96565b83811115613dbd576000848401525b50505050565b6020815260008251806020840152613de2816040850160208701613d93565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169190910160400192915050565b60008060408385031215613e2757600080fd5b8235613e3281613cdb565b946020939093013593505050565b600060208284031215613e5257600080fd5b81356fffffffffffffffffffffffffffffffff8116811461121157600080fd5b600080600060608486031215613e8757600080fd5b8335613e9281613cdb565b92506020840135613ea281613cdb565b929592945050506040919091013590565b600060208284031215613ec557600080fd5b813561121181613cdb565b803563ffffffff8116811461191557600080fd5b60008060408385031215613ef757600080fd5b613f0083613ed0565b9150602083013564ffffffffff81168114613f1a57600080fd5b809150509250929050565b600080600080600080600060e0888a031215613f4057600080fd5b8735613f4b81613cdb565b96506020880135613f5b81613cdb565b95506040880135945060608801359350608088013560ff81168114613f7f57600080fd5b9699959850939692959460a0840135945060c09093013592915050565b600060208284031215613fae57600080fd5b61121182613ed0565b60008060408385031215613fca57600080fd5b8235613fd581613cdb565b91506020830135613f1a81613cdb565b73ffffffffffffffffffffffffffffffffffffffff8616815284602082015283604082015260806060820152816080820152818360a0830137600081830160a090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0160101949350505050565b60006020828403121561406f57600080fd5b5051919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000828210156140b7576140b7614076565b500390565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156140f4576140f4614076565b500290565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082614137576141376140f9565b500490565b6000821982111561414f5761414f614076565b500190565b60006fffffffffffffffffffffffffffffffff80831681851680830382111561417f5761417f614076565b01949350505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000602082840312156141c957600080fd5b815167ffffffffffffffff808211156141e157600080fd5b818401915084601f8301126141f557600080fd5b81518181111561420757614207614188565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f0116810190838211818310171561424d5761424d614188565b8160405282815287602084870101111561426657600080fd5b613bf1836020830160208801613d93565b60008451614289818460208901613d93565b80830190507f2d0000000000000000000000000000000000000000000000000000000000000080825285516142c5816001850160208a01613d93565b600192019182015283516142e0816002840160208801613d93565b0160020195945050505050565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361431e5761431e614076565b5060010190565b600082614334576143346140f9565b500690565b60006020828403121561434b57600080fd5b815161121181613cdb565b60006020828403121561436857600080fd5b8151801515811461121157600080fd5b6000825161438a818460208701613d93565b919091019291505056fea26469706673582212209c0499a9d8420b24d33a3a218c42e9fca62cc10ba6a9137b9775a622c5d2247264736f6c634300080f0033

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7

-----Decoded View---------------
Arg [0] : _token0 (address): 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48
Arg [1] : _token1 (address): 0xdAC17F958D2ee523a2206206994597C13D831ec7

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7


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.