Contract 0x26607aC599266b21d13c7aCF7942c7701a8b699c 5

Token Contract Sybil Delegate  
 
 
Txn Hash
Method
Block
From
To
Value
0xa4f5944a25cc63e2478099118109214d557fbcf407198445d80c0c6b413702e5Approve161217252022-12-05 22:59:5922 hrs 2 mins ago0xbda1498585a6b1c77b50fc3add3f1b50020ca759 IN  PowerIndex: PIPT Token0 Ether0.00062282 13.40930092
0x9121b9cfdee095efe9c9ab301c5f9b33b66bc6437fb87e77f142ec5fa31b54ecApprove160712022022-11-28 21:34:117 days 23 hrs ago0x212d094b0b33760b7a7277b679ab2283cc6b4bdf IN  PowerIndex: PIPT Token0 Ether0.00058125 12.51434176
0x4e6a9bcf85329de1bfe1ec43c7aad1084195e59f04fe45b5c270929950939301Approve160598122022-11-27 7:24:479 days 13 hrs ago0xd4de9f0fa7c40853146ad4994bb3a52615ffdb40 IN  PowerIndex: PIPT Token0 Ether0.00025476 10.54348551
0x25d64d563c3956bec85af7b15e0e73f9487113f512ae318394dc159c421ea8ebApprove160598122022-11-27 7:24:479 days 13 hrs ago0xd4de9f0fa7c40853146ad4994bb3a52615ffdb40 IN  PowerIndex: PIPT Token0 Ether0.00025476 10.54348551
0xd95056c75d17774870631ddfb2b5ba8d812c9cda346f0a15f3609c4483be9d80Approve160387332022-11-24 8:45:5912 days 12 hrs ago0xcb70c73907ac286cf2d4ff39b3212d5d9e803ed4 IN  PowerIndex: PIPT Token0 Ether0.00027526 11.3919725
0x423bb309677c7305368b2006b1fca99c86c2210cdda5471c91931a512363d14dExit Pool160349012022-11-23 19:53:2313 days 1 hr ago0x3402a176993c247c178adbb03c1a651052744842 IN  PowerIndex: PIPT Token0 Ether0.01079305 14.23471246
0xa4f57303bcf4e14551a293dcf1c63d1f26e5f63576bd11c833196cfd22206629Approve160348772022-11-23 19:48:3513 days 1 hr ago0x3402a176993c247c178adbb03c1a651052744842 IN  PowerIndex: PIPT Token0 Ether0.00046666 16.04585326
0xb0412faf303dfe0d8ee9ba12dbe1ed85b8d6bf29d9728b45544d6a79ed4bbb40Approve159632452022-11-13 19:38:2323 days 1 hr agoENS Name t0zem00n.eth IN  PowerIndex: PIPT Token0 Ether0.0005096 19.47807774
0xd3820ad11578fc6035aa402f50f34a164f9eaa24de26718c8ea194afe0110b5aApprove159589822022-11-13 5:22:2323 days 15 hrs agoENS Name *🐵🐒🐵🐒🐵🐒🐵🐒🐵🐒🐵🐒.eth IN  PowerIndex: PIPT Token0 Ether0.00055372 11.92156075
0xe23ac0d5b47b9fd776275302c6baf05355923b4abf2909cefa8c418430637fd7Approve159589352022-11-13 5:12:5923 days 15 hrs ago0x12478d1a60a910c9cbffb90648766a2bdd5918f5 IN  PowerIndex: PIPT Token0 Ether0.00050058 10.77751033
0x59ddcd8bb1d35b8a7961282f6a8cafb1b520a404394d0f1f9bd992600f9db7edExitswap Pool Am...159491432022-11-11 20:25:3525 days 36 mins ago0xd2b971fbb356c05d8916faa4a3047755a4a6e57e IN  PowerIndex: PIPT Token0 Ether0.00479504 18.38281563
0x0eaa3fca4def498d8ceb4682c8fb7e2210ae586d6ec7763423fe79e21e01b1dcApprove159491392022-11-11 20:24:4725 days 37 mins ago0xd2b971fbb356c05d8916faa4a3047755a4a6e57e IN  PowerIndex: PIPT Token0 Ether0.0008545 18.50744842
0x05e2746e219400f972b3e80c7bd53b63a3baee7dadb9db0159f29d158e95fc63Approve159491192022-11-11 20:20:4725 days 41 mins ago0xd2b971fbb356c05d8916faa4a3047755a4a6e57e IN  PowerIndex: PIPT Token0 Ether0.00078447 16.88963089
0x81c1cdf8ee096226cb92bdb8781357782ffb847d2dc6d8dee131f7108322ab0eExitswap Pool Am...159320242022-11-09 10:57:4727 days 10 hrs ago0x891bad61014e35395474a260b58bb6df4fd8991b IN  PowerIndex: PIPT Token0 Ether0.00783882 39.48634537
0x95d51c9b94ade0f8c3fee0e890383251fb974fd5e419e6b60f6f6ba547e6c118Exitswap Pool Am...159320102022-11-09 10:54:5927 days 10 hrs ago0x891bad61014e35395474a260b58bb6df4fd8991b IN  PowerIndex: PIPT Token0 Ether0.00927145 45.60567391
0xb55d4a3f740fee38472b803580c95ca384484f2874a8015514faf241a76e6d06Exitswap Pool Am...159320042022-11-09 10:53:4727 days 10 hrs ago0x891bad61014e35395474a260b58bb6df4fd8991b IN  PowerIndex: PIPT Token0 Ether0.01109323 50.33321624
0x765969770c4903c9606217291805b7445ad50e421f18e997929fb9e6f7b66e9bApprove159319872022-11-09 10:50:2327 days 10 hrs ago0x891bad61014e35395474a260b58bb6df4fd8991b IN  PowerIndex: PIPT Token0 Ether0.00248688 53.84847457
0x642611c5d72bb0343a0200e64df299fccea71514f066320d60727658ce0550d1Exitswap Pool Am...158543482022-10-29 14:36:2338 days 6 hrs ago0xe4989e7b39a21089b128908e1603fdc9939dbb78 IN  PowerIndex: PIPT Token0 Ether0.00408837 15.67364449
0x207ac05aa018b3efc17d273a2478e7858cf88c7d0ba00bbc319db049b0838c2bExitswap Pool Am...158543192022-10-29 14:30:3538 days 6 hrs ago0xe4989e7b39a21089b128908e1603fdc9939dbb78 IN  PowerIndex: PIPT Token0 Ether0.00423018 15.59330087
0xc53116ab22889b3e26e911a720ac6d481e91f552b24ea7f8f6d92a24f1549932Exitswap Pool Am...158542972022-10-29 14:26:1138 days 6 hrs ago0xe4989e7b39a21089b128908e1603fdc9939dbb78 IN  PowerIndex: PIPT Token0 Ether0.00666384 14.85022889
0x2b31565b13416570af7697432839053a5b9242a13017412794caf5eef5e16b48Approve158542352022-10-29 14:13:4738 days 6 hrs ago0xe4989e7b39a21089b128908e1603fdc9939dbb78 IN  PowerIndex: PIPT Token0 Ether0.00060867 20.92886054
0x64c9b4d4c24493ca8c1ab00dfe6b29977f4381fe213be2ca9b80e60712149047Approve158391372022-10-27 11:32:1140 days 9 hrs ago0x4da94e682326bd14997d1e1c62350654d8e44c5d IN  PowerIndex: PIPT Token0 Ether0.00047273 10.17803083
0xc24ef2e75e7acc1cde6f6f847109a0dfba00e584bf94265e9d923a1c2d8d0cc5Approve158089372022-10-23 6:11:4744 days 14 hrs ago0x0dd16c537cdb346826203f3ab762030e7f20c78a IN  PowerIndex: PIPT Token0 Ether0.00066773 14.37625665
0xec88db745bc06fd077a2873812c6afab1254747589d79e4f62297a5fddab0c70Approve157720492022-10-18 2:37:1149 days 18 hrs ago0x05d687fbd98718068f583a17274f3a61e1f845b9 IN  PowerIndex: PIPT Token0 Ether0.0010011 21.55362442
0xe8a406acb7c3803db2ef89ad79b538fc88e4a028351eeeaecc7397d5b463a1e3Exitswap Pool Am...157542642022-10-15 14:58:3552 days 6 hrs ago0xe4989e7b39a21089b128908e1603fdc9939dbb78 IN  PowerIndex: PIPT Token0 Ether0.00704222 15.86225024
[ Download CSV Export 

OVERVIEW

PIPT is a PowerIndex Pool Token - a share of PowerIndex pool. PowerIndex stores a basket of 8 assets on a special smart-contract in Ethereum. This token can be issued only by supplying liquidity to it. When someone supplies liquidity to the contract, PIPT token is minted.

Latest 1 internal transaction
Parent Txn Hash Block From To Value
0xba781a359fd1d017eeddd3f0ffd1746a0e4fccf4a0d3c8a2a96cba98d75fce8d113623682020-11-30 20:41:50736 days 20 mins ago PowerIndex: Deployer  Contract Creation0 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PowerIndexPool

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 2 runs

Other Settings:
default evmVersion
File 1 of 11 : BConst.sol
// SPDX-License-Identifier: GPL-3.0
// 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.6.12;

contract BConst {
    uint public constant BONE              = 10**18;

    uint public constant MIN_BOUND_TOKENS  = 2;
    uint public constant MAX_BOUND_TOKENS  = 9;

    uint public constant MIN_FEE           = BONE / 10**6;
    uint public constant MAX_FEE           = BONE / 10;

    uint public constant MIN_WEIGHT        = 1000000000;
    uint public constant MAX_WEIGHT        = BONE * 50;
    uint public constant MAX_TOTAL_WEIGHT  = BONE * 50;
    uint public constant MIN_BALANCE       = BONE / 10**12;

    uint public constant INIT_POOL_SUPPLY  = BONE * 100;

    uint public constant MIN_BPOW_BASE     = 1 wei;
    uint public constant MAX_BPOW_BASE     = (2 * BONE) - 1 wei;
    uint public constant BPOW_PRECISION    = BONE / 10**10;

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

File 2 of 11 : BNum.sol
// SPDX-License-Identifier: GPL-3.0
// 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.6.12;

import "./BConst.sol";

contract BNum is BConst {

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

    function bfloor(uint a)
        internal pure
        returns (uint)
    {
        return btoi(a) * BONE;
    }

    function badd(uint a, uint b)
        internal pure
        returns (uint)
    {
        uint c = a + b;
        require(c >= a, "ERR_ADD_OVERFLOW");
        return c;
    }

    function bsub(uint a, uint b)
        internal pure
        returns (uint)
    {
        (uint c, bool flag) = bsubSign(a, b);
        require(!flag, "ERR_SUB_UNDERFLOW");
        return c;
    }

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

    function bmul(uint a, uint b)
        internal pure
        returns (uint)
    {
        uint c0 = a * b;
        require(a == 0 || c0 / a == b, "ERR_MUL_OVERFLOW");
        uint c1 = c0 + (BONE / 2);
        require(c1 >= c0, "ERR_MUL_OVERFLOW");
        uint c2 = c1 / BONE;
        return c2;
    }

    function bdiv(uint a, uint b)
        internal pure
        returns (uint)
    {
        require(b != 0, "ERR_DIV_ZERO");
        uint c0 = a * BONE;
        require(a == 0 || c0 / a == BONE, "ERR_DIV_INTERNAL"); // bmul overflow
        uint c1 = c0 + (b / 2);
        require(c1 >= c0, "ERR_DIV_INTERNAL"); //  badd require
        uint c2 = c1 / b;
        return c2;
    }

    function div(uint256 a, uint256 b) internal pure returns (uint256) {
      require(b > 0, "ERR_DIV_ZERO");
      return a / b;
    }

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

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

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

    // Compute b^(e.w) by splitting it into (b^e)*(b^0.w).
    // Use `bpowi` for `b^e` and `bpowK` for k iterations
    // of approximation of b^0.w
    function bpow(uint base, uint exp)
        internal pure
        returns (uint)
    {
        require(base >= MIN_BPOW_BASE, "ERR_BPOW_BASE_TOO_LOW");
        require(base <= MAX_BPOW_BASE, "ERR_BPOW_BASE_TOO_HIGH");

        uint whole  = bfloor(exp);
        uint remain = bsub(exp, whole);

        uint wholePow = bpowi(base, btoi(whole));

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

        uint partialResult = bpowApprox(base, remain, BPOW_PRECISION);
        return bmul(wholePow, partialResult);
    }

    function bpowApprox(uint base, uint exp, uint precision)
        internal pure
        returns (uint)
    {
        // term 0:
        uint a     = exp;
        (uint x, bool xneg)  = bsubSign(base, BONE);
        uint term = BONE;
        uint 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) = bsubSign(a, bsub(bigK, BONE));
            term = bmul(term, bmul(c, x));
            term = bdiv(term, bigK);
            if (term == 0) break;

            if (xneg) negative = !negative;
            if (cneg) negative = !negative;
            if (negative) {
                sum = bsub(sum, term);
            } else {
                sum = badd(sum, term);
            }
        }

        return sum;
    }

}

File 3 of 11 : BToken.sol
// SPDX-License-Identifier: GPL-3.0
// 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.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./BNum.sol";

contract BTokenBase is BNum {

    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)] = badd(_balance[address(this)], amt);
        _totalSupply = badd(_totalSupply, amt);
        emit Transfer(address(0), address(this), amt);
    }

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

    function _move(address src, address dst, uint amt) internal {
        require(_balance[src] >= amt, "ERR_INSUFFICIENT_BAL");
        _validateAddress(src);
        _validateAddress(dst);
        _balance[src] = bsub(_balance[src], amt);
        _balance[dst] = badd(_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);
    }

    function _validateAddress(address addr) internal {
        require(addr != address(0), "ERR_NULL_ADDRESS");
    }
}

