ETH Price: $3,077.26 (+2.88%)
Gas: 4 Gwei

Contract

0x2786f6C09f7732681B857216c07C424a6e47e12a
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Approve125854812021-06-07 5:14:091128 days ago1623042849IN
0x2786f6C0...a6e47e12a
0 ETH0.0005071311
Approve125353102021-05-30 10:55:421136 days ago1622372142IN
0x2786f6C0...a6e47e12a
0 ETH0.0002455117.00000134
Approve124438712021-05-16 6:19:151150 days ago1621145955IN
0x2786f6C0...a6e47e12a
0 ETH0.0024481752.8
Approve124231222021-05-13 1:42:081153 days ago1620870128IN
0x2786f6C0...a6e47e12a
0 ETH0.0095516206
Approve124077392021-05-10 16:38:001156 days ago1620664680IN
0x2786f6C0...a6e47e12a
0 ETH0.01400283302
Approve124002302021-05-09 12:45:371157 days ago1620564337IN
0x2786f6C0...a6e47e12a
0 ETH0.00533082115
Approve123984992021-05-09 6:11:531157 days ago1620540713IN
0x2786f6C0...a6e47e12a
0 ETH0.0041266689
Approve123885132021-05-07 17:30:121159 days ago1620408612IN
0x2786f6C0...a6e47e12a
0 ETH0.0046367100
Approve123880382021-05-07 15:50:351159 days ago1620402635IN
0x2786f6C0...a6e47e12a
0 ETH0.00528583114
Approve123874742021-05-07 13:40:581159 days ago1620394858IN
0x2786f6C0...a6e47e12a
0 ETH0.0029999464.7000016
Approve123872302021-05-07 12:48:091159 days ago1620391689IN
0x2786f6C0...a6e47e12a
0 ETH0.0028283861
Approve123867702021-05-07 11:03:301159 days ago1620385410IN
0x2786f6C0...a6e47e12a
0 ETH0.0023039550
Approve123864342021-05-07 9:45:241159 days ago1620380724IN
0x2786f6C0...a6e47e12a
0 ETH0.0024574553
Approve123860002021-05-07 8:11:251159 days ago1620375085IN
0x2786f6C0...a6e47e12a
0 ETH0.0028747562
Approve123850612021-05-07 4:31:081159 days ago1620361868IN
0x2786f6C0...a6e47e12a
0 ETH0.0015811134.1
Approve123849222021-05-07 4:02:201159 days ago1620360140IN
0x2786f6C0...a6e47e12a
0 ETH0.0016228235.2
Approve123824842021-05-06 18:55:581159 days ago1620327358IN
0x2786f6C0...a6e47e12a
0 ETH0.0042414792
Approve123820652021-05-06 17:26:271160 days ago1620321987IN
0x2786f6C0...a6e47e12a
0 ETH0.0029505964
Approve123806002021-05-06 11:57:161160 days ago1620302236IN
0x2786f6C0...a6e47e12a
0 ETH0.0022719849
Approve123793062021-05-06 7:04:431160 days ago1620284683IN
0x2786f6C0...a6e47e12a
0 ETH0.0019937843
Approve123791742021-05-06 6:34:421160 days ago1620282882IN
0x2786f6C0...a6e47e12a
0 ETH0.0021328846
Approve123791652021-05-06 6:33:151160 days ago1620282795IN
0x2786f6C0...a6e47e12a
0 ETH0.0017155737
Approve123789432021-05-06 5:36:161160 days ago1620279376IN
0x2786f6C0...a6e47e12a
0 ETH0.0016692136
Approve123788982021-05-06 5:27:051160 days ago1620278825IN
0x2786f6C0...a6e47e12a
0 ETH0.0017619438
Approve123785002021-05-06 4:00:091160 days ago1620273609IN
0x2786f6C0...a6e47e12a
0 ETH0.0016228435
View all transactions

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To Value
123403122021-04-30 6:45:441166 days ago1619765144  Contract Creation0 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
Pool

Compiler Version
v0.7.6+commit.7338295f

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
File 1 of 17 : Pool.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "./libs/complifi/tokens/IERC20Metadata.sol";
import "./libs/complifi/tokens/EIP20NonStandardInterface.sol";
import "./libs/complifi/tokens/TokenMetadataGenerator.sol";

import "./Token.sol";
import "./Math.sol";
import "./repricers/IRepricer.sol";
import "./IDynamicFee.sol";
import "./IVault.sol";

contract Pool is Ownable, Pausable, Bronze, Token, Math, TokenMetadataGenerator {

    struct Record {
        uint leverage;
        uint balance;
    }

    event LOG_SWAP(
        address indexed caller,
        address indexed tokenIn,
        address indexed tokenOut,
        uint256         tokenAmountIn,
        uint256         tokenAmountOut,
        uint256         fee,
        uint256         tokenBalanceIn,
        uint256         tokenBalanceOut,
        uint256         tokenLeverageIn,
        uint256         tokenLeverageOut
    );

    event LOG_JOIN(
        address indexed caller,
        address indexed tokenIn,
        uint256         tokenAmountIn
    );

    event LOG_EXIT(
        address indexed caller,
        address indexed tokenOut,
        uint256         tokenAmountOut
    );

    event LOG_REPRICE(
        uint256         repricingBlock,
        uint256         balancePrimary,
        uint256         balanceComplement,
        uint256         leveragePrimary,
        uint256         leverageComplement,
        uint256         newLeveragePrimary,
        uint256         newLeverageComplement,
        int256          estPricePrimary,
        int256          estPriceComplement,
        int256          liveUnderlingValue
    );

    event LOG_CALL(
        bytes4  indexed sig,
        address indexed caller,
        bytes           data
    ) anonymous;

    modifier _logs_() {
        emit LOG_CALL(msg.sig, msg.sender, msg.data);
        _;
    }

    modifier _lock_() {
        requireLock();
        _mutex = true;
        _;
        _mutex = false;
    }

    modifier _viewlock_() {
        requireLock();
        _;
    }

    modifier onlyFinalized() {
        require(_finalized, "NOT_FINALIZED");
        _;
    }

    modifier onlyLiveDerivative() {
        require(
            block.timestamp < derivativeVault.settleTime(),
            "SETTLED"
        );
        _;
    }

    function requireLock() internal view
    {
        require(!_mutex, "REENTRY");
    }

    bool private _mutex;

    address private controller; // has CONTROL role

    // `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
    bool private _finalized;

    uint public constant BOUND_TOKENS  = 2;
    address[BOUND_TOKENS] private _tokens;
    mapping(address => Record) internal _records;

    uint public repricingBlock;

    uint public baseFee;
    uint public feeAmp;
    uint public maxFee;

    uint public pMin;
    uint public qMin;
    uint public exposureLimit;
    uint public volatility;

    IVault public derivativeVault;
    IDynamicFee public dynamicFee;
    IRepricer public repricer;

    constructor(
        address _derivativeVault,
        address _dynamicFee,
        address _repricer,
        uint _baseFee,
        uint _maxFee,
        uint _feeAmp,
        address _controller
    )
        public
    {
        require(_derivativeVault != address(0), "NOT_D_VAULT");
        derivativeVault = IVault(_derivativeVault);

        require(_dynamicFee != address(0), "NOT_FEE");
        dynamicFee = IDynamicFee(_dynamicFee);

        require(_repricer != address(0), "NOT_REPRICER");
        repricer = IRepricer(_repricer);

        baseFee = _baseFee;
        feeAmp = _feeAmp;
        maxFee = _maxFee;

        require(_controller != address(0), "NOT_CONTROLLER");
        controller = _controller;

        string memory settlementDate = formatDate(derivativeVault.settleTime());

        setName(makeTokenName(derivativeVault.derivativeSpecification().name(), settlementDate, " LP"));
        setSymbol(makeTokenSymbol(derivativeVault.derivativeSpecification().symbol(), settlementDate, "-LP"));
    }

    function pause() external onlyOwner
    {
        _pause();
    }
    function unpause() external onlyOwner
    {
        _unpause();
    }

    function isFinalized()
        external view
        returns (bool)
    {
        return _finalized;
    }

    function getTokens()
        external view _viewlock_
        returns (address[BOUND_TOKENS] memory tokens)
    {
        return _tokens;
    }

    function getLeverage(address token)
        external view
        _viewlock_
        returns (uint)
    {

        return _records[token].leverage;
    }

    function getBalance(address token)
        external view
        _viewlock_
        returns (uint)
    {

        return _records[token].balance;
    }

    function finalize(
        uint _primaryBalance,
        uint _primaryLeverage,
        uint _complementBalance,
        uint _complementLeverage,
        uint _exposureLimit,
        uint _volatility,
        uint _pMin,
        uint _qMin
    )
        external
        _logs_
        _lock_
        onlyLiveDerivative
    {
        require(!_finalized, "IS_FINALIZED");
        require(msg.sender == controller, "NOT_CONTROLLER");

        require(_primaryBalance == _complementBalance, "NOT_SYMMETRIC");

        pMin = _pMin;
        qMin = _qMin;
        exposureLimit = _exposureLimit;
        volatility = _volatility;

        _finalized = true;

        bind(0, address(derivativeVault.primaryToken()), _primaryBalance, _primaryLeverage);
        bind(1, address(derivativeVault.complementToken()), _complementBalance, _complementLeverage);

        uint initPoolSupply = getDerivativeDenomination() * _primaryBalance;

        uint collateralDecimals = uint(IERC20Metadata(address(derivativeVault.collateralToken())).decimals());
        if(collateralDecimals >= 0 && collateralDecimals < 18) {
            initPoolSupply = initPoolSupply * (10 ** (18 - collateralDecimals));
        }

        _mintPoolShare(initPoolSupply);
        _pushPoolShare(msg.sender, initPoolSupply);
    }

    function bind(uint index, address token, uint balance, uint leverage)
    internal
    {
        require(balance >= qMin, "MIN_BALANCE");
        require(leverage > 0, "ZERO_LEVERAGE");

        _records[token] = Record({
            leverage: leverage,
            balance: balance
        });

        _tokens[index] = token;

        _pullUnderlying(token, msg.sender, balance);
    }

    function joinPool(uint poolAmountOut, uint[2] calldata maxAmountsIn)
        external
        _logs_
        _lock_
        onlyFinalized
    {

        uint poolTotal = totalSupply();
        uint ratio = div(poolAmountOut, poolTotal);
        require(ratio != 0, "MATH_APPROX");

        for (uint i = 0; i < BOUND_TOKENS; i++) {
            address token = _tokens[i];
            uint bal = _records[token].balance;
            require(bal > 0, "NO_BALANCE");
            uint tokenAmountIn = mul(ratio, bal);
            require(tokenAmountIn <= maxAmountsIn[i], "LIMIT_IN");
            _records[token].balance = add(_records[token].balance, tokenAmountIn);
            emit LOG_JOIN(msg.sender, token, tokenAmountIn);
            _pullUnderlying(token, msg.sender, tokenAmountIn);
        }

        _mintPoolShare(poolAmountOut);
        _pushPoolShare(msg.sender, poolAmountOut);
    }

    function exitPool(uint poolAmountIn, uint[2] calldata minAmountsOut)
        external
        _logs_
        _lock_
        onlyFinalized
    {

        uint poolTotal = totalSupply();
        uint ratio = div(poolAmountIn, poolTotal);
        require(ratio != 0, "MATH_APPROX");

        _pullPoolShare(msg.sender, poolAmountIn);
        _burnPoolShare(poolAmountIn);

        for (uint i = 0; i < BOUND_TOKENS; i++) {
            address token = _tokens[i];
            uint bal = _records[token].balance;
            require(bal > 0, "NO_BALANCE");
            uint tokenAmountOut = mul(ratio, bal);
            require(tokenAmountOut >= minAmountsOut[i], "LIMIT_OUT");
            _records[token].balance = sub(_records[token].balance, tokenAmountOut);
            emit LOG_EXIT(msg.sender, token, tokenAmountOut);
            _pushUnderlying(token, msg.sender, tokenAmountOut);
        }
    }

    function reprice()
        internal virtual
    {
        if(repricingBlock == block.number) return;
        repricingBlock = block.number;

        Record storage primaryRecord = _records[_getPrimaryDerivativeAddress()];
        Record storage complementRecord = _records[_getComplementDerivativeAddress()];

        uint256[2] memory primaryParams = [primaryRecord.balance, primaryRecord.leverage];
        uint256[2] memory complementParams = [complementRecord.balance, complementRecord.leverage];

        (
            uint newPrimaryLeverage,
            uint newComplementLeverage,
            int estPricePrimary,
            int estPriceComplement
        ) = repricer.reprice(
            pMin,
            int(volatility),
            derivativeVault,
            primaryParams,
            complementParams,
            derivativeVault.underlyingStarts(0)
        );

        emit LOG_REPRICE(
            repricingBlock,
            primaryParams[0],
            complementParams[0],
            primaryParams[1],
            complementParams[1],
            newPrimaryLeverage,
            newComplementLeverage,
            estPricePrimary,
            estPriceComplement,
            derivativeVault.underlyingStarts(0)
        );

        primaryRecord.leverage = newPrimaryLeverage;
        complementRecord.leverage = newComplementLeverage;
    }

    function calcFee(
        Record memory inRecord,
        uint tokenAmountIn,
        Record memory outRecord,
        uint tokenAmountOut
    )
    internal
    returns (uint fee, int expStart)
    {
        int ifee;
        (ifee, expStart) = dynamicFee.calc(
            [int(inRecord.balance), int(inRecord.leverage), int(tokenAmountIn)],
            [int(outRecord.balance), int(outRecord.leverage), int(tokenAmountOut)],
            int(baseFee),
            int(feeAmp),
            int(maxFee)
        );
        require(ifee > 0, "BAD_FEE");
        fee = uint(ifee);
    }

    function calcExpStart(
        int _inBalance,
        int _outBalance
    )
    internal pure
    returns(int) {
        return (_inBalance - _outBalance) * iBONE / (_inBalance + _outBalance);
    }

    function performSwap(
        address tokenIn,
        uint tokenAmountIn,
        address tokenOut,
        uint tokenAmountOut,
        uint spotPriceBefore,
        uint fee
    )
    internal returns(uint spotPriceAfter)
    {
        Record storage inRecord = _records[tokenIn];
        Record storage outRecord = _records[tokenOut];

        requireBoundaryConditions(inRecord, tokenAmountIn, outRecord, tokenAmountOut);

        updateLeverages(inRecord, tokenAmountIn, outRecord, tokenAmountOut);

        inRecord.balance = add(inRecord.balance, tokenAmountIn);
        outRecord.balance = sub(outRecord.balance, tokenAmountOut);

        spotPriceAfter = calcSpotPrice(
            getLeveragedBalance(inRecord),
            getLeveragedBalance(outRecord),
            dynamicFee.calcSpotFee(
                calcExpStart(
                    int(inRecord.balance),
                    int(outRecord.balance)
                ),
                baseFee,
                feeAmp,
                maxFee
            )
        );

        require(spotPriceAfter >= spotPriceBefore, "MATH_APPROX");
        require(spotPriceBefore <= div(tokenAmountIn, tokenAmountOut), "MATH_APPROX_OTHER");

        emit LOG_SWAP(
            msg.sender,
            tokenIn,
            tokenOut,
            tokenAmountIn,
            tokenAmountOut,
            fee,
            inRecord.balance,
            outRecord.balance,
            inRecord.leverage,
            outRecord.leverage
        );

        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
    }

    function swapExactAmountIn(
        address tokenIn,
        uint tokenAmountIn,
        address tokenOut,
        uint minAmountOut
    )
        external
        _logs_
        _lock_
        whenNotPaused
        onlyFinalized
        onlyLiveDerivative
        returns (uint tokenAmountOut, uint spotPriceAfter)
    {

        require(tokenIn != tokenOut, "SAME_TOKEN");
        require(tokenAmountIn >= qMin, "MIN_TOKEN_IN");

        reprice();

        Record memory inRecord = _records[tokenIn];
        Record memory outRecord = _records[tokenOut];

        require(tokenAmountIn <= mul(min(getLeveragedBalance(inRecord), inRecord.balance), MAX_IN_RATIO), "MAX_IN_RATIO");

        tokenAmountOut = calcOutGivenIn(
            getLeveragedBalance(inRecord),
            getLeveragedBalance(outRecord),
            tokenAmountIn,
            0
        );

        uint fee;
        int expStart;
        (fee, expStart) = calcFee(
            inRecord,
            tokenAmountIn,
            outRecord,
            tokenAmountOut
        );

        uint spotPriceBefore = calcSpotPrice(
                                    getLeveragedBalance(inRecord),
                                    getLeveragedBalance(outRecord),
                                    dynamicFee.calcSpotFee(expStart, baseFee, feeAmp, maxFee)
                                );

        tokenAmountOut = calcOutGivenIn(
                            getLeveragedBalance(inRecord),
                            getLeveragedBalance(outRecord),
                            tokenAmountIn,
                            fee
                        );
        require(tokenAmountOut >= minAmountOut, "LIMIT_OUT");

        spotPriceAfter = performSwap(
            tokenIn,
            tokenAmountIn,
            tokenOut,
            tokenAmountOut,
            spotPriceBefore,
            fee
        );
    }

    // Method temporary is not available for external usage.
    function swapExactAmountOut(
        address tokenIn,
        uint maxAmountIn,
        address tokenOut,
        uint tokenAmountOut
    )
        private
        _logs_
        _lock_
        whenNotPaused
        onlyFinalized
        onlyLiveDerivative
        returns (uint tokenAmountIn, uint spotPriceAfter)
    {
        require(tokenIn != tokenOut, "SAME_TOKEN");
        require(tokenAmountOut >= qMin, "MIN_TOKEN_OUT");

        reprice();

        Record memory inRecord = _records[tokenIn];
        Record memory outRecord = _records[tokenOut];

        require(tokenAmountOut <= mul(min(getLeveragedBalance(outRecord), outRecord.balance), MAX_OUT_RATIO), "MAX_OUT_RATIO");

        tokenAmountIn = calcInGivenOut(
            getLeveragedBalance(inRecord),
            getLeveragedBalance(outRecord),
            tokenAmountOut,
            0
        );

        uint fee;
        int expStart;
        (fee, expStart) = calcFee(
            inRecord,
            tokenAmountIn,
            outRecord,
            tokenAmountOut
        );

        uint spotPriceBefore = calcSpotPrice(
                                    getLeveragedBalance(inRecord),
                                    getLeveragedBalance(outRecord),
                                    dynamicFee.calcSpotFee(expStart, baseFee, feeAmp, maxFee)
                                );

        tokenAmountIn = calcInGivenOut(
                            getLeveragedBalance(inRecord),
                            getLeveragedBalance(outRecord),
                            tokenAmountOut,
                            fee
                        );

        require(tokenAmountIn <= maxAmountIn, "LIMIT_IN");

        spotPriceAfter = performSwap(
            tokenIn,
            tokenAmountIn,
            tokenOut,
            tokenAmountOut,
            spotPriceBefore,
            fee
        );
    }

    function getLeveragedBalance(
        Record memory r
    )
    internal pure
    returns(uint)
    {
        return mul(r.balance, r.leverage);
    }

    function requireBoundaryConditions(
        Record storage inToken,
        uint tokenAmountIn,
        Record storage outToken,
        uint tokenAmountOut
    )
    internal view
    {

        require( sub(getLeveragedBalance(outToken), tokenAmountOut) > qMin, "BOUNDARY_LEVERAGED");
        require( sub(outToken.balance, tokenAmountOut) > qMin, "BOUNDARY_NON_LEVERAGED");

        uint denomination = getDerivativeDenomination() * BONE;
        uint lowerBound = div(pMin, sub(denomination, pMin));
        uint upperBound = div(sub(denomination, pMin), pMin);
        uint value = div(add(getLeveragedBalance(inToken), tokenAmountIn), sub(getLeveragedBalance(outToken), tokenAmountOut));

        require(lowerBound < value, "BOUNDARY_LOWER");
        require(value < upperBound, "BOUNDARY_UPPER");

        uint numerator;
        (numerator,) = subSign(add(add(inToken.balance, tokenAmountIn), tokenAmountOut), outToken.balance);

        uint denominator = sub(add(add(inToken.balance, tokenAmountIn), outToken.balance), tokenAmountOut);
        require(div(numerator, denominator) < exposureLimit, "BOUNDARY_EXPOSURE");
    }

    function updateLeverages(
        Record storage inToken,
        uint tokenAmountIn,
        Record storage outToken,
        uint tokenAmountOut
    )
    internal
    {
        outToken.leverage = div(
            sub(getLeveragedBalance(outToken), tokenAmountOut),
            sub(outToken.balance, tokenAmountOut)
        );
        require(outToken.leverage > 0, "ZERO_OUT_LEVERAGE");

        inToken.leverage = div(
            add(getLeveragedBalance(inToken), tokenAmountIn),
            add(inToken.balance, tokenAmountIn)
        );
        require(inToken.leverage > 0, "ZERO_IN_LEVERAGE");
    }

    function getDerivativeDenomination()
    internal view
    returns(uint denomination)
    {
        denomination =
            derivativeVault.derivativeSpecification().primaryNominalValue() +
            derivativeVault.derivativeSpecification().complementNominalValue();
    }

    function _getPrimaryDerivativeAddress()
    internal view
    returns(address)
    {
        return _tokens[0];
    }

    function _getComplementDerivativeAddress()
    internal view
    returns(address)
    {
        return _tokens[1];
    }

    // ==
    // 'Underlying' token-manipulation functions make external calls but are NOT locked
    // You must `_lock_` or otherwise ensure reentry-safety

    function _pullPoolShare(address from, uint amount)
        internal
    {
        _pull(from, amount);
    }

    function _pushPoolShare(address to, uint amount)
        internal
    {
        _push(to, amount);
    }

    function _mintPoolShare(uint amount)
        internal
    {
        _mint(amount);
    }

    function _burnPoolShare(uint amount)
        internal
    {
        _burn(amount);
    }

    /// @dev Similar to EIP20 transfer, except it handles a False result from `transferFrom` and reverts in that case.
    /// This will revert due to insufficient balance or insufficient allowance.
    /// This function returns the actual amount received,
    /// which may be less than `amount` if there is a fee attached to the transfer.
    /// @notice This wrapper safely handles non-standard ERC-20 tokens that do not return a value.
    /// See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
    function _pullUnderlying(address erc20, address from, uint256 amount)
    internal
    returns (uint256)
    {
        uint256 balanceBefore = IERC20(erc20).balanceOf(address(this));
        EIP20NonStandardInterface(erc20).transferFrom(
            from,
            address(this),
            amount
        );

        bool success;
        assembly {
            switch returndatasize()
            case 0 {
            // This is a non-standard ERC-20
                success := not(0) // set success to true
            }
            case 32 {
            // This is a compliant ERC-20
                returndatacopy(0, 0, 32)
                success := mload(0) // Set `success = returndata` of external call
            }
            default {
            // This is an excessively non-compliant ERC-20, revert.
                revert(0, 0)
            }
        }
        require(success, "TOKEN_TRANSFER_IN_FAILED");

        // Calculate the amount that was *actually* transferred
        uint256 balanceAfter = IERC20(erc20).balanceOf(address(this));
        require(balanceAfter >= balanceBefore, "TOKEN_TRANSFER_IN_OVERFLOW");
        return balanceAfter - balanceBefore; // underflow already checked above, just subtract
    }

    /// @dev Similar to EIP20 transfer, except it handles a False success from `transfer` and returns an explanatory
    /// error code rather than reverting. If caller has not called checked protocol's balance, this may revert due to
    /// insufficient cash held in this contract. If caller has checked protocol's balance prior to this call, and verified
    /// it is >= amount, this should not revert in normal conditions.
    /// @notice This wrapper safely handles non-standard ERC-20 tokens that do not return a value.
    /// See here: https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
    function _pushUnderlying(address erc20, address to, uint256 amount) internal {
        EIP20NonStandardInterface(erc20).transfer(
            to,
            amount
        );

        bool success;
        assembly {
            switch returndatasize()
            case 0 {
            // This is a non-standard ERC-20
                success := not(0) // set success to true
            }
            case 32 {
            // This is a complaint ERC-20
                returndatacopy(0, 0, 32)
                success := mload(0) // Set `success = returndata` of external call
            }
            default {
            // This is an excessively non-compliant ERC-20, revert.
                revert(0, 0)
            }
        }
        require(success, "TOKEN_TRANSFER_OUT_FAILED");
    }
}

