Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- BFactory
- Optimization enabled
- true
- Compiler version
- v0.5.17+commit.d19bba13
- Optimization runs
- 100
- EVM Version
- istanbul
- Verified at
- 2026-01-23T00:22:02.254179Z
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BFactory.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is disstributed 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.5.16;
// Builds new BPools, logging their addresses and providing `isBPool(address) -> (bool)`
import "./BPool.sol";
contract BFactory is BBronze {
event LOG_NEW_POOL(
address indexed caller,
address indexed pool
);
event LOG_BLABS(
address indexed caller,
address indexed blabs
);
mapping(address=>bool) private _isBPool;
function isBPool(address b)
external view returns (bool)
{
return _isBPool[b];
}
function newBPool()
external
returns (BPool)
{
BPool bpool = new BPool();
_isBPool[address(bpool)] = true;
emit LOG_NEW_POOL(msg.sender, address(bpool));
bpool.setController(msg.sender);
return bpool;
}
address private _blabs;
constructor() public {
_blabs = msg.sender;
}
function getBLabs()
external view
returns (address)
{
return _blabs;
}
function setBLabs(address b)
external
{
require(msg.sender == _blabs, "ERR_NOT_BLABS");
emit LOG_BLABS(msg.sender, b);
_blabs = b;
}
function collect(BPool pool)
external
{
require(msg.sender == _blabs, "ERR_NOT_BLABS");
uint collected = IERC20(pool).balanceOf(address(this));
bool xfer = pool.transfer(_blabs, collected);
require(xfer, "ERR_ERC20_FAILED");
}
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BColor.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
contract BColor {
function getColor()
external view
returns (bytes32);
}
contract BBronze is BColor {
function getColor()
external view
returns (bytes32) {
return bytes32("BRONZE");
}
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BConst.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
import "./BColor.sol";
contract BConst is BBronze {
uint public constant BONE = 10**18;
uint public constant MIN_BOUND_TOKENS = 2;
uint public constant MAX_BOUND_TOKENS = 8;
uint public constant MIN_FEE = BONE / 10**6;
uint public constant MAX_FEE = BONE / 10;
uint public constant EXIT_FEE = 0;
uint public constant MIN_WEIGHT = BONE;
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;
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BMath.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
import "./BNum.sol";
contract BMath is BBronze, BConst, BNum {
/**********************************************************************************************
// 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
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 - eF)) \ / 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);
// charge exit fee on the pool token side
// pAiAfterExitFee = pAi*(1-exitFee)
uint poolAmountInAfterExitFee = bmul(poolAmountIn, bsub(BONE, EXIT_FEE));
uint newPoolSupply = bsub(poolSupply, poolAmountInAfterExitFee);
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 ( 1 - eF ) //
// eF = exitFee //
**********************************************************************************************/
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 poolAmountInAfterExitFee = bsub(poolSupply, newPoolSupply);
// charge exit fee on the pool token side
// pAi = pAiAfterExitFee/(1-exitFee)
poolAmountIn = bdiv(poolAmountInAfterExitFee, bsub(BONE, EXIT_FEE));
return poolAmountIn;
}
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BNum.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
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;
}
// 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;
}
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/BPool.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
import "./CToken.sol";
import "./BMath.sol";
contract BPool is BBronze, CToken, BMath {
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;
modifier _logs_() {
emit LOG_CALL(msg.sig, msg.sender, msg.data);
_;
}
modifier _lock_() {
require(!_mutex, "ERR_REENTRY");
_mutex = true;
_;
_mutex = false;
}
modifier _viewlock_() {
require(!_mutex, "ERR_REENTRY");
_;
}
bool private _mutex;
address private _factory; // BFactory address to push token exitFee to
address private _controller; // has CONTROL role
bool private _publicSwap; // true if PUBLIC can call SWAP functions
// `setSwapFee` and `finalize` require CONTROL
// `finalize` sets `PUBLIC can SWAP`, `PUBLIC can JOIN`
uint private _swapFee;
bool private _finalized;
address[] private _tokens;
mapping(address=>Record) private _records;
uint private _totalWeight;
constructor() public {
_controller = msg.sender;
_factory = msg.sender;
_swapFee = MIN_FEE;
_publicSwap = false;
_finalized = false;
}
function isPublicSwap()
external view
returns (bool)
{
return _publicSwap;
}
function isFinalized()
external view
returns (bool)
{
return _finalized;
}
function isBound(address t)
external view
returns (bool)
{
return _records[t].bound;
}
function getNumTokens()
external view
returns (uint)
{
return _tokens.length;
}
function getCurrentTokens()
external view _viewlock_
returns (address[] memory tokens)
{
return _tokens;
}
function getFinalTokens()
external view
_viewlock_
returns (address[] memory tokens)
{
require(_finalized, "ERR_NOT_FINALIZED");
return _tokens;
}
function getDenormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].denorm;
}
function getTotalDenormalizedWeight()
external view
_viewlock_
returns (uint)
{
return _totalWeight;
}
function getNormalizedWeight(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
uint denorm = _records[token].denorm;
return bdiv(denorm, _totalWeight);
}
function getBalance(address token)
external view
_viewlock_
returns (uint)
{
require(_records[token].bound, "ERR_NOT_BOUND");
return _records[token].balance;
}
function getSwapFee()
external view
_viewlock_
returns (uint)
{
return _swapFee;
}
function getController()
external view
_viewlock_
returns (address)
{
return _controller;
}
function setSwapFee(uint swapFee)
external
_logs_
_lock_
{
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(swapFee >= MIN_FEE, "ERR_MIN_FEE");
require(swapFee <= MAX_FEE, "ERR_MAX_FEE");
_swapFee = swapFee;
}
function setController(address manager)
external
_logs_
_lock_
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
_controller = manager;
}
function setPublicSwap(bool public_)
external
_logs_
_lock_
{
require(!_finalized, "ERR_IS_FINALIZED");
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
_publicSwap = public_;
}
function finalize()
external
_logs_
_lock_
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length >= MIN_BOUND_TOKENS, "ERR_MIN_TOKENS");
_finalized = true;
_publicSwap = true;
_mintPoolShare(INIT_POOL_SUPPLY);
_pushPoolShare(msg.sender, INIT_POOL_SUPPLY);
}
function bind(address token, uint balance, uint denorm)
external
_logs_
// _lock_ Bind does not lock because it jumps to `rebind`, which does
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(!_records[token].bound, "ERR_IS_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(_tokens.length < MAX_BOUND_TOKENS, "ERR_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
_logs_
_lock_
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
require(denorm >= MIN_WEIGHT, "ERR_MIN_WEIGHT");
require(denorm <= MAX_WEIGHT, "ERR_MAX_WEIGHT");
require(balance >= MIN_BALANCE, "ERR_MIN_BALANCE");
// Adjust the denorm and totalWeight
uint oldWeight = _records[token].denorm;
if (denorm > oldWeight) {
_totalWeight = badd(_totalWeight, bsub(denorm, oldWeight));
require(_totalWeight <= MAX_TOTAL_WEIGHT, "ERR_MAX_TOTAL_WEIGHT");
} else if (denorm < oldWeight) {
_totalWeight = bsub(_totalWeight, 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) {
// In this case liquidity is being withdrawn, so charge EXIT_FEE
uint tokenBalanceWithdrawn = bsub(oldBalance, balance);
uint tokenExitFee = bmul(tokenBalanceWithdrawn, EXIT_FEE);
_pushUnderlying(token, msg.sender, bsub(tokenBalanceWithdrawn, tokenExitFee));
_pushUnderlying(token, _factory, tokenExitFee);
}
}
function unbind(address token)
external
_logs_
_lock_
{
require(msg.sender == _controller, "ERR_NOT_CONTROLLER");
require(_records[token].bound, "ERR_NOT_BOUND");
require(!_finalized, "ERR_IS_FINALIZED");
uint tokenBalance = _records[token].balance;
uint tokenExitFee = bmul(tokenBalance, EXIT_FEE);
_totalWeight = bsub(_totalWeight, _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, bsub(tokenBalance, tokenExitFee));
_pushUnderlying(token, _factory, tokenExitFee);
}
// Absorb any tokens that have been sent to this contract into the pool
function gulp(address token)
external
_logs_
_lock_
{
require(_records[token].bound, "ERR_NOT_BOUND");
_records[token].balance = IERC20(token).balanceOf(address(this));
}
function getSpotPrice(address tokenIn, address tokenOut)
external view
_viewlock_
returns (uint spotPrice)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
Record storage outRecord = _records[tokenOut];
return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, _swapFee);
}
function getSpotPriceSansFee(address tokenIn, address tokenOut)
external view
_viewlock_
returns (uint spotPrice)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
Record storage outRecord = _records[tokenOut];
return calcSpotPrice(inRecord.balance, inRecord.denorm, outRecord.balance, outRecord.denorm, 0);
}
function joinPool(uint poolAmountOut, uint[] calldata maxAmountsIn)
external
_logs_
_lock_
{
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = totalSupply();
uint ratio = bdiv(poolAmountOut, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountIn = bmul(ratio, bal);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountsIn[i], "ERR_LIMIT_IN");
_records[t].balance = badd(_records[t].balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, t, tokenAmountIn);
_pullUnderlying(t, msg.sender, tokenAmountIn);
}
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
}
function exitPool(uint poolAmountIn, uint[] calldata minAmountsOut)
external
_logs_
_lock_
{
require(_finalized, "ERR_NOT_FINALIZED");
uint poolTotal = totalSupply();
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
uint pAiAfterExitFee = bsub(poolAmountIn, exitFee);
uint ratio = bdiv(pAiAfterExitFee, poolTotal);
require(ratio != 0, "ERR_MATH_APPROX");
_pullPoolShare(msg.sender, poolAmountIn);
_pushPoolShare(_factory, exitFee);
_burnPoolShare(pAiAfterExitFee);
for (uint i = 0; i < _tokens.length; i++) {
address t = _tokens[i];
uint bal = _records[t].balance;
uint tokenAmountOut = bmul(ratio, bal);
require(tokenAmountOut != 0, "ERR_MATH_APPROX");
require(tokenAmountOut >= minAmountsOut[i], "ERR_LIMIT_OUT");
_records[t].balance = bsub(_records[t].balance, tokenAmountOut);
emit LOG_EXIT(msg.sender, t, tokenAmountOut);
_pushUnderlying(t, msg.sender, tokenAmountOut);
}
}
function swapExactAmountIn(
address tokenIn,
uint tokenAmountIn,
address tokenOut,
uint minAmountOut,
uint maxPrice
)
external
_logs_
_lock_
returns (uint tokenAmountOut, uint spotPriceAfter)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountIn <= bmul(inRecord.balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
tokenAmountOut = calcOutGivenIn(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountIn,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
return (tokenAmountOut, spotPriceAfter);
}
function swapExactAmountOut(
address tokenIn,
uint maxAmountIn,
address tokenOut,
uint tokenAmountOut,
uint maxPrice
)
external
_logs_
_lock_
returns (uint tokenAmountIn, uint spotPriceAfter)
{
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(_publicSwap, "ERR_SWAP_NOT_PUBLIC");
Record storage inRecord = _records[address(tokenIn)];
Record storage outRecord = _records[address(tokenOut)];
require(tokenAmountOut <= bmul(outRecord.balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
uint spotPriceBefore = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceBefore <= maxPrice, "ERR_BAD_LIMIT_PRICE");
tokenAmountIn = calcInGivenOut(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
tokenAmountOut,
_swapFee
);
require(tokenAmountIn <= maxAmountIn, "ERR_LIMIT_IN");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
spotPriceAfter = calcSpotPrice(
inRecord.balance,
inRecord.denorm,
outRecord.balance,
outRecord.denorm,
_swapFee
);
require(spotPriceAfter >= spotPriceBefore, "ERR_MATH_APPROX");
require(spotPriceAfter <= maxPrice, "ERR_LIMIT_PRICE");
require(spotPriceBefore <= bdiv(tokenAmountIn, tokenAmountOut), "ERR_MATH_APPROX");
emit LOG_SWAP(msg.sender, tokenIn, tokenOut, tokenAmountIn, tokenAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
return (tokenAmountIn, spotPriceAfter);
}
function joinswapExternAmountIn(address tokenIn, uint tokenAmountIn, uint minPoolAmountOut)
external
_logs_
_lock_
returns (uint poolAmountOut)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
Record storage inRecord = _records[tokenIn];
poolAmountOut = calcPoolOutGivenSingleIn(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountIn,
_swapFee
);
require(poolAmountOut >= minPoolAmountOut, "ERR_LIMIT_OUT");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
return poolAmountOut;
}
function joinswapPoolAmountOut(address tokenIn, uint poolAmountOut, uint maxAmountIn)
external
_logs_
_lock_
returns (uint tokenAmountIn)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenIn].bound, "ERR_NOT_BOUND");
Record storage inRecord = _records[tokenIn];
tokenAmountIn = calcSingleInGivenPoolOut(
inRecord.balance,
inRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountOut,
_swapFee
);
require(tokenAmountIn != 0, "ERR_MATH_APPROX");
require(tokenAmountIn <= maxAmountIn, "ERR_LIMIT_IN");
require(tokenAmountIn <= bmul(_records[tokenIn].balance, MAX_IN_RATIO), "ERR_MAX_IN_RATIO");
inRecord.balance = badd(inRecord.balance, tokenAmountIn);
emit LOG_JOIN(msg.sender, tokenIn, tokenAmountIn);
_mintPoolShare(poolAmountOut);
_pushPoolShare(msg.sender, poolAmountOut);
_pullUnderlying(tokenIn, msg.sender, tokenAmountIn);
return tokenAmountIn;
}
function exitswapPoolAmountIn(address tokenOut, uint poolAmountIn, uint minAmountOut)
external
_logs_
_lock_
returns (uint tokenAmountOut)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
Record storage outRecord = _records[tokenOut];
tokenAmountOut = calcSingleOutGivenPoolIn(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
poolAmountIn,
_swapFee
);
require(tokenAmountOut >= minAmountOut, "ERR_LIMIT_OUT");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
return tokenAmountOut;
}
function exitswapExternAmountOut(address tokenOut, uint tokenAmountOut, uint maxPoolAmountIn)
external
_logs_
_lock_
returns (uint poolAmountIn)
{
require(_finalized, "ERR_NOT_FINALIZED");
require(_records[tokenOut].bound, "ERR_NOT_BOUND");
require(tokenAmountOut <= bmul(_records[tokenOut].balance, MAX_OUT_RATIO), "ERR_MAX_OUT_RATIO");
Record storage outRecord = _records[tokenOut];
poolAmountIn = calcPoolInGivenSingleOut(
outRecord.balance,
outRecord.denorm,
_totalSupply,
_totalWeight,
tokenAmountOut,
_swapFee
);
require(poolAmountIn != 0, "ERR_MATH_APPROX");
require(poolAmountIn <= maxPoolAmountIn, "ERR_LIMIT_IN");
outRecord.balance = bsub(outRecord.balance, tokenAmountOut);
uint exitFee = bmul(poolAmountIn, EXIT_FEE);
emit LOG_EXIT(msg.sender, tokenOut, tokenAmountOut);
_pullPoolShare(msg.sender, poolAmountIn);
_burnPoolShare(bsub(poolAmountIn, exitFee));
_pushPoolShare(_factory, exitFee);
_pushUnderlying(tokenOut, msg.sender, tokenAmountOut);
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, "ERR_ERC20_FALSE");
}
function _pushUnderlying(address erc20, address to, uint amount)
internal
{
bool xfer = IERC20(erc20).transfer(to, amount);
require(xfer, "ERR_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
{
_mint(amount);
}
function _burnPoolShare(uint amount)
internal
{
_burn(amount);
}
}
/media/eagle/Data/Source/Symmetric/BACKUP/Symmetric.Core/contracts/CToken.sol
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.5.16;
import "./BNum.sol";
// Highly opinionated token implementation
interface IERC20 {
event Approval(address indexed src, address indexed dst, uint amt);
event Transfer(address indexed src, address indexed dst, uint amt);
function totalSupply() external view returns (uint);
function balanceOf(address whom) external view returns (uint);
function allowance(address src, address dst) external view returns (uint);
function approve(address dst, uint amt) external returns (bool);
function transfer(address dst, uint amt) external returns (bool);
function transferFrom(
address src, address dst, uint amt
) external returns (bool);
}
contract CTokenBase 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");
_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);
}
}
contract CToken is CTokenBase, IERC20 {
string private _name = "Cent Pool Token";
string private _symbol = "CPT";
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 view returns (uint) {
return _allowance[src][dst];
}
function balanceOf(address whom) external view returns (uint) {
return _balance[whom];
}
function totalSupply() public view returns (uint) {
return _totalSupply;
}
function approve(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = amt;
emit Approval(msg.sender, dst, amt);
return true;
}
function increaseApproval(address dst, uint amt) external returns (bool) {
_allowance[msg.sender][dst] = 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) {
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 returns (bool) {
_move(msg.sender, dst, amt);
return true;
}
function transferFrom(address src, address dst, uint amt) external returns (bool) {
require(msg.sender == src || amt <= _allowance[src][msg.sender], "ERR_CTOKEN_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(msg.sender, dst, _allowance[src][msg.sender]);
}
return true;
}
}
Compiler Settings
{"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":100,"enabled":true},"libraries":{},"evmVersion":"istanbul"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","payable":false,"inputs":[]},{"type":"event","name":"LOG_BLABS","inputs":[{"type":"address","name":"caller","internalType":"address","indexed":true},{"type":"address","name":"blabs","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"LOG_NEW_POOL","inputs":[{"type":"address","name":"caller","internalType":"address","indexed":true},{"type":"address","name":"pool","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"collect","inputs":[{"type":"address","name":"pool","internalType":"contract BPool"}],"constant":false},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"address","name":"","internalType":"address"}],"name":"getBLabs","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"getColor","inputs":[],"constant":true},{"type":"function","stateMutability":"view","payable":false,"outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"isBPool","inputs":[{"type":"address","name":"b","internalType":"address"}],"constant":true},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[{"type":"address","name":"","internalType":"contract BPool"}],"name":"newBPool","inputs":[],"constant":false},{"type":"function","stateMutability":"nonpayable","payable":false,"outputs":[],"name":"setBLabs","inputs":[{"type":"address","name":"b","internalType":"address"}],"constant":false}]
Contract Creation Code
0x608060405234801561001057600080fd5b50600180546001600160a01b03191633179055615af1806100326000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806306ec16f81461006757806336ffb1671461008f5780639a86139b146100b3578063c2bb6dc2146100cd578063c6ce34fb14610107578063d556c5dc1461012d575b600080fd5b61008d6004803603602081101561007d57600080fd5b50356001600160a01b0316610135565b005b6100976102cd565b604080516001600160a01b039092168252519081900360200190f35b6100bb6102dc565b60408051918252519081900360200190f35b6100f3600480360360208110156100e357600080fd5b50356001600160a01b03166102e9565b604080519115158252519081900360200190f35b61008d6004803603602081101561011d57600080fd5b50356001600160a01b0316610307565b6100976103ae565b6001546001600160a01b03163314610184576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4e4f545f424c41425360981b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156101ce57600080fd5b505afa1580156101e2573d6000803e3d6000fd5b505050506040513d60208110156101f857600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293506000929185169163a9059cbb9160448082019260209290919082900301818787803b15801561025557600080fd5b505af1158015610269573d6000803e3d6000fd5b505050506040513d602081101561027f57600080fd5b50519050806102c8576040805162461bcd60e51b815260206004820152601060248201526f11549497d15490cc8c17d1905253115160821b604482015290519081900360640190fd5b505050565b6001546001600160a01b031690565b6542524f4e5a4560d01b90565b6001600160a01b031660009081526020819052604090205460ff1690565b6001546001600160a01b03163314610356576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4e4f545f424c41425360981b604482015290519081900360640190fd5b6040516001600160a01b0382169033907ff586fa6ee1fc42f5b727f3b214ccbd0b6d7e698c45d49ba32f224fbb8670155d90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000806040516103bd9061048e565b604051809103906000f0801580156103d9573d6000803e3d6000fd5b506001600160a01b038116600081815260208190526040808220805460ff1916600117905551929350909133917f8ccec77b0cb63ac2cafd0f5de8cdfadab91ce656d262240ba8a6343bccc5f94591a3604080516392eefe9b60e01b815233600482015290516001600160a01b038316916392eefe9b91602480830192600092919082900301818387803b15801561047057600080fd5b505af1158015610484573d6000803e3d6000fd5b5092935050505090565b6156218061049c8339019056fe60c0604052600f60808190526e21b2b73a102837b7b6102a37b5b2b760891b60a0908152620000329160039190620000cc565b506040805180820190915260038082526210d41560ea1b60209092019182526200005f91600491620000cc565b506005805460ff191660121790553480156200007a57600080fd5b50600680546005805462010000600160b01b031916336201000081029190911790915564e8d4a510006007556001600160a01b03199091161760ff60a01b191690556008805460ff1916905562000171565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200010f57805160ff19168380011785556200013f565b828001600101855582156200013f579182015b828111156200013f57825182559160200191906001019062000122565b506200014d92915062000151565b5090565b6200016e91905b808211156200014d576000815560010162000158565b90565b6154a080620001816000396000f3fe608060405234801561001057600080fd5b506004361061035b5760003560e01c80638d4e4083116101ca578063bc694ea211610105578063d73dd623116100a8578063d73dd62314610b5e578063dd62ed3e14610b8a578063e4a28a5214610461578063e4e1e53814610bb8578063ec09302114610bea578063f1b8a9b714610bf2578063f8b2cb4f14610c18578063f8d6aed414610c3e578063fde924f714610c795761035b565b8063bc694ea214610ab8578063be3bbd2e14610ac0578063c36596a6146104d5578063c6580d1214610b18578063cc77828d14610b20578063cd2ed8fb14610b28578063cf5e7bd314610b30578063d4cadf6814610b565761035b565b8063a221ee491161016d578063a221ee4914610987578063a9059cbb146109bc578063b02f0b73146109e8578063b0e0d13614610a5d578063b7b800a414610a65578063ba019dab14610a6d578063ba9530a614610a75578063bc063e1a14610ab05761035b565b80638d4e40831461090b57806392eefe9b14610913578063936c3477146109395780639381cd2b14610941578063948d8ce61461094957806395d89b411461096f578063992e2a92146109775780639a86139b1461097f5761035b565b806349b595521161029a57806376c7a3c71161023d57806376c7a3c71461078b5780637c5e9ea4146107935780638201aa3f146107ec57806382f652ad1461082c5780638656b65314610867578063867378c5146108a257806389298012146108aa5780638c28cbe8146108e55761035b565b806349b59552146105fe5780634bb278f31461061d5780634f69c0d4146106255780635c1bbaf71461069a5780635db34277146106d557806366188463146107075780636d06dfa01461073357806370a08231146107655761035b565b8063218b538211610302578063218b5382146104d557806323b872dd146104dd5780632f37b624146105135780633018205f14610539578063313ce5671461055d57806334e199071461057b5780633fdddaa21461059a57806346ab38f1146105cc5761035b565b806302c967481461036057806306fdde03146103a4578063095ea7b31461042157806309a3bbe4146104615780631446a7ff1461046957806315e84af91461049757806318160ddd146104c5578063189d00ca146104cd575b600080fd5b6103926004803603606081101561037657600080fd5b506001600160a01b038135169060208101359060400135610c81565b60408051918252519081900360200190f35b6103ac610fcf565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103e65781810151838201526020016103ce565b50505050905090810190601f1680156104135780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61044d6004803603604081101561043757600080fd5b506001600160a01b038135169060200135611065565b604080519115158252519081900360200190f35b6103926110ba565b6103926004803603604081101561047f57600080fd5b506001600160a01b03813581169160200135166110c7565b610392600480360360408110156104ad57600080fd5b506001600160a01b038135811691602001351661121c565b610392611368565b61039261136e565b610392611382565b61044d600480360360608110156104f357600080fd5b506001600160a01b0381358116916020810135909116906040013561138e565b61044d6004803603602081101561052957600080fd5b50356001600160a01b03166114e8565b610541611506565b604080516001600160a01b039092168252519081900360200190f35b610565611564565b6040805160ff9092168252519081900360200190f35b6105986004803603602081101561059157600080fd5b503561156d565b005b610598600480360360608110156105b057600080fd5b506001600160a01b03813516906020810135906040013561176a565b610392600480360360608110156105e257600080fd5b506001600160a01b038135169060208101359060400135611b77565b6105986004803603602081101561061457600080fd5b50351515611e64565b610598611fe7565b6105986004803603604081101561063b57600080fd5b81359190810190604081016020820135600160201b81111561065c57600080fd5b82018360208201111561066e57600080fd5b803590602001918460208302840111600160201b8311171561068f57600080fd5b5090925090506121de565b610392600480360360c08110156106b057600080fd5b5080359060208101359060408101359060608101359060808101359060a001356124c5565b610392600480360360608110156106eb57600080fd5b506001600160a01b03813516906020810135906040013561257d565b61044d6004803603604081101561071d57600080fd5b506001600160a01b03813516906020013561284e565b6103926004803603606081101561074957600080fd5b506001600160a01b038135169060208101359060400135612926565b6103926004803603602081101561077b57600080fd5b50356001600160a01b0316612c25565b610392612c40565b6107d3600480360360a08110156107a957600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135612c52565b6040805192835260208301919091528051918290030190f35b6107d3600480360360a081101561080257600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135613115565b610392600480360360c081101561084257600080fd5b5080359060208101359060408101359060608101359060808101359060a001356135bf565b610392600480360360c081101561087d57600080fd5b5080359060208101359060408101359060608101359060808101359060a0013561367e565b61039261371f565b610392600480360360c08110156108c057600080fd5b5080359060208101359060408101359060608101359060808101359060a00135613733565b610598600480360360208110156108fb57600080fd5b50356001600160a01b03166137e3565b61044d613997565b6105986004803603602081101561092957600080fd5b50356001600160a01b03166139a0565b610392613ade565b610392613b33565b6103926004803603602081101561095f57600080fd5b50356001600160a01b0316613b40565b6103ac613c0a565b610392613c6b565b610392613c77565b610392600480360360a081101561099d57600080fd5b5080359060208101359060408101359060608101359060800135613c84565b61044d600480360360408110156109d257600080fd5b506001600160a01b038135169060200135613ce9565b610598600480360360408110156109fe57600080fd5b81359190810190604081016020820135600160201b811115610a1f57600080fd5b820183602082011115610a3157600080fd5b803590602001918460208302840111600160201b83111715610a5257600080fd5b509092509050613cff565b610392614034565b610392614039565b61039261403e565b610392600480360360c0811015610a8b57600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614043565b6103926140c4565b6103926140d4565b610ac86140e0565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610b04578181015183820152602001610aec565b505050509050019250505060405180910390f35b6103926141d8565b610ac86141dd565b61039261422b565b61059860048036036020811015610b4657600080fd5b50356001600160a01b0316614231565b6103926145b3565b61044d60048036036040811015610b7457600080fd5b506001600160a01b038135169060200135614608565b61039260048036036040811015610ba057600080fd5b506001600160a01b0381358116916020013516614689565b61059860048036036060811015610bce57600080fd5b506001600160a01b0381351690602081013590604001356146b4565b61039261490b565b61039260048036036020811015610c0857600080fd5b50356001600160a01b031661491b565b61039260048036036020811015610c2e57600080fd5b50356001600160a01b03166149f7565b610392600480360360c0811015610c5457600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614ac1565b61044d614b44565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615610d2f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16610d89576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16610de6576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a60205260409020600390810154610e1b91670de0b6b3a76400005b04600101614b54565b831115610e63576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754610e9d949392919089906135bf565b915081610ee3576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115610f27576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b610f35816003015485614c1d565b60038201556000610f468382614b54565b6040805187815290519192506001600160a01b03881691339160008051602061542c833981519152919081900360200190a3610f823384614c7f565b610f94610f8f8483614c1d565b614c8d565b600554610fb0906201000090046001600160a01b031682614c99565b610fbb863387614ca3565b50506005805461ff00191690559392505050565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561105b5780601f106110305761010080835404028352916020019161105b565b820191906000526020600020905b81548152906001019060200180831161103e57829003601f168201915b5050505050905090565b3360008181526001602090815260408083206001600160a01b0387168085529083528184208690558151868152915193949093909260008051602061544c833981519152928290030190a35060015b92915050565b6802b5e3af16b188000081565b600554600090610100900460ff1615611115576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff16611172576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff166111cf576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a602052604080822092851682528120600380840154600280860154928401549084015493946112139492939290613c84565b95945050505050565b600554600090610100900460ff161561126a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff166112c7576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16611324576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a602052604080822092851682529020600380830154600280850154928401549084015460075461121394929190613c84565b60025490565b6402540be400670de0b6b3a76400005b0481565b670de0b6b3a764000081565b6000336001600160a01b03851614806113ca57506001600160a01b03841660009081526001602090815260408083203384529091529020548211155b611413576040805162461bcd60e51b815260206004820152601560248201527422a9292fa1aa27a5a2a72fa120a22fa1a0a62622a960591b604482015290519081900360640190fd5b61141e848484614d6e565b336001600160a01b0385161480159061145c57506001600160a01b038416600090815260016020908152604080832033845290915290205460001914155b156114de576001600160a01b038416600090815260016020908152604080832033845290915290205461148f9083614c1d565b6001600160a01b038581166000908152600160209081526040808320338085529083529281902085905580519485525192871693919260008051602061544c8339815191529281900390910190a35b5060019392505050565b6001600160a01b03166000908152600a602052604090205460ff1690565b600554600090610100900460ff1615611554576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b506006546001600160a01b031690565b60055460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611619576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1615611673576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b031633146116c7576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b64e8d4a5100081101561170f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d494e5f46454560a81b604482015290519081900360640190fd5b67016345785d8a000081111561175a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d41585f46454560a81b604482015290519081900360640190fd5b6007556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611816576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b039091161461187b576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff166118d8576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff1615611923576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b670de0b6b3a7640000811015611971576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3525397d5d15251d21560921b604482015290519081900360640190fd5b6802b5e3af16b18800008111156119c0576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3505617d5d15251d21560921b604482015290519081900360640190fd5b620f4240821015611a0a576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4d494e5f42414c414e434560881b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090206002015480821115611aa157611a43600b54611a3e8484614c1d565b614e6c565b600b8190556802b5e3af16b18800001015611a9c576040805162461bcd60e51b815260206004820152601460248201527311549497d3505617d513d5105317d5d15251d21560621b604482015290519081900360640190fd5b611ac2565b80821015611ac257611abe600b54611ab98385614c1d565b614c1d565b600b555b6001600160a01b0384166000908152600a602052604090206002810183905560030180549084905580841115611b0b57611b068533611b018785614c1d565b614eb9565b611b65565b80841015611b65576000611b1f8286614c1d565b90506000611b2e826000614b54565b9050611b448733611b3f8585614c1d565b614ca3565b600554611b629088906201000090046001600160a01b031683614ca3565b50505b50506005805461ff0019169055505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611c25576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16611c7f576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16611cdc576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754611d1694939291908990613733565b915082821015611d5d576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a60205260409020600390810154611d8d91670de0b6b3a7640000610e12565b821115611dd5576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b611de3816003015483614c1d565b60038201556000611df48582614b54565b6040805185815290519192506001600160a01b03881691339160008051602061542c833981519152919081900360200190a3611e303386614c7f565b611e3d610f8f8683614c1d565b600554611e59906201000090046001600160a01b031682614c99565b610fbb863385614ca3565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611f10576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1615611f6a576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b03163314611fbe576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60068054911515600160a01b0260ff60a01b199092169190911790556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612093576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b03909116146120f8576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60085460ff1615612143576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6009546002111561218c576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d494e5f544f4b454e5360901b604482015290519081900360640190fd5b6008805460ff191660011790556006805460ff60a01b1916600160a01b1790556121be68056bc75e2d63100000614f12565b6121d13368056bc75e2d63100000614c99565b6005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561228a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff166122e4576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b60006122ee611368565b905060006122fc8583614f1b565b905080612342576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b60005b6009548110156124b15760006009828154811061235e57fe5b60009182526020808320909101546001600160a01b0316808352600a9091526040822060030154909250906123938583614b54565b9050806123d9576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b8787858181106123e557fe5b9050602002013581111561242f576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a60205260409020600301546124559082614e6c565b6001600160a01b0384166000818152600a60209081526040918290206003019390935580518481529051919233926000805160206153ec8339815191529281900390910190a36124a6833383614eb9565b505050600101612345565b506124bb85614f12565b611b653386614c99565b6000806124d28786614f1b565b905060006124e08786614e6c565b905060006124ee8289614f1b565b90506000612504670de0b6b3a764000085614f1b565b905060006125128383615023565b90506000612520828e614b54565b9050600061252e828f614c1d565b9050600061254d612547670de0b6b3a76400008a614c1d565b8b614b54565b905061256a82612565670de0b6b3a764000084614c1d565b614f1b565b9f9e505050505050505050505050505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561262b576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612685576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff166126e2576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060030154612714906002670de0b6b3a76400005b04614b54565b83111561275b576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b546007546127959493929190899061367e565b9150828210156127dc576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6127ea816003015485614e6c565b60038201556040805185815290516001600160a01b0387169133916000805160206153ec8339815191529181900360200190a361282682614f12565b6128303383614c99565b61283b853386614eb9565b506005805461ff00191690559392505050565b3360009081526001602090815260408083206001600160a01b0386168452909152812054808311156128a3573360009081526001602090815260408083206001600160a01b03881684529091528120556128d2565b6128ad8184614c1d565b3360009081526001602090815260408083206001600160a01b03891684529091529020555b3360008181526001602090815260408083206001600160a01b03891680855290835292819020548151908152905192939260008051602061544c833981519152929181900390910190a35060019392505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156129d4576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612a2e576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16612a8b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754612ac5949392919089906124c5565b915081612b0b576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115612b4f576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a6020526040902060030154612b7f906002670de0b6b3a764000061270e565b821115612bc6576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b612bd4816003015483614e6c565b60038201556040805183815290516001600160a01b0387169133916000805160206153ec8339815191529181900360200190a3612c1084614f12565b612c1a3385614c99565b61283b853384614eb9565b6001600160a01b031660009081526020819052604090205490565b620f4240670de0b6b3a764000061137e565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612cef576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff16612d5b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff16612db8576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff16612e0c576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600a602052604080822092881682529020600380820154612e4591670de0b6b3a7640000610e12565b861115612e8d576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b6000612eae8360030154846002015484600301548560020154600754613c84565b905085811115612efb576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b612f1b83600301548460020154846003015485600201548b600754614ac1565b945088851115612f61576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b612f6f836003015486614e6c565b8360030181905550612f85826003015488614c1d565b600380840182905584015460028086015490850154600754612fa8949190613c84565b935080841015612ff1576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b85841115613038576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b6130428588614f1b565b811115613088576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378888b604051808381526020018281526020019250505060405180910390a46130f08a3387614eb9565b6130fb883389614ca3565b5050506005805461ff001916905590969095509350505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156131b2576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff1661321e576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff1661327b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff166132cf576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600a6020526040808220928816825290206003820154613309906002670de0b6b3a764000061270e565b881115613350576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b60006133718360030154846002015484600301548560020154600754613c84565b9050858111156133be576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b6133de83600301548460020154846003015485600201548d600754614043565b945086851015613425576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b61343383600301548a614e6c565b8360030181905550613449826003015486614c1d565b60038084018290558401546002808601549085015460075461346c949190613c84565b9350808410156134b5576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b858411156134fc576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b6135068986614f1b565b81111561354c576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d433788c89604051808381526020018281526020019250505060405180910390a46135b48a338b614eb9565b6130fb883387614ca3565b6000806135cc8786614f1b565b905060006135e2670de0b6b3a764000083614c1d565b905060006135f08286614b54565b9050600061360a87612565670de0b6b3a764000085614c1d565b905060006136188c83614c1d565b90506000613626828e614f1b565b905060006136348288615023565b90506000613642828e614b54565b905060006136508e83614c1d565b905061366981612565670de0b6b3a76400006000614c1d565b99505050505050505050509695505050505050565b60008061368b8786614f1b565b905060006136aa6136a4670de0b6b3a764000084614c1d565b85614b54565b905060006136c9866136c4670de0b6b3a764000085614c1d565b614b54565b905060006136d78b83614e6c565b905060006136e5828d614f1b565b905060006136f38287615023565b90506000613701828d614b54565b905061370d818d614c1d565b9e9d5050505050505050505050505050565b64e8d4a51000670de0b6b3a764000061137e565b6000806137408786614f1b565b9050600061375b856136c4670de0b6b3a76400006000614c1d565b905060006137698883614c1d565b90506000613777828a614f1b565b9050600061379682613791670de0b6b3a764000088614f1b565b615023565b905060006137a4828e614b54565b905060006137b28e83614c1d565b905060006137cb612547670de0b6b3a76400008a614c1d565b905061256a826136c4670de0b6b3a764000084614c1d565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561388f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0381166000908152600a602052604090205460ff166138fb576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b15801561394157600080fd5b505afa158015613955573d6000803e3d6000fd5b505050506040513d602081101561396b57600080fd5b50516001600160a01b039091166000908152600a60205260409020600301556005805461ff0019169055565b60085460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613a4c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614613ab1576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03929092169190911790556005805461ff0019169055565b600554600090610100900460ff1615613b2c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b50600b5490565b68056bc75e2d6310000081565b600554600090610100900460ff1615613b8e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16613beb576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206002015490565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561105b5780601f106110305761010080835404028352916020019161105b565b6704a03ce68d21555681565b6542524f4e5a4560d01b90565b600080613c918787614f1b565b90506000613c9f8686614f1b565b90506000613cad8383614f1b565b90506000613ccf670de0b6b3a7640000612565670de0b6b3a764000089614c1d565b9050613cdb8282614b54565b9a9950505050505050505050565b6000613cf6338484614d6e565b50600192915050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613dab576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16613e05576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6000613e0f611368565b90506000613e1e856000614b54565b90506000613e2c8683614c1d565b90506000613e3a8285614f1b565b905080613e80576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b613e8a3388614c7f565b600554613ea6906201000090046001600160a01b031684614c99565b613eaf82614c8d565b60005b60095481101561401f57600060098281548110613ecb57fe5b60009182526020808320909101546001600160a01b0316808352600a909152604082206003015490925090613f008583614b54565b905080613f46576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b898985818110613f5257fe5b90506020020135811015613f9d576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a6020526040902060030154613fc39082614c1d565b6001600160a01b0384166000818152600a602090815260409182902060030193909355805184815290519192339260008051602061542c8339815191529281900390910190a3614014833383614ca3565b505050600101613eb2565b50506005805461ff0019169055505050505050565b600881565b600281565b600181565b6000806140508786614f1b565b90506000614066670de0b6b3a764000085614c1d565b90506140728582614b54565b905060006140848a6125658c85614e6c565b905060006140928285615023565b905060006140a8670de0b6b3a764000083614c1d565b90506140b48a82614b54565b9c9b505050505050505050505050565b600a670de0b6b3a764000061137e565b671bc16d674ec7ffff81565b600554606090610100900460ff161561412e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60085460ff16614179576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b600980548060200260200160405190810160405280929190818152602001828054801561105b57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116141b1575050505050905090565b600081565b600554606090610100900460ff1615614179576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60095490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156142dd576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614614342576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff1661439f576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff16156143ea576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a6020526040812060030154906144118282614b54565b600b546001600160a01b0385166000908152600a602052604090206002015491925061443c91614c1d565b600b556001600160a01b0383166000908152600a602052604090206001015460098054600019810191908290811061447057fe5b600091825260209091200154600980546001600160a01b03909216918490811061449657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600a6000600985815481106144d657fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902060010155600980548061450957fe5b60008281526020808220600019908401810180546001600160a01b031916905590920190925560408051608081018252838152808301848152818301858152606083018681526001600160a01b038c168752600a909552929094209051815460ff191690151517815592516001840155516002830155516003909101556145958533611b3f8787614c1d565b600554611b659086906201000090046001600160a01b031685614ca3565b600554600090610100900460ff1615614601576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b5060075490565b3360009081526001602090815260408083206001600160a01b03861684529091528120546146369083614e6c565b3360008181526001602090815260408083206001600160a01b03891680855290835292819020859055805194855251919360008051602061544c833981519152929081900390910190a350600192915050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26006546001600160a01b03163314614769576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff16156147c6576040805162461bcd60e51b815260206004820152600c60248201526b11549497d254d7d093d5539160a21b604482015290519081900360640190fd5b60085460ff1615614811576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b600954600811614859576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d41585f544f4b454e5360901b604482015290519081900360640190fd5b6040805160808101825260018082526009805460208085019182526000858701818152606087018281526001600160a01b038c16808452600a9094529782209651875460ff1916901515178755925186860155915160028601559451600390940193909355805491820181559091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b031916909117905561490683838361176a565b505050565b6002670de0b6b3a764000061137e565b600554600090610100900460ff1615614969576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff166149c6576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a6020526040902060020154600b546149f0908290614f1b565b9392505050565b600554600090610100900460ff1615614a45576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16614aa2576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206003015490565b600080614ace8588614f1b565b90506000614adc8786614c1d565b90506000614aea8883614f1b565b90506000614af88285615023565b9050614b0c81670de0b6b3a7640000614c1d565b9050614b20670de0b6b3a764000087614c1d565b9450614b35614b2f8c83614b54565b86614f1b565b9b9a5050505050505050505050565b600654600160a01b900460ff1690565b6000828202831580614b6e575082848281614b6b57fe5b04145b614bb2576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6706f05b59d3b20000810181811015614c05576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6000670de0b6b3a7640000825b049695505050505050565b6000806000614c2c8585615131565b915091508015614c77576040805162461bcd60e51b81526020600482015260116024820152704552525f5355425f554e444552464c4f5760781b604482015290519081900360640190fd5b509392505050565b614c898282615156565b5050565b614c9681615161565b50565b614c89828261521f565b6040805163a9059cbb60e01b81526001600160a01b03848116600483015260248201849052915160009286169163a9059cbb91604480830192602092919082900301818787803b158015614cf657600080fd5b505af1158015614d0a573d6000803e3d6000fd5b505050506040513d6020811015614d2057600080fd5b5051905080614d68576040805162461bcd60e51b815260206004820152600f60248201526e4552525f45524332305f46414c534560881b604482015290519081900360640190fd5b50505050565b6001600160a01b038316600090815260208190526040902054811115614dd2576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b6001600160a01b038316600090815260208190526040902054614df59082614c1d565b6001600160a01b038085166000908152602081905260408082209390935590841681522054614e249082614e6c565b6001600160a01b0380841660008181526020818152604091829020949094558051858152905191939287169260008051602061540c83398151915292918290030190a3505050565b6000828201838110156149f0576040805162461bcd60e51b815260206004820152601060248201526f4552525f4144445f4f564552464c4f5760801b604482015290519081900360640190fd5b604080516323b872dd60e01b81526001600160a01b0384811660048301523060248301526044820184905291516000928616916323b872dd91606480830192602092919082900301818787803b158015614cf657600080fd5b614c968161522a565b600081614f5e576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b670de0b6b3a76400008302831580614f865750670de0b6b3a7640000848281614f8357fe5b04145b614fca576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b60028304810181811015615018576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b6000848281614c1257fe5b60006001831015615073576040805162461bcd60e51b81526020600482015260156024820152744552525f42504f575f424153455f544f4f5f4c4f5760581b604482015290519081900360640190fd5b671bc16d674ec7ffff8311156150c9576040805162461bcd60e51b815260206004820152601660248201527508aa4a4be84a09eaebe8482a68abea89e9ebe90928e960531b604482015290519081900360640190fd5b60006150d48361528d565b905060006150e28483614c1d565b905060006150f8866150f3856152a8565b6152b6565b9050816151095792506110b4915050565b600061511a87846305f5e10061530d565b90506151268282614b54565b979650505050505050565b600080828410615147575050808203600061514f565b505081810360015b9250929050565b614c89823083614d6e565b306000908152602081905260409020548111156151bc576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b306000908152602081905260409020546151d69082614c1d565b306000908152602081905260409020556002546151f39082614c1d565b600255604080518281529051600091309160008051602061540c8339815191529181900360200190a350565b614c89308383614d6e565b306000908152602081905260409020546152449082614e6c565b306000908152602081905260409020556002546152619082614e6c565b600255604080518281529051309160009160008051602061540c8339815191529181900360200190a350565b6000670de0b6b3a76400006152a1836152a8565b0292915050565b670de0b6b3a7640000900490565b600080600283066152cf57670de0b6b3a76400006152d1565b835b90506002830492505b82156149f0576152ea8485614b54565b93506002830615615302576152ff8185614b54565b90505b6002830492506152da565b600082818061532487670de0b6b3a7640000615131565b9092509050670de0b6b3a764000080600060015b8884106153dc576000670de0b6b3a76400008202905060008061536c8a61536785670de0b6b3a7640000614c1d565b615131565b9150915061537e876136c4848c614b54565b965061538a8784614f1b565b965086615399575050506153dc565b87156153a3579315935b80156153ad579315935b84156153c4576153bd8688614c1d565b95506153d1565b6153ce8688614e6c565b95505b505050600101615338565b5090999850505050505050505056fe63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a265627a7a723158202f8ff34eae9564c9b4a37ca4b6c84d50dd9e5c197e612d669c8dcaf4cc8ec4a164736f6c63430005110032a265627a7a723158204f864cdb54481576676fce917a482d12919194bcf1796b48a085471445563de664736f6c63430005110032
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100625760003560e01c806306ec16f81461006757806336ffb1671461008f5780639a86139b146100b3578063c2bb6dc2146100cd578063c6ce34fb14610107578063d556c5dc1461012d575b600080fd5b61008d6004803603602081101561007d57600080fd5b50356001600160a01b0316610135565b005b6100976102cd565b604080516001600160a01b039092168252519081900360200190f35b6100bb6102dc565b60408051918252519081900360200190f35b6100f3600480360360208110156100e357600080fd5b50356001600160a01b03166102e9565b604080519115158252519081900360200190f35b61008d6004803603602081101561011d57600080fd5b50356001600160a01b0316610307565b6100976103ae565b6001546001600160a01b03163314610184576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4e4f545f424c41425360981b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b1580156101ce57600080fd5b505afa1580156101e2573d6000803e3d6000fd5b505050506040513d60208110156101f857600080fd5b50516001546040805163a9059cbb60e01b81526001600160a01b0392831660048201526024810184905290519293506000929185169163a9059cbb9160448082019260209290919082900301818787803b15801561025557600080fd5b505af1158015610269573d6000803e3d6000fd5b505050506040513d602081101561027f57600080fd5b50519050806102c8576040805162461bcd60e51b815260206004820152601060248201526f11549497d15490cc8c17d1905253115160821b604482015290519081900360640190fd5b505050565b6001546001600160a01b031690565b6542524f4e5a4560d01b90565b6001600160a01b031660009081526020819052604090205460ff1690565b6001546001600160a01b03163314610356576040805162461bcd60e51b815260206004820152600d60248201526c4552525f4e4f545f424c41425360981b604482015290519081900360640190fd5b6040516001600160a01b0382169033907ff586fa6ee1fc42f5b727f3b214ccbd0b6d7e698c45d49ba32f224fbb8670155d90600090a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b6000806040516103bd9061048e565b604051809103906000f0801580156103d9573d6000803e3d6000fd5b506001600160a01b038116600081815260208190526040808220805460ff1916600117905551929350909133917f8ccec77b0cb63ac2cafd0f5de8cdfadab91ce656d262240ba8a6343bccc5f94591a3604080516392eefe9b60e01b815233600482015290516001600160a01b038316916392eefe9b91602480830192600092919082900301818387803b15801561047057600080fd5b505af1158015610484573d6000803e3d6000fd5b5092935050505090565b6156218061049c8339019056fe60c0604052600f60808190526e21b2b73a102837b7b6102a37b5b2b760891b60a0908152620000329160039190620000cc565b506040805180820190915260038082526210d41560ea1b60209092019182526200005f91600491620000cc565b506005805460ff191660121790553480156200007a57600080fd5b50600680546005805462010000600160b01b031916336201000081029190911790915564e8d4a510006007556001600160a01b03199091161760ff60a01b191690556008805460ff1916905562000171565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200010f57805160ff19168380011785556200013f565b828001600101855582156200013f579182015b828111156200013f57825182559160200191906001019062000122565b506200014d92915062000151565b5090565b6200016e91905b808211156200014d576000815560010162000158565b90565b6154a080620001816000396000f3fe608060405234801561001057600080fd5b506004361061035b5760003560e01c80638d4e4083116101ca578063bc694ea211610105578063d73dd623116100a8578063d73dd62314610b5e578063dd62ed3e14610b8a578063e4a28a5214610461578063e4e1e53814610bb8578063ec09302114610bea578063f1b8a9b714610bf2578063f8b2cb4f14610c18578063f8d6aed414610c3e578063fde924f714610c795761035b565b8063bc694ea214610ab8578063be3bbd2e14610ac0578063c36596a6146104d5578063c6580d1214610b18578063cc77828d14610b20578063cd2ed8fb14610b28578063cf5e7bd314610b30578063d4cadf6814610b565761035b565b8063a221ee491161016d578063a221ee4914610987578063a9059cbb146109bc578063b02f0b73146109e8578063b0e0d13614610a5d578063b7b800a414610a65578063ba019dab14610a6d578063ba9530a614610a75578063bc063e1a14610ab05761035b565b80638d4e40831461090b57806392eefe9b14610913578063936c3477146109395780639381cd2b14610941578063948d8ce61461094957806395d89b411461096f578063992e2a92146109775780639a86139b1461097f5761035b565b806349b595521161029a57806376c7a3c71161023d57806376c7a3c71461078b5780637c5e9ea4146107935780638201aa3f146107ec57806382f652ad1461082c5780638656b65314610867578063867378c5146108a257806389298012146108aa5780638c28cbe8146108e55761035b565b806349b59552146105fe5780634bb278f31461061d5780634f69c0d4146106255780635c1bbaf71461069a5780635db34277146106d557806366188463146107075780636d06dfa01461073357806370a08231146107655761035b565b8063218b538211610302578063218b5382146104d557806323b872dd146104dd5780632f37b624146105135780633018205f14610539578063313ce5671461055d57806334e199071461057b5780633fdddaa21461059a57806346ab38f1146105cc5761035b565b806302c967481461036057806306fdde03146103a4578063095ea7b31461042157806309a3bbe4146104615780631446a7ff1461046957806315e84af91461049757806318160ddd146104c5578063189d00ca146104cd575b600080fd5b6103926004803603606081101561037657600080fd5b506001600160a01b038135169060208101359060400135610c81565b60408051918252519081900360200190f35b6103ac610fcf565b6040805160208082528351818301528351919283929083019185019080838360005b838110156103e65781810151838201526020016103ce565b50505050905090810190601f1680156104135780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61044d6004803603604081101561043757600080fd5b506001600160a01b038135169060200135611065565b604080519115158252519081900360200190f35b6103926110ba565b6103926004803603604081101561047f57600080fd5b506001600160a01b03813581169160200135166110c7565b610392600480360360408110156104ad57600080fd5b506001600160a01b038135811691602001351661121c565b610392611368565b61039261136e565b610392611382565b61044d600480360360608110156104f357600080fd5b506001600160a01b0381358116916020810135909116906040013561138e565b61044d6004803603602081101561052957600080fd5b50356001600160a01b03166114e8565b610541611506565b604080516001600160a01b039092168252519081900360200190f35b610565611564565b6040805160ff9092168252519081900360200190f35b6105986004803603602081101561059157600080fd5b503561156d565b005b610598600480360360608110156105b057600080fd5b506001600160a01b03813516906020810135906040013561176a565b610392600480360360608110156105e257600080fd5b506001600160a01b038135169060208101359060400135611b77565b6105986004803603602081101561061457600080fd5b50351515611e64565b610598611fe7565b6105986004803603604081101561063b57600080fd5b81359190810190604081016020820135600160201b81111561065c57600080fd5b82018360208201111561066e57600080fd5b803590602001918460208302840111600160201b8311171561068f57600080fd5b5090925090506121de565b610392600480360360c08110156106b057600080fd5b5080359060208101359060408101359060608101359060808101359060a001356124c5565b610392600480360360608110156106eb57600080fd5b506001600160a01b03813516906020810135906040013561257d565b61044d6004803603604081101561071d57600080fd5b506001600160a01b03813516906020013561284e565b6103926004803603606081101561074957600080fd5b506001600160a01b038135169060208101359060400135612926565b6103926004803603602081101561077b57600080fd5b50356001600160a01b0316612c25565b610392612c40565b6107d3600480360360a08110156107a957600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135612c52565b6040805192835260208301919091528051918290030190f35b6107d3600480360360a081101561080257600080fd5b506001600160a01b0381358116916020810135916040820135169060608101359060800135613115565b610392600480360360c081101561084257600080fd5b5080359060208101359060408101359060608101359060808101359060a001356135bf565b610392600480360360c081101561087d57600080fd5b5080359060208101359060408101359060608101359060808101359060a0013561367e565b61039261371f565b610392600480360360c08110156108c057600080fd5b5080359060208101359060408101359060608101359060808101359060a00135613733565b610598600480360360208110156108fb57600080fd5b50356001600160a01b03166137e3565b61044d613997565b6105986004803603602081101561092957600080fd5b50356001600160a01b03166139a0565b610392613ade565b610392613b33565b6103926004803603602081101561095f57600080fd5b50356001600160a01b0316613b40565b6103ac613c0a565b610392613c6b565b610392613c77565b610392600480360360a081101561099d57600080fd5b5080359060208101359060408101359060608101359060800135613c84565b61044d600480360360408110156109d257600080fd5b506001600160a01b038135169060200135613ce9565b610598600480360360408110156109fe57600080fd5b81359190810190604081016020820135600160201b811115610a1f57600080fd5b820183602082011115610a3157600080fd5b803590602001918460208302840111600160201b83111715610a5257600080fd5b509092509050613cff565b610392614034565b610392614039565b61039261403e565b610392600480360360c0811015610a8b57600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614043565b6103926140c4565b6103926140d4565b610ac86140e0565b60408051602080825283518183015283519192839290830191858101910280838360005b83811015610b04578181015183820152602001610aec565b505050509050019250505060405180910390f35b6103926141d8565b610ac86141dd565b61039261422b565b61059860048036036020811015610b4657600080fd5b50356001600160a01b0316614231565b6103926145b3565b61044d60048036036040811015610b7457600080fd5b506001600160a01b038135169060200135614608565b61039260048036036040811015610ba057600080fd5b506001600160a01b0381358116916020013516614689565b61059860048036036060811015610bce57600080fd5b506001600160a01b0381351690602081013590604001356146b4565b61039261490b565b61039260048036036020811015610c0857600080fd5b50356001600160a01b031661491b565b61039260048036036020811015610c2e57600080fd5b50356001600160a01b03166149f7565b610392600480360360c0811015610c5457600080fd5b5080359060208101359060408101359060608101359060808101359060a00135614ac1565b61044d614b44565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615610d2f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16610d89576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16610de6576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a60205260409020600390810154610e1b91670de0b6b3a76400005b04600101614b54565b831115610e63576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754610e9d949392919089906135bf565b915081610ee3576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115610f27576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b610f35816003015485614c1d565b60038201556000610f468382614b54565b6040805187815290519192506001600160a01b03881691339160008051602061542c833981519152919081900360200190a3610f823384614c7f565b610f94610f8f8483614c1d565b614c8d565b600554610fb0906201000090046001600160a01b031682614c99565b610fbb863387614ca3565b50506005805461ff00191690559392505050565b60038054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561105b5780601f106110305761010080835404028352916020019161105b565b820191906000526020600020905b81548152906001019060200180831161103e57829003601f168201915b5050505050905090565b3360008181526001602090815260408083206001600160a01b0387168085529083528184208690558151868152915193949093909260008051602061544c833981519152928290030190a35060015b92915050565b6802b5e3af16b188000081565b600554600090610100900460ff1615611115576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff16611172576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff166111cf576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a602052604080822092851682528120600380840154600280860154928401549084015493946112139492939290613c84565b95945050505050565b600554600090610100900460ff161561126a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff166112c7576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16611324576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b038084166000908152600a602052604080822092851682529020600380830154600280850154928401549084015460075461121394929190613c84565b60025490565b6402540be400670de0b6b3a76400005b0481565b670de0b6b3a764000081565b6000336001600160a01b03851614806113ca57506001600160a01b03841660009081526001602090815260408083203384529091529020548211155b611413576040805162461bcd60e51b815260206004820152601560248201527422a9292fa1aa27a5a2a72fa120a22fa1a0a62622a960591b604482015290519081900360640190fd5b61141e848484614d6e565b336001600160a01b0385161480159061145c57506001600160a01b038416600090815260016020908152604080832033845290915290205460001914155b156114de576001600160a01b038416600090815260016020908152604080832033845290915290205461148f9083614c1d565b6001600160a01b038581166000908152600160209081526040808320338085529083529281902085905580519485525192871693919260008051602061544c8339815191529281900390910190a35b5060019392505050565b6001600160a01b03166000908152600a602052604090205460ff1690565b600554600090610100900460ff1615611554576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b506006546001600160a01b031690565b60055460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611619576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1615611673576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b031633146116c7576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b64e8d4a5100081101561170f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d494e5f46454560a81b604482015290519081900360640190fd5b67016345785d8a000081111561175a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f4d41585f46454560a81b604482015290519081900360640190fd5b6007556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611816576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b039091161461187b576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff166118d8576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff1615611923576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b670de0b6b3a7640000811015611971576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3525397d5d15251d21560921b604482015290519081900360640190fd5b6802b5e3af16b18800008111156119c0576040805162461bcd60e51b815260206004820152600e60248201526d11549497d3505617d5d15251d21560921b604482015290519081900360640190fd5b620f4240821015611a0a576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4d494e5f42414c414e434560881b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090206002015480821115611aa157611a43600b54611a3e8484614c1d565b614e6c565b600b8190556802b5e3af16b18800001015611a9c576040805162461bcd60e51b815260206004820152601460248201527311549497d3505617d513d5105317d5d15251d21560621b604482015290519081900360640190fd5b611ac2565b80821015611ac257611abe600b54611ab98385614c1d565b614c1d565b600b555b6001600160a01b0384166000908152600a602052604090206002810183905560030180549084905580841115611b0b57611b068533611b018785614c1d565b614eb9565b611b65565b80841015611b65576000611b1f8286614c1d565b90506000611b2e826000614b54565b9050611b448733611b3f8585614c1d565b614ca3565b600554611b629088906201000090046001600160a01b031683614ca3565b50505b50506005805461ff0019169055505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611c25576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16611c7f576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16611cdc576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754611d1694939291908990613733565b915082821015611d5d576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a60205260409020600390810154611d8d91670de0b6b3a7640000610e12565b821115611dd5576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b611de3816003015483614c1d565b60038201556000611df48582614b54565b6040805185815290519192506001600160a01b03881691339160008051602061542c833981519152919081900360200190a3611e303386614c7f565b611e3d610f8f8683614c1d565b600554611e59906201000090046001600160a01b031682614c99565b610fbb863385614ca3565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615611f10576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff1615611f6a576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6006546001600160a01b03163314611fbe576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60068054911515600160a01b0260ff60a01b199092169190911790556005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612093576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b03909116146120f8576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b60085460ff1615612143576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6009546002111561218c576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d494e5f544f4b454e5360901b604482015290519081900360640190fd5b6008805460ff191660011790556006805460ff60a01b1916600160a01b1790556121be68056bc75e2d63100000614f12565b6121d13368056bc75e2d63100000614c99565b6005805461ff0019169055565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561228a576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff166122e4576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b60006122ee611368565b905060006122fc8583614f1b565b905080612342576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b60005b6009548110156124b15760006009828154811061235e57fe5b60009182526020808320909101546001600160a01b0316808352600a9091526040822060030154909250906123938583614b54565b9050806123d9576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b8787858181106123e557fe5b9050602002013581111561242f576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a60205260409020600301546124559082614e6c565b6001600160a01b0384166000818152600a60209081526040918290206003019390935580518481529051919233926000805160206153ec8339815191529281900390910190a36124a6833383614eb9565b505050600101612345565b506124bb85614f12565b611b653386614c99565b6000806124d28786614f1b565b905060006124e08786614e6c565b905060006124ee8289614f1b565b90506000612504670de0b6b3a764000085614f1b565b905060006125128383615023565b90506000612520828e614b54565b9050600061252e828f614c1d565b9050600061254d612547670de0b6b3a76400008a614c1d565b8b614b54565b905061256a82612565670de0b6b3a764000084614c1d565b614f1b565b9f9e505050505050505050505050505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561262b576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612685576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff166126e2576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060030154612714906002670de0b6b3a76400005b04614b54565b83111561275b576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b546007546127959493929190899061367e565b9150828210156127dc576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6127ea816003015485614e6c565b60038201556040805185815290516001600160a01b0387169133916000805160206153ec8339815191529181900360200190a361282682614f12565b6128303383614c99565b61283b853386614eb9565b506005805461ff00191690559392505050565b3360009081526001602090815260408083206001600160a01b0386168452909152812054808311156128a3573360009081526001602090815260408083206001600160a01b03881684529091528120556128d2565b6128ad8184614c1d565b3360009081526001602090815260408083206001600160a01b03891684529091529020555b3360008181526001602090815260408083206001600160a01b03891680855290835292819020548151908152905192939260008051602061544c833981519152929181900390910190a35060019392505050565b6000336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156129d4576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16612a2e576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a602052604090205460ff16612a8b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0384166000908152600a6020526040902060038101546002808301549054600b54600754612ac5949392919089906124c5565b915081612b0b576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b82821115612b4f576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a6020526040902060030154612b7f906002670de0b6b3a764000061270e565b821115612bc6576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b612bd4816003015483614e6c565b60038201556040805183815290516001600160a01b0387169133916000805160206153ec8339815191529181900360200190a3612c1084614f12565b612c1a3385614c99565b61283b853384614eb9565b6001600160a01b031660009081526020819052604090205490565b620f4240670de0b6b3a764000061137e565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615612cef576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff16612d5b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff16612db8576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff16612e0c576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600a602052604080822092881682529020600380820154612e4591670de0b6b3a7640000610e12565b861115612e8d576040805162461bcd60e51b81526020600482015260116024820152704552525f4d41585f4f55545f524154494f60781b604482015290519081900360640190fd5b6000612eae8360030154846002015484600301548560020154600754613c84565b905085811115612efb576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b612f1b83600301548460020154846003015485600201548b600754614ac1565b945088851115612f61576040805162461bcd60e51b815260206004820152600c60248201526b22a9292fa624a6a4aa2fa4a760a11b604482015290519081900360640190fd5b612f6f836003015486614e6c565b8360030181905550612f85826003015488614c1d565b600380840182905584015460028086015490850154600754612fa8949190613c84565b935080841015612ff1576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b85841115613038576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b6130428588614f1b565b811115613088576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d43378888b604051808381526020018281526020019250505060405180910390a46130f08a3387614eb9565b6130fb883389614ca3565b5050506005805461ff001916905590969095509350505050565b60408051602080825236908201819052600092839233926001600160e01b03198535169285929081908101848480828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156131b2576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0387166000908152600a602052604090205460ff1661321e576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0385166000908152600a602052604090205460ff1661327b576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b600654600160a01b900460ff166132cf576040805162461bcd60e51b81526020600482015260136024820152724552525f535741505f4e4f545f5055424c494360681b604482015290519081900360640190fd5b6001600160a01b038088166000908152600a6020526040808220928816825290206003820154613309906002670de0b6b3a764000061270e565b881115613350576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d41585f494e5f524154494f60801b604482015290519081900360640190fd5b60006133718360030154846002015484600301548560020154600754613c84565b9050858111156133be576040805162461bcd60e51b81526020600482015260136024820152724552525f4241445f4c494d49545f505249434560681b604482015290519081900360640190fd5b6133de83600301548460020154846003015485600201548d600754614043565b945086851015613425576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b61343383600301548a614e6c565b8360030181905550613449826003015486614c1d565b60038084018290558401546002808601549085015460075461346c949190613c84565b9350808410156134b5576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b858411156134fc576040805162461bcd60e51b815260206004820152600f60248201526e4552525f4c494d49545f505249434560881b604482015290519081900360640190fd5b6135068986614f1b565b81111561354c576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b876001600160a01b03168a6001600160a01b0316336001600160a01b03167f908fb5ee8f16c6bc9bc3690973819f32a4d4b10188134543c88706e0e1d433788c89604051808381526020018281526020019250505060405180910390a46135b48a338b614eb9565b6130fb883387614ca3565b6000806135cc8786614f1b565b905060006135e2670de0b6b3a764000083614c1d565b905060006135f08286614b54565b9050600061360a87612565670de0b6b3a764000085614c1d565b905060006136188c83614c1d565b90506000613626828e614f1b565b905060006136348288615023565b90506000613642828e614b54565b905060006136508e83614c1d565b905061366981612565670de0b6b3a76400006000614c1d565b99505050505050505050509695505050505050565b60008061368b8786614f1b565b905060006136aa6136a4670de0b6b3a764000084614c1d565b85614b54565b905060006136c9866136c4670de0b6b3a764000085614c1d565b614b54565b905060006136d78b83614e6c565b905060006136e5828d614f1b565b905060006136f38287615023565b90506000613701828d614b54565b905061370d818d614c1d565b9e9d5050505050505050505050505050565b64e8d4a51000670de0b6b3a764000061137e565b6000806137408786614f1b565b9050600061375b856136c4670de0b6b3a76400006000614c1d565b905060006137698883614c1d565b90506000613777828a614f1b565b9050600061379682613791670de0b6b3a764000088614f1b565b615023565b905060006137a4828e614b54565b905060006137b28e83614c1d565b905060006137cb612547670de0b6b3a76400008a614c1d565b905061256a826136c4670de0b6b3a764000084614c1d565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff161561388f576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff0019166101001790556001600160a01b0381166000908152600a602052604090205460ff166138fb576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b604080516370a0823160e01b815230600482015290516001600160a01b038316916370a08231916024808301926020929190829003018186803b15801561394157600080fd5b505afa158015613955573d6000803e3d6000fd5b505050506040513d602081101561396b57600080fd5b50516001600160a01b039091166000908152600a60205260409020600301556005805461ff0019169055565b60085460ff1690565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613a4c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614613ab1576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b600680546001600160a01b0319166001600160a01b03929092169190911790556005805461ff0019169055565b600554600090610100900460ff1615613b2c576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b50600b5490565b68056bc75e2d6310000081565b600554600090610100900460ff1615613b8e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16613beb576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206002015490565b60048054604080516020601f600260001961010060018816150201909516949094049384018190048102820181019092528281526060939092909183018282801561105b5780601f106110305761010080835404028352916020019161105b565b6704a03ce68d21555681565b6542524f4e5a4560d01b90565b600080613c918787614f1b565b90506000613c9f8686614f1b565b90506000613cad8383614f1b565b90506000613ccf670de0b6b3a7640000612565670de0b6b3a764000089614c1d565b9050613cdb8282614b54565b9a9950505050505050505050565b6000613cf6338484614d6e565b50600192915050565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff1615613dab576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff00191661010017905560085460ff16613e05576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b6000613e0f611368565b90506000613e1e856000614b54565b90506000613e2c8683614c1d565b90506000613e3a8285614f1b565b905080613e80576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b613e8a3388614c7f565b600554613ea6906201000090046001600160a01b031684614c99565b613eaf82614c8d565b60005b60095481101561401f57600060098281548110613ecb57fe5b60009182526020808320909101546001600160a01b0316808352600a909152604082206003015490925090613f008583614b54565b905080613f46576040805162461bcd60e51b815260206004820152600f60248201526e08aa4a4be9a82a890be82a0a0a49eb608b1b604482015290519081900360640190fd5b898985818110613f5257fe5b90506020020135811015613f9d576040805162461bcd60e51b815260206004820152600d60248201526c11549497d31253525517d3d555609a1b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a6020526040902060030154613fc39082614c1d565b6001600160a01b0384166000818152600a602090815260409182902060030193909355805184815290519192339260008051602061542c8339815191529281900390910190a3614014833383614ca3565b505050600101613eb2565b50506005805461ff0019169055505050505050565b600881565b600281565b600181565b6000806140508786614f1b565b90506000614066670de0b6b3a764000085614c1d565b90506140728582614b54565b905060006140848a6125658c85614e6c565b905060006140928285615023565b905060006140a8670de0b6b3a764000083614c1d565b90506140b48a82614b54565b9c9b505050505050505050505050565b600a670de0b6b3a764000061137e565b671bc16d674ec7ffff81565b600554606090610100900460ff161561412e576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60085460ff16614179576040805162461bcd60e51b815260206004820152601160248201527011549497d393d517d19253905312569151607a1b604482015290519081900360640190fd5b600980548060200260200160405190810160405280929190818152602001828054801561105b57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116141b1575050505050905090565b600081565b600554606090610100900460ff1615614179576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b60095490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a2600554610100900460ff16156142dd576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6005805461ff001916610100179055600654336001600160a01b0390911614614342576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a602052604090205460ff1661439f576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b60085460ff16156143ea576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b6001600160a01b0381166000908152600a6020526040812060030154906144118282614b54565b600b546001600160a01b0385166000908152600a602052604090206002015491925061443c91614c1d565b600b556001600160a01b0383166000908152600a602052604090206001015460098054600019810191908290811061447057fe5b600091825260209091200154600980546001600160a01b03909216918490811061449657fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b0316021790555081600a6000600985815481106144d657fe5b60009182526020808320909101546001600160a01b03168352820192909252604001902060010155600980548061450957fe5b60008281526020808220600019908401810180546001600160a01b031916905590920190925560408051608081018252838152808301848152818301858152606083018681526001600160a01b038c168752600a909552929094209051815460ff191690151517815592516001840155516002830155516003909101556145958533611b3f8787614c1d565b600554611b659086906201000090046001600160a01b031685614ca3565b600554600090610100900460ff1615614601576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b5060075490565b3360009081526001602090815260408083206001600160a01b03861684529091528120546146369083614e6c565b3360008181526001602090815260408083206001600160a01b03891680855290835292819020859055805194855251919360008051602061544c833981519152929081900390910190a350600192915050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b336001600160a01b03166000356001600160e01b0319166001600160e01b03191660003660405180806020018281038252848482818152602001925080828437600083820152604051601f909101601f19169092018290039550909350505050a26006546001600160a01b03163314614769576040805162461bcd60e51b815260206004820152601260248201527122a9292fa727aa2fa1a7a72a2927a62622a960711b604482015290519081900360640190fd5b6001600160a01b0383166000908152600a602052604090205460ff16156147c6576040805162461bcd60e51b815260206004820152600c60248201526b11549497d254d7d093d5539160a21b604482015290519081900360640190fd5b60085460ff1615614811576040805162461bcd60e51b815260206004820152601060248201526f11549497d254d7d1925390531256915160821b604482015290519081900360640190fd5b600954600811614859576040805162461bcd60e51b815260206004820152600e60248201526d4552525f4d41585f544f4b454e5360901b604482015290519081900360640190fd5b6040805160808101825260018082526009805460208085019182526000858701818152606087018281526001600160a01b038c16808452600a9094529782209651875460ff1916901515178755925186860155915160028601559451600390940193909355805491820181559091527f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af0180546001600160a01b031916909117905561490683838361176a565b505050565b6002670de0b6b3a764000061137e565b600554600090610100900460ff1615614969576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff166149c6576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a6020526040902060020154600b546149f0908290614f1b565b9392505050565b600554600090610100900460ff1615614a45576040805162461bcd60e51b815260206004820152600b60248201526a4552525f5245454e54525960a81b604482015290519081900360640190fd5b6001600160a01b0382166000908152600a602052604090205460ff16614aa2576040805162461bcd60e51b815260206004820152600d60248201526c11549497d393d517d093d55391609a1b604482015290519081900360640190fd5b506001600160a01b03166000908152600a602052604090206003015490565b600080614ace8588614f1b565b90506000614adc8786614c1d565b90506000614aea8883614f1b565b90506000614af88285615023565b9050614b0c81670de0b6b3a7640000614c1d565b9050614b20670de0b6b3a764000087614c1d565b9450614b35614b2f8c83614b54565b86614f1b565b9b9a5050505050505050505050565b600654600160a01b900460ff1690565b6000828202831580614b6e575082848281614b6b57fe5b04145b614bb2576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6706f05b59d3b20000810181811015614c05576040805162461bcd60e51b815260206004820152601060248201526f4552525f4d554c5f4f564552464c4f5760801b604482015290519081900360640190fd5b6000670de0b6b3a7640000825b049695505050505050565b6000806000614c2c8585615131565b915091508015614c77576040805162461bcd60e51b81526020600482015260116024820152704552525f5355425f554e444552464c4f5760781b604482015290519081900360640190fd5b509392505050565b614c898282615156565b5050565b614c9681615161565b50565b614c89828261521f565b6040805163a9059cbb60e01b81526001600160a01b03848116600483015260248201849052915160009286169163a9059cbb91604480830192602092919082900301818787803b158015614cf657600080fd5b505af1158015614d0a573d6000803e3d6000fd5b505050506040513d6020811015614d2057600080fd5b5051905080614d68576040805162461bcd60e51b815260206004820152600f60248201526e4552525f45524332305f46414c534560881b604482015290519081900360640190fd5b50505050565b6001600160a01b038316600090815260208190526040902054811115614dd2576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b6001600160a01b038316600090815260208190526040902054614df59082614c1d565b6001600160a01b038085166000908152602081905260408082209390935590841681522054614e249082614e6c565b6001600160a01b0380841660008181526020818152604091829020949094558051858152905191939287169260008051602061540c83398151915292918290030190a3505050565b6000828201838110156149f0576040805162461bcd60e51b815260206004820152601060248201526f4552525f4144445f4f564552464c4f5760801b604482015290519081900360640190fd5b604080516323b872dd60e01b81526001600160a01b0384811660048301523060248301526044820184905291516000928616916323b872dd91606480830192602092919082900301818787803b158015614cf657600080fd5b614c968161522a565b600081614f5e576040805162461bcd60e51b815260206004820152600c60248201526b4552525f4449565f5a45524f60a01b604482015290519081900360640190fd5b670de0b6b3a76400008302831580614f865750670de0b6b3a7640000848281614f8357fe5b04145b614fca576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b60028304810181811015615018576040805162461bcd60e51b815260206004820152601060248201526f11549497d1125597d25395115493905360821b604482015290519081900360640190fd5b6000848281614c1257fe5b60006001831015615073576040805162461bcd60e51b81526020600482015260156024820152744552525f42504f575f424153455f544f4f5f4c4f5760581b604482015290519081900360640190fd5b671bc16d674ec7ffff8311156150c9576040805162461bcd60e51b815260206004820152601660248201527508aa4a4be84a09eaebe8482a68abea89e9ebe90928e960531b604482015290519081900360640190fd5b60006150d48361528d565b905060006150e28483614c1d565b905060006150f8866150f3856152a8565b6152b6565b9050816151095792506110b4915050565b600061511a87846305f5e10061530d565b90506151268282614b54565b979650505050505050565b600080828410615147575050808203600061514f565b505081810360015b9250929050565b614c89823083614d6e565b306000908152602081905260409020548111156151bc576040805162461bcd60e51b815260206004820152601460248201527311549497d25394d551919250d251539517d0905360621b604482015290519081900360640190fd5b306000908152602081905260409020546151d69082614c1d565b306000908152602081905260409020556002546151f39082614c1d565b600255604080518281529051600091309160008051602061540c8339815191529181900360200190a350565b614c89308383614d6e565b306000908152602081905260409020546152449082614e6c565b306000908152602081905260409020556002546152619082614e6c565b600255604080518281529051309160009160008051602061540c8339815191529181900360200190a350565b6000670de0b6b3a76400006152a1836152a8565b0292915050565b670de0b6b3a7640000900490565b600080600283066152cf57670de0b6b3a76400006152d1565b835b90506002830492505b82156149f0576152ea8485614b54565b93506002830615615302576152ff8185614b54565b90505b6002830492506152da565b600082818061532487670de0b6b3a7640000615131565b9092509050670de0b6b3a764000080600060015b8884106153dc576000670de0b6b3a76400008202905060008061536c8a61536785670de0b6b3a7640000614c1d565b615131565b9150915061537e876136c4848c614b54565b965061538a8784614f1b565b965086615399575050506153dc565b87156153a3579315935b80156153ad579315935b84156153c4576153bd8688614c1d565b95506153d1565b6153ce8688614e6c565b95505b505050600101615338565b5090999850505050505050505056fe63982df10efd8dfaaaa0fcc7f50b2d93b7cba26ccc48adee2873220d485dc39addf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efe74c91552b64c2e2e7bd255639e004e693bd3e1d01cc33e65610b86afcc1ffed8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a265627a7a723158202f8ff34eae9564c9b4a37ca4b6c84d50dd9e5c197e612d669c8dcaf4cc8ec4a164736f6c63430005110032a265627a7a723158204f864cdb54481576676fce917a482d12919194bcf1796b48a085471445563de664736f6c63430005110032