contract BToken is BTokenBase, IERC20 {

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

    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 override view returns (uint) {
        return _allowance[src][dst];
    }

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

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

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

    function increaseApproval(address dst, uint amt) external returns (bool) {
        _validateAddress(dst);
        _allowance[msg.sender][dst] = badd(_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) {
        _validateAddress(dst);
        uint oldValue = _allowance[msg.sender][dst];
        if (amt > oldValue) {
            _allowance[msg.sender][dst] = 0;
        } else {
            _allowance[msg.sender][dst] = bsub(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) {
        require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_BTOKEN_BAD_CALLER");
        _move(src, dst, amt);
        if (msg.sender != src && _allowance[src][msg.sender] != uint256(-1)) {
            _allowance[src][msg.sender] = bsub(_allowance[src][msg.sender], amt);
            emit Approval(src, msg.sender, _allowance[src][msg.sender]);
        }
        return true;
    }
}

File 4 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.6.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

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

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

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

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

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

File 5 of 11 : BPoolInterface.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./BMathInterface.sol";

interface BPoolInterface is IERC20, BMathInterface {
  function joinPool(uint256 poolAmountOut, uint256[] calldata maxAmountsIn) external;

  function exitPool(uint256 poolAmountIn, uint256[] calldata minAmountsOut) external;

  function swapExactAmountIn(
    address,
    uint256,
    address,
    uint256,
    uint256
  ) external returns (uint256, uint256);

  function swapExactAmountOut(
    address,
    uint256,
    address,
    uint256,
    uint256
  ) external returns (uint256, uint256);

  function joinswapExternAmountIn(
    address,
    uint256,
    uint256
  ) external returns (uint256);

  function joinswapPoolAmountOut(
    address,
    uint256,
    uint256
  ) external returns (uint256);

  function exitswapPoolAmountIn(
    address,
    uint256,
    uint256
  ) external returns (uint256);

  function exitswapExternAmountOut(
    address,
    uint256,
    uint256
  ) external returns (uint256);

  function getDenormalizedWeight(address) external view returns (uint256);

  function getBalance(address) external view returns (uint256);

  function getSwapFee() external view returns (uint256);

  function getTotalDenormalizedWeight() external view returns (uint256);

  function getCommunityFee()
    external
    view
    returns (
      uint256,
      uint256,
      uint256,
      address
    );

  function calcAmountWithCommunityFee(
    uint256,
    uint256,
    address
  ) external view returns (uint256, uint256);

  function getRestrictions() external view returns (address);

  function isPublicSwap() external view returns (bool);

  function isFinalized() external view returns (bool);

  function isBound(address t) external view returns (bool);

  function getCurrentTokens() external view returns (address[] memory tokens);

  function getFinalTokens() external view returns (address[] memory tokens);

  function setSwapFee(uint256) external;

  function setCommunityFeeAndReceiver(
    uint256,
    uint256,
    uint256,
    address
  ) external;

  function setController(address) external;

  function setPublicSwap(bool) external;

  function finalize() external;

  function bind(
    address,
    uint256,
    uint256
  ) external;

  function rebind(
    address,
    uint256,
    uint256
  ) external;

  function unbind(address) external;

  function callVoting(
    address voting,
    bytes4 signature,
    bytes calldata args,
    uint256 value
  ) external;

  function getMinWeight() external view returns (uint256);

  function getMaxBoundTokens() external view returns (uint256);
}

File 6 of 11 : BMathInterface.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface BMathInterface {
  function calcInGivenOut(
    uint256 tokenBalanceIn,
    uint256 tokenWeightIn,
    uint256 tokenBalanceOut,
    uint256 tokenWeightOut,
    uint256 tokenAmountOut,
    uint256 swapFee
  ) external pure returns (uint256 tokenAmountIn);
}

File 7 of 11 : PowerIndexPoolInterface.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

import "./BPoolInterface.sol";

interface PowerIndexPoolInterface is BPoolInterface {
  function bind(
    address,
    uint256,
    uint256,
    uint256,
    uint256
  ) external;

  function setDynamicWeight(
    address token,
    uint256 targetDenorm,
    uint256 fromTimestamp,
    uint256 targetTimestamp
  ) external;

  function getDynamicWeightSettings(address token)
    external
    view
    returns (
      uint256 fromTimestamp,
      uint256 targetTimestamp,
      uint256 fromDenorm,
      uint256 targetDenorm
    );

  function getMinWeight() external view override returns (uint256);
}

File 8 of 11 : PowerIndexPool.sol
/*
https://powerpool.finance/

          wrrrw r wrr
         ppwr rrr wppr0       prwwwrp                                 prwwwrp                   wr0
        rr 0rrrwrrprpwp0      pp   pr  prrrr0 pp   0r  prrrr0  0rwrrr pp   pr  prrrr0  prrrr0    r0
        rrp pr   wr00rrp      prwww0  pp   wr pp w00r prwwwpr  0rw    prwww0  pp   wr pp   wr    r0
        r0rprprwrrrp pr0      pp      wr   pr pp rwwr wr       0r     pp      wr   pr wr   pr    r0
         prwr wrr0wpwr        00        www0   0w0ww    www0   0w     00        www0    www0   0www0
          wrr ww0rrrr

*/

// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.6.12;

import "./balancer-core/BPool.sol";
import "./interfaces/PowerIndexPoolInterface.sol";

contract PowerIndexPool is BPool {
  /// @notice The event emitted when a dynamic weight set to token
  event SetDynamicWeight(
    address indexed token,
    uint256 fromDenorm,
    uint256 targetDenorm,
    uint256 fromTimestamp,
    uint256 targetTimestamp
  );

  /// @notice The event emitted when weight per second bounds set
  event SetWeightPerSecondBounds(uint256 minWeightPerSecond, uint256 maxWeightPerSecond);

  struct DynamicWeight {
    uint256 fromTimestamp;
    uint256 targetTimestamp;
    uint256 targetDenorm;
  }

  /// @dev Mapping for storing dynamic weights settings. fromDenorm stored in _records mapping as denorm variable
  mapping(address => DynamicWeight) private _dynamicWeights;

  /// @dev Min weight per second limit
  uint256 private _minWeightPerSecond;
  /// @dev Max weight per second limit
  uint256 private _maxWeightPerSecond;

  constructor(
    string memory name,
    string memory symbol,
    uint256 minWeightPerSecond,
    uint256 maxWeightPerSecond
  ) public BPool(name, symbol) {
    _minWeightPerSecond = minWeightPerSecond;
    _maxWeightPerSecond = maxWeightPerSecond;
  }

  /*** Controller Interface ***/

  /**
   * @notice Set weight per second bounds by controller
   * @param minWeightPerSecond Min weight per second
   * @param maxWeightPerSecond Max weight per second
   */
  function setWeightPerSecondBounds(uint256 minWeightPerSecond, uint256 maxWeightPerSecond) public _logs_ _lock_ {
    _onlyController();
    _minWeightPerSecond = minWeightPerSecond;
    _maxWeightPerSecond = maxWeightPerSecond;

    emit SetWeightPerSecondBounds(minWeightPerSecond, maxWeightPerSecond);
  }

  /**
   * @notice Set dynamic weight for token by controller
   * @param token Token for change settings
   * @param targetDenorm Target weight. fromDenorm will be fetch by current value of _getDenormWeight
   * @param fromTimestamp From timestamp of dynamic weight
   * @param targetTimestamp Target timestamp of dynamic weight
   */
  function setDynamicWeight(
    address token,
    uint256 targetDenorm,
    uint256 fromTimestamp,
    uint256 targetTimestamp
  ) public _logs_ _lock_ {
    _onlyController();
    _requireTokenIsBound(token);

    require(fromTimestamp > block.timestamp, "CANT_SET_PAST_TIMESTAMP");
    require(targetTimestamp > fromTimestamp, "TIMESTAMP_INCORRECT_DELTA");
    require(targetDenorm >= MIN_WEIGHT && targetDenorm <= MAX_WEIGHT, "TARGET_WEIGHT_BOUNDS");

    uint256 fromDenorm = _getDenormWeight(token);
    uint256 weightPerSecond = _getWeightPerSecond(fromDenorm, targetDenorm, fromTimestamp, targetTimestamp);
    require(weightPerSecond <= _maxWeightPerSecond, "MAX_WEIGHT_PER_SECOND");
    require(weightPerSecond >= _minWeightPerSecond, "MIN_WEIGHT_PER_SECOND");

    _records[token].denorm = fromDenorm;

    _dynamicWeights[token] = DynamicWeight({
      fromTimestamp: fromTimestamp,
      targetTimestamp: targetTimestamp,
      targetDenorm: targetDenorm
    });

    uint256 denormSum = 0;
    uint256 len = _tokens.length;
    for (uint256 i = 0; i < len; i++) {
      denormSum = badd(denormSum, _dynamicWeights[_tokens[i]].targetDenorm);
    }

    require(denormSum <= MAX_TOTAL_WEIGHT, "MAX_TARGET_TOTAL_WEIGHT");

    emit SetDynamicWeight(token, fromDenorm, targetDenorm, fromTimestamp, targetTimestamp);
  }

  /**
   * @notice Bind and setDynamicWeight at the same time
   * @param token Token for bind
   * @param balance Initial balance
   * @param targetDenorm Target weight
   * @param fromTimestamp From timestamp of dynamic weight
   * @param targetTimestamp Target timestamp of dynamic weight
   */
  function bind(
    address token,
    uint256 balance,
    uint256 targetDenorm,
    uint256 fromTimestamp,
    uint256 targetTimestamp
  )
    external
    _logs_ // _lock_  Bind does not lock because it jumps to `rebind` and `setDynamicWeight`, which does
  {
    super.bind(token, balance, MIN_WEIGHT);

    setDynamicWeight(token, targetDenorm, fromTimestamp, targetTimestamp);
  }

  /**
   * @notice Override parent unbind function
   * @param token Token for unbind
   */
  function unbind(address token) public override {
    super.unbind(token);

    _dynamicWeights[token] = DynamicWeight(0, 0, 0);
  }

  /**
   * @notice Override parent bind function and disable.
   */
  function bind(
    address,
    uint256,
    uint256
  ) public override {
    revert("DISABLED"); // Only new bind function is allowed
  }

  /**
   * @notice Override parent rebind function. Allowed only for calling from bind function
   * @param token Token for rebind
   * @param balance Balance for rebind
   * @param denorm Weight for rebind
   */
  function rebind(
    address token,
    uint256 balance,
    uint256 denorm
  ) public override {
    require(denorm == MIN_WEIGHT && _dynamicWeights[token].fromTimestamp == 0, "ONLY_NEW_TOKENS_ALLOWED");
    super.rebind(token, balance, denorm);
  }

  /*** View Functions ***/

  function getDynamicWeightSettings(address token)
    external
    view
    returns (
      uint256 fromTimestamp,
      uint256 targetTimestamp,
      uint256 fromDenorm,
      uint256 targetDenorm
    )
  {
    DynamicWeight storage dw = _dynamicWeights[token];
    return (dw.fromTimestamp, dw.targetTimestamp, _records[token].denorm, dw.targetDenorm);
  }

  function getWeightPerSecondBounds() external view returns (uint256 minWeightPerSecond, uint256 maxWeightPerSecond) {
    return (_minWeightPerSecond, _maxWeightPerSecond);
  }

  /*** Internal Functions ***/

  function _getDenormWeight(address token) internal view override returns (uint256) {
    DynamicWeight memory dw = _dynamicWeights[token];
    uint256 fromDenorm = _records[token].denorm;

    if (dw.fromTimestamp == 0 || dw.targetDenorm == fromDenorm || block.timestamp <= dw.fromTimestamp) {
      return fromDenorm;
    }
    if (block.timestamp >= dw.targetTimestamp) {
      return dw.targetDenorm;
    }

    uint256 weightPerSecond = _getWeightPerSecond(fromDenorm, dw.targetDenorm, dw.fromTimestamp, dw.targetTimestamp);
    uint256 deltaCurrentTime = bsub(block.timestamp, dw.fromTimestamp);
    if (dw.targetDenorm > fromDenorm) {
      return badd(fromDenorm, deltaCurrentTime * weightPerSecond);
    } else {
      return bsub(fromDenorm, deltaCurrentTime * weightPerSecond);
    }
  }

  function _getWeightPerSecond(
    uint256 fromDenorm,
    uint256 targetDenorm,
    uint256 fromTimestamp,
    uint256 targetTimestamp
  ) internal pure returns (uint256) {
    uint256 delta = targetDenorm > fromDenorm ? bsub(targetDenorm, fromDenorm) : bsub(fromDenorm, targetDenorm);
    return div(delta, bsub(targetTimestamp, fromTimestamp));
  }

  function _getTotalWeight() internal view override returns (uint256) {
    uint256 sum = 0;
    uint256 len = _tokens.length;
    for (uint256 i = 0; i < len; i++) {
      sum = badd(sum, _getDenormWeight(_tokens[i]));
    }
    return sum;
  }

  function _addTotalWeight(uint256 _amount) internal virtual override {
    // storage total weight don't change, it's calculated only by _getTotalWeight()
  }

  function _subTotalWeight(uint256 _amount) internal virtual override {
    // storage total weight don't change, it's calculated only by _getTotalWeight()
  }
}

File 9 of 11 : BPool.sol
// SPDX-License-Identifier: GPL-3.0
// 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.6.12;

import "./BToken.sol";
import "./BMath.sol";
import "../interfaces/IPoolRestrictions.sol";
import "../interfaces/BPoolInterface.sol";

contract BPool is BToken, BMath, BPoolInterface {

    struct Record {
        bool bound;   // is token bound to pool
        uint index;   // private
        uint denorm;  // denormalized weight
        uint balance;
    }

    event LOG_SWAP(
        address indexed caller,
        address indexed tokenIn,
        address indexed tokenOut,
        uint256         tokenAmountIn,
        uint256         tokenAmountOut
    );

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

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

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

    event LOG_CALL_VOTING(
        address indexed voting,
        bool    indexed success,
        bytes4  indexed inputSig,
        bytes           inputData,
        bytes           outputData
    );

    event LOG_COMMUNITY_FEE(
        address indexed caller,
        address indexed receiver,
        address indexed token,
        uint256         tokenAmount
    );

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

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

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

    bool private _mutex;

    address private _controller; // has CONTROL role
    bool private _publicSwap; // true if PUBLIC can call SWAP functions

    address private _wrapper; // can join, exit and swaps when _wrapperMode is true
    bool private _wrapperMode;

    IPoolRestrictions private _restrictions;

    // `setSwapFee` and `finalize` require CONTROL
    // `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
    uint private _swapFee;
    uint private _communitySwapFee;
    uint private _communityJoinFee;
    uint private _communityExitFee;
    address private _communityFeeReceiver;
    bool private _finalized;

    address[] internal _tokens;
    mapping(address => Record) internal _records;
    uint internal _totalWeight;

    mapping(address => uint256) internal _lastSwapBlock;

    constructor(string memory name, string memory symbol) public {
        _name = name;
        _symbol = symbol;
        _controller = msg.sender;
        _swapFee = MIN_FEE;
        _communitySwapFee = 0;
        _communityJoinFee = 0;
        _communityExitFee = 0;
        _publicSwap = false;
        _finalized = false;
    }

    function isPublicSwap()
        external view override
        returns (bool)
    {
        return _publicSwap;
    }

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

    function isBound(address t)
        external view override
        returns (bool)
    {
        return _records[t].bound;
    }

    function getNumTokens()
        external view
        returns (uint)
    {
        return _tokens.length;
    }

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

    function getFinalTokens()
        external view override
        _viewlock_
        returns (address[] memory tokens)
    {
        _requireContractIsFinalized();
        return _tokens;
    }

    function getDenormalizedWeight(address token)
        external view override
        _viewlock_
        returns (uint)
    {

        _requireTokenIsBound(token);
        return _getDenormWeight(token);
    }

    function getTotalDenormalizedWeight()
        external view override
        _viewlock_
        returns (uint)
    {
        return _getTotalWeight();
    }

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

        _requireTokenIsBound(token);
        return bdiv(_getDenormWeight(token), _getTotalWeight());
    }

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

        _requireTokenIsBound(token);
        return _records[token].balance;
    }

    function getSwapFee()
        external view override
        _viewlock_
        returns (uint)
    {
        return _swapFee;
    }

    function getCommunityFee()
        external view override
        _viewlock_
        returns (uint communitySwapFee, uint communityJoinFee, uint communityExitFee, address communityFeeReceiver)
    {
        return (_communitySwapFee, _communityJoinFee, _communityExitFee, _communityFeeReceiver);
    }

    function getController()
        external view
        _viewlock_
        returns (address)
    {
        return _controller;
    }

    function getWrapper()
        external view
        _viewlock_
        returns (address)
    {
        return _wrapper;
    }

    function getWrapperMode()
        external view
        _viewlock_
        returns (bool)
    {
        return _wrapperMode;
    }

    function getRestrictions()
        external view override
        _viewlock_
        returns (address)
    {
        return address(_restrictions);
    }

    function setSwapFee(uint swapFee)
        external override
        _logs_
        _lock_
    {
        _onlyController();
        _requireFeeInBounds(swapFee);
        _swapFee = swapFee;
    }

    function setCommunityFeeAndReceiver(
        uint communitySwapFee,
        uint communityJoinFee,
        uint communityExitFee,
        address communityFeeReceiver
    )
        external override
        _logs_
        _lock_
    {
        _onlyController();
        _requireFeeInBounds(communitySwapFee);
        _requireFeeInBounds(communityJoinFee);
        _requireFeeInBounds(communityExitFee);
        _communitySwapFee = communitySwapFee;
        _communityJoinFee = communityJoinFee;
        _communityExitFee = communityExitFee;
        _communityFeeReceiver = communityFeeReceiver;
    }

    function setRestrictions(IPoolRestrictions restrictions)
        external
        _logs_
        _lock_
    {
        _onlyController();
        _restrictions = restrictions;
    }

    function setController(address manager)
        external override
        _logs_
        _lock_
    {
        _onlyController();
        _controller = manager;
    }

    function setPublicSwap(bool public_)
        external override
        _logs_
        _lock_
    {
        _requireContractIsNotFinalized();
        _onlyController();
        _publicSwap = public_;
    }

    function setWrapper(address wrapper, bool wrapperMode)
        external
        _logs_
        _lock_
    {
        _onlyController();
        _wrapper = wrapper;
        _wrapperMode = wrapperMode;
    }

    function finalize()
        external override
        _logs_
        _lock_
    {
        _onlyController();
        _requireContractIsNotFinalized();
        require(_tokens.length >= MIN_BOUND_TOKENS, "MIN_TOKENS");

        _finalized = true;
        _publicSwap = true;

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

    function callVoting(address voting, bytes4 signature, bytes calldata args, uint256 value)
        external override
        _logs_
        _lock_
    {
        require(_restrictions.isVotingSignatureAllowed(voting, signature), "NOT_ALLOWED_SIG");
        _onlyController();

        (bool success, bytes memory data) = voting.call{ value: value }(abi.encodePacked(signature, args));
        require(success, "NOT_SUCCESS");
        emit LOG_CALL_VOTING(voting, success, signature, args, data);
    }

    function bind(address token, uint balance, uint denorm)
        public override
        virtual
        _logs_
        // _lock_  Bind does not lock because it jumps to `rebind`, which does
    {
        _onlyController();
        require(!_records[token].bound, "IS_BOUND");

        require(_tokens.length < MAX_BOUND_TOKENS, "MAX_TOKENS");

        _records[token] = Record({
            bound: true,
            index: _tokens.length,
            denorm: 0,    // balance and denorm will be validated
            balance: 0   // and set by `rebind`
        });
        _tokens.push(token);
        rebind(token, balance, denorm);
    }

    function rebind(address token, uint balance, uint denorm)
        public override
        virtual
        _logs_
        _lock_
    {
        _onlyController();
        _requireTokenIsBound(token);

        require(denorm >= MIN_WEIGHT && denorm <= MAX_WEIGHT, "WEIGHT_BOUNDS");
        require(balance >= MIN_BALANCE, "MIN_BALANCE");

        // Adjust the denorm and totalWeight
        uint oldWeight = _records[token].denorm;
        if (denorm > oldWeight) {
            _addTotalWeight(bsub(denorm, oldWeight));
        } else if (denorm < oldWeight) {
            _subTotalWeight(bsub(oldWeight, denorm));
        }
        _records[token].denorm = denorm;

        // Adjust the balance record and actual token balance
        uint oldBalance = _records[token].balance;
        _records[token].balance = balance;
        if (balance > oldBalance) {
            _pullUnderlying(token, msg.sender, bsub(balance, oldBalance));
        } else if (balance < oldBalance) {
            uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
            _pushUnderlying(token, msg.sender, tokenBalanceWithdrawn);
        }
    }

    function unbind(address token)
        public override
        virtual
        _logs_
        _lock_
    {
        _onlyController();
        _requireTokenIsBound(token);

        uint tokenBalance = _records[token].balance;

        _subTotalWeight(_records[token].denorm);

        // Swap the token-to-unbind with the last token,
        // then delete the last token
        uint index = _records[token].index;
        uint last = _tokens.length - 1;
        _tokens[index] = _tokens[last];
        _records[_tokens[index]].index = index;
        _tokens.pop();
        _records[token] = Record({
            bound: false,
            index: 0,
            denorm: 0,
            balance: 0
        });

        _pushUnderlying(token, msg.sender, tokenBalance);
    }

    // Absorb any tokens that have been sent to this contract into the pool
    function gulp(address token)
        external
        _logs_
        _lock_
    {
        _requireTokenIsBound(token);
        _records[token].balance = IERC20(token).balanceOf(address(this));
    }

    function getSpotPrice(address tokenIn, address tokenOut)
        external view
        _viewlock_
        returns (uint spotPrice)
    {
        require(_records[tokenIn].bound && _records[tokenOut].bound, "NOT_BOUND");
        Record storage inRecord = _records[tokenIn];
        Record storage outRecord = _records[tokenOut];
        return calcSpotPrice(inRecord.balance, _getDenormWeight(tokenIn), outRecord.balance, _getDenormWeight(tokenOut), _swapFee);
    }

    function getSpotPriceSansFee(address tokenIn, address tokenOut)
        external view
        _viewlock_
        returns (uint spotPrice)
    {
        _requireTokenIsBound(tokenIn);
        _requireTokenIsBound(tokenOut);
        Record storage inRecord = _records[tokenIn];
        Record storage outRecord = _records[tokenOut];
        return calcSpotPrice(inRecord.balance, _getDenormWeight(tokenIn), outRecord.balance, _getDenormWeight(tokenOut), 0);
    }

    function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn)
        external override
        _logs_
        _lock_
    {
        _preventSameTxOrigin();
        _onlyWrapperOrNotWrapperMode();
        _requireContractIsFinalized();

        uint poolTotal = totalSupply();
        uint ratio = bdiv(poolAmountOut, poolTotal);
        _requireMathApprox(ratio);

        for (uint i = 0; i < _tokens.length; i++) {
            address t = _tokens[i];
            uint bal = _records[t].balance;
            uint tokenAmountIn = bmul(ratio, bal);
            _requireMathApprox(tokenAmountIn);
            require(tokenAmountIn <= maxAmountsIn[i], "LIMIT_IN");
            _records[t].balance = badd(_records[t].balance, tokenAmountIn);
            emit LOG_JOIN(msg.sender, t, tokenAmountIn);
            _pullUnderlying(t, msg.sender, tokenAmountIn);
        }

        (uint poolAmountOutAfterFee, uint poolAmountOutFee) = calcAmountWithCommunityFee(
            poolAmountOut,
            _communityJoinFee,
            msg.sender
        );

        _mintPoolShare(poolAmountOut);
        _pushPoolShare(msg.sender, poolAmountOutAfterFee);
        _pushPoolShare(_communityFeeReceiver, poolAmountOutFee);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, address(this), poolAmountOutFee);
    }

    function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut)
        external override
        _logs_
        _lock_
    {
        _preventSameTxOrigin();
        _onlyWrapperOrNotWrapperMode();
        _requireContractIsFinalized();

        (uint poolAmountInAfterFee, uint poolAmountInFee) = calcAmountWithCommunityFee(
            poolAmountIn,
            _communityExitFee,
            msg.sender
        );

        uint poolTotal = totalSupply();
        uint ratio = bdiv(poolAmountInAfterFee, poolTotal);
        _requireMathApprox(ratio);

        _pullPoolShare(msg.sender, poolAmountIn);
        _pushPoolShare(_communityFeeReceiver, poolAmountInFee);
        _burnPoolShare(poolAmountInAfterFee);

        for (uint i = 0; i < _tokens.length; i++) {
            address t = _tokens[i];
            uint bal = _records[t].balance;
            uint tokenAmountOut = bmul(ratio, bal);
            _requireMathApprox(tokenAmountOut);
            require(tokenAmountOut >= minAmountsOut[i], "LIMIT_OUT");
            _records[t].balance = bsub(_records[t].balance, tokenAmountOut);
            emit LOG_EXIT(msg.sender, t, tokenAmountOut);
            _pushUnderlying(t, msg.sender, tokenAmountOut);
        }

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, address(this), poolAmountInFee);
    }


    function swapExactAmountIn(
        address tokenIn,
        uint tokenAmountIn,
        address tokenOut,
        uint minAmountOut,
        uint maxPrice
    )
        external override
        _logs_
        _lock_
        returns (uint tokenAmountOut, uint spotPriceAfter)
    {
        _preventSameTxOrigin();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenIn);
        _requireTokenIsBound(tokenOut);
        require(_publicSwap, "NOT_PUBLIC");

        Record storage inRecord = _records[address(tokenIn)];
        Record storage outRecord = _records[address(tokenOut)];

        uint spotPriceBefore = calcSpotPrice(
                                    inRecord.balance,
                                    _getDenormWeight(tokenIn),
                                    outRecord.balance,
                                    _getDenormWeight(tokenOut),
                                    _swapFee
                                );
        require(spotPriceBefore <= maxPrice, "LIMIT_PRICE");

        (uint tokenAmountInAfterFee, uint tokenAmountInFee) = calcAmountWithCommunityFee(
                                                                tokenAmountIn,
                                                                _communitySwapFee,
                                                                msg.sender
                                                            );

        require(tokenAmountInAfterFee <= bmul(inRecord.balance, MAX_IN_RATIO), "MAX_IN_RATIO");

        tokenAmountOut = calcOutGivenIn(
                            inRecord.balance,
                            _getDenormWeight(tokenIn),
                            outRecord.balance,
                            _getDenormWeight(tokenOut),
                            tokenAmountInAfterFee,
                            _swapFee
                        );
        require(tokenAmountOut >= minAmountOut, "LIMIT_OUT");

        inRecord.balance = badd(inRecord.balance, tokenAmountInAfterFee);
        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);

        spotPriceAfter = calcSpotPrice(
                                inRecord.balance,
                                _getDenormWeight(tokenIn),
                                outRecord.balance,
                                _getDenormWeight(tokenOut),
                                _swapFee
                            );
        require(
            spotPriceAfter >= spotPriceBefore &&
            spotPriceBefore <= bdiv(tokenAmountInAfterFee, tokenAmountOut),
            "MATH_APPROX"
        );
        require(spotPriceAfter <= maxPrice, "LIMIT_PRICE");

        emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountInAfterFee, tokenAmountOut);

        _pullCommunityFeeUnderlying(tokenIn, msg.sender, tokenAmountInFee);
        _pullUnderlying(tokenIn, msg.sender, tokenAmountInAfterFee);
        _pushUnderlying(tokenOut, msg.sender, tokenAmountOut);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, tokenIn, tokenAmountInFee);

        return (tokenAmountOut, spotPriceAfter);
    }

    function swapExactAmountOut(
        address tokenIn,
        uint maxAmountIn,
        address tokenOut,
        uint tokenAmountOut,
        uint maxPrice
    )
        external override
        _logs_
        _lock_
        returns (uint tokenAmountIn, uint spotPriceAfter)
    {
        _preventSameTxOrigin();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenIn);
        _requireTokenIsBound(tokenOut);
        require(_publicSwap, "NOT_PUBLIC");

        Record storage inRecord = _records[address(tokenIn)];
        Record storage outRecord = _records[address(tokenOut)];

        require(tokenAmountOut <= bmul(outRecord.balance, MAX_OUT_RATIO), "OUT_RATIO");

        uint spotPriceBefore = calcSpotPrice(
                                    inRecord.balance,
                                    _getDenormWeight(tokenIn),
                                    outRecord.balance,
                                    _getDenormWeight(tokenOut),
                                    _swapFee
                                );
        require(spotPriceBefore <= maxPrice, "LIMIT_PRICE");

        (uint tokenAmountOutAfterFee, uint tokenAmountOutFee) = calcAmountWithCommunityFee(
            tokenAmountOut,
            _communitySwapFee,
            msg.sender
        );

        tokenAmountIn = calcInGivenOut(
                            inRecord.balance,
                            _getDenormWeight(tokenIn),
                            outRecord.balance,
                            _getDenormWeight(tokenOut),
                            tokenAmountOut,
                            _swapFee
                        );
        require(tokenAmountIn <= maxAmountIn, "LIMIT_IN");

        inRecord.balance = badd(inRecord.balance, tokenAmountIn);
        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);

        spotPriceAfter = calcSpotPrice(
                                inRecord.balance,
                                _getDenormWeight(tokenIn),
                                outRecord.balance,
                                _getDenormWeight(tokenOut),
                                _swapFee
                            );
        require(
            spotPriceAfter >= spotPriceBefore &&
            spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOutAfterFee),
            "MATH_APPROX"
        );
        require(spotPriceAfter <= maxPrice, "LIMIT_PRICE");

        emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOutAfterFee);

        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
        _pushUnderlying(tokenOut, msg.sender, tokenAmountOutAfterFee);
        _pushUnderlying(tokenOut, _communityFeeReceiver, tokenAmountOutFee);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, tokenOut, tokenAmountOutFee);

        return (tokenAmountIn, spotPriceAfter);
    }


    function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)
        external override
        _logs_
        _lock_
        returns (uint poolAmountOut)

    {
        _preventSameTxOrigin();
        _requireContractIsFinalized();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenIn);
        require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "MAX_IN_RATIO");

        (uint tokenAmountInAfterFee, uint tokenAmountInFee) = calcAmountWithCommunityFee(
            tokenAmountIn,
            _communityJoinFee,
            msg.sender
        );

        Record storage inRecord = _records[tokenIn];

        poolAmountOut = calcPoolOutGivenSingleIn(
                            inRecord.balance,
                            _getDenormWeight(tokenIn),
                            _totalSupply,
                            _getTotalWeight(),
                            tokenAmountInAfterFee,
                            _swapFee
                        );

        require(poolAmountOut >= minPoolAmountOut, "LIMIT_OUT");

        inRecord.balance = badd(inRecord.balance, tokenAmountInAfterFee);

        emit LOG_JOIN(msg.sender, tokenIn, tokenAmountInAfterFee);

        _mintPoolShare(poolAmountOut);
        _pushPoolShare(msg.sender, poolAmountOut);
        _pullCommunityFeeUnderlying(tokenIn, msg.sender, tokenAmountInFee);
        _pullUnderlying(tokenIn, msg.sender, tokenAmountInAfterFee);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, tokenIn, tokenAmountInFee);

        return poolAmountOut;
    }

    function joinswapPoolAmountOut(address tokenIn, uint poolAmountOut, uint maxAmountIn)
        external override
        _logs_
        _lock_
        returns (uint tokenAmountIn)
    {
        _preventSameTxOrigin();
        _requireContractIsFinalized();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenIn);

        Record storage inRecord = _records[tokenIn];

        (uint poolAmountOutAfterFee, uint poolAmountOutFee) = calcAmountWithCommunityFee(
            poolAmountOut,
            _communityJoinFee,
            msg.sender
        );

        tokenAmountIn = calcSingleInGivenPoolOut(
                            inRecord.balance,
                            _getDenormWeight(tokenIn),
                            _totalSupply,
                            _getTotalWeight(),
                            poolAmountOut,
                            _swapFee
                        );

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

        require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "MAX_IN_RATIO");

        inRecord.balance = badd(inRecord.balance, tokenAmountIn);

        emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);

        _mintPoolShare(poolAmountOut);
        _pushPoolShare(msg.sender, poolAmountOutAfterFee);
        _pushPoolShare(_communityFeeReceiver, poolAmountOutFee);
        _pullUnderlying(tokenIn, msg.sender, tokenAmountIn);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, address(this), poolAmountOutFee);

        return tokenAmountIn;
    }

    function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut)
        external override
        _logs_
        _lock_
        returns (uint tokenAmountOut)
    {
        _preventSameTxOrigin();
        _requireContractIsFinalized();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenOut);

        Record storage outRecord = _records[tokenOut];

        tokenAmountOut = calcSingleOutGivenPoolIn(
                            outRecord.balance,
                            _getDenormWeight(tokenOut),
                            _totalSupply,
                            _getTotalWeight(),
                            poolAmountIn,
                            _swapFee
                        );

        require(tokenAmountOut >= minAmountOut, "LIMIT_OUT");

        require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "OUT_RATIO");

        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);

        (uint tokenAmountOutAfterFee, uint tokenAmountOutFee) = calcAmountWithCommunityFee(
            tokenAmountOut,
            _communityExitFee,
            msg.sender
        );

        emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOutAfterFee);

        _pullPoolShare(msg.sender, poolAmountIn);
        _burnPoolShare(poolAmountIn);
        _pushUnderlying(tokenOut, msg.sender, tokenAmountOutAfterFee);
        _pushUnderlying(tokenOut, _communityFeeReceiver, tokenAmountOutFee);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, tokenOut, tokenAmountOutFee);

        return tokenAmountOutAfterFee;
    }

    function exitswapExternAmountOut(address tokenOut, uint tokenAmountOut, uint maxPoolAmountIn)
        external override
        _logs_
        _lock_
        returns (uint poolAmountIn)
    {
        _preventSameTxOrigin();
        _requireContractIsFinalized();
        _onlyWrapperOrNotWrapperMode();
        _requireTokenIsBound(tokenOut);
        require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "OUT_RATIO");

        Record storage outRecord = _records[tokenOut];

        (uint tokenAmountOutAfterFee, uint tokenAmountOutFee) = calcAmountWithCommunityFee(
            tokenAmountOut,
            _communityExitFee,
            msg.sender
        );

        poolAmountIn = calcPoolInGivenSingleOut(
                            outRecord.balance,
                            _getDenormWeight(tokenOut),
                            _totalSupply,
                            _getTotalWeight(),
                            tokenAmountOut,
                            _swapFee
                        );

        _requireMathApprox(poolAmountIn);
        require(poolAmountIn <= maxPoolAmountIn, "LIMIT_IN");

        outRecord.balance = bsub(outRecord.balance, tokenAmountOut);

        emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOutAfterFee);

        _pullPoolShare(msg.sender, poolAmountIn);
        _burnPoolShare(poolAmountIn);
        _pushUnderlying(tokenOut, msg.sender, tokenAmountOutAfterFee);
        _pushUnderlying(tokenOut, _communityFeeReceiver, tokenAmountOutFee);

        emit LOG_COMMUNITY_FEE(msg.sender, _communityFeeReceiver, tokenOut, tokenAmountOutFee);

        return poolAmountIn;
    }


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

    function _pullUnderlying(address erc20, address from, uint amount)
        internal
    {
        bool xfer = IERC20(erc20).transferFrom(from, address(this), amount);
        require(xfer, "ERC20_FALSE");
    }

    function _pushUnderlying(address erc20, address to, uint amount)
        internal
    {
        bool xfer = IERC20(erc20).transfer(to, amount);
        require(xfer, "ERC20_FALSE");
    }

    function _pullCommunityFeeUnderlying(address erc20, address from, uint amount)
        internal
    {
        bool xfer = IERC20(erc20).transferFrom(from, _communityFeeReceiver, amount);
        require(xfer, "ERC20_FALSE");
    }

    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
    {
        if(address(_restrictions) != address(0)) {
            uint maxTotalSupply = _restrictions.getMaxTotalSupply(address(this));
            require(badd(_totalSupply, amount) <= maxTotalSupply, "MAX_SUPPLY");
        }
        _mint(amount);
    }

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

    function _requireTokenIsBound(address token)
        internal view
    {
        require(_records[token].bound, "NOT_BOUND");
    }

    function _onlyController()
        internal view
    {
        require(msg.sender == _controller, "NOT_CONTROLLER");
    }

    function _requireContractIsNotFinalized()
        internal view
    {
        require(!_finalized, "IS_FINALIZED");
    }

    function _requireContractIsFinalized()
        internal view
    {
        require(_finalized, "NOT_FINALIZED");
    }

    function _requireFeeInBounds(uint256 _fee)
        internal pure
    {
        require(_fee >= MIN_FEE && _fee <= MAX_FEE, "FEE_BOUNDS");
    }

    function _requireMathApprox(uint256 _value)
        internal pure
    {
        require(_value != 0, "MATH_APPROX");
    }

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

    function _onlyWrapperOrNotWrapperMode()
        internal view
    {
        require(!_wrapperMode || msg.sender == _wrapper, "ONLY_WRAPPER");
    }

    function _preventSameTxOrigin()
      internal
    {
      require(block.number > _lastSwapBlock[tx.origin], "SAME_TX_ORIGIN");
      _lastSwapBlock[tx.origin] = block.number;
    }

    function _getDenormWeight(address token)
        internal view virtual
        returns (uint)
    {
        return _records[token].denorm;
    }

    function _getTotalWeight()
        internal view virtual
        returns (uint)
    {
        return _totalWeight;
    }

    function _addTotalWeight(uint _amount) internal virtual {
        _totalWeight = badd(_totalWeight, _amount);
        require(_totalWeight <= MAX_TOTAL_WEIGHT, "MAX_TOTAL_WEIGHT");
    }

    function _subTotalWeight(uint _amount) internal virtual {
        _totalWeight = bsub(_totalWeight, _amount);
    }

    function calcAmountWithCommunityFee(
        uint tokenAmountIn,
        uint communityFee,
        address operator
    )
        public view override
        returns (uint tokenAmountInAfterFee, uint tokenAmountFee)
    {
        if (address(_restrictions) != address(0) && _restrictions.isWithoutFee(operator)) {
            return (tokenAmountIn, 0);
        }
        uint adjustedIn = bsub(BONE, communityFee);
        tokenAmountInAfterFee = bmul(tokenAmountIn, adjustedIn);
        tokenAmountFee = bsub(tokenAmountIn, tokenAmountInAfterFee);
        return (tokenAmountInAfterFee, tokenAmountFee);
    }

    function getMinWeight()
        external view override
        returns (uint)
    {
        return MIN_WEIGHT;
    }

    function getMaxBoundTokens()
        external view override
        returns (uint)
    {
      return MAX_BOUND_TOKENS;
    }
}