File 2 of 17 : Color.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

abstract contract Color {
    function getColor()
        external view virtual
        returns (bytes32);
}

contract Bronze is Color {
    function getColor()
        external view override
        returns (bytes32) {
            return bytes32("BRONZE");
        }
}

File 3 of 17 : Const.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Color.sol";

contract Const is Bronze {
    uint public constant BONE              = 10**18;
    int public constant  iBONE             = int(BONE);

    uint public constant MIN_POW_BASE      = 1 wei;
    uint public constant MAX_POW_BASE      = (2 * BONE) - 1 wei;
    uint public constant POW_PRECISION     = BONE / 10**10;

    uint public constant MAX_IN_RATIO      = BONE / 2;
    uint public constant MAX_OUT_RATIO     = (BONE / 3) + 1 wei;
}

File 4 of 17 : IDynamicFee.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;
pragma experimental ABIEncoderV2;

interface IDynamicFee {

    function calc(
        int[3] calldata _inRecord,
        int[3] calldata _outRecord,
        int _baseFee,
        int _feeAmp,
        int _maxFee
    )
    external
    returns(int fee, int expStart);

    function calcSpotFee(
        int _expStart,
        uint _baseFee,
        uint _feeAmp,
        uint _maxFee
    )
    external
    returns(uint);
}

File 5 of 17 : IVault.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

import "./libs/complifi/IDerivativeSpecification.sol";

/// @title Derivative implementation Vault
/// @notice A smart contract that references derivative specification and enables users to mint and redeem the derivative
interface IVault {
    enum State { Created, Live, Settled }

    /// @notice start of live period
    function liveTime() external view returns (uint256);

    /// @notice end of live period
    function settleTime() external view returns (uint256);

    /// @notice redeem function can only be called after the end of the Live period + delay
    function settlementDelay() external view returns (uint256);

    /// @notice underlying value at the start of live period
    function underlyingStarts(uint256 index) external view returns (int256);

    /// @notice underlying value at the end of live period
    function underlyingEnds(uint256 index) external view returns (int256);

    /// @notice primary token conversion rate multiplied by 10 ^ 12
    function primaryConversion() external view returns (uint256);

    /// @notice complement token conversion rate multiplied by 10 ^ 12
    function complementConversion() external view returns (uint256);

    /// @notice protocol fee multiplied by 10 ^ 12
    function protocolFee() external view returns (uint256);

    /// @notice limit on author fee multiplied by 10 ^ 12
    function authorFeeLimit() external view returns (uint256);

    // @notice protocol's fee receiving wallet
    function feeWallet() external view returns (address);

    // @notice current state of the vault
    function state() external view returns (State);

    // @notice derivative specification address
    function derivativeSpecification()
        external
        view
        returns (IDerivativeSpecification);

    // @notice collateral token address
    function collateralToken() external view returns (address);

    // @notice oracle address
    function oracles(uint256 index) external view returns (address);

    function oracleIterators(uint256 index) external view returns (address);

    // @notice collateral split address
    function collateralSplit() external view returns (address);

    // @notice derivative's token builder strategy address
    function tokenBuilder() external view returns (address);

    function feeLogger() external view returns (address);

    // @notice primary token address
    function primaryToken() external view returns (address);

    // @notice complement token address
    function complementToken() external view returns (address);

    /// @notice Switch to Settled state if appropriate time threshold is passed and
    /// set underlyingStarts value and set underlyingEnds value,
    /// calculate primaryConversion and complementConversion params
    /// @dev Reverts if underlyingStart or underlyingEnd are not available
    /// Vault cannot settle when it paused
    function settle(uint256[] calldata _underlyingEndRoundHints) external;

    function mintTo(address _recipient, uint256 _collateralAmount) external;

    /// @notice Mints primary and complement derivative tokens
    /// @dev Checks and switches to the right state and does nothing if vault is not in Live state
    function mint(uint256 _collateralAmount) external;

    /// @notice Refund equal amounts of derivative tokens for collateral at any time
    function refund(uint256 _tokenAmount) external;

    function refundTo(address _recipient, uint256 _tokenAmount) external;

    function redeemTo(
        address _recipient,
        uint256 _primaryTokenAmount,
        uint256 _complementTokenAmount,
        uint256[] calldata _underlyingEndRoundHints
    ) external;

    /// @notice Redeems unequal amounts previously calculated conversions if the vault is in Settled state
    function redeem(
        uint256 _primaryTokenAmount,
        uint256 _complementTokenAmount,
        uint256[] calldata _underlyingEndRoundHints
    ) external;
}

File 6 of 17 : Math.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Num.sol";