File 10 of 11 : BMath.sol
// SPDX-License-Identifier: GPL-3.0
// 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.6.12;

import "./BNum.sol";
import "../interfaces/BMathInterface.sol";

contract BMath is BConst, BNum, BMathInterface {
    /**********************************************************************************************
    // calcSpotPrice                                                                             //
    // sP = spotPrice                                                                            //
    // bI = tokenBalanceIn                ( bI / wI )         1                                  //
    // bO = tokenBalanceOut         sP =  -----------  *  ----------                             //
    // wI = tokenWeightIn                 ( bO / wO )     ( 1 - sF )                             //
    // wO = tokenWeightOut                                                                       //
    // sF = swapFee                                                                              //
    **********************************************************************************************/
    function calcSpotPrice(
        uint tokenBalanceIn,
        uint tokenWeightIn,
        uint tokenBalanceOut,
        uint tokenWeightOut,
        uint swapFee
    )
        public pure
        returns (uint spotPrice)
    {
        uint numer = bdiv(tokenBalanceIn, tokenWeightIn);
        uint denom = bdiv(tokenBalanceOut, tokenWeightOut);
        uint ratio = bdiv(numer, denom);
        uint scale = bdiv(BONE, bsub(BONE, swapFee));
        return  (spotPrice = bmul(ratio, scale));
    }

    /**********************************************************************************************
    // calcOutGivenIn                                                                            //
    // aO = tokenAmountOut                                                                       //
    // bO = tokenBalanceOut                                                                      //
    // bI = tokenBalanceIn              /      /            bI             \    (wI / wO) \      //
    // aI = tokenAmountIn    aO = bO * |  1 - | --------------------------  | ^            |     //
    // wI = tokenWeightIn               \      \ ( bI + ( aI * ( 1 - sF )) /              /      //
    // wO = tokenWeightOut                                                                       //
    // sF = swapFee                                                                              //
    **********************************************************************************************/
    function calcOutGivenIn(
        uint tokenBalanceIn,
        uint tokenWeightIn,
        uint tokenBalanceOut,
        uint tokenWeightOut,
        uint tokenAmountIn,
        uint swapFee
    )
        public pure
        returns (uint tokenAmountOut)
    {
        uint weightRatio = bdiv(tokenWeightIn, tokenWeightOut);
        uint adjustedIn = bsub(BONE, swapFee);
        adjustedIn = bmul(tokenAmountIn, adjustedIn);
        uint y = bdiv(tokenBalanceIn, badd(tokenBalanceIn, adjustedIn));
        uint foo = bpow(y, weightRatio);
        uint bar = bsub(BONE, foo);
        tokenAmountOut = bmul(tokenBalanceOut, bar);
        return tokenAmountOut;
    }

    /**********************************************************************************************
    // calcInGivenOut                                                                            //
    // aI = tokenAmountIn                                                                        //
    // bO = tokenBalanceOut               /  /     bO      \    (wO / wI)      \                 //
    // bI = tokenBalanceIn          bI * |  | ------------  | ^            - 1  |                //
    // aO = tokenAmountOut    aI =        \  \ ( bO - aO ) /                   /                 //
    // wI = tokenWeightIn           --------------------------------------------                 //
    // wO = tokenWeightOut                          ( 1 - sF )                                   //
    // sF = swapFee                                                                              //
    **********************************************************************************************/
    function calcInGivenOut(
        uint tokenBalanceIn,
        uint tokenWeightIn,
        uint tokenBalanceOut,
        uint tokenWeightOut,
        uint tokenAmountOut,
        uint swapFee
    )
        public pure override
        returns (uint tokenAmountIn)
    {
        uint weightRatio = bdiv(tokenWeightOut, tokenWeightIn);
        uint diff = bsub(tokenBalanceOut, tokenAmountOut);
        uint y = bdiv(tokenBalanceOut, diff);
        uint foo = bpow(y, weightRatio);
        foo = bsub(foo, BONE);
        tokenAmountIn = bsub(BONE, swapFee);
        tokenAmountIn = bdiv(bmul(tokenBalanceIn, foo), tokenAmountIn);
        return tokenAmountIn;
    }

    /**********************************************************************************************
    // calcPoolOutGivenSingleIn                                                                  //
    // pAo = poolAmountOut         /                                              \              //
    // tAi = tokenAmountIn        ///      /     //    wI \      \\       \     wI \             //
    // wI = tokenWeightIn        //| tAi *| 1 - || 1 - --  | * sF || + tBi \    --  \            //
    // tW = totalWeight     pAo=||  \      \     \\    tW /      //         | ^ tW   | * pS - pS //
    // tBi = tokenBalanceIn      \\  ------------------------------------- /        /            //
    // pS = poolSupply            \\                    tBi               /        /             //
    // sF = swapFee                \                                              /              //
    **********************************************************************************************/
    function calcPoolOutGivenSingleIn(
        uint tokenBalanceIn,
        uint tokenWeightIn,
        uint poolSupply,
        uint totalWeight,
        uint tokenAmountIn,
        uint swapFee
    )
        public pure
        returns (uint poolAmountOut)
    {
        // Charge the trading fee for the proportion of tokenAi
        ///  which is implicitly traded to the other pool tokens.
        // That proportion is (1- weightTokenIn)
        // tokenAiAfterFee = tAi * (1 - (1-weightTi) * poolFee);
        uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
        uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
        uint tokenAmountInAfterFee = bmul(tokenAmountIn, bsub(BONE, zaz));

        uint newTokenBalanceIn = badd(tokenBalanceIn, tokenAmountInAfterFee);
        uint tokenInRatio = bdiv(newTokenBalanceIn, tokenBalanceIn);

        // uint newPoolSupply = (ratioTi ^ weightTi) * poolSupply;
        uint poolRatio = bpow(tokenInRatio, normalizedWeight);
        uint newPoolSupply = bmul(poolRatio, poolSupply);
        poolAmountOut = bsub(newPoolSupply, poolSupply);
        return poolAmountOut;
    }

    /**********************************************************************************************
    // calcSingleInGivenPoolOut                                                                  //
    // tAi = tokenAmountIn              //(pS + pAo)\     /    1    \\                           //
    // pS = poolSupply                 || ---------  | ^ | --------- || * bI - bI                //
    // pAo = poolAmountOut              \\    pS    /     \(wI / tW)//                           //
    // bI = balanceIn          tAi =  --------------------------------------------               //
    // wI = weightIn                              /      wI  \                                   //
    // tW = totalWeight                          |  1 - ----  |  * sF                            //
    // sF = swapFee                               \      tW  /                                   //
    **********************************************************************************************/
    function calcSingleInGivenPoolOut(
        uint tokenBalanceIn,
        uint tokenWeightIn,
        uint poolSupply,
        uint totalWeight,
        uint poolAmountOut,
        uint swapFee
    )
        public pure
        returns (uint tokenAmountIn)
    {
        uint normalizedWeight = bdiv(tokenWeightIn, totalWeight);
        uint newPoolSupply = badd(poolSupply, poolAmountOut);
        uint poolRatio = bdiv(newPoolSupply, poolSupply);

        //uint newBalTi = poolRatio^(1/weightTi) * balTi;
        uint boo = bdiv(BONE, normalizedWeight);
        uint tokenInRatio = bpow(poolRatio, boo);
        uint newTokenBalanceIn = bmul(tokenInRatio, tokenBalanceIn);
        uint tokenAmountInAfterFee = bsub(newTokenBalanceIn, tokenBalanceIn);
        // Do reverse order of fees charged in joinswap_ExternAmountIn, this way
        //     ``` pAo == joinswap_ExternAmountIn(Ti, joinswap_PoolAmountOut(pAo, Ti)) ```
        //uint tAi = tAiAfterFee / (1 - (1-weightTi) * swapFee) ;
        uint zar = bmul(bsub(BONE, normalizedWeight), swapFee);
        tokenAmountIn = bdiv(tokenAmountInAfterFee, bsub(BONE, zar));
        return tokenAmountIn;
    }

    /**********************************************************************************************
    // calcSingleOutGivenPoolIn                                                                  //
    // tAo = tokenAmountOut            /      /                                             \\   //
    // bO = tokenBalanceOut           /      //       pS - pAi        \     /    1    \      \\  //
    // pAi = poolAmountIn            | bO - || ----------------------- | ^ | --------- | * b0 || //
    // ps = poolSupply                \      \\          pS           /     \(wO / tW)/      //  //
    // wI = tokenWeightIn      tAo =   \      \                                             //   //
    // tW = totalWeight                    /     /      wO \       \                             //
    // sF = swapFee                    *  | 1 - |  1 - ---- | * sF  |                            //
    // eF = exitFee                        \     \      tW /       /                             //
    **********************************************************************************************/
    function calcSingleOutGivenPoolIn(
        uint tokenBalanceOut,
        uint tokenWeightOut,
        uint poolSupply,
        uint totalWeight,
        uint poolAmountIn,
        uint swapFee
    )
        public pure
        returns (uint tokenAmountOut)
    {
        uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
        uint newPoolSupply = bsub(poolSupply, poolAmountIn);
        uint poolRatio = bdiv(newPoolSupply, poolSupply);

        // newBalTo = poolRatio^(1/weightTo) * balTo;
        uint tokenOutRatio = bpow(poolRatio, bdiv(BONE, normalizedWeight));
        uint newTokenBalanceOut = bmul(tokenOutRatio, tokenBalanceOut);

        uint tokenAmountOutBeforeSwapFee = bsub(tokenBalanceOut, newTokenBalanceOut);

        // charge swap fee on the output token side
        //uint tAo = tAoBeforeSwapFee * (1 - (1-weightTo) * swapFee)
        uint zaz = bmul(bsub(BONE, normalizedWeight), swapFee);
        tokenAmountOut = bmul(tokenAmountOutBeforeSwapFee, bsub(BONE, zaz));
        return tokenAmountOut;
    }

    /**********************************************************************************************
    // calcPoolInGivenSingleOut                                                                  //
    // pAi = poolAmountIn               // /               tAo             \\     / wO \     \   //
    // bO = tokenBalanceOut            // | bO - -------------------------- |\   | ---- |     \  //
    // tAo = tokenAmountOut      pS - ||   \     1 - ((1 - (tO / tW)) * sF)/  | ^ \ tW /  * pS | //
    // ps = poolSupply                 \\ -----------------------------------/                /  //
    // wO = tokenWeightOut  pAi =       \\               bO                 /                /   //
    // tW = totalWeight                                                                          //
    // sF = swapFee                                                                              //
    **********************************************************************************************/
    function calcPoolInGivenSingleOut(
        uint tokenBalanceOut,
        uint tokenWeightOut,
        uint poolSupply,
        uint totalWeight,
        uint tokenAmountOut,
        uint swapFee
    )
        public pure
        returns (uint poolAmountIn)
    {

        // charge swap fee on the output token side
        uint normalizedWeight = bdiv(tokenWeightOut, totalWeight);
        //uint tAoBeforeSwapFee = tAo / (1 - (1-weightTo) * swapFee) ;
        uint zoo = bsub(BONE, normalizedWeight);
        uint zar = bmul(zoo, swapFee);
        uint tokenAmountOutBeforeSwapFee = bdiv(tokenAmountOut, bsub(BONE, zar));

        uint newTokenBalanceOut = bsub(tokenBalanceOut, tokenAmountOutBeforeSwapFee);
        uint tokenOutRatio = bdiv(newTokenBalanceOut, tokenBalanceOut);

        //uint newPoolSupply = (ratioTo ^ weightTo) * poolSupply;
        uint poolRatio = bpow(tokenOutRatio, normalizedWeight);
        uint newPoolSupply = bmul(poolRatio, poolSupply);
        uint poolAmountIn = bsub(poolSupply, newPoolSupply);
        return poolAmountIn;
    }
}