contract Math is Bronze, Const, Num {
    /**********************************************************************************************
    // calcSpotPrice                                                                             //
    // sP = spotPrice                                                                            //
    // bI = tokenBalanceIn                 bI          1                                         //
    // bO = tokenBalanceOut         sP =  ----  *  ----------                                    //
    // sF = swapFee                        bO      ( 1 - sF )                                    //
    **********************************************************************************************/
    function calcSpotPrice(
        uint tokenBalanceIn,
        uint tokenBalanceOut,
        uint swapFee
    )
        public pure
        returns (uint spotPrice)
    {
        uint ratio = div(tokenBalanceIn, tokenBalanceOut);
        uint scale = div(BONE, sub(BONE, swapFee));
        spotPrice = mul(ratio, scale);
    }

    /**********************************************************************************************
    // calcOutGivenIn                                                                            //
    // aO = tokenAmountOut                                                                       //
    // bO = tokenBalanceOut                                                                      //
    // bI = tokenBalanceIn              /      /            bI             \   \                 //
    // aI = tokenAmountIn    aO = bO * |  1 - | --------------------------  |  |                 //
    // sF = swapFee                     \      \ ( bI + ( aI * ( 1 - sF )) /   /                 //
    **********************************************************************************************/
    function calcOutGivenIn(
        uint tokenBalanceIn,
        uint tokenBalanceOut,
        uint tokenAmountIn,
        uint swapFee
    )
        public pure
        returns (uint tokenAmountOut)
    {
        uint adjustedIn = sub(BONE, swapFee);
        adjustedIn = mul(tokenAmountIn, adjustedIn);
        uint y = div(tokenBalanceIn, add(tokenBalanceIn, adjustedIn));
        uint bar = sub(BONE, y);
        tokenAmountOut = mul(tokenBalanceOut, bar);
    }

    /**********************************************************************************************
    // calcInGivenOut                                                                            //
    // aI = tokenAmountIn                                                                        //
    // bO = tokenBalanceOut               /  /     bO      \       \                             //
    // bI = tokenBalanceIn          bI * |  | ------------  | - 1  |                             //
    // aO = tokenAmountOut    aI =        \  \ ( bO - aO ) /       /                             //
    // sF = swapFee                 --------------------------------                             //
    //                                              ( 1 - sF )                                   //
    **********************************************************************************************/
    function calcInGivenOut(
        uint tokenBalanceIn,
        uint tokenBalanceOut,
        uint tokenAmountOut,
        uint swapFee
    )
        public pure
        returns (uint tokenAmountIn)
    {
        uint diff = sub(tokenBalanceOut, tokenAmountOut);
        uint y = div(tokenBalanceOut, diff);
        uint foo = sub(y, BONE);
        tokenAmountIn = sub(BONE, swapFee);
        tokenAmountIn = div(mul(tokenBalanceIn, foo), tokenAmountIn);
    }
}

File 7 of 17 : Num.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Const.sol";

contract Num is Const {

    function toi(uint a)
        internal pure
        returns (uint)
    {
        return a / BONE;
    }

    function floor(uint a)
        internal pure
        returns (uint)
    {
        return toi(a) * BONE;
    }

    function add(uint a, uint b)
        internal pure
        returns (uint c)
    {
        c = a + b;
        require(c >= a, "ADD_OVERFLOW");
    }

    function sub(uint a, uint b)
        internal pure
        returns (uint c)
    {
        bool flag;
        (c, flag) = subSign(a, b);
        require(!flag, "SUB_UNDERFLOW");
    }

    function subSign(uint a, uint b)
        internal pure
        returns (uint, bool)
    {
        if (a >= b) {
            return (a - b, false);
        } else {
            return (b - a, true);
        }
    }

    function mul(uint a, uint b)
        internal pure
        returns (uint c)
    {
        uint c0 = a * b;
        require(a == 0 || c0 / a == b, "MUL_OVERFLOW");
        uint c1 = c0 + (BONE / 2);
        require(c1 >= c0, "MUL_OVERFLOW");
        c = c1 / BONE;
    }

    function div(uint a, uint b)
        internal pure
        returns (uint c)
    {
        require(b != 0, "DIV_ZERO");
        uint c0 = a * BONE;
        require(a == 0 || c0 / a == BONE, "DIV_INTERNAL"); // mul overflow
        uint c1 = c0 + (b / 2);
        require(c1 >= c0, "DIV_INTERNAL"); //  add require
        c = c1 / b;
    }

    // DSMath.wpow
    function powi(uint a, uint n)
        internal pure
        returns (uint z)
    {
        z = n % 2 != 0 ? a : BONE;

        for (n /= 2; n != 0; n /= 2) {
            a = mul(a, a);

            if (n % 2 != 0) {
                z = mul(z, a);
            }
        }
    }

    // Compute b^(e.w) by splitting it into (b^e)*(b^0.w).
    // Use `powi` for `b^e` and `powK` for k iterations
    // of approximation of b^0.w
    function pow(uint base, uint exp)
        internal pure
        returns (uint)
    {
        require(base >= MIN_POW_BASE, "POW_BASE_TOO_LOW");
        require(base <= MAX_POW_BASE, "POW_BASE_TOO_HIGH");

        uint whole  = floor(exp);
        uint remain = sub(exp, whole);

        uint wholePow = powi(base, toi(whole));

        if (remain == 0) {
            return wholePow;
        }

        uint partialResult = powApprox(base, remain, POW_PRECISION);
        return mul(wholePow, partialResult);
    }

    function powApprox(uint base, uint exp, uint precision)
        internal pure
        returns (uint sum)
    {
        // term 0:
        uint a     = exp;
        (uint x, bool xneg)  = subSign(base, BONE);
        uint term = BONE;
        sum   = term;
        bool negative = false;


        // term(k) = numer / denom
        //         = (product(a - i - 1, i=1-->k) * x^k) / (k!)
        // each iteration, multiply previous term by (a-(k-1)) * x / k
        // continue until term is less than precision
        for (uint i = 1; term >= precision; i++) {
            uint bigK = i * BONE;
            (uint c, bool cneg) = subSign(a, sub(bigK, BONE));
            term = mul(term, mul(c, x));
            term = div(term, bigK);
            if (term == 0) break;

            if (xneg) negative = !negative;
            if (cneg) negative = !negative;
            if (negative) {
                sum = sub(sum, term);
            } else {
                sum = add(sum, term);
            }
        }
    }

    function min(uint first, uint second)
        internal pure
        returns (uint)
    {
        if(first < second) {
            return first;
        }
        return second;
    }
}

File 8 of 17 : Token.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

pragma solidity 0.7.6;

import "./Num.sol";

// Highly opinionated token implementation

interface IERC20 {

    function totalSupply() external view returns (uint);
    function balanceOf(address whom) external view returns (uint);
    function allowance(address src, address dst) external view returns (uint);

    function approve(address dst, uint amt) external returns (bool);
    function transfer(address dst, uint amt) external returns (bool);
    function transferFrom(
        address src, address dst, uint amt
    ) external returns (bool);
}

contract TokenBase is Num {

    mapping(address => uint)                   internal _balance;
    mapping(address => mapping(address=>uint)) internal _allowance;
    uint internal _totalSupply;

    event Approval(address indexed src, address indexed dst, uint amt);
    event Transfer(address indexed src, address indexed dst, uint amt);

    function _mint(uint amt) internal {
        _balance[address(this)] = add(_balance[address(this)], amt);
        _totalSupply = add(_totalSupply, amt);
        emit Transfer(address(0), address(this), amt);
    }

    function _burn(uint amt) internal {
        require(_balance[address(this)] >= amt, "INSUFFICIENT_BAL");
        _balance[address(this)] = sub(_balance[address(this)], amt);
        _totalSupply = sub(_totalSupply, amt);
        emit Transfer(address(this), address(0), amt);
    }

    function _move(address src, address dst, uint amt) internal {
        require(_balance[src] >= amt, "INSUFFICIENT_BAL");
        _balance[src] = sub(_balance[src], amt);
        _balance[dst] = add(_balance[dst], amt);
        emit Transfer(src, dst, amt);
    }

    function _push(address to, uint amt) internal {
        _move(address(this), to, amt);
    }

    function _pull(address from, uint amt) internal {
        _move(from, address(this), amt);
    }
}

contract Token is TokenBase, IERC20 {

    string  private _name;
    string  private _symbol;
    uint8   private constant _decimals = 18;

    function setName(string memory name) internal {
        _name = name;
    }

    function setSymbol(string memory symbol) internal {
        _symbol = symbol;
    }

    function name() public view returns (string memory) {
        return _name;
    }

    function symbol() public view returns (string memory) {
        return _symbol;
    }

    function decimals() public view returns(uint8) {
        return _decimals;
    }

    function allowance(address src, address dst) external view override returns (uint) {
        return _allowance[src][dst];
    }

    function balanceOf(address whom) external view override returns (uint) {
        return _balance[whom];
    }

    function totalSupply() public view override returns (uint) {
        return _totalSupply;
    }

    function approve(address dst, uint amt) external override returns (bool) {
        _allowance[msg.sender][dst] = amt;
        emit Approval(msg.sender, dst, amt);
        return true;
    }

    function increaseApproval(address dst, uint amt) external returns (bool) {
        _allowance[msg.sender][dst] = add(_allowance[msg.sender][dst], amt);
        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
        return true;
    }

    function decreaseApproval(address dst, uint amt) external returns (bool) {
        uint oldValue = _allowance[msg.sender][dst];
        if (amt > oldValue) {
            _allowance[msg.sender][dst] = 0;
        } else {
            _allowance[msg.sender][dst] = sub(oldValue, amt);
        }
        emit Approval(msg.sender, dst, _allowance[msg.sender][dst]);
        return true;
    }

    function transfer(address dst, uint amt) external override returns (bool) {
        _move(msg.sender, dst, amt);
        return true;
    }

    function transferFrom(address src, address dst, uint amt) external override returns (bool) {
        uint oldValue = _allowance[src][msg.sender];
        require(msg.sender == src || amt <= oldValue, "TOKEN_BAD_CALLER");
        _move(src, dst, amt);
        if (msg.sender != src && oldValue != uint256(-1)) {
            _allowance[src][msg.sender] = sub(oldValue, amt);
            emit Approval(msg.sender, dst, _allowance[src][msg.sender]);
        }
        return true;
    }
}

File 9 of 17 : IDerivativeSpecification.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

/// @title Derivative Specification interface
/// @notice Immutable collection of derivative attributes
/// @dev Created by the derivative's author and published to the DerivativeSpecificationRegistry
interface IDerivativeSpecification {
    /// @notice Proof of a derivative specification
    /// @dev Verifies that contract is a derivative specification
    /// @return true if contract is a derivative specification
    function isDerivativeSpecification() external pure returns (bool);

    /// @notice Set of oracles that are relied upon to measure changes in the state of the world
    /// between the start and the end of the Live period
    /// @dev Should be resolved through OracleRegistry contract
    /// @return oracle symbols
    function oracleSymbols() external view returns (bytes32[] memory);

    /// @notice Algorithm that, for the type of oracle used by the derivative,
    /// finds the value closest to a given timestamp
    /// @dev Should be resolved through OracleIteratorRegistry contract
    /// @return oracle iterator symbols
    function oracleIteratorSymbols() external view returns (bytes32[] memory);

    /// @notice Type of collateral that users submit to mint the derivative
    /// @dev Should be resolved through CollateralTokenRegistry contract
    /// @return collateral token symbol
    function collateralTokenSymbol() external view returns (bytes32);

    /// @notice Mapping from the change in the underlying variable (as defined by the oracle)
    /// and the initial collateral split to the final collateral split
    /// @dev Should be resolved through CollateralSplitRegistry contract
    /// @return collateral split symbol
    function collateralSplitSymbol() external view returns (bytes32);

    /// @notice Lifecycle parameter that define the length of the derivative's Live period.
    /// @dev Set in seconds
    /// @return live period value
    function livePeriod() external view returns (uint256);

    /// @notice Parameter that determines starting nominal value of primary asset
    /// @dev Units of collateral theoretically swappable for 1 unit of primary asset
    /// @return primary nominal value
    function primaryNominalValue() external view returns (uint256);

    /// @notice Parameter that determines starting nominal value of complement asset
    /// @dev Units of collateral theoretically swappable for 1 unit of complement asset
    /// @return complement nominal value
    function complementNominalValue() external view returns (uint256);

    /// @notice Minting fee rate due to the author of the derivative specification.
    /// @dev Percentage fee multiplied by 10 ^ 12
    /// @return author fee
    function authorFee() external view returns (uint256);

    /// @notice Symbol of the derivative
    /// @dev Should be resolved through DerivativeSpecificationRegistry contract
    /// @return derivative specification symbol
    function symbol() external view returns (string memory);

    /// @notice Return optional long name of the derivative
    /// @dev Isn't used directly in the protocol
    /// @return long name
    function name() external view returns (string memory);

    /// @notice Optional URI to the derivative specs
    /// @dev Isn't used directly in the protocol
    /// @return URI to the derivative specs
    function baseURI() external view returns (string memory);

    /// @notice Derivative spec author
    /// @dev Used to set and receive author's fee
    /// @return address of the author
    function author() external view returns (address);
}

File 10 of 17 : BokkyPooBahsDateTimeLibrary.sol
pragma solidity ^0.7.0;

// ----------------------------------------------------------------------------
// BokkyPooBah's DateTime Library v1.01
//
// A gas-efficient Solidity date and time library
//
// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary
//
// Tested date range 1970/01/01 to 2345/12/31
//
// Conventions:
// Unit      | Range         | Notes
// :-------- |:-------------:|:-----
// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC
// year      | 1970 ... 2345 |
// month     | 1 ... 12      |
// day       | 1 ... 31      |
// hour      | 0 ... 23      |
// minute    | 0 ... 59      |
// second    | 0 ... 59      |
// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday
//
//
// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.
// ----------------------------------------------------------------------------