File 11 of 11 : IPoolRestrictions.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;

interface IPoolRestrictions {
  function getMaxTotalSupply(address _pool) external view returns (uint256);

  function isVotingSignatureAllowed(address _votingAddress, bytes4 _signature) external view returns (bool);

  function isVotingSenderAllowed(address _votingAddress, address _sender) external view returns (bool);

  function isWithoutFee(address _addr) external view returns (bool);
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint256","name":"minWeightPerSecond","type":"uint256"},{"internalType":"uint256","name":"maxWeightPerSecond","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":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":"voting","type":"address"},{"indexed":true,"internalType":"bool","name":"success","type":"bool"},{"indexed":true,"internalType":"bytes4","name":"inputSig","type":"bytes4"},{"indexed":false,"internalType":"bytes","name":"inputData","type":"bytes"},{"indexed":false,"internalType":"bytes","name":"outputData","type":"bytes"}],"name":"LOG_CALL_VOTING","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"caller","type":"address"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenAmount","type":"uint256"}],"name":"LOG_COMMUNITY_FEE","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":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"}],"name":"LOG_SWAP","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromDenorm","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetDenorm","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"fromTimestamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"targetTimestamp","type":"uint256"}],"name":"SetDynamicWeight","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"minWeightPerSecond","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"maxWeightPerSecond","type":"uint256"}],"name":"SetWeightPerSecondBounds","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"BONE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"BPOW_PRECISION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"INIT_POOL_SUPPLY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_FEE","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_TOTAL_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_WEIGHT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BALANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BOUND_TOKENS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_BPOW_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MIN_WEIGHT","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":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"targetDenorm","type":"uint256"},{"internalType":"uint256","name":"fromTimestamp","type":"uint256"},{"internalType":"uint256","name":"targetTimestamp","type":"uint256"}],"name":"bind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"bind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"communityFee","type":"uint256"},{"internalType":"address","name":"operator","type":"address"}],"name":"calcAmountWithCommunityFee","outputs":[{"internalType":"uint256","name":"tokenAmountInAfterFee","type":"uint256"},{"internalType":"uint256","name":"tokenAmountFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","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":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","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":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcPoolInGivenSingleOut","outputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcPoolOutGivenSingleIn","outputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSingleInGivenPoolOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"poolSupply","type":"uint256"},{"internalType":"uint256","name":"totalWeight","type":"uint256"},{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSingleOutGivenPoolIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenBalanceIn","type":"uint256"},{"internalType":"uint256","name":"tokenWeightIn","type":"uint256"},{"internalType":"uint256","name":"tokenBalanceOut","type":"uint256"},{"internalType":"uint256","name":"tokenWeightOut","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"calcSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"voting","type":"address"},{"internalType":"bytes4","name":"signature","type":"bytes4"},{"internalType":"bytes","name":"args","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"callVoting","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256[]","name":"minAmountsOut","type":"uint256[]"}],"name":"exitPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPoolAmountIn","type":"uint256"}],"name":"exitswapExternAmountOut","outputs":[{"internalType":"uint256","name":"poolAmountIn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"poolAmountIn","type":"uint256"},{"internalType":"uint256","name":"minAmountOut","type":"uint256"}],"name":"exitswapPoolAmountIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"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":"getCommunityFee","outputs":[{"internalType":"uint256","name":"communitySwapFee","type":"uint256"},{"internalType":"uint256","name":"communityJoinFee","type":"uint256"},{"internalType":"uint256","name":"communityExitFee","type":"uint256"},{"internalType":"address","name":"communityFeeReceiver","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getController","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getCurrentTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getDynamicWeightSettings","outputs":[{"internalType":"uint256","name":"fromTimestamp","type":"uint256"},{"internalType":"uint256","name":"targetTimestamp","type":"uint256"},{"internalType":"uint256","name":"fromDenorm","type":"uint256"},{"internalType":"uint256","name":"targetDenorm","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFinalTokens","outputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMaxBoundTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMinWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"getNormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNumTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRestrictions","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPrice","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"}],"name":"getSpotPriceSansFee","outputs":[{"internalType":"uint256","name":"spotPrice","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getSwapFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTotalDenormalizedWeight","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWeightPerSecondBounds","outputs":[{"internalType":"uint256","name":"minWeightPerSecond","type":"uint256"},{"internalType":"uint256","name":"maxWeightPerSecond","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrapper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWrapperMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"gulp","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"t","type":"address"}],"name":"isBound","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isFinalized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPublicSwap","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256[]","name":"maxAmountsIn","type":"uint256[]"}],"name":"joinPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"},{"internalType":"uint256","name":"minPoolAmountOut","type":"uint256"}],"name":"joinswapExternAmountIn","outputs":[{"internalType":"uint256","name":"poolAmountOut","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"poolAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"}],"name":"joinswapPoolAmountOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"denorm","type":"uint256"}],"name":"rebind","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"communitySwapFee","type":"uint256"},{"internalType":"uint256","name":"communityJoinFee","type":"uint256"},{"internalType":"uint256","name":"communityExitFee","type":"uint256"},{"internalType":"address","name":"communityFeeReceiver","type":"address"}],"name":"setCommunityFeeAndReceiver","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"manager","type":"address"}],"name":"setController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"targetDenorm","type":"uint256"},{"internalType":"uint256","name":"fromTimestamp","type":"uint256"},{"internalType":"uint256","name":"targetTimestamp","type":"uint256"}],"name":"setDynamicWeight","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"public_","type":"bool"}],"name":"setPublicSwap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPoolRestrictions","name":"restrictions","type":"address"}],"name":"setRestrictions","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"setSwapFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"minWeightPerSecond","type":"uint256"},{"internalType":"uint256","name":"maxWeightPerSecond","type":"uint256"}],"name":"setWeightPerSecondBounds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"wrapper","type":"address"},{"internalType":"bool","name":"wrapperMode","type":"bool"}],"name":"setWrapper","outputs":[],"stateMutability":"nonpayable","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"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountIn","outputs":[{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"spotPriceAfter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"maxAmountIn","type":"uint256"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"tokenAmountOut","type":"uint256"},{"internalType":"uint256","name":"maxPrice","type":"uint256"}],"name":"swapExactAmountOut","outputs":[{"internalType":"uint256","name":"tokenAmountIn","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":"token","type":"address"}],"name":"unbind","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040526005805460ff191660121790553480156200001e57600080fd5b5060405162005bf738038062005bf7833981810160405260808110156200004457600080fd5b81019080805160405193929190846401000000008211156200006557600080fd5b9083019060208201858111156200007b57600080fd5b82516401000000008111828201881017156200009657600080fd5b82525081516020918201929091019080838360005b83811015620000c5578181015183820152602001620000ab565b50505050905090810190601f168015620000f35780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200011757600080fd5b9083019060208201858111156200012d57600080fd5b82516401000000008111828201881017156200014857600080fd5b82525081516020918201929091019080838360005b83811015620001775781810151838201526020016200015d565b50505050905090810190601f168015620001a55780820380516001836020036101000a031916815260200191505b50604090815260208281015192909101518651929450925085918591620001d29160039185019062000242565b508051620001e890600490602084019062000242565b50506005805464e8d4a5100060085560006009819055600a819055600b5562010000600160b01b0319163362010000021760ff60b01b1916905550600c805460ff60a01b1916905560129190915560135550620002de9050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200028557805160ff1916838001178555620002b5565b82800160010185558215620002b5579182015b82811115620002b557825182559160200191906001019062000298565b50620002c3929150620002c7565b5090565b5b80821115620002c35760008155600101620002c8565b61590980620002ee6000396000f3fe608060405234801561001057600080fd5b50600436106103855760003560e01c806302c967481461038a57806306fdde03146103ce578063095ea7b31461044b57806309a3bbe41461048b5780630f7b1e3e146104935780631446a7ff146104cd57806315e84af9146104fb57806318160ddd14610529578063189d00ca14610531578063218b5382146105395780632245a08e1461054157806323b872dd1461058c5780632f37b624146105c25780633018205f146105e8578063313ce5671461060c57806334e199071461062a5780633fdddaa21461064757806341e5a5d414610679578063442e2152146106c557806346ab38f11461075257806349b59552146107845780634bb278f3146107a35780634d752ec3146107ab5780634f69c0d4146107e95780635c1bbaf71461085e5780635db342771461089957806366188463146108cb57806367cc71f0146108f75780636d06dfa0146108ff57806370a082311461093157806370eb8e7f1461095757806376c7a3c71461095f5780637c5e9ea4146109675780638201aa3f146109a757806382f652ad146109e75780638656b65314610a22578063867378c514610a5d5780638733ad7114610a655780638929801214610a885780638c28cbe814610ac35780638d4e408314610ae95780638f6b707014610af157806390ad688b14610af957806392eefe9b14610b30578063936c347714610b565780639381cd2b14610b5e578063948d8ce614610b6657806395d89b4114610b8c578063992e2a9214610b945780639a737aa214610b9c578063a221ee4914610ba4578063a9059cbb14610bd9578063b02f0b7314610c05578063b0e0d13614610c7a578063b7b800a414610c82578063ba019dab14610c8a578063ba9530a614610c92578063bc063e1a14610ccd578063bc694ea214610cd5578063be3bbd2e14610cdd578063c36596a614610d35578063c4195cb814610d3d578063c61641cd14610d45578063cc77828d14610d6b578063cd2ed8fb14610d73578063cf5e7bd314610d7b578063cfb2794514610da1578063d4cadf6814610dd9578063d73dd62314610de1578063d80817fb14610e0d578063dd62ed3e14610e15578063e0e5228d14610e43578063e4a28a521461048b578063e4e1e53814610e71578063ec09302114610ea3578063f1b8a9b714610eab578063f8b2cb4f14610ed1578063f8d6aed414610ef7578063fde924f714610f32575b600080fd5b6103bc600480360360608110156103a057600080fd5b506001600160a01b038135169060208101359060400135610f3a565b60408051918252519081900360200190f35b6103d66111aa565b6040805160208082528351818301528351919283929083019185019080838360005b838110156104105781810151838201526020016103f8565b50505050905090810190601f16801561043d5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6104776004803603604081101561046157600080fd5b506001600160a01b038135169060200135611240565b604080519115158252519081900360200190f35b6103bc6112a1565b6104cb600480360360808110156104a957600080fd5b50803590602081013590604081013590606001356001600160a01b03166112ae565b005b6103bc600480360360408110156104e357600080fd5b506001600160a01b0381358116916020013516611384565b6103bc6004803603604081101561051157600080fd5b506001600160a01b03813581169160200135166113f1565b6103bc6114c1565b6103bc6114c7565b6103bc6114db565b6105736004803603606081101561055757600080fd5b50803590602081013590604001356001600160a01b03166114e3565b6040805192835260208301919091528051918290030190f35b610477600480360360608110156105a257600080fd5b506001600160a01b038135811691602081013590911690604001356115bf565b610477600480360360208110156105d857600080fd5b50356001600160a01b0316611715565b6105f0611737565b604080516001600160a01b039092168252519081900360200190f35b610614611757565b6040805160ff9092168252519081900360200190f35b6104cb6004803603602081101561064057600080fd5b5035611760565b6104cb6004803603606081101561065d57600080fd5b506001600160a01b0381351690602081013590604001356117f9565b61069f6004803603602081101561068f57600080fd5b50356001600160a01b031661187d565b604080519485526020850193909352838301919091526060830152519081900360800190f35b6104cb600480360360808110156106db57600080fd5b6001600160a01b03823516916001600160e01b031960208201351691810190606081016040820135600160201b81111561071457600080fd5b82018360208201111561072657600080fd5b803590602001918460018302840111600160201b8311171561074757600080fd5b9193509150356118b7565b6103bc6004803603606081101561076857600080fd5b506001600160a01b038135169060208101359060400135611c1f565b6104cb6004803603602081101561079a57600080fd5b50351515611e8d565b6104cb611f38565b6104cb600480360360a08110156107c157600080fd5b506001600160a01b03813516906020810135906040810135906060810135906080013561205d565b6104cb600480360360408110156107ff57600080fd5b81359190810190604081016020820135600160201b81111561082057600080fd5b82018360208201111561083257600080fd5b803590602001918460208302840111600160201b8311171561085357600080fd5b5090925090506120e0565b6103bc600480360360c081101561087457600080fd5b5080359060208101359060408101359060608101359060808101359060a00135612347565b6103bc600480360360608110156108af57600080fd5b506001600160a01b0381351690602081013590604001356123ff565b610477600480360360408110156108e157600080fd5b506001600160a01b03813516906020013561265a565b61047761273d565b6103bc6004803603606081101561091557600080fd5b506001600160a01b038135169060208101359060400135612758565b6103bc6004803603602081101561094757600080fd5b50356001600160a01b03166129c2565b6103bc6129dd565b6103bc6129e5565b610573600480360360a081101561097d57600080fd5b506001600160a01b03813581169160208101359160408201351690606081013590608001356129f7565b610573600480360360a08110156109bd57600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135612ddb565b6103bc600480360360c08110156109fd57600080fd5b5080359060208101359060408101359060608101359060808101359060a001356131c2565b6103bc600480360360c0811015610a3857600080fd5b5080359060208101359060408101359060608101359060808101359060a00135613268565b6103bc613309565b6104cb60048036036040811015610a7b57600080fd5b508035906020013561331d565b6103bc600480360360c0811015610a9e57600080fd5b5080359060208101359060408101359060608101359060808101359060a001356133f1565b6104cb60048036036020811015610ad957600080fd5b50356001600160a01b031661348c565b6104776135a9565b6105f06135b9565b610b016135d3565b604080519485526020850193909352838301919091526001600160a01b03166060830152519081900360800190f35b6104cb60048036036020811015610b4657600080fd5b50356001600160a01b0316613604565b6103bc6136b3565b6103bc6136ca565b6103bc60048036036020811015610b7c57600080fd5b50356001600160a01b03166136d7565b6103d66136f3565b6103bc613754565b6103bc613760565b6103bc600480360360a0811015610bba57600080fd5b5080359060208101359060408101359060608101359060800135613765565b61047760048036036040811015610bef57600080fd5b506001600160a01b0381351690602001356137ca565b6104cb60048036036040811015610c1b57600080fd5b81359190810190604081016020820135600160201b811115610c3c57600080fd5b820183602082011115610c4e57600080fd5b803590602001918460208302840111600160201b83111715610c6f57600080fd5b5090925090506137e0565b6103bc613a48565b6103bc613a4d565b6103bc613a52565b6103bc600480360360c0811015610ca857600080fd5b5080359060208101359060408101359060608101359060808101359060a00135613a57565b6103bc613ad8565b6103bc613ae8565b610ce5613af4565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610d21578181015183820152602001610d09565b505050509050019250505060405180910390f35b6103bc613b65565b6105f0613b71565b6104cb60048036036020811015610d5b57600080fd5b50356001600160a01b0316613b8b565b610ce5613c38565b6103bc613c42565b6104cb60048036036020811015610d9157600080fd5b50356001600160a01b0316613c48565b6104cb60048036036080811015610db757600080fd5b506001600160a01b038135169060208101359060408101359060600135613c98565b6103bc614051565b61047760048036036040811015610df757600080fd5b506001600160a01b038135169060200135614062565b6105736140ee565b6103bc60048036036040811015610e2b57600080fd5b506001600160a01b03813581169160200135166140f8565b6104cb60048036036040811015610e5957600080fd5b506001600160a01b0381351690602001351515614123565b6104cb60048036036060811015610e8757600080fd5b506001600160a01b0381351690602081013590604001356141e4565b6103bc61421c565b6103bc60048036036020811015610ec157600080fd5b50356001600160a01b031661422c565b6103bc60048036036020811015610ee757600080fd5b50356001600160a01b0316614253565b6103bc600480360360c0811015610f0d57600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614285565b610477614308565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2610fa5614318565b6005805461ff001916610100179055610fbc614361565b610fc46143c9565b610fcc614417565b610fd58461447a565b6001600160a01b0384166000908152600e6020526040902060039081015461100a91670de0b6b3a76400005b046001016144d6565b83111561104a576040805162461bcd60e51b81526020600482015260096024820152684f55545f524154494f60b81b604482015290519081900360640190fd5b6001600160a01b0384166000908152600e60205260408120600b549091908190611076908790336114e3565b9150915061109f836003015461108b8961459f565b600254611096614690565b8a6008546131c2565b93506110aa846146e7565b848411156110ea576040805162461bcd60e51b81526020600482015260086024820152672624a6a4aa2fa4a760c11b604482015290519081900360640190fd5b6110f8836003015487614727565b60038401556040805183815290516001600160a01b0389169133916000805160206158748339815191529181900360200190a36111353385614789565b61113e84614797565b6111498733846147a0565b600c546111619088906001600160a01b0316836147a0565b600c546040805183815290516001600160a01b03808b1693169133916000805160206158948339815191529181900360200190a45050506005805461ff00191690559392505050565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112365780601f1061120b57610100808354040283529160200191611236565b820191906000526020600020905b81548152906001019060200180831161121957829003601f168201915b5050505050905090565b600061124b8361486d565b3360008181526001602090815260408083206001600160a01b03881680855290835292819020869055805186815290519293926000805160206158b4833981519152929181900390910190a35060015b92915050565b6802b5e3af16b188000081565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2611317614318565b6005805461ff00191661010017905561132e6148bb565b61133784614911565b61134083614911565b61134982614911565b600993909355600a91909155600b55600c80546001600160a01b0319166001600160a01b039092169190911790556005805461ff0019169055565b600061138e614318565b6113978361447a565b6113a08261447a565b6001600160a01b038084166000908152600e60205260408082209285168252902060038201546113e8906113d38761459f565b83600301546113e18861459f565b6000613765565b95945050505050565b60006113fb614318565b6001600160a01b0383166000908152600e602052604090205460ff16801561143b57506001600160a01b0382166000908152600e602052604090205460ff165b611478576040805162461bcd60e51b81526020600482015260096024820152681393d517d093d5539160ba1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600e60205260408082209285168252902060038201546113e8906114ab8761459f565b83600301546114b98861459f565b600854613765565b60025490565b6402540be400670de0b6b3a76400005b0481565b633b9aca0081565b60075460009081906001600160a01b031615801590611577575060075460408051630a499ad360e01b81526001600160a01b03868116600483015291519190921691630a499ad3916024808301926020929190829003018186803b15801561154a57600080fd5b505afa15801561155e573d6000803e3d6000fd5b505050506040513d602081101561157457600080fd5b50515b15611587575083905060006115b7565b600061159b670de0b6b3a764000086614727565b90506115a786826144d6565b92506115b38684614727565b9150505b935093915050565b6000336001600160a01b03851614806115fb57506001600160a01b03841660009081526001602090815260408083203384529091529020548211155b611644576040805162461bcd60e51b815260206004820152601560248201527422a9292fa12a27a5a2a72fa120a22fa1a0a62622a960591b604482015290519081900360640190fd5b61164f84848461496c565b336001600160a01b0385161480159061168d57506001600160a01b038416600090815260016020908152604080832033845290915290205460001914155b1561170b576001600160a01b03841660009081526001602090815260408083203384529091529020546116c09083614727565b6001600160a01b0385166000818152600160209081526040808320338085529083529281902085905580519485525191936000805160206158b4833981519152929081900390910190a35b5060019392505050565b6001600160a01b0381166000908152600e602052604090205460ff165b919050565b6000611741614318565b506005546201000090046001600160a01b031690565b60055460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26117c9614318565b6005805461ff0019166101001790556117e06148bb565b6117e981614911565b6008556005805461ff0019169055565b633b9aca008114801561182257506001600160a01b038316600090815260116020526040902054155b61186d576040805162461bcd60e51b815260206004820152601760248201527613d3931657d39155d7d513d2d15394d7d0531313d5d151604a1b604482015290519081900360640190fd5b611878838383614a7c565b505050565b6001600160a01b0316600090815260116020908152604080832080546001820154600e909452919093206002908101549301549093919291565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2611920614318565b6005805461ff0019166101001790556007546040805163ea3457b760e01b81526001600160a01b0388811660048301526001600160e01b0319881660248301529151919092169163ea3457b7916044808301926020929190829003018186803b15801561198c57600080fd5b505afa1580156119a0573d6000803e3d6000fd5b505050506040513d60208110156119b657600080fd5b50516119fb576040805162461bcd60e51b815260206004820152600f60248201526e4e4f545f414c4c4f5745445f53494760881b604482015290519081900360640190fd5b611a036148bb565b60006060866001600160a01b03168387878760405160200180846001600160e01b03191681526004018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310611a7c5780518252601f199092019160209182019101611a5d565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114611ade576040519150601f19603f3d011682016040523d82523d6000602084013e611ae3565b606091505b509150915081611b28576040805162461bcd60e51b815260206004820152600b60248201526a4e4f545f5355434345535360a81b604482015290519081900360640190fd5b856001600160e01b031916821515886001600160a01b03167f32258dd51d74a04508615e0840c1fc905dff28c96b7335e69d9a41023ecd286e88888660405180806020018060200183810383528686828181526020019250808284376000838201819052601f909101601f191690920185810384528651815286516020918201939188019250908190849084905b83811015611bce578181015183820152602001611bb6565b50505050905090810190601f168015611bfb5780820380516001836020036101000a031916815260200191505b509550505050505060405180910390a450506005805461ff00191690555050505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2611c8a614318565b6005805461ff001916610100179055611ca1614361565b611ca96143c9565b611cb1614417565b611cba8461447a565b6001600160a01b0384166000908152600e602052604090206003810154611cf890611ce48761459f565b600254611cef614690565b886008546133f1565b915082821015611d3b576040805162461bcd60e51b8152602060048201526009602482015268131253525517d3d55560ba1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600e60205260409020600390810154611d6b91670de0b6b3a7640000611001565b821115611dab576040805162461bcd60e51b81526020600482015260096024820152684f55545f524154494f60b81b604482015290519081900360640190fd5b611db9816003015483614727565b8160030181905550600080611dd184600b54336114e3565b91509150866001600160a01b0316336001600160a01b0316600080516020615874833981519152846040518082815260200191505060405180910390a3611e183387614789565b611e2186614797565b611e2c8733846147a0565b600c54611e449088906001600160a01b0316836147a0565b600c546040805183815290516001600160a01b03808b1693169133916000805160206158948339815191529181900360200190a4506005805461ff001916905595945050505050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2611ef6614318565b6005805461ff001916610100179055611f0d614c77565b611f156148bb565b6005805461ff0019921515600160b01b0260ff60b01b1990911617919091169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2611fa1614318565b6005805461ff001916610100179055611fb86148bb565b611fc0614c77565b600d5460021115612005576040805162461bcd60e51b815260206004820152600a6024820152694d494e5f544f4b454e5360b01b604482015290519081900360640190fd5b600c805460ff60a01b1916600160a01b1790556005805460ff60b01b1916600160b01b17905561203d68056bc75e2d63100000614cc5565b6120503368056bc75e2d63100000614daa565b6005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26120cd8585633b9aca00614db4565b6120d985848484613c98565b5050505050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2612149614318565b6005805461ff001916610100179055612160614361565b612168614417565b6121706143c9565b600061217a6114c1565b905060006121888583614f67565b9050612193816146e7565b60005b600d548110156122c3576000600d82815481106121af57fe5b60009182526020808320909101546001600160a01b0316808352600e9091526040822060030154909250906121e485836144d6565b90506121ef816146e7565b8787858181106121fb57fe5b90506020020135811115612241576040805162461bcd60e51b81526020600482015260086024820152672624a6a4aa2fa4a760c11b604482015290519081900360640190fd5b6001600160a01b0383166000908152600e6020526040902060030154612267908261506f565b6001600160a01b0384166000818152600e60209081526040918290206003019390935580518481529051919233926000805160206158148339815191529281900390910190a36122b88333836150c3565b505050600101612196565b506000806122d487600a54336114e3565b915091506122e187614cc5565b6122eb3383614daa565b600c54612301906001600160a01b031682614daa565b600c5460408051838152905130926001600160a01b03169133916000805160206158948339815191529181900360200190a450506005805461ff00191690555050505050565b6000806123548786614f67565b90506000612362878661506f565b905060006123708289614f67565b90506000612386670de0b6b3a764000085614f67565b90506000612394838361511c565b905060006123a2828e6144d6565b905060006123b0828f614727565b905060006123cf6123c9670de0b6b3a76400008a614727565b8b6144d6565b90506123ec826123e7670de0b6b3a764000084614727565b614f67565b9f9e505050505050505050505050505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a261246a614318565b6005805461ff001916610100179055612481614361565b6124896143c9565b612491614417565b61249a8461447a565b6001600160a01b0384166000908152600e60205260409020600301546124cc906002670de0b6b3a76400005b046144d6565b83111561250f576040805162461bcd60e51b815260206004820152600c60248201526b4d41585f494e5f524154494f60a01b604482015290519081900360640190fd5b60008061251f85600a54336114e3565b6001600160a01b0388166000908152600e60205260409020600381015492945090925090612564906125508961459f565b60025461255b614690565b87600854613268565b9350848410156125a7576040805162461bcd60e51b8152602060048201526009602482015268131253525517d3d55560ba1b604482015290519081900360640190fd5b6125b581600301548461506f565b60038201556040805184815290516001600160a01b0389169133916000805160206158148339815191529181900360200190a36125f184614cc5565b6125fb3385614daa565b61260687338461522a565b6126118733856150c3565b600c546040805184815290516001600160a01b03808b1693169133916000805160206158948339815191529181900360200190a45050506005805461ff00191690559392505050565b60006126658361486d565b3360009081526001602090815260408083206001600160a01b0387168452909152902054808311156126ba573360009081526001602090815260408083206001600160a01b03881684529091528120556126e9565b6126c48184614727565b3360009081526001602090815260408083206001600160a01b03891684529091529020555b3360008181526001602090815260408083206001600160a01b0389168085529083529281902054815190815290519293926000805160206158b4833981519152929181900390910190a35060019392505050565b6000612747614318565b50600654600160a01b900460ff1690565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26127c3614318565b6005805461ff0019166101001790556127da614361565b6127e26143c9565b6127ea614417565b6127f38461447a565b6001600160a01b0384166000908152600e60205260408120600a54909190819061281f908790336114e3565b9150915061284883600301546128348961459f565b60025461283f614690565b8a600854612347565b9350612853846146e7565b84841115612893576040805162461bcd60e51b81526020600482015260086024820152672624a6a4aa2fa4a760c11b604482015290519081900360640190fd5b6001600160a01b0387166000908152600e60205260409020600301546128c3906002670de0b6b3a76400006124c6565b841115612906576040805162461bcd60e51b815260206004820152600c60248201526b4d41585f494e5f524154494f60a01b604482015290519081900360640190fd5b61291483600301548561506f565b60038401556040805185815290516001600160a01b0389169133916000805160206158148339815191529181900360200190a361295086614cc5565b61295a3383614daa565b600c54612970906001600160a01b031682614daa565b61297b8733866150c3565b600c5460408051838152905130926001600160a01b03169133916000805160206158948339815191529181900360200190a45050506005805461ff00191690559392505050565b6001600160a01b031660009081526020819052604090205490565b633b9aca0090565b620f4240670de0b6b3a76400006114d7565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2612a51614318565b6005805461ff001916610100179055612a68614361565b612a70614417565b612a798761447a565b612a828561447a565b600554600160b01b900460ff16612acd576040805162461bcd60e51b815260206004820152600a6024820152694e4f545f5055424c494360b01b604482015290519081900360640190fd5b6001600160a01b038088166000908152600e602052604080822092881682529020600380820154612b0691670de0b6b3a7640000611001565b861115612b46576040805162461bcd60e51b81526020600482015260096024820152684f55545f524154494f60b81b604482015290519081900360640190fd5b6000612b678360030154612b598c61459f565b84600301546114b98c61459f565b905085811115612bac576040805162461bcd60e51b815260206004820152600b60248201526a4c494d49545f505249434560a81b604482015290519081900360640190fd5b600080612bbc89600954336114e3565b91509150612be88560030154612bd18e61459f565b8660030154612bdf8e61459f565b8d600854614285565b96508a871115612c2a576040805162461bcd60e51b81526020600482015260086024820152672624a6a4aa2fa4a760c11b604482015290519081900360640190fd5b612c3885600301548861506f565b8560030181905550612c4e84600301548a614727565b8460030181905550612c758560030154612c678e61459f565b86600301546114b98e61459f565b9550828610158015612c905750612c8c8783614f67565b8311155b612ccf576040805162461bcd60e51b815260206004820152600b60248201526a09a82a890be82a0a0a49eb60ab1b604482015290519081900360640190fd5b87861115612d12576040805162461bcd60e51b815260206004820152600b60248201526a4c494d49545f505249434560a81b604482015290519081900360640190fd5b896001600160a01b03168c6001600160a01b0316336001600160a01b03166000805160206158348339815191528a86604051808381526020018281526020019250505060405180910390a4612d688c33896150c3565b612d738a33846147a0565b600c54612d8b908b906001600160a01b0316836147a0565b600c546040805183815290516001600160a01b03808e1693169133916000805160206158948339815191529181900360200190a450505050506005805461ff001916905590969095509350505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2612e35614318565b6005805461ff001916610100179055612e4c614361565b612e54614417565b612e5d8761447a565b612e668561447a565b600554600160b01b900460ff16612eb1576040805162461bcd60e51b815260206004820152600a6024820152694e4f545f5055424c494360b01b604482015290519081900360640190fd5b6001600160a01b038088166000908152600e6020526040808220928816825281206003830154909190612ee790612b598c61459f565b905085811115612f2c576040805162461bcd60e51b815260206004820152600b60248201526a4c494d49545f505249434560a81b604482015290519081900360640190fd5b600080612f3c8b600954336114e3565b91509150612f5a85600301546002670de0b6b3a7640000816124c657fe5b821115612f9d576040805162461bcd60e51b815260206004820152600c60248201526b4d41585f494e5f524154494f60a01b604482015290519081900360640190fd5b612fc58560030154612fae8e61459f565b8660030154612fbc8e61459f565b86600854613a57565b965088871015613008576040805162461bcd60e51b8152602060048201526009602482015268131253525517d3d55560ba1b604482015290519081900360640190fd5b61301685600301548361506f565b856003018190555061302c846003015488614727565b84600301819055506130458560030154612c678e61459f565b9550828610158015613060575061305c8288614f67565b8311155b61309f576040805162461bcd60e51b815260206004820152600b60248201526a09a82a890be82a0a0a49eb60ab1b604482015290519081900360640190fd5b878611156130e2576040805162461bcd60e51b815260206004820152600b60248201526a4c494d49545f505249434560a81b604482015290519081900360640190fd5b896001600160a01b03168c6001600160a01b0316336001600160a01b0316600080516020615834833981519152858b604051808381526020018281526020019250505060405180910390a46131388c338361522a565b6131438c33846150c3565b61314e8a33896147a0565b8b6001600160a01b0316600c60009054906101000a90046001600160a01b03166001600160a01b0316336001600160a01b0316600080516020615894833981519152846040518082815260200191505060405180910390a450505050506005805461ff001916905590969095509350505050565b6000806131cf8786614f67565b905060006131e5670de0b6b3a764000083614727565b905060006131f382866144d6565b9050600061320d876123e7670de0b6b3a764000085614727565b9050600061321b8c83614727565b90506000613229828e614f67565b90506000613237828861511c565b90506000613245828e6144d6565b905060006132538e83614727565b99505050505050505050509695505050505050565b6000806132758786614f67565b9050600061329461328e670de0b6b3a764000084614727565b856144d6565b905060006132b3866132ae670de0b6b3a764000085614727565b6144d6565b905060006132c18b8361506f565b905060006132cf828d614f67565b905060006132dd828761511c565b905060006132eb828d6144d6565b90506132f7818d614727565b9e9d5050505050505050505050505050565b64e8d4a51000670de0b6b3a76400006114d7565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2613386614318565b6005805461ff00191661010017905561339d6148bb565b60128290556013819055604080518381526020810183905281517fad659e822a6c18906bbabc64f81c2a16ce19173f83c8d0bacf028b507c9ee937929181900390910190a150506005805461ff0019169055565b6000806133fe8786614f67565b9050600061340c8786614727565b9050600061341a8289614f67565b9050600061343982613434670de0b6b3a764000087614f67565b61511c565b90506000613447828d6144d6565b905060006134558d83614727565b9050600061347461346e670de0b6b3a764000089614727565b8a6144d6565b90506132f7826132ae670de0b6b3a764000084614727565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26134f5614318565b6005805461ff00191661010017905561350d8161447a565b604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b15801561355357600080fd5b505afa158015613567573d6000803e3d6000fd5b505050506040513d602081101561357d57600080fd5b50516001600160a01b039091166000908152600e60205260409020600301556005805461ff0019169055565b600c54600160a01b900460ff1690565b60006135c3614318565b506006546001600160a01b031690565b6000806000806135e1614318565b5050600954600a54600b54600c54929591945092506001600160a01b0390911690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a261366d614318565b6005805461ff0019166101001790556136846148bb565b6005805461ff00196001600160a01b03909316620100000262010000600160b01b031990911617919091169055565b60006136bd614318565b6136c5614690565b905090565b68056bc75e2d6310000081565b60006136e1614318565b6136ea8261447a565b61129b8261459f565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156112365780601f1061120b57610100808354040283529160200191611236565b6704a03ce68d21555681565b600990565b6000806137728787614f67565b905060006137808686614f67565b9050600061378e8383614f67565b905060006137b0670de0b6b3a76400006123e7670de0b6b3a764000089614727565b90506137bc82826144d6565b9a9950505050505050505050565b60006137d733848461496c565b50600192915050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2613849614318565b6005805461ff001916610100179055613860614361565b613868614417565b6138706143c9565b60008061388085600b54336114e3565b91509150600061388e6114c1565b9050600061389c8483614f67565b90506138a7816146e7565b6138b13388614789565b600c546138c7906001600160a01b031684614daa565b6138d084614797565b60005b600d54811015613a01576000600d82815481106138ec57fe5b60009182526020808320909101546001600160a01b0316808352600e90915260408220600301549092509061392185836144d6565b905061392c816146e7565b89898581811061393857fe5b9050602002013581101561397f576040805162461bcd60e51b8152602060048201526009602482015268131253525517d3d55560ba1b604482015290519081900360640190fd5b6001600160a01b0383166000908152600e60205260409020600301546139a59082614727565b6001600160a01b0384166000818152600e60209081526040918290206003019390935580518481529051919233926000805160206158748339815191529281900390910190a36139f68333836147a0565b5050506001016138d3565b50600c5460408051858152905130926001600160a01b03169133916000805160206158948339815191529181900360200190a450506005805461ff00191690555050505050565b600981565b600281565b600181565b600080613a648786614f67565b90506000613a7a670de0b6b3a764000085614727565b9050613a8685826144d6565b90506000613a988a6123e78c8561506f565b90506000613aa6828561511c565b90506000613abc670de0b6b3a764000083614727565b9050613ac88a826144d6565b9c9b505050505050505050505050565b600a670de0b6b3a76400006114d7565b671bc16d674ec7ffff81565b6060613afe614318565b613b066143c9565b600d80548060200260200160405190810160405280929190818152602001828054801561123657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613b3e575050505050905090565b670de0b6b3a764000081565b6000613b7b614318565b506007546001600160a01b031690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2613bf4614318565b6005805461ff001916610100179055613c0b6148bb565b600780546001600160a01b0319166001600160a01b03929092169190911790556005805461ff0019169055565b6060613b06614318565b600d5490565b613c5181615288565b60408051606081018252600080825260208083018281528385018381526001600160a01b039096168352601190915292902090518155905160018201559051600290910155565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2613d01614318565b6005805461ff001916610100179055613d186148bb565b613d218461447a565b428211613d6f576040805162461bcd60e51b8152602060048201526017602482015276043414e545f5345545f504153545f54494d455354414d5604c1b604482015290519081900360640190fd5b818111613dbf576040805162461bcd60e51b815260206004820152601960248201527854494d455354414d505f494e434f52524543545f44454c544160381b604482015290519081900360640190fd5b633b9aca008310158015613ddc57506802b5e3af16b18800008311155b613e24576040805162461bcd60e51b81526020600482015260146024820152735441524745545f5745494748545f424f554e445360601b604482015290519081900360640190fd5b6000613e2f8561459f565b90506000613e3f828686866154a0565b9050601354811115613e90576040805162461bcd60e51b815260206004820152601560248201527413505617d5d15251d21517d4115497d4d150d3d391605a1b604482015290519081900360640190fd5b601254811015613edf576040805162461bcd60e51b815260206004820152601560248201527413525397d5d15251d21517d4115497d4d150d3d391605a1b604482015290519081900360640190fd5b6001600160a01b0386166000818152600e60209081526040808320600290810187905581516060810183528981528084018981528184018c8152968652601190945291842091518255915160018201559251920191909155600d54815b81811015613f9057613f868360116000600d8581548110613f5957fe5b60009182526020808320909101546001600160a01b0316835282019290925260400190206002015461506f565b9250600101613f3c565b506802b5e3af16b1880000821115613fe9576040805162461bcd60e51b815260206004820152601760248201527613505617d5105491d15517d513d5105317d5d15251d215604a1b604482015290519081900360640190fd5b60408051858152602081018990528082018890526060810187905290516001600160a01b038a16917f0667af890d2d91f5a21a17df455617ff8f0fcc445cc6286d717c1144a1bcd001919081900360800190a250506005805461ff0019169055505050505050565b600061405b614318565b5060085490565b600061406d8361486d565b3360009081526001602090815260408083206001600160a01b038716845290915290205461409b908361506f565b3360008181526001602090815260408083206001600160a01b0389168085529083529281902085905580519485525191936000805160206158b4833981519152929081900390910190a350600192915050565b6012546013549091565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a261418c614318565b6005805461ff0019166101001790556141a36148bb565b600680546001600160a01b0319166001600160a01b03939093169290921760ff60a01b1916600160a01b911515919091021790556005805461ff0019169055565b6040805162461bcd60e51b8152602060048201526008602482015267111254d05093115160c21b604482015290519081900360640190fd5b6002670de0b6b3a76400006114d7565b6000614236614318565b61423f8261447a565b61129b61424b8361459f565b6123e7614690565b600061425d614318565b6142668261447a565b506001600160a01b03166000908152600e602052604090206003015490565b6000806142928588614f67565b905060006142a08786614727565b905060006142ae8883614f67565b905060006142bc828561511c565b90506142d081670de0b6b3a7640000614727565b90506142e4670de0b6b3a764000087614727565b94506142f96142f38c836144d6565b86614f67565b9b9a5050505050505050505050565b600554600160b01b900460ff1690565b600554610100900460ff161561435f576040805162461bcd60e51b81526020600482015260076024820152665245454e54525960c81b604482015290519081900360640190fd5b565b3260009081526010602052604090205443116143b5576040805162461bcd60e51b815260206004820152600e60248201526d29a0a6a2afaa2c2fa7a924a3a4a760911b604482015290519081900360640190fd5b326000908152601060205260409020439055565b600c54600160a01b900460ff1661435f576040805162461bcd60e51b815260206004820152600d60248201526c1393d517d19253905312569151609a1b604482015290519081900360640190fd5b600654600160a01b900460ff16158061443a57506006546001600160a01b031633145b61435f576040805162461bcd60e51b815260206004820152600c60248201526b27a7262cafaba920a82822a960a11b604482015290519081900360640190fd5b6001600160a01b0381166000908152600e602052604090205460ff166144d3576040805162461bcd60e51b81526020600482015260096024820152681393d517d093d5539160ba1b604482015290519081900360640190fd5b50565b60008282028315806144f05750828482816144ed57fe5b04145b614534576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6706f05b59d3b20000810181811015614587576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6000670de0b6b3a7640000825b049695505050505050565b60006145a96157f2565b506001600160a01b038216600081815260116020908152604080832081516060810183528154815260018201548185015260029182015481840152948452600e9092529091200154815115806146025750808260400151145b8061460e575081514211155b1561461c5791506117329050565b816020015142106146335750604001519050611732565b600061464d828460400151856000015186602001516154a0565b9050600061465f428560000151614727565b90508284604001511115614684576146798383830261506f565b945050505050611732565b61467983838302614727565b600d546000908190815b818110156146df576146d5836146d0600d84815481106146b657fe5b6000918252602090912001546001600160a01b031661459f565b61506f565b925060010161469a565b509091505090565b806144d3576040805162461bcd60e51b815260206004820152600b60248201526a09a82a890be82a0a0a49eb60ab1b604482015290519081900360640190fd5b600080600061473685856154e2565b915091508015614781576040805162461bcd60e51b81526020600482015260116024820152704552525f5355425f554e444552464c4f5760781b604482015290519081900360640190fd5b509392505050565b6147938282615507565b5050565b6144d381615512565b6000836001600160a01b031663a9059cbb84846040518363ffffffff1660e01b815260040180836001600160a01b0316815260200182815260200192505050602060405180830381600087803b1580156147f957600080fd5b505af115801561480d573d6000803e3d6000fd5b505050506040513d602081101561482357600080fd5b5051905080614867576040805162461bcd60e51b815260206004820152600b60248201526a45524332305f46414c534560a81b604482015290519081900360640190fd5b50505050565b6001600160a01b0381166144d3576040805162461bcd60e51b815260206004820152601060248201526f4552525f4e554c4c5f4144445245535360801b604482015290519081900360640190fd5b6005546201000090046001600160a01b0316331461435f576040805162461bcd60e51b815260206004820152600e60248201526d2727aa2fa1a7a72a2927a62622a960911b604482015290519081900360640190fd5b64e8d4a51000811080159061492e575067016345785d8a00008111155b6144d3576040805162461bcd60e51b815260206004820152600a6024820152694645455f424f554e445360b01b604482015290519081900360640190fd5b6001600160a01b0383166000908152602081905260409020548111156149d0576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b6149d98361486d565b6149e28261486d565b6001600160a01b038316600090815260208190526040902054614a059082614727565b6001600160a01b038085166000908152602081905260408082209390935590841681522054614a34908261506f565b6001600160a01b0380841660008181526020818152604091829020949094558051858152905191939287169260008051602061585483398151915292918290030190a3505050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2614ae5614318565b6005805461ff001916610100179055614afc6148bb565b614b058361447a565b633b9aca008110158015614b2257506802b5e3af16b18800008111155b614b63576040805162461bcd60e51b815260206004820152600d60248201526c5745494748545f424f554e445360981b604482015290519081900360640190fd5b620f4240821015614ba9576040805162461bcd60e51b815260206004820152600b60248201526a4d494e5f42414c414e434560a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600e602052604090206002015480821115614be457614bdf614bda8383614727565b6144d3565b614bf9565b80821015614bf957614bf9614bda8284614727565b6001600160a01b0384166000908152600e602052604090206002810183905560030180549084905580841115614c4257614c3d8533614c388785614727565b6150c3565b614c65565b80841015614c65576000614c568286614727565b9050614c638633836147a0565b505b50506005805461ff0019169055505050565b600c54600160a01b900460ff161561435f576040805162461bcd60e51b815260206004820152600c60248201526b1254d7d1925390531256915160a21b604482015290519081900360640190fd5b6007546001600160a01b031615614da1576007546040805163afff324960e01b815230600482015290516000926001600160a01b03169163afff3249916024808301926020929190829003018186803b158015614d2157600080fd5b505afa158015614d35573d6000803e3d6000fd5b505050506040513d6020811015614d4b57600080fd5b50516002549091508190614d5f908461506f565b1115614d9f576040805162461bcd60e51b815260206004820152600a6024820152694d41585f535550504c5960b01b604482015290519081900360640190fd5b505b6144d3816155d0565b6147938282615633565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2614e1d6148bb565b6001600160a01b0383166000908152600e602052604090205460ff1615614e76576040805162461bcd60e51b81526020600482015260086024820152671254d7d093d5539160c21b604482015290519081900360640190fd5b600d54600911614eba576040805162461bcd60e51b815260206004820152600a6024820152694d41585f544f4b454e5360b01b604482015290519081900360640190fd5b604080516080810182526001808252600d805460208085019182526000858701818152606087018281526001600160a01b038c16808452600e9094529782209651875460ff1916901515178755925186860155915160028601559451600390940193909355805491820181559091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b03191690911790556118788383836117f9565b600081614faa576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b670de0b6b3a76400008302831580614fd25750670de0b6b3a7640000848281614fcf57fe5b04145b615016576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b60028304810181811015615064576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b600084828161459457fe5b6000828201838110156150bc576040805162461bcd60e51b815260206004820152601060248201526f4552525f4144445f4f564552464c4f5760801b604482015290519081900360640190fd5b9392505050565b604080516323b872dd60e01b81526001600160a01b0384811660048301523060248301526044820184905291516000928616916323b872dd91606480830192602092919082900301818787803b1580156147f957600080fd5b6000600183101561516c576040805162461bcd60e51b81526020600482015260156024820152744552525f42504f575f424153455f544f4f5f4c4f5760581b604482015290519081900360640190fd5b671bc16d674ec7ffff8311156151c2576040805162461bcd60e51b815260206004820152601660248201527508aa4a4be84a09eaebe8482a68abea89e9ebe90928e960531b604482015290519081900360640190fd5b60006151cd8361563e565b905060006151db8483614727565b905060006151f1866151ec85615659565b615667565b90508161520257925061129b915050565b600061521387846305f5e1006156be565b905061521f82826144d6565b979650505050505050565b600c54604080516323b872dd60e01b81526001600160a01b03858116600483015292831660248201526044810184905290516000928616916323b872dd91606480830192602092919082900301818787803b1580156147f957600080fd5b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26152f1614318565b6005805461ff0019166101001790556153086148bb565b6153118161447a565b6001600160a01b0381166000908152600e60205260409020600381015460029091015461533d906144d3565b6001600160a01b0382166000908152600e6020526040902060010154600d8054600019810191908290811061536e57fe5b600091825260209091200154600d80546001600160a01b03909216918490811061539457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600e6000600d85815481106153d457fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902060010155600d80548061540757fe5b60008281526020808220600019908401810180546001600160a01b031916905590920190925560408051608081018252838152808301848152818301858152606083018681526001600160a01b038b168752600e909552929094209051815460ff1916901515178155925160018401555160028301555160039091015561548f8433856147a0565b50506005805461ff00191690555050565b6000808585116154b9576154b48686614727565b6154c3565b6154c38587614727565b90506154d8816154d38587614727565b61579c565b9695505050505050565b6000808284106154f85750508082036000615500565b505081810360015b9250929050565b61479382308361496c565b3060009081526020819052604090205481111561556d576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b306000908152602081905260409020546155879082614727565b306000908152602081905260409020556002546155a49082614727565b60025560408051828152905160009130916000805160206158548339815191529181900360200190a350565b306000908152602081905260409020546155ea908261506f565b30600090815260208190526040902055600254615607908261506f565b60025560408051828152905130916000916000805160206158548339815191529181900360200190a350565b61479330838361496c565b6000670de0b6b3a764000061565283615659565b0292915050565b670de0b6b3a7640000900490565b6000806002830661568057670de0b6b3a7640000615682565b835b90506002830492505b82156150bc5761569b84856144d6565b935060028306156156b3576156b081856144d6565b90505b60028304925061568b565b60008281806156d587670de0b6b3a76400006154e2565b9092509050670de0b6b3a764000080600060015b88841061578d576000670de0b6b3a76400008202905060008061571d8a61571885670de0b6b3a7640000614727565b6154e2565b9150915061572f876132ae848c6144d6565b965061573b8784614f67565b96508661574a5750505061578d565b8715615754579315935b801561575e579315935b84156157755761576e8688614727565b9550615782565b61577f868861506f565b95505b5050506001016156e9565b50909998505050505050505050565b60008082116157e1576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b8183816157ea57fe5b049392505050565b6040518060600160405280600081526020016000815260200160008152509056fe63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39a908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed5b5ddc912843b56bbfa1620dc5a27cc3b1b82c88ab626118af8dc1319b4a86568c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a264697066735822122062589b3b35fe5b3ab79b385208b3967cb5281ecde120ea0669764a48e9b0608264736f6c634300060c0033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000004b3090ab80100000000000000000000000000000000000000000000000000000d287fb79cd10000000000000000000000000000000000000000000000000000000000000016506f77657220496e64657820506f6f6c20546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000045049505400000000000000000000000000000000000000000000000000000000

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

000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000004b3090ab80100000000000000000000000000000000000000000000000000000d287fb79cd10000000000000000000000000000000000000000000000000000000000000016506f77657220496e64657820506f6f6c20546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000045049505400000000000000000000000000000000000000000000000000000000

-----Decoded View---------------
Arg [0] : name (string): Power Index Pool Token
Arg [1] : symbol (string): PIPT
Arg [2] : minWeightPerSecond (uint256): 5166997354497
Arg [3] : maxWeightPerSecond (uint256): 14467592592593

-----Encoded View---------------
8 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [1] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [2] : 000000000000000000000000000000000000000000000000000004b3090ab801
Arg [3] : 00000000000000000000000000000000000000000000000000000d287fb79cd1
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000016
Arg [5] : 506f77657220496e64657820506f6f6c20546f6b656e00000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000004
Arg [7] : 5049505400000000000000000000000000000000000000000000000000000000


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

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.