library BokkyPooBahsDateTimeLibrary {
    uint256 constant SECONDS_PER_DAY = 24 * 60 * 60;
    uint256 constant SECONDS_PER_HOUR = 60 * 60;
    uint256 constant SECONDS_PER_MINUTE = 60;
    int256 constant OFFSET19700101 = 2440588;

    uint256 constant DOW_MON = 1;
    uint256 constant DOW_TUE = 2;
    uint256 constant DOW_WED = 3;
    uint256 constant DOW_THU = 4;
    uint256 constant DOW_FRI = 5;
    uint256 constant DOW_SAT = 6;
    uint256 constant DOW_SUN = 7;

    // ------------------------------------------------------------------------
    // Calculate the number of days from 1970/01/01 to year/month/day using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and subtracting the offset 2440588 so that 1970/01/01 is day 0
    //
    // days = day
    //      - 32075
    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4
    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12
    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4
    //      - offset
    // ------------------------------------------------------------------------
    function _daysFromDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (uint256 _days) {
        require(year >= 1970);
        int256 _year = int256(year);
        int256 _month = int256(month);
        int256 _day = int256(day);

        int256 __days =
            _day -
                32075 +
                (1461 * (_year + 4800 + (_month - 14) / 12)) /
                4 +
                (367 * (_month - 2 - ((_month - 14) / 12) * 12)) /
                12 -
                (3 * ((_year + 4900 + (_month - 14) / 12) / 100)) /
                4 -
                OFFSET19700101;

        _days = uint256(__days);
    }

    // ------------------------------------------------------------------------
    // Calculate year/month/day from the number of days since 1970/01/01 using
    // the date conversion algorithm from
    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php
    // and adding the offset 2440588 so that 1970/01/01 is day 0
    //
    // int L = days + 68569 + offset
    // int N = 4 * L / 146097
    // L = L - (146097 * N + 3) / 4
    // year = 4000 * (L + 1) / 1461001
    // L = L - 1461 * year / 4 + 31
    // month = 80 * L / 2447
    // dd = L - 2447 * month / 80
    // L = month / 11
    // month = month + 2 - 12 * L
    // year = 100 * (N - 49) + year + L
    // ------------------------------------------------------------------------
    function _daysToDate(uint256 _days)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day
        )
    {
        int256 __days = int256(_days);

        int256 L = __days + 68569 + OFFSET19700101;
        int256 N = (4 * L) / 146097;
        L = L - (146097 * N + 3) / 4;
        int256 _year = (4000 * (L + 1)) / 1461001;
        L = L - (1461 * _year) / 4 + 31;
        int256 _month = (80 * L) / 2447;
        int256 _day = L - (2447 * _month) / 80;
        L = _month / 11;
        _month = _month + 2 - 12 * L;
        _year = 100 * (N - 49) + _year + L;

        year = uint256(_year);
        month = uint256(_month);
        day = uint256(_day);
    }

    function timestampFromDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (uint256 timestamp) {
        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;
    }

    function timestampFromDateTime(
        uint256 year,
        uint256 month,
        uint256 day,
        uint256 hour,
        uint256 minute,
        uint256 second
    ) internal pure returns (uint256 timestamp) {
        timestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            hour *
            SECONDS_PER_HOUR +
            minute *
            SECONDS_PER_MINUTE +
            second;
    }

    function timestampToDate(uint256 timestamp)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day
        )
    {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function timestampToDateTime(uint256 timestamp)
        internal
        pure
        returns (
            uint256 year,
            uint256 month,
            uint256 day,
            uint256 hour,
            uint256 minute,
            uint256 second
        )
    {
        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);
        uint256 secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
        secs = secs % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
        second = secs % SECONDS_PER_MINUTE;
    }

    function isValidDate(
        uint256 year,
        uint256 month,
        uint256 day
    ) internal pure returns (bool valid) {
        if (year >= 1970 && month > 0 && month <= 12) {
            uint256 daysInMonth = _getDaysInMonth(year, month);
            if (day > 0 && day <= daysInMonth) {
                valid = true;
            }
        }
    }

    function isValidDateTime(
        uint256 year,
        uint256 month,
        uint256 day,
        uint256 hour,
        uint256 minute,
        uint256 second
    ) internal pure returns (bool valid) {
        if (isValidDate(year, month, day)) {
            if (hour < 24 && minute < 60 && second < 60) {
                valid = true;
            }
        }
    }

    function isLeapYear(uint256 timestamp)
        internal
        pure
        returns (bool leapYear)
    {
        (uint256 year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
        leapYear = _isLeapYear(year);
    }

    function _isLeapYear(uint256 year) internal pure returns (bool leapYear) {
        leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);
    }

    function isWeekDay(uint256 timestamp) internal pure returns (bool weekDay) {
        weekDay = getDayOfWeek(timestamp) <= DOW_FRI;
    }

    function isWeekEnd(uint256 timestamp) internal pure returns (bool weekEnd) {
        weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;
    }

    function getDaysInMonth(uint256 timestamp)
        internal
        pure
        returns (uint256 daysInMonth)
    {
        (uint256 year, uint256 month, ) =
            _daysToDate(timestamp / SECONDS_PER_DAY);
        daysInMonth = _getDaysInMonth(year, month);
    }

    function _getDaysInMonth(uint256 year, uint256 month)
        internal
        pure
        returns (uint256 daysInMonth)
    {
        if (
            month == 1 ||
            month == 3 ||
            month == 5 ||
            month == 7 ||
            month == 8 ||
            month == 10 ||
            month == 12
        ) {
            daysInMonth = 31;
        } else if (month != 2) {
            daysInMonth = 30;
        } else {
            daysInMonth = _isLeapYear(year) ? 29 : 28;
        }
    }

    // 1 = Monday, 7 = Sunday
    function getDayOfWeek(uint256 timestamp)
        internal
        pure
        returns (uint256 dayOfWeek)
    {
        uint256 _days = timestamp / SECONDS_PER_DAY;
        dayOfWeek = ((_days + 3) % 7) + 1;
    }

    function getYear(uint256 timestamp) internal pure returns (uint256 year) {
        (year, , ) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getMonth(uint256 timestamp) internal pure returns (uint256 month) {
        (, month, ) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getDay(uint256 timestamp) internal pure returns (uint256 day) {
        (, , day) = _daysToDate(timestamp / SECONDS_PER_DAY);
    }

    function getHour(uint256 timestamp) internal pure returns (uint256 hour) {
        uint256 secs = timestamp % SECONDS_PER_DAY;
        hour = secs / SECONDS_PER_HOUR;
    }

    function getMinute(uint256 timestamp)
        internal
        pure
        returns (uint256 minute)
    {
        uint256 secs = timestamp % SECONDS_PER_HOUR;
        minute = secs / SECONDS_PER_MINUTE;
    }

    function getSecond(uint256 timestamp)
        internal
        pure
        returns (uint256 second)
    {
        second = timestamp % SECONDS_PER_MINUTE;
    }

    function addYears(uint256 timestamp, uint256 _years)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        (uint256 year, uint256 month, uint256 day) =
            _daysToDate(timestamp / SECONDS_PER_DAY);
        year += _years;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            (timestamp % SECONDS_PER_DAY);
        require(newTimestamp >= timestamp);
    }

    function addMonths(uint256 timestamp, uint256 _months)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        (uint256 year, uint256 month, uint256 day) =
            _daysToDate(timestamp / SECONDS_PER_DAY);
        month += _months;
        year += (month - 1) / 12;
        month = ((month - 1) % 12) + 1;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            (timestamp % SECONDS_PER_DAY);
        require(newTimestamp >= timestamp);
    }

    function addDays(uint256 timestamp, uint256 _days)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp + _days * SECONDS_PER_DAY;
        require(newTimestamp >= timestamp);
    }

    function addHours(uint256 timestamp, uint256 _hours)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;
        require(newTimestamp >= timestamp);
    }

    function addMinutes(uint256 timestamp, uint256 _minutes)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp >= timestamp);
    }

    function addSeconds(uint256 timestamp, uint256 _seconds)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp + _seconds;
        require(newTimestamp >= timestamp);
    }

    function subYears(uint256 timestamp, uint256 _years)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        (uint256 year, uint256 month, uint256 day) =
            _daysToDate(timestamp / SECONDS_PER_DAY);
        year -= _years;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            (timestamp % SECONDS_PER_DAY);
        require(newTimestamp <= timestamp);
    }

    function subMonths(uint256 timestamp, uint256 _months)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        (uint256 year, uint256 month, uint256 day) =
            _daysToDate(timestamp / SECONDS_PER_DAY);
        uint256 yearMonth = year * 12 + (month - 1) - _months;
        year = yearMonth / 12;
        month = (yearMonth % 12) + 1;
        uint256 daysInMonth = _getDaysInMonth(year, month);
        if (day > daysInMonth) {
            day = daysInMonth;
        }
        newTimestamp =
            _daysFromDate(year, month, day) *
            SECONDS_PER_DAY +
            (timestamp % SECONDS_PER_DAY);
        require(newTimestamp <= timestamp);
    }

    function subDays(uint256 timestamp, uint256 _days)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp - _days * SECONDS_PER_DAY;
        require(newTimestamp <= timestamp);
    }

    function subHours(uint256 timestamp, uint256 _hours)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;
        require(newTimestamp <= timestamp);
    }

    function subMinutes(uint256 timestamp, uint256 _minutes)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;
        require(newTimestamp <= timestamp);
    }

    function subSeconds(uint256 timestamp, uint256 _seconds)
        internal
        pure
        returns (uint256 newTimestamp)
    {
        newTimestamp = timestamp - _seconds;
        require(newTimestamp <= timestamp);
    }

    function diffYears(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _years)
    {
        require(fromTimestamp <= toTimestamp);
        (uint256 fromYear, , ) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint256 toYear, , ) = _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _years = toYear - fromYear;
    }

    function diffMonths(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _months)
    {
        require(fromTimestamp <= toTimestamp);
        (uint256 fromYear, uint256 fromMonth, ) =
            _daysToDate(fromTimestamp / SECONDS_PER_DAY);
        (uint256 toYear, uint256 toMonth, ) =
            _daysToDate(toTimestamp / SECONDS_PER_DAY);
        _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;
    }

    function diffDays(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _days)
    {
        require(fromTimestamp <= toTimestamp);
        _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;
    }

    function diffHours(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _hours)
    {
        require(fromTimestamp <= toTimestamp);
        _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;
    }

    function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _minutes)
    {
        require(fromTimestamp <= toTimestamp);
        _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;
    }

    function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp)
        internal
        pure
        returns (uint256 _seconds)
    {
        require(fromTimestamp <= toTimestamp);
        _seconds = toTimestamp - fromTimestamp;
    }
}

File 11 of 17 : EIP20NonStandardInterface.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

/// @title EIP20NonStandardInterface
/// @dev Version of ERC20 with no return values for `transfer` and `transferFrom`
/// See https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
interface EIP20NonStandardInterface {
    /// @notice Get the total number of tokens in circulation
    /// @return The supply of tokens
    function totalSupply() external view returns (uint256);

    /// @notice Gets the balance of the specified address
    /// @param owner The address from which the balance will be retrieved
    /// @return balance The balance
    function balanceOf(address owner) external view returns (uint256 balance);

    //
    // !!!!!!!!!!!!!!
    // !!! NOTICE !!! `transfer` does not return a value, in violation of the ERC-20 specification
    // !!!!!!!!!!!!!!
    //

    /// @notice Transfer `amount` tokens from `msg.sender` to `dst`
    /// @param dst The address of the destination account
    /// @param amount The number of tokens to transfer
    function transfer(address dst, uint256 amount) external;

    //
    // !!!!!!!!!!!!!!
    // !!! NOTICE !!! `transferFrom` does not return a value, in violation of the ERC-20 specification
    // !!!!!!!!!!!!!!
    //

    /// @notice Transfer `amount` tokens from `src` to `dst`
    /// @param src The address of the source account
    /// @param dst The address of the destination account
    /// @param amount The number of tokens to transfer
    function transferFrom(
        address src,
        address dst,
        uint256 amount
    ) external;

    /// @notice Approve `spender` to transfer up to `amount` from `src`
    /// @dev This will overwrite the approval amount for `spender`
    ///  and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
    /// @param spender The address of the account which may transfer tokens
    /// @param amount The number of tokens that are approved
    /// @return success Whether or not the approval succeeded
    function approve(address spender, uint256 amount)
        external
        returns (bool success);

    /// @notice Get the current allowance from `owner` for `spender`
    /// @param owner The address of the account which owns the tokens to be spent
    /// @param spender The address of the account which may transfer tokens
    /// @return remaining The number of tokens allowed to be spent
    function allowance(address owner, address spender)
        external
        view
        returns (uint256 remaining);

    event Transfer(address indexed from, address indexed to, uint256 amount);
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 amount
    );
}

File 12 of 17 : IERC20Metadata.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

interface IERC20Metadata {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);

    function decimals() external view returns (uint8);
}

File 13 of 17 : TokenMetadataGenerator.sol
// "SPDX-License-Identifier: GPL-3.0-or-later"

pragma solidity 0.7.6;

import "../libs/BokkyPooBahsDateTimeLibrary/BokkyPooBahsDateTimeLibrary.sol";

contract TokenMetadataGenerator {
    function formatDate(uint256 _posixDate)
        internal
        view
        returns (string memory)
    {
        uint256 year;
        uint256 month;
        uint256 day;
        (year, month, day) = BokkyPooBahsDateTimeLibrary.timestampToDate(
            _posixDate
        );

        return
            concat(
                uint2str(day),
                concat(
                    getMonthShortName(month),
                    uint2str(getCenturyYears(year))
                )
            );
    }

    function formatMeta(
        string memory _prefix,
        string memory _concatenator,
        string memory _date,
        string memory _postfix
    ) internal pure returns (string memory) {
        return concat(_prefix, concat(_concatenator, concat(_date, _postfix)));
    }

    function makeTokenName(
        string memory _baseName,
        string memory _date,
        string memory _postfix
    ) internal pure returns (string memory) {
        return formatMeta(_baseName, " ", _date, _postfix);
    }

    function makeTokenSymbol(
        string memory _baseName,
        string memory _date,
        string memory _postfix
    ) internal pure returns (string memory) {
        return formatMeta(_baseName, "-", _date, _postfix);
    }

    function getCenturyYears(uint256 _year) internal pure returns (uint256) {
        return _year % 100;
    }

    function concat(string memory _a, string memory _b)
        internal
        pure
        returns (string memory)
    {
        return string(abi.encodePacked(bytes(_a), bytes(_b)));
    }

    function uint2str(uint256 _i)
        internal
        pure
        returns (string memory _uintAsString)
    {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len - 1;
        while (_i != 0) {
            bstr[k--] = bytes1(uint8(48 + (_i % 10)));
            _i /= 10;
        }
        return string(bstr);
    }

    function getMonthShortName(uint256 _month)
        internal
        pure
        returns (string memory)
    {
        if (_month == 1) {
            return "Jan";
        }
        if (_month == 2) {
            return "Feb";
        }
        if (_month == 3) {
            return "Mar";
        }
        if (_month == 4) {
            return "Arp";
        }
        if (_month == 5) {
            return "May";
        }
        if (_month == 6) {
            return "Jun";
        }
        if (_month == 7) {
            return "Jul";
        }
        if (_month == 8) {
            return "Aug";
        }
        if (_month == 9) {
            return "Sep";
        }
        if (_month == 10) {
            return "Oct";
        }
        if (_month == 11) {
            return "Nov";
        }
        if (_month == 12) {
            return "Dec";
        }
        return "NaN";
    }
}

File 14 of 17 : IRepricer.sol
// "SPDX-License-Identifier: GNU General Public License v3.0"

pragma solidity 0.7.6;

import "../IVault.sol";

interface IRepricer {

    function isRepricer() external pure returns(bool);

    function symbol() external pure returns (string memory);

    function reprice(
        uint _pMin,
        int _volatility,
        IVault _vault,
        uint[2] memory _primary,
        uint[2] memory _complement,
        int _liveUnderlingValue
    )
    external view returns(
        uint newPrimaryLeverage, uint newComplementLeverage, int estPricePrimary, int estPriceComplement
    );
}

File 15 of 17 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "../utils/Context.sol";
/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

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

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        address msgSender = _msgSender();
        _owner = msgSender;
        emit OwnershipTransferred(address(0), msgSender);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

File 16 of 17 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 17 of 17 : Pausable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_derivativeVault","type":"address"},{"internalType":"address","name":"_dynamicFee","type":"address"},{"internalType":"address","name":"_repricer","type":"address"},{"internalType":"uint256","name":"_baseFee","type":"uint256"},{"internalType":"uint256","name":"_maxFee","type":"uint256"},{"internalType":"uint256","name":"_feeAmp","type":"uint256"},{"internalType":"address","name":"_controller","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"amt","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":true,"inputs":[{"indexed":true,"internalType":"bytes4","name":"sig","type":"bytes4"},{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"LOG_CALL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"name":"LOG_EXIT","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"name":"LOG_JOIN","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"repricingBlock","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balancePrimary","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"balanceComplement","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leveragePrimary","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"leverageComplement","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLeveragePrimary","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newLeverageComplement","type":"uint256"},{"indexed":false,"internalType":"int256","name":"estPricePrimary","type":"int256"},{"indexed":false,"internalType":"int256","name":"estPriceComplement","type":"int256"},{"indexed":false,"internalType":"int256","name":"liveUnderlingValue","type":"int256"}],"name":"LOG_REPRICE","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":true,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenLeverageIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenLeverageOut","type":"uint256"}],"name":"LOG_SWAP","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"src","type":"address"},{"indexed":true,"internalType":"address","name":"dst","type":"address"},{"indexed":false,"internalType":"uint256","name":"amt","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_IN_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_OUT_RATIO","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_POW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_POW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"whom","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcInGivenOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcOutGivenIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"decreaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"derivativeVault","outputs":[{"internalType":"contract IVault","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dynamicFee","outputs":[{"internalType":"contract IDynamicFee","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256[2]","name":"minAmountsOut","type":"uint256[2]"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"exposureLimit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAmp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_primaryBalance","type":"uint256"},{"internalType":"uint256","name":"_primaryLeverage","type":"uint256"},{"internalType":"uint256","name":"_complementBalance","type":"uint256"},{"internalType":"uint256","name":"_complementLeverage","type":"uint256"},{"internalType":"uint256","name":"_exposureLimit","type":"uint256"},{"internalType":"uint256","name":"_volatility","type":"uint256"},{"internalType":"uint256","name":"_pMin","type":"uint256"},{"internalType":"uint256","name":"_qMin","type":"uint256"}],"name":"finalize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getColor","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getLeverage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTokens","outputs":[{"internalType":"address[2]","name":"tokens","type":"address[2]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"iBONE","outputs":[{"internalType":"int256","name":"","type":"int256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"increaseApproval","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256[2]","name":"maxAmountsIn","type":"uint256[2]"}],"name":"joinPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"maxFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"qMin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"repricer","outputs":[{"internalType":"contract IRepricer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"repricingBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"swapExactAmountIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"src","type":"address"},{"internalType":"address","name":"dst","type":"address"},{"internalType":"uint256","name":"amt","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"volatility","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

60806040523480156200001157600080fd5b506040516200585c3803806200585c833981810160405260e08110156200003757600080fd5b508051602082015160408301516060840151608085015160a086015160c0909601519495939492939192909190600062000070620006b4565b600080546001600160a01b0319166001600160a01b0383169081178255604051929350917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3506000805460ff60a01b191690556001600160a01b03871662000111576040805162461bcd60e51b815260206004820152600b60248201526a1393d517d117d59055531560aa1b604482015290519081900360640190fd5b601280546001600160a01b0319166001600160a01b038981169190911790915586166200016f576040805162461bcd60e51b81526020600482015260076024820152664e4f545f46454560c81b604482015290519081900360640190fd5b601380546001600160a01b0319166001600160a01b03888116919091179091558516620001d2576040805162461bcd60e51b815260206004820152600c60248201526b2727aa2fa922a82924a1a2a960a11b604482015290519081900360640190fd5b601480546001600160a01b0319166001600160a01b0387811691909117909155600b859055600c839055600d849055811662000246576040805162461bcd60e51b815260206004820152600e60248201526d2727aa2fa1a7a72a2927a62622a960911b604482015290519081900360640190fd5b600680546001600160a01b0380841661010002610100600160a81b0319909216919091179091556012546040805163198406d960e21b81529051600093620002e49316916366101b64916004808301926020929190829003018186803b158015620002b057600080fd5b505afa158015620002c5573d6000803e3d6000fd5b505050506040513d6020811015620002dc57600080fd5b5051620006b8565b9050620004c6620004c0601260009054906101000a90046001600160a01b03166001600160a01b031663dbcb32bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200033d57600080fd5b505afa15801562000352573d6000803e3d6000fd5b505050506040513d60208110156200036957600080fd5b5051604080516306fdde0360e01b815290516001600160a01b03909216916306fdde0391600480820192600092909190829003018186803b158015620003ae57600080fd5b505afa158015620003c3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015620003ed57600080fd5b81019080805160405193929190846401000000008211156200040e57600080fd5b9083019060208201858111156200042457600080fd5b82516401000000008111828201881017156200043f57600080fd5b82525081516020918201929091019080838360005b838110156200046e57818101518382015260200162000454565b50505050905090810190601f1680156200049c5780820380516001836020036101000a031916815260200191505b506040818101905260038152620204c560ec1b602082015287935091505062000720565b62000757565b620006a6620006a0601260009054906101000a90046001600160a01b03166001600160a01b031663dbcb32bf6040518163ffffffff1660e01b815260040160206040518083038186803b1580156200051d57600080fd5b505afa15801562000532573d6000803e3d6000fd5b505050506040513d60208110156200054957600080fd5b5051604080516395d89b4160e01b815290516001600160a01b03909216916395d89b4191600480820192600092909190829003018186803b1580156200058e57600080fd5b505afa158015620005a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526020811015620005cd57600080fd5b8101908080516040519392919084640100000000821115620005ee57600080fd5b9083019060208201858111156200060457600080fd5b82516401000000008111828201881017156200061f57600080fd5b82525081516020918201929091019080838360005b838110156200064e57818101518382015260200162000634565b50505050905090810190601f1680156200067c5780820380516001836020036101000a031916815260200191505b5060408181019052600381526202d4c560ec1b602082015287935091505062000770565b6200079f565b505050505050505062000d01565b3390565b60606000806000620006d585620007b460201b62002b241760201c565b9194509250905062000715620006eb82620007d5565b6200070f620006fa85620008b5565b6200070f620007098862000ada565b620007d5565b62000ae1565b93505050505b919050565b60606200074f84604051806040016040528060018152602001600160fd1b815250858562000ba060201b60201c565b949350505050565b80516200076c90600490602084019062000c55565b5050565b60606200074f84604051806040016040528060018152602001602d60f81b815250858562000ba060201b60201c565b80516200076c90600590602084019062000c55565b60008080620007c862015180850462000bbe565b9196909550909350915050565b606081620007fc57506040805180820190915260018152600360fc1b60208201526200071b565b8160005b81156200081657600101600a8204915062000800565b6000816001600160401b03811180156200082f57600080fd5b506040519080825280601f01601f1916602001820160405280156200085b576020820181803683370190505b50905060001982015b8515620008ac57600a860660300160f81b828280600190039350815181106200088957fe5b60200101906001600160f81b031916908160001a905350600a8604955062000864565b50949350505050565b60608160011415620008e257506040805180820190915260038152622530b760e91b60208201526200071b565b81600214156200090d57506040805180820190915260038152622332b160e91b60208201526200071b565b816003141562000938575060408051808201909152600381526226b0b960e91b60208201526200071b565b816004141562000963575060408051808201909152600381526204172760ec1b60208201526200071b565b81600514156200098e57506040805180820190915260038152624d617960e81b60208201526200071b565b8160061415620009b95750604080518082019091526003815262253ab760e91b60208201526200071b565b8160071415620009e45750604080518082019091526003815262129d5b60ea1b60208201526200071b565b816008141562000a0f575060408051808201909152600381526241756760e81b60208201526200071b565b816009141562000a3a575060408051808201909152600381526205365760ec1b60208201526200071b565b81600a141562000a65575060408051808201909152600381526213d8dd60ea1b60208201526200071b565b81600b141562000a9057506040805180820190915260038152622737bb60e91b60208201526200071b565b81600c141562000abb575060408051808201909152600381526244656360e81b60208201526200071b565b50506040805180820190915260038152622730a760e91b602082015290565b6064900690565b606082826040516020018083805190602001908083835b6020831062000b195780518252601f19909201916020918201910162000af8565b51815160209384036101000a600019018019909216911617905285519190930192850191508083835b6020831062000b635780518252601f19909201916020918201910162000b42565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052905092915050565b606062000bb5856200070f8681878762000ae1565b95945050505050565b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f846050028162000c1657fe5b0590506000605061098f83020585039050600b820560301994909401606402929092018301996002600c90940290910392909201975095509350505050565b828054600181600116156101000203166002900490600052602060002090601f01602090048101928262000c8d576000855562000cd8565b82601f1062000ca857805160ff191683800117855562000cd8565b8280016001018555821562000cd8579182015b8281111562000cd857825182559160200191906001019062000cbb565b5062000ce692915062000cea565b5090565b5b8082111562000ce6576000815560010162000ceb565b614b4b8062000d116000396000f3fe608060405234801561001057600080fd5b50600436106103205760003560e01c80638456cb59116101a7578063adab6cfe116100ee578063dd3584e811610097578063ec09302111610071578063ec0930211461085f578063f2fde38b14610867578063f8b2cb4f1461089a57610320565b8063dd3584e814610814578063dd43eb571461081c578063dd62ed3e1461082457610320565b8063cce99230116100c8578063cce99230146107b1578063d73dd623146107b9578063db08a5e3146107f257610320565b8063adab6cfe146107a1578063b20d550b146107a9578063c36596a6146104f857610320565b806395d89b4111610150578063a45de7df1161012a578063a45de7df146106dd578063a9059cbb14610725578063aa6ca8081461075e57610320565b806395d89b41146106c5578063992e2a92146106cd5780639a86139b146106d557610320565b806388f1e0e71161018157806388f1e0e7146106935780638d4e4083146106b55780638da5cb5b146106bd57610320565b80638456cb591461067b57806385272a6e1461068357806387b53b7c1461068b57610320565b806340179d831161026b57806370a082311161021457806373d1747b116101ee57806373d1747b1461063c57806376a38e911461064457806378cebb9b1461067357610320565b806370a08231146105d2578063715018a61461060557806372ee63411461060d57610320565b80635c975abb116102455780635c975abb1461058957806366188463146105915780636ef25c3a146105ca57610320565b806340179d83146104f8578063436f9be41461050057806358f030aa1461052957610320565b806322950746116102cd578063313ce567116102a7578063313ce5671461049d5780633b15a718146104bb5780633f4ba83a146104ee57610320565b8063229507461461044a57806322aa14e71461045257806323b872dd1461045a57610320565b8063095ea7b3116102fe578063095ea7b3146103c457806313c43c931461041157806318160ddd1461044257610320565b806301032adc1461032557806301f59d161461033f57806306fdde0314610347575b600080fd5b61032d6108cd565b60408051918252519081900360200190f35b61032d6108d9565b61034f6108df565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610389578181015183820152602001610371565b50505050905090810190601f1680156103b65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103fd600480360360408110156103da57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610993565b604080519115158252519081900360200190f35b610419610a07565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61032d610a23565b61032d610a29565b61032d610a2f565b6103fd6004803603606081101561047057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610a35565b6104a5610bb8565b6040805160ff9092168252519081900360200190f35b61032d600480360360208110156104d157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610bbd565b6104f6610bf0565b005b61032d610ca2565b61032d6004803603606081101561051657600080fd5b5080359060208101359060400135610cae565b6105706004803603608081101561053f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135169060600135610cf8565b6040805192835260208301919091528051918290030190f35b6103fd61139c565b6103fd600480360360408110156105a757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113bd565b61032d6114db565b61032d600480360360208110156105e857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114e1565b6104f6611509565b61032d6004803603608081101561062357600080fd5b5080359060208101359060408101359060600135611620565b61032d611681565b61032d6004803603608081101561065a57600080fd5b5080359060208101359060408101359060600135611695565b6104196116ef565b6104f661170b565b61032d6117bb565b61032d6117c1565b6104f6600480360360608110156106a957600080fd5b508035906020016117c7565b6103fd611bf8565b610419611c1a565b61034f611c36565b61032d611cb5565b61032d611cc1565b6104f660048036036101008110156106f457600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e00135611ce5565b6103fd6004803603604081101561073b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561238b565b6107666123a1565b6040518082600260200280838360005b8381101561078e578181015183820152602001610776565b5050505090500191505060405180910390f35b61032d6123fa565b610419612400565b61032d61241c565b6103fd600480360360408110156107cf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612422565b6104f66004803603606081101561080857600080fd5b508035906020016124cf565b61032d6128fb565b61032d612900565b61032d6004803603604081101561083a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612905565b61032d61293d565b6104f66004803603602081101561087d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661294d565b61032d600480360360208110156108b057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612aee565b671bc16d674ec7ffff81565b600d5481565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109895780601f1061095e57610100808354040283529160200191610989565b820191906000526020600020905b81548152906001019060200180831161096c57829003601f168201915b5050505050905090565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b60145473ffffffffffffffffffffffffffffffffffffffff1681565b60035490565b600e5481565b600a5481565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020908152604080832033808552925282205491921480610a745750808311155b610adf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f544f4b454e5f4241445f43414c4c455200000000000000000000000000000000604482015290519081900360640190fd5b610aea858585612b43565b3373ffffffffffffffffffffffffffffffffffffffff861614801590610b3057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114155b15610bad57610b3f8184612cac565b73ffffffffffffffffffffffffffffffffffffffff868116600090815260026020908152604080832033808552908352928190208590558051948552519288169391927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a35b506001949350505050565b601290565b6000610bc7612d32565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205490565b610bf8612da4565b73ffffffffffffffffffffffffffffffffffffffff16610c16611c1a565b73ffffffffffffffffffffffffffffffffffffffff1614610c9857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610ca0612da8565b565b670de0b6b3a764000081565b600080610cbb8585612e96565b90506000610ce2670de0b6b3a7640000610cdd670de0b6b3a764000087612cac565b612e96565b9050610cee828261301f565b9695505050505050565b60408051602080825236908201819052600092839233927fffffffff000000000000000000000000000000000000000000000000000000008535169285929081908101848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2610d88612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610dbb61139c565b15610e2757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6006547501000000000000000000000000000000000000000000900460ff16610eb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166366101b646040518163ffffffff1660e01b815260040160206040518083038186803b158015610f1957600080fd5b505afa158015610f2d573d6000803e3d6000fd5b505050506040513d6020811015610f4357600080fd5b50514210610fb257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f534554544c454400000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141561104d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f53414d455f544f4b454e00000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f548510156110be57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d494e5f544f4b454e5f494e0000000000000000000000000000000000000000604482015290519081900360640190fd5b6110c661312d565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152600960208181526040808420815180830183528154815260019182015481850152958a16855292825292839020835180850190945280548452909101549082015261114b61113d611133846134e7565b84602001516134fb565b6706f05b59d3b2000061301f565b8711156111b957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d41585f494e5f524154494f0000000000000000000000000000000000000000604482015290519081900360640190fd5b6111d66111c5836134e7565b6111ce836134e7565b896000611620565b93506000806111e7848a8589613512565b909250905060006112c56111fa866134e7565b611203866134e7565b601354600b54600c54600d54604080517fe91fe030000000000000000000000000000000000000000000000000000000008152600481018b90526024810194909452604484019290925260648301525173ffffffffffffffffffffffffffffffffffffffff9092169163e91fe030916084808201926020929091908290030181600087803b15801561129457600080fd5b505af11580156112a8573d6000803e3d6000fd5b505050506040513d60208110156112be57600080fd5b5051610cae565b90506112e36112d3866134e7565b6112dc866134e7565b8c86611620565b96508787101561135457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4c494d49545f4f55540000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6113628b8b8b8a85886136f0565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055969b969a509598505050505050505050565b60005474010000000000000000000000000000000000000000900460ff1690565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120548083111561142c5733600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff88168452909152812055611468565b6114368184612cac565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529020555b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b600b5481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b611511612da4565b73ffffffffffffffffffffffffffffffffffffffff1661152f611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146115b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600080611635670de0b6b3a764000084612cac565b9050611641848261301f565b9050600061165387610cdd89856139ca565b90506000611669670de0b6b3a764000083612cac565b9050611675878261301f565b98975050505050505050565b6402540be400670de0b6b3a76400005b0481565b6000806116a28585612cac565b905060006116b08683612e96565b905060006116c682670de0b6b3a7640000612cac565b90506116da670de0b6b3a764000086612cac565b93506116756116e9898361301f565b85612e96565b60125473ffffffffffffffffffffffffffffffffffffffff1681565b611713612da4565b73ffffffffffffffffffffffffffffffffffffffff16611731611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146117b357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610ca0613a3c565b60105481565b600c5481565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2611888612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117908190557501000000000000000000000000000000000000000000900460ff1661193c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b6000611946610a23565b905060006119548483612e96565b9050806119c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b60005b6002811015611bb6576000600782600281106119dd57fe5b015473ffffffffffffffffffffffffffffffffffffffff1660008181526009602052604090206001015490915080611a7657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f5f42414c414e434500000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000611a82858361301f565b9050868460028110611a9057fe5b6020020135811115611b0357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4c494d49545f494e000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902060010154611b3690826139ca565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600960209081526040918290206001019390935580518481529051919233927f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9281900390910190a3611ba6833383613b18565b5050600190920191506119c59050565b50611bc084613e13565b611bca3385613e1f565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b6006547501000000000000000000000000000000000000000000900460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b60058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109895780601f1061095e57610100808354040283529160200191610989565b6704a03ce68d21555681565b7f42524f4e5a45000000000000000000000000000000000000000000000000000090565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2611da6612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055601254604080517f66101b64000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916366101b6491600480820192602092909190829003018186803b158015611e3c57600080fd5b505afa158015611e50573d6000803e3d6000fd5b505050506040513d6020811015611e6657600080fd5b50514210611ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f534554544c454400000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6006547501000000000000000000000000000000000000000000900460ff1615611f6057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f49535f46494e414c495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b600654610100900473ffffffffffffffffffffffffffffffffffffffff163314611feb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f434f4e54524f4c4c4552000000000000000000000000000000000000604482015290519081900360640190fd5b85881461205957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f53594d4d455452494300000000000000000000000000000000000000604482015290519081900360640190fd5b600e829055600f81905560108490556011839055600680547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055601254604080517f91ac094c00000000000000000000000000000000000000000000000000000000815290516121529260009273ffffffffffffffffffffffffffffffffffffffff909116916391ac094c91600480820192602092909190829003018186803b15801561211f57600080fd5b505afa158015612133573d6000803e3d6000fd5b505050506040513d602081101561214957600080fd5b50518a8a613e2d565b6121f26001601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166394f973d66040518163ffffffff1660e01b815260040160206040518083038186803b1580156121bf57600080fd5b505afa1580156121d3573d6000803e3d6000fd5b505050506040513d60208110156121e957600080fd5b50518888613e2d565b6000886121fd613fb5565b0290506000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b2016bd46040518163ffffffff1660e01b815260040160206040518083038186803b15801561226a57600080fd5b505afa15801561227e573d6000803e3d6000fd5b505050506040513d602081101561229457600080fd5b5051604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce56791600480820192602092909190829003018186803b1580156122fe57600080fd5b505afa158015612312573d6000803e3d6000fd5b505050506040513d602081101561232857600080fd5b505160ff16905060128110156123445780601203600a0a820291505b61234d82613e13565b6123573383613e1f565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050505050505050565b6000612398338484612b43565b50600192915050565b6123a9614ad1565b6123b1612d32565b60408051808201918290529060079060029082845b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116123c6575050505050905090565b600f5481565b60135473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281205461245d90836139ca565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2612590612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117908190557501000000000000000000000000000000000000000000900460ff1661264457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b600061264e610a23565b9050600061265c8483612e96565b9050806126ca57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b6126d43385614211565b6126dd8461421b565b60005b60028110156128cc576000600782600281106126f857fe5b015473ffffffffffffffffffffffffffffffffffffffff166000818152600960205260409020600101549091508061279157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f5f42414c414e434500000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061279d858361301f565b90508684600281106127ab57fe5b602002013581101561281e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4c494d49545f4f55540000000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600960205260409020600101546128519082612cac565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600960209081526040918290206001019390935580518481529051919233927fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9281900390910190a36128c1833383614224565b5050506001016126e0565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055505050565b600281565b600181565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b6002670de0b6b3a7640000611691565b612955612da4565b73ffffffffffffffffffffffffffffffffffffffff16612973611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146129f557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614af06026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000612af8612d32565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090206001015490565b60008080612b3662015180850461436c565b9196909550909350915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054811115612bd757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f494e53554646494349454e545f42414c00000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054612c079082612cac565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054612c4390826139ca565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600080612cb98484614420565b90925090508015612d2b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f5355425f554e444552464c4f5700000000000000000000000000000000000000604482015290519081900360640190fd5b5092915050565b60065460ff1615610ca057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f5245454e54525900000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b612db061139c565b612e1b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612e6c612da4565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190a1565b600081612f0457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4449565f5a45524f000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a76400008302831580612f2c5750670de0b6b3a7640000848281612f2957fe5b04145b612f9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b6002830481018181101561300c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b83818161301557fe5b0495945050505050565b600082820283158061303957508284828161303657fe5b04145b6130a457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b6706f05b59d3b2000081018181101561311e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a764000081613015565b43600a54141561313c57610ca0565b43600a55600060098161314d614445565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060096000613197614468565b73ffffffffffffffffffffffffffffffffffffffff90811682526020808301939093526040918201600090812083518085018552600180890154825288548288015285518087018752908301548152825481880152601454600e5460115460125489517fb4ba0231000000000000000000000000000000000000000000000000000000008152600481018990529951969b5094999398969788978897889795831696631a1afbc596909316928d928d92859263b4ba02319260248082019391829003018186803b15801561326a57600080fd5b505afa15801561327e573d6000803e3d6000fd5b505050506040513d602081101561329457600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08a901b168152600481018881526024820188905273ffffffffffffffffffffffffffffffffffffffff8716604483015291606490910190859080838360005b838110156133145781810151838201526020016132fc565b5050505090500183600260200280838360005b8381101561333f578181015183820152602001613327565b50505050905001828152602001965050505050505060806040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d608081101561339657600080fd5b508051602080830151604080850151606090950151600a548c518c518e8701518e88015160125487517fb4ba02310000000000000000000000000000000000000000000000000000000081526000600482015297519a9f50979d50999b509399507f20a9a7e8eddd119db42373ce305e5cd9ca3521682c54e58bca672a721dd0281898929791969095939492938d938d938d938d9373ffffffffffffffffffffffffffffffffffffffff169263b4ba02319260248083019392829003018186803b15801561346357600080fd5b505afa158015613477573d6000803e3d6000fd5b505050506040513d602081101561348d57600080fd5b5051604080519a8b5260208b0199909952898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015251908190036101400190a150509455505055565b6000610a018260200151836000015161301f565b60008183101561350c575081610a01565b50919050565b6000806000601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a18034d160405180606001604052808a6020015181526020018a600001518152602001898152506040518060600160405280896020015181526020018960000151815260200188815250600b54600c54600d546040518663ffffffff1660e01b81526004018086600360200280838360005b838110156135db5781810151838201526020016135c3565b5050505090500185600360200280838360005b838110156136065781810151838201526020016135ee565b50505050905001848152602001838152602001828152602001955050505050506040805180830381600087803b15801561363f57600080fd5b505af1158015613653573d6000803e3d6000fd5b505050506040513d604081101561366957600080fd5b50805160209091015192509050600081136136e557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f4241445f46454500000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152600960205260408082209287168252812090919061372d82898389614473565b613739828983896147e2565b6137478260010154896139ca565b826001018190555061375d816001015487612cac565b60018083019190915560408051808201909152835481529083015460208201526138349061378a906134e7565b6040805180820190915283548152600184015460208201526137ab906134e7565b6013546001868101549086015473ffffffffffffffffffffffffffffffffffffffff9092169163e91fe030916137e091614932565b600b54600c54600d546040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050602060405180830381600087803b15801561129457600080fd5b9250848310156138a557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b6138af8887612e96565b85111561391d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4d4154485f415050524f585f4f54484552000000000000000000000000000000604482015290519081900360640190fd5b6001808301549082015483548354604080518d8152602081018c90528082018a90526060810195909552608085019390935260a084019190915260c08301525173ffffffffffffffffffffffffffffffffffffffff808a1692908c169133917f1c5fe691bf1a10c1e6c35d8974514451cd3f40ed1135a0450fe2550e3ebae597919081900360e00190a46139b289338a613b18565b506139be873388614224565b50509695505050505050565b81810182811015610a0157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4144445f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b613a4461139c565b15613ab057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612e6c612da4565b6000808473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613b8257600080fd5b505afa158015613b96573d6000803e3d6000fd5b505050506040513d6020811015613bac57600080fd5b5051604080517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152306024830152604482018790529151929350908716916323b872dd9160648082019260009290919082900301818387803b158015613c2f57600080fd5b505af1158015613c43573d6000803e3d6000fd5b5050505060003d60008114613c5f5760208114613c8757600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9150613c93565b60206000803e60005191505b5080613d0057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b60008673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613d6957600080fd5b505afa158015613d7d573d6000803e3d6000fd5b505050506040513d6020811015613d9357600080fd5b5051905082811015613e0657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f544f4b454e5f5452414e534645525f494e5f4f564552464c4f57000000000000604482015290519081900360640190fd5b9190910395945050505050565b613e1c81614953565b50565b613e2982826149c8565b5050565b600f54821015613e9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d494e5f42414c414e4345000000000000000000000000000000000000000000604482015290519081900360640190fd5b60008111613f0d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f5a45524f5f4c4556455241474500000000000000000000000000000000000000604482015290519081900360640190fd5b604080518082018252828152602080820185815273ffffffffffffffffffffffffffffffffffffffff8716600090815260099092529290209051815590516001909101558260078560028110613f5f57fe5b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613fae833384613b18565b5050505050565b601254604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163dbcb32bf916004808301926020929190829003018186803b15801561402057600080fd5b505afa158015614034573d6000803e3d6000fd5b505050506040513d602081101561404a57600080fd5b5051604080517fab56c592000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163ab56c59291600480820192602092909190829003018186803b1580156140b457600080fd5b505afa1580156140c8573d6000803e3d6000fd5b505050506040513d60208110156140de57600080fd5b5051601254604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163dbcb32bf91600480820192602092909190829003018186803b15801561414b57600080fd5b505afa15801561415f573d6000803e3d6000fd5b505050506040513d602081101561417557600080fd5b5051604080517fc6bb30e2000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163c6bb30e291600480820192602092909190829003018186803b1580156141df57600080fd5b505afa1580156141f3573d6000803e3d6000fd5b505050506040513d602081101561420957600080fd5b505101919050565b613e2982826149d3565b613e1c816149de565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561429557600080fd5b505af11580156142a9573d6000803e3d6000fd5b5050505060003d600081146142c557602081146142ed57600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91506142f9565b60206000803e60005191505b508061436657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b50505050565b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f84605002816143c357fe5b0590506000605061098f83020585039050600b82057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcf94909401606402929092018301996002600c90940290910392909201975095509350505050565b600080828410614436575050808203600061443e565b505081810360015b9250929050565b60006007815b015473ffffffffffffffffffffffffffffffffffffffff16905090565b60006007600161444b565b600f546040805180820190915283548152600184015460208201526144a19061449b906134e7565b83612cac565b1161450d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f424f554e444152595f4c45564552414745440000000000000000000000000000604482015290519081900360640190fd5b600f5461451e836001015483612cac565b1161458a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f424f554e444152595f4e4f4e5f4c455645524147454400000000000000000000604482015290519081900360640190fd5b6000670de0b6b3a764000061459d613fb5565b02905060006145b4600e54610cdd84600e54612cac565b905060006145cf6145c784600e54612cac565b600e54612e96565b905060006146326146076146018a604051806040016040529081600082015481526020016001820154815250506134e7565b896139ca565b604080518082019091528854815260018901546020820152610cdd9061462c906134e7565b88612cac565b90508083106146a257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f424f554e444152595f4c4f574552000000000000000000000000000000000000604482015290519081900360640190fd5b81811061471057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f424f554e444152595f5550504552000000000000000000000000000000000000604482015290519081900360640190fd5b600061473661472c6147268b600101548b6139ca565b886139ca565b8860010154614420565b5080915050600061475b61462c6147518c600101548c6139ca565b8a600101546139ca565b905060105461476a8383612e96565b106147d657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f424f554e444152595f4558504f53555245000000000000000000000000000000604482015290519081900360640190fd5b50505050505050505050565b6040805180820190915282548152600183015460208201526148199061480b9061449b906134e7565b610cdd846001015484612cac565b80835561488757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5a45524f5f4f55545f4c45564552414745000000000000000000000000000000604482015290519081900360640190fd5b6040805180820190915284548152600185015460208201526148c4906148b6906148b0906134e7565b856139ca565b610cdd8660010154866139ca565b80855561436657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5a45524f5f494e5f4c4556455241474500000000000000000000000000000000604482015290519081900360640190fd5b6000818301670de0b6b3a7640000838503028161494b57fe5b059392505050565b3060009081526001602052604090205461496d90826139ca565b3060009081526001602052604090205560035461498a90826139ca565b60035560408051828152905130916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b613e29308383612b43565b613e29823083612b43565b30600090815260016020526040902054811115614a5c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f494e53554646494349454e545f42414c00000000000000000000000000000000604482015290519081900360640190fd5b30600090815260016020526040902054614a769082612cac565b30600090815260016020526040902055600354614a939082612cac565b60035560408051828152905160009130917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b6040518060400160405280600290602082028036833750919291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a26469706673582212203d1d5f5109d6b6fd6706cfca3141555ad03b66bfe251fe16f38afc347192dbf864736f6c634300070600330000000000000000000000004eba099f97ffed8de47a14f835820815f141ea08000000000000000000000000db635eebaedef9801653f559e2c859aa81ac1ff4000000000000000000000000ee981eb86df4569b6368d9cb2172ff971bf453de0000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007a596c2d3e0f390a212a8ed47308cf621b5e949c

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106103205760003560e01c80638456cb59116101a7578063adab6cfe116100ee578063dd3584e811610097578063ec09302111610071578063ec0930211461085f578063f2fde38b14610867578063f8b2cb4f1461089a57610320565b8063dd3584e814610814578063dd43eb571461081c578063dd62ed3e1461082457610320565b8063cce99230116100c8578063cce99230146107b1578063d73dd623146107b9578063db08a5e3146107f257610320565b8063adab6cfe146107a1578063b20d550b146107a9578063c36596a6146104f857610320565b806395d89b4111610150578063a45de7df1161012a578063a45de7df146106dd578063a9059cbb14610725578063aa6ca8081461075e57610320565b806395d89b41146106c5578063992e2a92146106cd5780639a86139b146106d557610320565b806388f1e0e71161018157806388f1e0e7146106935780638d4e4083146106b55780638da5cb5b146106bd57610320565b80638456cb591461067b57806385272a6e1461068357806387b53b7c1461068b57610320565b806340179d831161026b57806370a082311161021457806373d1747b116101ee57806373d1747b1461063c57806376a38e911461064457806378cebb9b1461067357610320565b806370a08231146105d2578063715018a61461060557806372ee63411461060d57610320565b80635c975abb116102455780635c975abb1461058957806366188463146105915780636ef25c3a146105ca57610320565b806340179d83146104f8578063436f9be41461050057806358f030aa1461052957610320565b806322950746116102cd578063313ce567116102a7578063313ce5671461049d5780633b15a718146104bb5780633f4ba83a146104ee57610320565b8063229507461461044a57806322aa14e71461045257806323b872dd1461045a57610320565b8063095ea7b3116102fe578063095ea7b3146103c457806313c43c931461041157806318160ddd1461044257610320565b806301032adc1461032557806301f59d161461033f57806306fdde0314610347575b600080fd5b61032d6108cd565b60408051918252519081900360200190f35b61032d6108d9565b61034f6108df565b6040805160208082528351818301528351919283929083019185019080838360005b83811015610389578181015183820152602001610371565b50505050905090810190601f1680156103b65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6103fd600480360360408110156103da57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135610993565b604080519115158252519081900360200190f35b610419610a07565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190f35b61032d610a23565b61032d610a29565b61032d610a2f565b6103fd6004803603606081101561047057600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813581169160208101359091169060400135610a35565b6104a5610bb8565b6040805160ff9092168252519081900360200190f35b61032d600480360360208110156104d157600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16610bbd565b6104f6610bf0565b005b61032d610ca2565b61032d6004803603606081101561051657600080fd5b5080359060208101359060400135610cae565b6105706004803603608081101561053f57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020810135916040820135169060600135610cf8565b6040805192835260208301919091528051918290030190f35b6103fd61139c565b6103fd600480360360408110156105a757600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81351690602001356113bd565b61032d6114db565b61032d600480360360208110156105e857600080fd5b503573ffffffffffffffffffffffffffffffffffffffff166114e1565b6104f6611509565b61032d6004803603608081101561062357600080fd5b5080359060208101359060408101359060600135611620565b61032d611681565b61032d6004803603608081101561065a57600080fd5b5080359060208101359060408101359060600135611695565b6104196116ef565b6104f661170b565b61032d6117bb565b61032d6117c1565b6104f6600480360360608110156106a957600080fd5b508035906020016117c7565b6103fd611bf8565b610419611c1a565b61034f611c36565b61032d611cb5565b61032d611cc1565b6104f660048036036101008110156106f457600080fd5b5080359060208101359060408101359060608101359060808101359060a08101359060c08101359060e00135611ce5565b6103fd6004803603604081101561073b57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff813516906020013561238b565b6107666123a1565b6040518082600260200280838360005b8381101561078e578181015183820152602001610776565b5050505090500191505060405180910390f35b61032d6123fa565b610419612400565b61032d61241c565b6103fd600480360360408110156107cf57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff8135169060200135612422565b6104f66004803603606081101561080857600080fd5b508035906020016124cf565b61032d6128fb565b61032d612900565b61032d6004803603604081101561083a57600080fd5b5073ffffffffffffffffffffffffffffffffffffffff81358116916020013516612905565b61032d61293d565b6104f66004803603602081101561087d57600080fd5b503573ffffffffffffffffffffffffffffffffffffffff1661294d565b61032d600480360360208110156108b057600080fd5b503573ffffffffffffffffffffffffffffffffffffffff16612aee565b671bc16d674ec7ffff81565b600d5481565b60048054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109895780601f1061095e57610100808354040283529160200191610989565b820191906000526020600020905b81548152906001019060200180831161096c57829003601f168201915b5050505050905090565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552908352818420869055815186815291519394909390927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925928290030190a35060015b92915050565b60145473ffffffffffffffffffffffffffffffffffffffff1681565b60035490565b600e5481565b600a5481565b73ffffffffffffffffffffffffffffffffffffffff8316600081815260026020908152604080832033808552925282205491921480610a745750808311155b610adf57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f544f4b454e5f4241445f43414c4c455200000000000000000000000000000000604482015290519081900360640190fd5b610aea858585612b43565b3373ffffffffffffffffffffffffffffffffffffffff861614801590610b3057507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114155b15610bad57610b3f8184612cac565b73ffffffffffffffffffffffffffffffffffffffff868116600090815260026020908152604080832033808552908352928190208590558051948552519288169391927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a35b506001949350505050565b601290565b6000610bc7612d32565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090205490565b610bf8612da4565b73ffffffffffffffffffffffffffffffffffffffff16610c16611c1a565b73ffffffffffffffffffffffffffffffffffffffff1614610c9857604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610ca0612da8565b565b670de0b6b3a764000081565b600080610cbb8585612e96565b90506000610ce2670de0b6b3a7640000610cdd670de0b6b3a764000087612cac565b612e96565b9050610cee828261301f565b9695505050505050565b60408051602080825236908201819052600092839233927fffffffff000000000000000000000000000000000000000000000000000000008535169285929081908101848480828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2610d88612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055610dbb61139c565b15610e2757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b6006547501000000000000000000000000000000000000000000900460ff16610eb157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166366101b646040518163ffffffff1660e01b815260040160206040518083038186803b158015610f1957600080fd5b505afa158015610f2d573d6000803e3d6000fd5b505050506040513d6020811015610f4357600080fd5b50514210610fb257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f534554544c454400000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b8373ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16141561104d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f53414d455f544f4b454e00000000000000000000000000000000000000000000604482015290519081900360640190fd5b600f548510156110be57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d494e5f544f4b454e5f494e0000000000000000000000000000000000000000604482015290519081900360640190fd5b6110c661312d565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152600960208181526040808420815180830183528154815260019182015481850152958a16855292825292839020835180850190945280548452909101549082015261114b61113d611133846134e7565b84602001516134fb565b6706f05b59d3b2000061301f565b8711156111b957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d41585f494e5f524154494f0000000000000000000000000000000000000000604482015290519081900360640190fd5b6111d66111c5836134e7565b6111ce836134e7565b896000611620565b93506000806111e7848a8589613512565b909250905060006112c56111fa866134e7565b611203866134e7565b601354600b54600c54600d54604080517fe91fe030000000000000000000000000000000000000000000000000000000008152600481018b90526024810194909452604484019290925260648301525173ffffffffffffffffffffffffffffffffffffffff9092169163e91fe030916084808201926020929091908290030181600087803b15801561129457600080fd5b505af11580156112a8573d6000803e3d6000fd5b505050506040513d60208110156112be57600080fd5b5051610cae565b90506112e36112d3866134e7565b6112dc866134e7565b8c86611620565b96508787101561135457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4c494d49545f4f55540000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6113628b8b8b8a85886136f0565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055969b969a509598505050505050505050565b60005474010000000000000000000000000000000000000000900460ff1690565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff861684529091528120548083111561142c5733600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff88168452909152812055611468565b6114368184612cac565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff891684529091529020555b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168085529083529281902054815190815290519293927f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929181900390910190a35060019392505050565b600b5481565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205490565b611511612da4565b73ffffffffffffffffffffffffffffffffffffffff1661152f611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146115b157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080547fffffffffffffffffffffffff0000000000000000000000000000000000000000169055565b600080611635670de0b6b3a764000084612cac565b9050611641848261301f565b9050600061165387610cdd89856139ca565b90506000611669670de0b6b3a764000083612cac565b9050611675878261301f565b98975050505050505050565b6402540be400670de0b6b3a76400005b0481565b6000806116a28585612cac565b905060006116b08683612e96565b905060006116c682670de0b6b3a7640000612cac565b90506116da670de0b6b3a764000086612cac565b93506116756116e9898361301f565b85612e96565b60125473ffffffffffffffffffffffffffffffffffffffff1681565b611713612da4565b73ffffffffffffffffffffffffffffffffffffffff16611731611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146117b357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b610ca0613a3c565b60105481565b600c5481565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2611888612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117908190557501000000000000000000000000000000000000000000900460ff1661193c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b6000611946610a23565b905060006119548483612e96565b9050806119c257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b60005b6002811015611bb6576000600782600281106119dd57fe5b015473ffffffffffffffffffffffffffffffffffffffff1660008181526009602052604090206001015490915080611a7657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f5f42414c414e434500000000000000000000000000000000000000000000604482015290519081900360640190fd5b6000611a82858361301f565b9050868460028110611a9057fe5b6020020135811115611b0357604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4c494d49545f494e000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260096020526040902060010154611b3690826139ca565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600960209081526040918290206001019390935580518481529051919233927f63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a9281900390910190a3611ba6833383613b18565b5050600190920191506119c59050565b50611bc084613e13565b611bca3385613e1f565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050565b6006547501000000000000000000000000000000000000000000900460ff1690565b60005473ffffffffffffffffffffffffffffffffffffffff1690565b60058054604080516020601f60027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156109895780601f1061095e57610100808354040283529160200191610989565b6704a03ce68d21555681565b7f42524f4e5a45000000000000000000000000000000000000000000000000000090565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2611da6612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055601254604080517f66101b64000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff909216916366101b6491600480820192602092909190829003018186803b158015611e3c57600080fd5b505afa158015611e50573d6000803e3d6000fd5b505050506040513d6020811015611e6657600080fd5b50514210611ed557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f534554544c454400000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b6006547501000000000000000000000000000000000000000000900460ff1615611f6057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f49535f46494e414c495a45440000000000000000000000000000000000000000604482015290519081900360640190fd5b600654610100900473ffffffffffffffffffffffffffffffffffffffff163314611feb57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f4e4f545f434f4e54524f4c4c4552000000000000000000000000000000000000604482015290519081900360640190fd5b85881461205957604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f53594d4d455452494300000000000000000000000000000000000000604482015290519081900360640190fd5b600e829055600f81905560108490556011839055600680547fffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffff167501000000000000000000000000000000000000000000179055601254604080517f91ac094c00000000000000000000000000000000000000000000000000000000815290516121529260009273ffffffffffffffffffffffffffffffffffffffff909116916391ac094c91600480820192602092909190829003018186803b15801561211f57600080fd5b505afa158015612133573d6000803e3d6000fd5b505050506040513d602081101561214957600080fd5b50518a8a613e2d565b6121f26001601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166394f973d66040518163ffffffff1660e01b815260040160206040518083038186803b1580156121bf57600080fd5b505afa1580156121d3573d6000803e3d6000fd5b505050506040513d60208110156121e957600080fd5b50518888613e2d565b6000886121fd613fb5565b0290506000601260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663b2016bd46040518163ffffffff1660e01b815260040160206040518083038186803b15801561226a57600080fd5b505afa15801561227e573d6000803e3d6000fd5b505050506040513d602081101561229457600080fd5b5051604080517f313ce567000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163313ce56791600480820192602092909190829003018186803b1580156122fe57600080fd5b505afa158015612312573d6000803e3d6000fd5b505050506040513d602081101561232857600080fd5b505160ff16905060128110156123445780601203600a0a820291505b61234d82613e13565b6123573383613e1f565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001690555050505050505050565b6000612398338484612b43565b50600192915050565b6123a9614ad1565b6123b1612d32565b60408051808201918290529060079060029082845b815473ffffffffffffffffffffffffffffffffffffffff1681526001909101906020018083116123c6575050505050905090565b600f5481565b60135473ffffffffffffffffffffffffffffffffffffffff1681565b60115481565b33600090815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff8616845290915281205461245d90836139ca565b33600081815260026020908152604080832073ffffffffffffffffffffffffffffffffffffffff89168085529083529281902085905580519485525191937f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925929081900390910190a350600192915050565b3373ffffffffffffffffffffffffffffffffffffffff166000357fffffffff00000000000000000000000000000000000000000000000000000000167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018290039550909350505050a2612590612d32565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117908190557501000000000000000000000000000000000000000000900460ff1661264457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f4e4f545f46494e414c495a454400000000000000000000000000000000000000604482015290519081900360640190fd5b600061264e610a23565b9050600061265c8483612e96565b9050806126ca57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b6126d43385614211565b6126dd8461421b565b60005b60028110156128cc576000600782600281106126f857fe5b015473ffffffffffffffffffffffffffffffffffffffff166000818152600960205260409020600101549091508061279157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600a60248201527f4e4f5f42414c414e434500000000000000000000000000000000000000000000604482015290519081900360640190fd5b600061279d858361301f565b90508684600281106127ab57fe5b602002013581101561281e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600960248201527f4c494d49545f4f55540000000000000000000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff83166000908152600960205260409020600101546128519082612cac565b73ffffffffffffffffffffffffffffffffffffffff84166000818152600960209081526040918290206001019390935580518481529051919233927fe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed9281900390910190a36128c1833383614224565b5050506001016126e0565b5050600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055505050565b600281565b600181565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260026020908152604080832093909416825291909152205490565b6002670de0b6b3a7640000611691565b612955612da4565b73ffffffffffffffffffffffffffffffffffffffff16612973611c1a565b73ffffffffffffffffffffffffffffffffffffffff16146129f557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8116612a61576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180614af06026913960400191505060405180910390fd5b6000805460405173ffffffffffffffffffffffffffffffffffffffff808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b6000612af8612d32565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526009602052604090206001015490565b60008080612b3662015180850461436c565b9196909550909350915050565b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054811115612bd757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f494e53554646494349454e545f42414c00000000000000000000000000000000604482015290519081900360640190fd5b73ffffffffffffffffffffffffffffffffffffffff8316600090815260016020526040902054612c079082612cac565b73ffffffffffffffffffffffffffffffffffffffff8085166000908152600160205260408082209390935590841681522054612c4390826139ca565b73ffffffffffffffffffffffffffffffffffffffff80841660008181526001602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600080612cb98484614420565b90925090508015612d2b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f5355425f554e444552464c4f5700000000000000000000000000000000000000604482015290519081900360640190fd5b5092915050565b60065460ff1615610ca057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f5245454e54525900000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b3390565b612db061139c565b612e1b57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f7420706175736564000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa612e6c612da4565b6040805173ffffffffffffffffffffffffffffffffffffffff9092168252519081900360200190a1565b600081612f0457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600860248201527f4449565f5a45524f000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a76400008302831580612f2c5750670de0b6b3a7640000848281612f2957fe5b04145b612f9757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b6002830481018181101561300c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4449565f494e5445524e414c0000000000000000000000000000000000000000604482015290519081900360640190fd5b83818161301557fe5b0495945050505050565b600082820283158061303957508284828161303657fe5b04145b6130a457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b6706f05b59d3b2000081018181101561311e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4d554c5f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b670de0b6b3a764000081613015565b43600a54141561313c57610ca0565b43600a55600060098161314d614445565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600060096000613197614468565b73ffffffffffffffffffffffffffffffffffffffff90811682526020808301939093526040918201600090812083518085018552600180890154825288548288015285518087018752908301548152825481880152601454600e5460115460125489517fb4ba0231000000000000000000000000000000000000000000000000000000008152600481018990529951969b5094999398969788978897889795831696631a1afbc596909316928d928d92859263b4ba02319260248082019391829003018186803b15801561326a57600080fd5b505afa15801561327e573d6000803e3d6000fd5b505050506040513d602081101561329457600080fd5b5051604080517fffffffff0000000000000000000000000000000000000000000000000000000060e08a901b168152600481018881526024820188905273ffffffffffffffffffffffffffffffffffffffff8716604483015291606490910190859080838360005b838110156133145781810151838201526020016132fc565b5050505090500183600260200280838360005b8381101561333f578181015183820152602001613327565b50505050905001828152602001965050505050505060806040518083038186803b15801561336c57600080fd5b505afa158015613380573d6000803e3d6000fd5b505050506040513d608081101561339657600080fd5b508051602080830151604080850151606090950151600a548c518c518e8701518e88015160125487517fb4ba02310000000000000000000000000000000000000000000000000000000081526000600482015297519a9f50979d50999b509399507f20a9a7e8eddd119db42373ce305e5cd9ca3521682c54e58bca672a721dd0281898929791969095939492938d938d938d938d9373ffffffffffffffffffffffffffffffffffffffff169263b4ba02319260248083019392829003018186803b15801561346357600080fd5b505afa158015613477573d6000803e3d6000fd5b505050506040513d602081101561348d57600080fd5b5051604080519a8b5260208b0199909952898901979097526060890195909552608088019390935260a087019190915260c086015260e085015261010084015261012083015251908190036101400190a150509455505055565b6000610a018260200151836000015161301f565b60008183101561350c575081610a01565b50919050565b6000806000601360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a18034d160405180606001604052808a6020015181526020018a600001518152602001898152506040518060600160405280896020015181526020018960000151815260200188815250600b54600c54600d546040518663ffffffff1660e01b81526004018086600360200280838360005b838110156135db5781810151838201526020016135c3565b5050505090500185600360200280838360005b838110156136065781810151838201526020016135ee565b50505050905001848152602001838152602001828152602001955050505050506040805180830381600087803b15801561363f57600080fd5b505af1158015613653573d6000803e3d6000fd5b505050506040513d604081101561366957600080fd5b50805160209091015192509050600081136136e557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600760248201527f4241445f46454500000000000000000000000000000000000000000000000000604482015290519081900360640190fd5b969095509350505050565b73ffffffffffffffffffffffffffffffffffffffff8087166000908152600960205260408082209287168252812090919061372d82898389614473565b613739828983896147e2565b6137478260010154896139ca565b826001018190555061375d816001015487612cac565b60018083019190915560408051808201909152835481529083015460208201526138349061378a906134e7565b6040805180820190915283548152600184015460208201526137ab906134e7565b6013546001868101549086015473ffffffffffffffffffffffffffffffffffffffff9092169163e91fe030916137e091614932565b600b54600c54600d546040518563ffffffff1660e01b815260040180858152602001848152602001838152602001828152602001945050505050602060405180830381600087803b15801561129457600080fd5b9250848310156138a557604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d4154485f415050524f58000000000000000000000000000000000000000000604482015290519081900360640190fd5b6138af8887612e96565b85111561391d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f4d4154485f415050524f585f4f54484552000000000000000000000000000000604482015290519081900360640190fd5b6001808301549082015483548354604080518d8152602081018c90528082018a90526060810195909552608085019390935260a084019190915260c08301525173ffffffffffffffffffffffffffffffffffffffff808a1692908c169133917f1c5fe691bf1a10c1e6c35d8974514451cd3f40ed1135a0450fe2550e3ebae597919081900360e00190a46139b289338a613b18565b506139be873388614224565b50509695505050505050565b81810182811015610a0157604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600c60248201527f4144445f4f564552464c4f570000000000000000000000000000000000000000604482015290519081900360640190fd5b613a4461139c565b15613ab057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a2070617573656400000000000000000000000000000000604482015290519081900360640190fd5b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612e6c612da4565b6000808473ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613b8257600080fd5b505afa158015613b96573d6000803e3d6000fd5b505050506040513d6020811015613bac57600080fd5b5051604080517f23b872dd00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8781166004830152306024830152604482018790529151929350908716916323b872dd9160648082019260009290919082900301818387803b158015613c2f57600080fd5b505af1158015613c43573d6000803e3d6000fd5b5050505060003d60008114613c5f5760208114613c8757600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9150613c93565b60206000803e60005191505b5080613d0057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601860248201527f544f4b454e5f5452414e534645525f494e5f4641494c45440000000000000000604482015290519081900360640190fd5b60008673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015613d6957600080fd5b505afa158015613d7d573d6000803e3d6000fd5b505050506040513d6020811015613d9357600080fd5b5051905082811015613e0657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f544f4b454e5f5452414e534645525f494e5f4f564552464c4f57000000000000604482015290519081900360640190fd5b9190910395945050505050565b613e1c81614953565b50565b613e2982826149c8565b5050565b600f54821015613e9e57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600b60248201527f4d494e5f42414c414e4345000000000000000000000000000000000000000000604482015290519081900360640190fd5b60008111613f0d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600d60248201527f5a45524f5f4c4556455241474500000000000000000000000000000000000000604482015290519081900360640190fd5b604080518082018252828152602080820185815273ffffffffffffffffffffffffffffffffffffffff8716600090815260099092529290209051815590516001909101558260078560028110613f5f57fe5b0180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055613fae833384613b18565b5050505050565b601254604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905160009273ffffffffffffffffffffffffffffffffffffffff169163dbcb32bf916004808301926020929190829003018186803b15801561402057600080fd5b505afa158015614034573d6000803e3d6000fd5b505050506040513d602081101561404a57600080fd5b5051604080517fab56c592000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163ab56c59291600480820192602092909190829003018186803b1580156140b457600080fd5b505afa1580156140c8573d6000803e3d6000fd5b505050506040513d60208110156140de57600080fd5b5051601254604080517fdbcb32bf000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163dbcb32bf91600480820192602092909190829003018186803b15801561414b57600080fd5b505afa15801561415f573d6000803e3d6000fd5b505050506040513d602081101561417557600080fd5b5051604080517fc6bb30e2000000000000000000000000000000000000000000000000000000008152905173ffffffffffffffffffffffffffffffffffffffff9092169163c6bb30e291600480820192602092909190829003018186803b1580156141df57600080fd5b505afa1580156141f3573d6000803e3d6000fd5b505050506040513d602081101561420957600080fd5b505101919050565b613e2982826149d3565b613e1c816149de565b8273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050600060405180830381600087803b15801561429557600080fd5b505af11580156142a9573d6000803e3d6000fd5b5050505060003d600081146142c557602081146142ed57600080fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff91506142f9565b60206000803e60005191505b508061436657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f544f4b454e5f5452414e534645525f4f55545f4641494c454400000000000000604482015290519081900360640190fd5b50505050565b60008080836226496581018262023ab1600483020590506004600362023ab18302010590910390600062164b09610fa0600185010205905060046105b58202058303601f019250600061098f84605002816143c357fe5b0590506000605061098f83020585039050600b82057fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcf94909401606402929092018301996002600c90940290910392909201975095509350505050565b600080828410614436575050808203600061443e565b505081810360015b9250929050565b60006007815b015473ffffffffffffffffffffffffffffffffffffffff16905090565b60006007600161444b565b600f546040805180820190915283548152600184015460208201526144a19061449b906134e7565b83612cac565b1161450d57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f424f554e444152595f4c45564552414745440000000000000000000000000000604482015290519081900360640190fd5b600f5461451e836001015483612cac565b1161458a57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f424f554e444152595f4e4f4e5f4c455645524147454400000000000000000000604482015290519081900360640190fd5b6000670de0b6b3a764000061459d613fb5565b02905060006145b4600e54610cdd84600e54612cac565b905060006145cf6145c784600e54612cac565b600e54612e96565b905060006146326146076146018a604051806040016040529081600082015481526020016001820154815250506134e7565b896139ca565b604080518082019091528854815260018901546020820152610cdd9061462c906134e7565b88612cac565b90508083106146a257604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f424f554e444152595f4c4f574552000000000000000000000000000000000000604482015290519081900360640190fd5b81811061471057604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f424f554e444152595f5550504552000000000000000000000000000000000000604482015290519081900360640190fd5b600061473661472c6147268b600101548b6139ca565b886139ca565b8860010154614420565b5080915050600061475b61462c6147518c600101548c6139ca565b8a600101546139ca565b905060105461476a8383612e96565b106147d657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f424f554e444152595f4558504f53555245000000000000000000000000000000604482015290519081900360640190fd5b50505050505050505050565b6040805180820190915282548152600183015460208201526148199061480b9061449b906134e7565b610cdd846001015484612cac565b80835561488757604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601160248201527f5a45524f5f4f55545f4c45564552414745000000000000000000000000000000604482015290519081900360640190fd5b6040805180820190915284548152600185015460208201526148c4906148b6906148b0906134e7565b856139ca565b610cdd8660010154866139ca565b80855561436657604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5a45524f5f494e5f4c4556455241474500000000000000000000000000000000604482015290519081900360640190fd5b6000818301670de0b6b3a7640000838503028161494b57fe5b059392505050565b3060009081526001602052604090205461496d90826139ca565b3060009081526001602052604090205560035461498a90826139ca565b60035560408051828152905130916000917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b613e29308383612b43565b613e29823083612b43565b30600090815260016020526040902054811115614a5c57604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f494e53554646494349454e545f42414c00000000000000000000000000000000604482015290519081900360640190fd5b30600090815260016020526040902054614a769082612cac565b30600090815260016020526040902055600354614a939082612cac565b60035560408051828152905160009130917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a350565b6040518060400160405280600290602082028036833750919291505056fe4f776e61626c653a206e6577206f776e657220697320746865207a65726f2061646472657373a26469706673582212203d1d5f5109d6b6fd6706cfca3141555ad03b66bfe251fe16f38afc347192dbf864736f6c63430007060033

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

0000000000000000000000004eba099f97ffed8de47a14f835820815f141ea08000000000000000000000000db635eebaedef9801653f559e2c859aa81ac1ff4000000000000000000000000ee981eb86df4569b6368d9cb2172ff971bf453de0000000000000000000000000000000000000000000000000011c37937e0800000000000000000000000000000000000000000000000000003782dace9d90000000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000007a596c2d3e0f390a212a8ed47308cf621b5e949c

-----Decoded View---------------
Arg [0] : _derivativeVault (address): 0x4eba099F97ffeD8de47a14f835820815f141Ea08
Arg [1] : _dynamicFee (address): 0xdB635EEbaEdEF9801653F559E2C859aA81Ac1FF4
Arg [2] : _repricer (address): 0xee981EB86DF4569b6368d9Cb2172Ff971Bf453dE
Arg [3] : _baseFee (uint256): 5000000000000000
Arg [4] : _maxFee (uint256): 250000000000000000
Arg [5] : _feeAmp (uint256): 10
Arg [6] : _controller (address): 0x7A596C2d3e0f390A212a8Ed47308cf621b5E949C

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000004eba099f97ffed8de47a14f835820815f141ea08
Arg [1] : 000000000000000000000000db635eebaedef9801653f559e2c859aa81ac1ff4
Arg [2] : 000000000000000000000000ee981eb86df4569b6368d9cb2172ff971bf453de
Arg [3] : 0000000000000000000000000000000000000000000000000011c37937e08000
Arg [4] : 00000000000000000000000000000000000000000000000003782dace9d90000
Arg [5] : 000000000000000000000000000000000000000000000000000000000000000a
Arg [6] : 0000000000000000000000007a596c2d3e0f390a212a8ed47308cf621b5e949c


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.