Contract Overview
Balance:
0 ETH
EtherValue:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x912a284c3c0f5b6b789624ea1d2ce8f5bcec6c1d7c5a2d0b411e871fc2b7020e | 0x60806040 | 1507959 | 826 days 6 hrs ago | Thales: Deployer | IN | Create: ThalesAMM | 0 ETH | 0.023981780719 |
[ Download CSV Export ]
Contract Name:
ThalesAMM
Compiler Version
v0.5.16+commit.9c3226ce
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.5.16; import "synthetix-2.50.4-ovm/contracts/interfaces/IERC20.sol"; import "openzeppelin-solidity-2.3.0/contracts/math/Math.sol"; import "synthetix-2.50.4-ovm/contracts/SafeDecimalMath.sol"; import "@openzeppelin/upgrades-core/contracts/Initializable.sol"; import "../utils/proxy/ProxyReentrancyGuard.sol"; import "../utils/proxy/ProxyOwned.sol"; import "../utils/proxy/ProxyPausable.sol"; import "../interfaces/IPriceFeed.sol"; import "../interfaces/IBinaryOptionMarket.sol"; import "../interfaces/IBinaryOptionMarketManager.sol"; import "../interfaces/IBinaryOption.sol"; import "./DeciMath.sol"; contract ThalesAMM is ProxyOwned, ProxyPausable, ProxyReentrancyGuard, Initializable { using SafeMath for uint; using SafeDecimalMath for uint; DeciMath public deciMath; uint private constant ONE = 1e18; uint private constant ONE_PERCENT = 1e16; uint private constant MIN_SUPPORTED_PRICE = 10e16; uint private constant MAX_SUPPORTED_PRICE = 90e16; IPriceFeed public priceFeed; IERC20 public sUSD; address public manager; uint public capPerMarket; uint public min_spread; uint public max_spread; mapping(bytes32 => uint) public impliedVolatilityPerAsset; uint public minimalTimeLeftToMaturity; struct MarketSkew { uint longs; uint shorts; } enum Position {Long, Short} mapping(address => uint) public spentOnMarket; function initialize( address _owner, IPriceFeed _priceFeed, IERC20 _sUSD, uint _capPerMarket, DeciMath _deciMath, uint _min_spread, uint _max_spread, uint _minimalTimeLeftToMaturity ) public initializer { setOwner(_owner); initNonReentrant(); priceFeed = _priceFeed; sUSD = _sUSD; capPerMarket = _capPerMarket; deciMath = _deciMath; min_spread = _min_spread; max_spread = _max_spread; minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity; } function availableToBuyFromAMM(address market, Position position) public view returns (uint) { if (isMarketInAMMTrading(market)) { uint basePrice = price(market, position); // ignore extremes if (basePrice <= MIN_SUPPORTED_PRICE || basePrice >= MAX_SUPPORTED_PRICE) { return 0; } uint balance = _balanceOfPositionOnMarket(market, position); uint buy_max_price = basePrice.mul(ONE.add(max_spread)).div(ONE); // ignore extremes if (buy_max_price >= ONE.sub(ONE_PERCENT) || buy_max_price <= ONE_PERCENT) { return 0; } uint divider_max_price = ONE.sub(buy_max_price); uint additionalBufferFromSelling = balance.mul(buy_max_price).div(ONE); if (capPerMarket.add(additionalBufferFromSelling) <= spentOnMarket[market]) { return 0; } uint availableUntilCapSUSD = capPerMarket.add(additionalBufferFromSelling).sub(spentOnMarket[market]); return balance.add(availableUntilCapSUSD.div(divider_max_price).mul(ONE)); } else { return 0; } } function buyFromAmmQuote( address market, Position position, uint amount ) public view returns (uint) { if (amount > availableToBuyFromAMM(market, position)) { return 0; } uint basePrice = price(market, position); return amount.mul(basePrice.mul(ONE.add(_buyPriceImpact(market, position, amount))).div(ONE)).div(ONE); } function buyPriceImpact( address market, Position position, uint amount ) public view returns (uint) { if (amount > availableToBuyFromAMM(market, position)) { return 0; } return _buyPriceImpact(market, position, amount); } function availableToSellToAMM(address market, Position position) public view returns (uint) { if (isMarketInAMMTrading(market)) { uint basePrice = price(market, position); // ignore extremes if (basePrice <= MIN_SUPPORTED_PRICE || basePrice >= MAX_SUPPORTED_PRICE) { return 0; } uint sell_max_price = basePrice.mul(ONE.sub(max_spread)).div(ONE); require(sell_max_price > 0, "div by zero sell_max_price"); (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); uint balanceOfTheOtherSide = position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this)); // can burn straight away balanceOfTheOtherSide uint willPay = balanceOfTheOtherSide.mul(sell_max_price).div(ONE); uint usdAvailable = capPerMarket.add(balanceOfTheOtherSide).sub(spentOnMarket[market]).sub(willPay); return usdAvailable.div(sell_max_price).mul(ONE).add(balanceOfTheOtherSide); } else return 0; } function sellToAmmQuote( address market, Position position, uint amount ) public view returns (uint) { if (amount > availableToSellToAMM(market, position)) { return 0; } uint basePrice = price(market, position); return amount.mul(basePrice.mul(ONE.sub(_sellPriceImpact(market, position, amount))).div(ONE)).div(ONE); } function sellPriceImpact( address market, Position position, uint amount ) public view returns (uint) { if (amount > availableToSellToAMM(market, position)) { return 0; } return _sellPriceImpact(market, position, amount); } function price(address market, Position position) public view returns (uint) { if (isMarketInAMMTrading(market)) { // add price calculation IBinaryOptionMarket marketContract = IBinaryOptionMarket(market); (uint maturity, uint destructino) = marketContract.times(); uint timeLeftToMaturity = maturity - block.timestamp; uint timeLeftToMaturityInDays = timeLeftToMaturity.mul(ONE).div(86400); uint oraclePrice = marketContract.oraclePrice(); (bytes32 key, uint strikePrice, uint finalPrice) = marketContract.oracleDetails(); if (position == Position.Long) { return calculateOdds(oraclePrice, strikePrice, timeLeftToMaturityInDays, impliedVolatilityPerAsset[key]).div( 1e2 ); } else { return ONE.sub( calculateOdds(oraclePrice, strikePrice, timeLeftToMaturityInDays, impliedVolatilityPerAsset[key]) .div(1e2) ); } } else return 0; } function calculateOdds( uint price, uint strike, uint timeLeftInDays, uint volatility ) public view returns (uint) { uint vt = volatility.div(100).mul(sqrt(timeLeftInDays.div(365))).div(1e9); bool direction = strike >= price; uint lnBase = strike >= price ? strike.mul(ONE).div(price) : price.mul(ONE).div(strike); uint d1 = deciMath.ln(lnBase, 99).mul(ONE).div(vt); uint y = ONE.mul(ONE).div(ONE.add(d1.mul(2316419).div(1e7))); uint d2 = d1.mul(d1).div(2).div(ONE); uint z = _expneg(d2).mul(3989423).div(1e7); uint y5 = deciMath.pow(y, 5 * ONE).mul(1330274).div(1e6); uint y4 = deciMath.pow(y, 4 * ONE).mul(1821256).div(1e6); uint y3 = deciMath.pow(y, 3 * ONE).mul(1781478).div(1e6); uint y2 = deciMath.pow(y, 2 * ONE).mul(356538).div(1e6); uint y1 = y.mul(3193815).div(1e7); uint x1 = y5.add(y3).add(y1).sub(y4).sub(y2); uint x = ONE.sub(z.mul(x1).div(ONE)); uint result = ONE.mul(1e2).sub(x.mul(1e2)); if (direction) { return result; } else { return ONE.mul(1e2).sub(result); } } function isMarketInAMMTrading(address market) public view returns (bool) { if (IBinaryOptionMarketManager(manager).isActiveMarket(market)) { IBinaryOptionMarket marketContract = IBinaryOptionMarket(market); (bytes32 key, uint strikePrice, uint finalPrice) = marketContract.oracleDetails(); //check if asset is supported if (impliedVolatilityPerAsset[key] == 0) { return false; } // add price calculation (uint maturity, uint destructino) = marketContract.times(); uint timeLeftToMaturity = maturity - block.timestamp; return timeLeftToMaturity > minimalTimeLeftToMaturity; } else { return false; } } function canExerciseMaturedMarket(address market) public view returns (bool) { if ( IBinaryOptionMarketManager(manager).isKnownMarket(market) && (IBinaryOptionMarket(market).phase() == IBinaryOptionMarket.Phase.Maturity) ) { (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); if ((long.balanceOf(address(this)) > 0) || (short.balanceOf(address(this)) > 0)) { return true; } } return false; } // write methods function buyFromAMM( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage ) public nonReentrant notPaused { require(isMarketInAMMTrading(market), "Market is not in Trading phase"); uint availableToBuyFromAMMATM = availableToBuyFromAMM(market, position); require(availableToBuyFromAMMATM > 0 && amount <= availableToBuyFromAMMATM, "Not enough liquidity."); uint sUSDPaid = buyFromAmmQuote(market, position, amount); require(sUSD.balanceOf(msg.sender) >= sUSDPaid, "You dont have enough sUSD."); require(sUSD.allowance(msg.sender, address(this)) >= sUSDPaid, "No allowance."); require(sUSDPaid.mul(ONE).div(expectedPayout) <= ONE.add(additionalSlippage), "Slippage too high"); sUSD.transferFrom(msg.sender, address(this), sUSDPaid); uint toMint = _getMintableAmount(market, position, amount); if (toMint > 0) { require(sUSD.balanceOf(address(this)) >= toMint, "Not enough sUSD in contract."); IBinaryOptionMarket(market).mint(toMint); spentOnMarket[market] = spentOnMarket[market].add(toMint); } (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); IBinaryOption target = position == Position.Long ? long : short; IERC20(address(target)).transfer(msg.sender, amount); if (spentOnMarket[market] <= sUSDPaid) { spentOnMarket[market] = 0; } else { spentOnMarket[market] = spentOnMarket[market].sub(sUSDPaid); } emit BoughtFromAmm(msg.sender, market, position, amount, sUSDPaid, address(sUSD), address(target)); } function sellToAMM( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage ) public nonReentrant notPaused { require(isMarketInAMMTrading(market), "Market is not in Trading phase"); uint availableToSellToAMMATM = availableToSellToAMM(market, position); require(availableToSellToAMMATM > 0 && amount <= availableToSellToAMMATM, "Not enough liquidity."); uint pricePaid = sellToAmmQuote(market, position, amount); require(expectedPayout.mul(ONE).div(pricePaid) <= (ONE.add(additionalSlippage)), "Slippage too high"); (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); IBinaryOption target = position == Position.Long ? long : short; require(target.balanceOf(msg.sender) >= amount, "You dont have enough options."); require(IERC20(address(target)).allowance(msg.sender, address(this)) >= amount, "No allowance."); //transfer options first to have max burn available IERC20(address(target)).transferFrom(msg.sender, address(this), amount); uint sUSDFromBurning = IBinaryOptionMarket(market).getMaximumBurnable(address(this)); if (sUSDFromBurning > 0) { IBinaryOptionMarket(market).burnOptionsMaximum(); } require(sUSD.balanceOf(address(this)) >= pricePaid, "Not enough sUSD in contract."); sUSD.transfer(msg.sender, pricePaid); spentOnMarket[market] = spentOnMarket[market].add(pricePaid); if (spentOnMarket[market] <= sUSDFromBurning) { spentOnMarket[market] = 0; } else { spentOnMarket[market] = spentOnMarket[market].sub(sUSDFromBurning); } emit SoldToAMM(msg.sender, market, position, amount, pricePaid, address(sUSD), address(target)); } function exerciseMaturedMarket(address market) external { require( IBinaryOptionMarket(market).phase() == IBinaryOptionMarket.Phase.Maturity, "Market is not in Maturity phase" ); require(IBinaryOptionMarketManager(manager).isKnownMarket(market), "Unknown market"); require(canExerciseMaturedMarket(market), "No options to exercise"); IBinaryOptionMarket(market).exerciseOptions(); } // setters function setMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity) public onlyOwner { minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity; emit SetMinimalTimeLeftToMaturity(_minimalTimeLeftToMaturity); } function setMinSpread(uint _spread) public onlyOwner { min_spread = _spread; emit SetMinSpread(_spread); } function setMaxSpread(uint _spread) public onlyOwner { max_spread = _spread; emit SetMaxSpread(_spread); } function setImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility) public onlyOwner { impliedVolatilityPerAsset[asset] = _impliedVolatility; emit SetImpliedVolatilityPerAsset(asset, _impliedVolatility); } function setCapPerMarket(uint _capPerMarket) public onlyOwner { capPerMarket = _capPerMarket; emit SetCapPerMarket(_capPerMarket); } function setPriceFeed(IPriceFeed _priceFeed) public onlyOwner { priceFeed = _priceFeed; emit SetPriceFeed(address(_priceFeed)); } function setSUSD(IERC20 _sUSD) public onlyOwner { sUSD = _sUSD; emit SetSUSD(address(sUSD)); } function setBinaryOptionsMarketManager(address _manager) public onlyOwner { if (address(_manager) != address(0)) { sUSD.approve(address(_manager), 0); } manager = _manager; sUSD.approve(manager, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); emit SetBinaryOptionsMarketManager(_manager); } // Internal functions function _buyPriceImpact( address market, Position position, uint amount ) internal view returns (uint) { (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); uint balancePosition = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this)); uint balanceOtherSide = position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this)); uint balancePositionAfter = balancePosition > amount ? balancePosition.sub(amount) : 0; uint balanceOtherSideAfter = balancePosition > amount ? balanceOtherSide : balanceOtherSide.add(amount.sub(balancePosition)); uint pricePaid = _minimalBuyPrice(market, position).mul(amount).div(ONE); if (balancePositionAfter >= balanceOtherSideAfter) { //minimal price impact as it will balance the AMM exposure return min_spread; } else { uint basePriceOtherSide = price(market, position == Position.Long ? Position.Short : Position.Long); uint skew = balanceOtherSideAfter.sub(balancePositionAfter); uint maxPossibleSkew = capPerMarket.mul(ONE).div(basePriceOtherSide); return min_spread.add(max_spread.sub(min_spread).mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE)); } } function _sellPriceImpact( address market, Position position, uint amount ) internal view returns (uint) { (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); uint balancePosition = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this)); uint balanceOtherSide = position == Position.Long ? short.balanceOf(address(this)) : long.balanceOf(address(this)); uint balancePositionAfter = balancePosition.add(amount); uint pricePaid = _minimalSellPrice(market, position).mul(amount).div(ONE); if (balancePositionAfter < balanceOtherSide) { //minimal price impact as it will balance the AMM exposure return min_spread; } else { uint basePrice = price(market, position); uint skew = balancePositionAfter.sub(balanceOtherSide); require(basePrice > 0, "div by zero basePrice"); uint maxPossibleSkew = capPerMarket.mul(ONE).div(basePrice); require(maxPossibleSkew > 0, "div by zero maxPossibleSkew"); return min_spread.add(max_spread.sub(min_spread).mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE)); } } function _getMintableAmount( address market, Position position, uint amount ) internal view returns (uint mintable) { uint availableInContract = _balanceOfPositionOnMarket(market, position); mintable = 0; if (availableInContract < amount) { mintable = amount.sub(availableInContract); } } function _minimalBuyPrice(address market, Position position) internal view returns (uint) { return price(market, position).mul(ONE.add(min_spread)).div(ONE); } function _minimalSellPrice(address market, Position position) internal view returns (uint) { return price(market, position).mul(ONE.sub(min_spread)).div(ONE); } function _balanceOfPositionOnMarket(address market, Position position) internal view returns (uint) { (IBinaryOption long, IBinaryOption short) = IBinaryOptionMarket(market).options(); uint balance = position == Position.Long ? long.balanceOf(address(this)) : short.balanceOf(address(this)); return balance; } function _expneg(uint x) internal view returns (uint result) { result = (ONE * ONE) / _expNegPow(x); } function _expNegPow(uint x) internal view returns (uint result) { uint e = 2718280000000000000; result = deciMath.pow(e, x); } function sqrt(uint y) internal pure returns (uint z) { if (y > 3) { z = y; uint x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } } function retrieveSUSD(address payable account) external onlyOwner { sUSD.transfer(account, sUSD.balanceOf(address(this))); } // events event SoldToAMM( address seller, address market, Position position, uint amount, uint sUSDPaid, address susd, address asset ); event BoughtFromAmm( address buyer, address market, Position position, uint amount, uint sUSDPaid, address susd, address asset ); event SetBinaryOptionsMarketManager(address _manager); event SetSUSD(address sUSD); event SetPriceFeed(address _priceFeed); event SetCapPerMarket(uint _capPerMarket); event SetImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility); event SetMaxSpread(uint _spread); event SetMinSpread(uint _spread); event SetMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity); }
pragma solidity >=0.4.24; // https://docs.synthetix.io/contracts/source/interfaces/ierc20 interface IERC20 { // ERC20 Optional Views function name() external view returns (string memory); function symbol() external view returns (string memory); function decimals() external view returns (uint8); // Views function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); // Mutative functions function transfer(address to, uint value) external returns (bool); function approve(address spender, uint value) external returns (bool); function transferFrom( address from, address to, uint value ) external returns (bool); // Events event Transfer(address indexed from, address indexed to, uint value); event Approval(address indexed owner, address indexed spender, uint value); }
pragma solidity ^0.5.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
pragma solidity ^0.5.16; // Libraries import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol"; // https://docs.synthetix.io/contracts/source/libraries/safedecimalmath library SafeDecimalMath { using SafeMath for uint; /* Number of decimal places in the representations. */ uint8 public constant decimals = 18; uint8 public constant highPrecisionDecimals = 27; /* The number representing 1.0. */ uint public constant UNIT = 10**uint(decimals); /* The number representing 1.0 for higher fidelity numbers. */ uint public constant PRECISE_UNIT = 10**uint(highPrecisionDecimals); uint private constant UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR = 10**uint(highPrecisionDecimals - decimals); /** * @return Provides an interface to UNIT. */ function unit() external pure returns (uint) { return UNIT; } /** * @return Provides an interface to PRECISE_UNIT. */ function preciseUnit() external pure returns (uint) { return PRECISE_UNIT; } /** * @return The result of multiplying x and y, interpreting the operands as fixed-point * decimals. * * @dev A unit factor is divided out after the product of x and y is evaluated, * so that product must be less than 2**256. As this is an integer division, * the internal division always rounds down. This helps save on gas. Rounding * is more expensive on gas. */ function multiplyDecimal(uint x, uint y) internal pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ return x.mul(y) / UNIT; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of the specified precision unit. * * @dev The operands should be in the form of a the specified unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function _multiplyDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { /* Divide by UNIT to remove the extra factor introduced by the product. */ uint quotientTimesTen = x.mul(y) / (precisionUnit / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a precise unit. * * @dev The operands should be in the precise unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, PRECISE_UNIT); } /** * @return The result of safely multiplying x and y, interpreting the operands * as fixed-point decimals of a standard unit. * * @dev The operands should be in the standard unit factor which will be * divided out after the product of x and y is evaluated, so that product must be * less than 2**256. * * Unlike multiplyDecimal, this function rounds the result to the nearest increment. * Rounding is useful when you need to retain fidelity for small decimal numbers * (eg. small fractions or percentages). */ function multiplyDecimalRound(uint x, uint y) internal pure returns (uint) { return _multiplyDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is a high * precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and UNIT must be less than 2**256. As * this is an integer division, the result is always rounded down. * This helps save on gas. Rounding is more expensive on gas. */ function divideDecimal(uint x, uint y) internal pure returns (uint) { /* Reintroduce the UNIT factor that will be divided out by y. */ return x.mul(UNIT).div(y); } /** * @return The result of safely dividing x and y. The return value is as a rounded * decimal in the precision unit specified in the parameter. * * @dev y is divided after the product of x and the specified precision unit * is evaluated, so the product of x and the specified precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function _divideDecimalRound( uint x, uint y, uint precisionUnit ) private pure returns (uint) { uint resultTimesTen = x.mul(precisionUnit * 10).div(y); if (resultTimesTen % 10 >= 5) { resultTimesTen += 10; } return resultTimesTen / 10; } /** * @return The result of safely dividing x and y. The return value is as a rounded * standard precision decimal. * * @dev y is divided after the product of x and the standard precision unit * is evaluated, so the product of x and the standard precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRound(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, UNIT); } /** * @return The result of safely dividing x and y. The return value is as a rounded * high precision decimal. * * @dev y is divided after the product of x and the high precision unit * is evaluated, so the product of x and the high precision unit must * be less than 2**256. The result is rounded to the nearest increment. */ function divideDecimalRoundPrecise(uint x, uint y) internal pure returns (uint) { return _divideDecimalRound(x, y, PRECISE_UNIT); } /** * @dev Convert a standard decimal representation to a high precision one. */ function decimalToPreciseDecimal(uint i) internal pure returns (uint) { return i.mul(UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR); } /** * @dev Convert a high precision decimal to a standard decimal representation. */ function preciseDecimalToDecimal(uint i) internal pure returns (uint) { uint quotientTimesTen = i / (UNIT_TO_HIGH_PRECISION_CONVERSION_FACTOR / 10); if (quotientTimesTen % 10 >= 5) { quotientTimesTen += 10; } return quotientTimesTen / 10; } // Computes `a - b`, setting the value to 0 if b > a. function floorsub(uint a, uint b) internal pure returns (uint) { return b >= a ? 0 : a - b; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24 <0.7.0; /** * @title Initializable * * @dev Helper contract to support initializer functions. To use it, replace * the constructor with a function that has the `initializer` modifier. * WARNING: Unlike constructors, initializer functions must be manually * invoked. This applies both to deploying an Initializable contract, as well * as extending an Initializable contract via inheritance. * WARNING: When used with inheritance, manual care must be taken to not invoke * a parent initializer twice, or ensure that all initializers are idempotent, * because this is not dealt with automatically as with constructors. */ contract Initializable { /** * @dev Indicates that the contract has been initialized. */ bool private initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private initializing; /** * @dev Modifier to use in the initializer function of a contract. */ modifier initializer() { require(initializing || isConstructor() || !initialized, "Contract instance has already been initialized"); bool isTopLevelCall = !initializing; if (isTopLevelCall) { initializing = true; initialized = true; } _; if (isTopLevelCall) { initializing = false; } } /// @dev Returns true if and only if the function is running in the constructor function isConstructor() private view returns (bool) { // extcodesize checks the size of the code stored in an address, and // address returns the current address. Since the code is still not // deployed when running a constructor, any checks on its code size will // yield zero, making it an effective way to detect if a contract is // under construction or not. address self = address(this); uint256 cs; assembly { cs := extcodesize(self) } return cs == 0; } // Reserved storage space to allow for layout changes in the future. uint256[50] private ______gap; }
pragma solidity ^0.5.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the `nonReentrant` modifier * available, which can be aplied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. */ contract ProxyReentrancyGuard { /// @dev counter to allow mutex lock with only one SSTORE operation uint256 private _guardCounter; bool private _initialized; function initNonReentrant() public { require(!_initialized, "Already initialized"); _initialized = true; _guardCounter = 1; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and make it call a * `private` function that does the actual work. */ modifier nonReentrant() { _guardCounter += 1; uint256 localCounter = _guardCounter; _; require(localCounter == _guardCounter, "ReentrancyGuard: reentrant call"); } }
pragma solidity ^0.5.16; // Clone of syntetix contract without constructor contract ProxyOwned { address public owner; address public nominatedOwner; bool private _initialized; bool private _transferredAtInit; function setOwner(address _owner) public { require(_owner != address(0), "Owner address cannot be 0"); require(!_initialized, "Already initialized, use nominateNewOwner"); _initialized = true; owner = _owner; emit OwnerChanged(address(0), _owner); } function nominateNewOwner(address _owner) external onlyOwner { nominatedOwner = _owner; emit OwnerNominated(_owner); } function acceptOwnership() external { require(msg.sender == nominatedOwner, "You must be nominated before you can accept ownership"); emit OwnerChanged(owner, nominatedOwner); owner = nominatedOwner; nominatedOwner = address(0); } function transferOwnershipAtInit(address proxyAddress) external onlyOwner { require(proxyAddress != address(0), "Invalid address"); require(!_transferredAtInit, "Already transferred"); owner = proxyAddress; _transferredAtInit = true; emit OwnerChanged(owner, proxyAddress); } modifier onlyOwner { _onlyOwner(); _; } function _onlyOwner() private view { require(msg.sender == owner, "Only the contract owner may perform this action"); } event OwnerNominated(address newOwner); event OwnerChanged(address oldOwner, address newOwner); }
pragma solidity ^0.5.16; // Inheritance import "./ProxyOwned.sol"; // Clone of syntetix contract without constructor contract ProxyPausable is ProxyOwned { uint public lastPauseTime; bool public paused; /** * @notice Change the paused state of the contract * @dev Only the contract owner may call this. */ function setPaused(bool _paused) external onlyOwner { // Ensure we're actually changing the state before we do anything if (_paused == paused) { return; } // Set our paused state. paused = _paused; // If applicable, set the last pause time. if (paused) { lastPauseTime = now; } // Let everyone know that our pause state has changed. emit PauseChanged(paused); } event PauseChanged(bool isPaused); modifier notPaused { require(!paused, "This action cannot be performed while the contract is paused"); _; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.4.24; interface IPriceFeed { // Structs struct RateAndUpdatedTime { uint216 rate; uint40 time; } // Mutative functions function addAggregator(bytes32 currencyKey, address aggregatorAddress) external; function removeAggregator(bytes32 currencyKey) external; // Views function aggregators(bytes32 currencyKey) external view returns (address); function rateForCurrency(bytes32 currencyKey) external view returns (uint); function rateAndUpdatedTime(bytes32 currencyKey) external view returns (uint rate, uint time); function getRates() external view returns (uint[] memory); function getCurrencies() external view returns (bytes32[] memory); }
pragma solidity ^0.5.16; import "../interfaces/IBinaryOptionMarketManager.sol"; import "../interfaces/IBinaryOption.sol"; import "../interfaces/IPriceFeed.sol"; interface IBinaryOptionMarket { /* ========== TYPES ========== */ enum Phase {Trading, Maturity, Expiry} enum Side {Long, Short} /* ========== VIEWS / VARIABLES ========== */ function options() external view returns (IBinaryOption long, IBinaryOption short); function times() external view returns (uint maturity, uint destructino); function oracleDetails() external view returns ( bytes32 key, uint strikePrice, uint finalPrice ); function fees() external view returns (uint poolFee, uint creatorFee); function deposited() external view returns (uint); function creator() external view returns (address); function resolved() external view returns (bool); function phase() external view returns (Phase); function oraclePrice() external view returns (uint); function oraclePriceAndTimestamp() external view returns (uint price, uint updatedAt); function canResolve() external view returns (bool); function result() external view returns (Side); function balancesOf(address account) external view returns (uint long, uint short); function totalSupplies() external view returns (uint long, uint short); function getMaximumBurnable(address account) external view returns (uint amount); /* ========== MUTATIVE FUNCTIONS ========== */ function mint(uint value) external; function exerciseOptions() external returns (uint); function burnOptions(uint amount) external; function burnOptionsMaximum() external; }
pragma solidity ^0.5.16; import "../interfaces/IBinaryOptionMarket.sol"; interface IBinaryOptionMarketManager { /* ========== VIEWS / VARIABLES ========== */ function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity); function capitalRequirement() external view returns (uint); function marketCreationEnabled() external view returns (bool); function totalDeposited() external view returns (uint); function numActiveMarkets() external view returns (uint); function activeMarkets(uint index, uint pageSize) external view returns (address[] memory); function numMaturedMarkets() external view returns (uint); function maturedMarkets(uint index, uint pageSize) external view returns (address[] memory); function isActiveMarket(address candidate) external view returns (bool); function isKnownMarket(address candidate) external view returns (bool); /* ========== MUTATIVE FUNCTIONS ========== */ function createMarket( bytes32 oracleKey, uint strikePrice, uint maturity, uint initialMint, // initial sUSD to mint options for, bool customMarket, address customOracle ) external returns (IBinaryOptionMarket); function resolveMarket(address market) external; function expireMarkets(address[] calldata market) external; function transferSusdTo( address sender, address receiver, uint amount ) external; }
pragma solidity ^0.5.16; import "../interfaces/IBinaryOptionMarket.sol"; import "synthetix-2.50.4-ovm/contracts/interfaces/IERC20.sol"; interface IBinaryOption { /* ========== VIEWS / VARIABLES ========== */ function market() external view returns (IBinaryOptionMarket); function balanceOf(address account) external view returns (uint); function totalSupply() external view returns (uint); }
pragma solidity ^0.5.0; contract DeciMath { // Abbreviation: DP stands for 'Decimal Places' uint constant TEN38 = 10**38; uint constant TEN30 = 10**30; uint constant TEN20 = 10**20; uint constant TEN19 = 10**19; uint constant TEN18 = 10**18; uint constant TEN17 = 10**17; uint constant TEN12 = 10**12; uint constant TEN11 = 10**11; uint constant TEN10 = 10**10; uint constant TEN9 = 10**9; uint constant TEN8 = 10**8; uint constant TEN7 = 10**7; // ln(2) - used in ln(x). 30 DP. uint constant LN2 = 693147180559945309417232121458; // 1 / ln(2) - used in exp(x). 30 DP. uint constant ONE_OVER_LN2 = 1442695040888963407359924681002; /***** LOOKUP TABLES *****/ // Lookup table arrays (LUTs) for log_2(x) uint[100] public table_log_2; uint[100] public table2_log_2; // Lookup table for pow2(). Table contains 39 arrays, each array contains 10 uint slots. uint[10][39] public table_pow2; // LUT flags bool LUT1_isSet = false; bool LUT2_isSet = false; bool LUT3_1_isSet = false; bool LUT3_2_isSet = false; bool LUT3_3_isSet = false; bool LUT3_4_isSet = false; /****** BASIC MATH OPERATORS ******/ // Integer math operators. Identical to Zeppelin's SafeMath function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "uint overflow from multiplication"); return c; } function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0, "division by zero"); uint256 c = a / b; return c; } function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "uint underflow from subtraction"); uint256 c = a - b; return c; } function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "uint overflow from multiplication"); return c; } // Basic decimal math operators. Inputs and outputs are uint representations of fixed-point decimals. // 18 Decimal places function decMul18(uint x, uint y) public pure returns (uint decProd) { uint prod_xy = mul(x, y); decProd = add(prod_xy, TEN18 / 2) / TEN18; } function decDiv18(uint x, uint y) public pure returns (uint decQuotient) { uint prod_xTEN18 = mul(x, TEN18); decQuotient = add(prod_xTEN18, y / 2) / y; } // 30 Decimal places function decMul30(uint x, uint y) public pure returns (uint decProd) { uint prod_xy = mul(x, y); decProd = add(prod_xy, TEN30 / 2) / TEN30; } // 38 Decimal places function decMul38(uint x, uint y) public pure returns (uint decProd) { uint prod_xy = mul(x, y); decProd = add(prod_xy, TEN38 / 2) / TEN38; } /****** HELPER FUNCTIONS ******/ function convert38To18DP(uint x) public pure returns (uint y) { uint digit = (x % TEN20) / TEN19; // grab 20th digit from-right return chopAndRound(x, digit, 20); } function convert38To30DP(uint x) public pure returns (uint y) { uint digit = (x % TEN8) / TEN7; // grab 8th digit from-right return chopAndRound(x, digit, 8); } function convert30To20DP(uint x) public pure returns (uint y) { uint digit = (x % TEN10) / TEN9; // grab 10th digit from-right return chopAndRound(x, digit, 10); } function convert30To18DP(uint x) public pure returns (uint y) { uint digit = (x % TEN12) / TEN11; // grab 12th digit from-right return chopAndRound(x, digit, 12); } // Chop the last digits, and round the resulting number function chopAndRound( uint num, uint digit, uint positionOfChop ) public pure returns (uint chopped) { if (digit < 5) { chopped = div(num, 10**positionOfChop); // round down } else if (digit >= 5) { chopped = div(num, 10**positionOfChop) + 1; // round up } return chopped; } // return the floor of a fixed-point 20DP number function floor(uint x) public pure returns (uint num) { num = x - (x % TEN20); return num; } function countDigits(uint num) public view returns (uint) { uint digits = 0; while (num != 0) { num /= 10; // When num < 10, yields 0 due to EVM floor division digits++; } return digits; } /****** MATH FUNCTIONS ******/ // b^x for integer exponent. Use highly performant 'exponentiation-by-squaring' algorithm. O(log(n)) operations. // b^x - integer base, integer exponent function powBySquare(uint x, uint n) public pure returns (uint) { if (n == 0) return 1; uint y = 1; while (n > 1) if (n % 2 == 0) { x = mul(x, x); n = n / 2; } else if (n % 2 != 0) { y = mul(x, y); x = mul(x, x); n = (n - 1) / 2; } return mul(x, y); } // b^x - fixed-point 18 DP base, integer exponent function powBySquare18(uint base, uint n) public pure returns (uint) { if (n == 0) return TEN18; uint y = TEN18; while (n > 1) { if (n % 2 == 0) { base = decMul18(base, base); n = n / 2; } else if (n % 2 != 0) { y = decMul18(base, y); base = decMul18(base, base); n = (n - 1) / 2; } } return decMul18(base, y); } // b^x - fixed-point 38 DP base, integer exponent n function powBySquare38(uint base, uint n) public pure returns (uint) { if (n == 0) return TEN38; uint y = TEN38; while (n > 1) { if (n % 2 == 0) { base = decMul38(base, base); n = n / 2; } else if (n % 2 != 0) { y = decMul38(base, y); base = decMul38(base, base); n = (n - 1) / 2; } } return decMul38(base, y); } /* exp(x) function. Input 18 DP, output 18 DP. Uses identities: A) e^x = 2^(x / ln(2)) and B) 2^y = (2^r) * 2^(y - r); where r = floor(y) - 1, and (y - r) is in range [1,2[ */ function exp(uint x) public view returns (uint num) { uint intExponent; // 20 DP uint decExponent; // 20 DP uint coefficient; // 38 DP x = mul(x, TEN12); // make x 30DP x = decMul30(ONE_OVER_LN2, x); x = convert30To20DP(x); // if x < 1, do: (2^-1) * 2^(1 + x) if (x < TEN20 && x >= 0) { decExponent = add(TEN20, x); coefficient = TEN38 / 2; num = decMul38(coefficient, pow2(decExponent)); } // Use identity B) else { intExponent = floor(x) - TEN20; decExponent = x - intExponent; // decimal exponent in range [1,2[ coefficient = powBySquare(2, div(intExponent, TEN20)); num = mul(coefficient, pow2(decExponent)); // use normal mul to avoid overflow, as coeff. is an int } return convert38To18DP(num); } // Base-2 logarithm function, for x in range [1,2[. For use in ln(x). Input 18 DP, output 30 DP. function log_2(uint x, uint accuracy) public view _onlyLUT1andLUT2AreSet returns (uint) { require(x >= TEN18 && x < 2 * TEN18, "input x must be within range [1,2["); uint prod = mul(x, TEN20); // make x 38 DP uint newProd = TEN38; uint output = 0; for (uint i = 1; i <= accuracy; i++) { newProd = decMul38(table_log_2[i], prod); if (newProd >= TEN38) { prod = newProd; output += table2_log_2[i]; } } return convert38To30DP(output); } // pow2(x) function, for use in exp(x). Uses 2D-array LUT. Valid for x in range [1,2[. Input 20DP, output 38DP function pow2(uint x) public view _onlyLUT3isSet returns (uint) { require(x >= TEN20 && x < 2 * TEN20, "input x must be within range [1,2["); uint x_38dp = x * TEN18; uint prod = 2 * TEN38; uint fractPart = x_38dp % TEN38; uint digitsLength = countDigits(fractPart); // loop backwards through mantissa digits - multiply each by the Lookup-table value for (uint i = 0; i < digitsLength; i++) { uint digit = (fractPart % (10**(i + 1))) / (10**i); // grab the i'th digit from right if (digit == 0) continue; // Save gas - skip the step if digit = 0 and there would be no resultant change to prod // computer i'th term, and new product uint term = table_pow2[37 - i][digit]; prod = decMul38(prod, term); } return prod; } /* Natural log function ln(x). Input 18 DP, output 18 DP. Uses identities: A) ln(x) = log_2(x) * ln(2) and B) log_2(x) = log_2(2^q * y) y in range [1,2[ = q + log_2(y) The algorithm finds q and y by repeated division by powers-of-two. */ function ln(uint x, uint accuracy) public view returns (uint) { require(x >= TEN18, "input must be >= 1"); uint count = 0; // track uint TWO = mul(TEN18, 2); /* Calculate q. Use branches to divide by powers-of-two, until output is in range [1,2[. Branch approach is more performant than simple successive division by 2. As max input of ln(x) is ~= 2^132, starting division at 2^30 yields sufficiently few operations for large x. */ while (x >= 2 * TEN18) { if (x >= 1073741824 * TEN18) { // start at 2^30 x = decDiv18(x, 1073741824 * TEN18); count += 30; } else if (x >= 1048576 * TEN18) { x = decDiv18(x, 1048576 * TEN18); count += 20; } else if (x >= 32768 * TEN18) { x = decDiv18(x, 32768 * TEN18); count += 15; } else if (x >= 1024 * TEN18) { x = decDiv18(x, 1024 * TEN18); count += 10; } else if (x >= 512 * TEN18) { x = decDiv18(x, 512 * TEN18); count += 9; } else if (x >= 256 * TEN18) { x = decDiv18(x, 256 * TEN18); count += 8; } else if (x >= 128 * TEN18) { x = decDiv18(x, 128 * TEN18); count += 7; } else if (x >= 64 * TEN18) { x = decDiv18(x, 64 * TEN18); count += 6; } else if (x >= 32 * TEN18) { x = decDiv18(x, 32 * TEN18); count += 5; } else if (x >= 16 * TEN18) { x = decDiv18(x, 16 * TEN18); count += 4; } else if (x >= 8 * TEN18) { x = decDiv18(x, 8 * TEN18); count += 3; } else if (x >= 4 * TEN18) { x = decDiv18(x, 4 * TEN18); count += 2; } else if (x >= 2 * TEN18) { x = decDiv18(x, 2 * TEN18); count += 1; } } uint q = count * TEN30; uint output = decMul30(LN2, add(q, log_2(x, accuracy))); return convert30To18DP(output); } /* pow(b, x) function for 18 DP base and exponent. Output 18 DP. Uses identity: b^x = exp (x * ln(b)). For b < 1, rewrite b^x as: b^x = exp( x * (-ln(1/b)) ) = 1/exp(x * ln(1/b)). Thus, we avoid passing argument y < 1 to ln(y), and z < 0 to exp(z). */ function pow(uint base, uint x) public view returns (uint power) { if (base >= TEN18) { return exp(decMul18(x, ln(base, 70))); } if (base < TEN18) { uint exponent = decMul18(x, ln(decDiv18(TEN18, base), 70)); return decDiv18(TEN18, exp(exponent)); } } // Taylor series implementation of exp(x) - lower accuracy and higher gas cost than exp(x). 18 DP input and output. function exp_taylor(uint x) public pure returns (uint) { uint tolerance = 1; uint term = TEN18; uint sum = TEN18; uint i = 0; while (term > tolerance) { i += TEN18; term = decDiv18(decMul18(term, x), i); sum += term; } return sum; } /* Lookup Tables (LUTs). 38 DP fixed-point numbers. */ // LUT1 for log_2(x). The i'th term is 1/(2^(1/2^i)) function setLUT1() public { table_log_2[0] = 0; table_log_2[1] = 70710678118654752440084436210484903928; table_log_2[2] = 84089641525371454303112547623321489504; table_log_2[3] = 91700404320467123174354159479414442804; table_log_2[4] = 95760328069857364693630563514791544393; table_log_2[5] = 97857206208770013450916112581343574560; table_log_2[6] = 98922801319397548412912495906558366777; table_log_2[7] = 99459942348363317565247768622216631446; table_log_2[8] = 99729605608547012625765991384792260112; table_log_2[9] = 99864711289097017358812131808592040806; table_log_2[10] = 99932332750265075236028365984373804116; table_log_2[11] = 99966160649624368394219686876281565561; table_log_2[12] = 99983078893192906311748078019767389868; table_log_2[13] = 99991539088661349753372497156418872723; table_log_2[14] = 99995769454843113254396753730099797524; table_log_2[15] = 99997884705049192982650067113039327478; table_log_2[16] = 99998942346931446424221059225315431670; table_log_2[17] = 99999471172067428300770241277030532519; table_log_2[18] = 99999735585684139498225234636504270993; table_log_2[19] = 99999867792754675970531776759801063698; table_log_2[20] = 99999933896355489526178052900624509795; table_log_2[21] = 99999966948172282646511738368820575117; table_log_2[22] = 99999983474084775793885880947314828005; table_log_2[23] = 99999991737042046514572235133214264694; table_log_2[24] = 99999995868520937911689915196095249000; table_log_2[25] = 99999997934260447619445466250978583193; table_log_2[26] = 99999998967130218475622805194415901619; table_log_2[27] = 99999999483565107904286413727651274869; table_log_2[28] = 99999999741782553618761958785587923503; table_log_2[29] = 99999999870891276726035667265628464908; table_log_2[30] = 99999999935445638342181505587572099682; table_log_2[31] = 99999999967722819165881670780794171827; table_log_2[32] = 99999999983861409581638564886938948308; table_log_2[33] = 99999999991930704790493714817578668739; table_log_2[34] = 99999999995965352395165465502313349139; table_log_2[35] = 99999999997982676197562384774537267778; table_log_2[36] = 99999999998991338098776105393113730880; table_log_2[37] = 99999999999495669049386780948018133274; table_log_2[38] = 99999999999747834524693072536874382794; table_log_2[39] = 99999999999873917262346456784153520336; table_log_2[40] = 99999999999936958631173208521005842390; table_log_2[41] = 99999999999968479315586599292735191749; table_log_2[42] = 99999999999984239657793298404425663513; table_log_2[43] = 99999999999992119828896648891727348666; table_log_2[44] = 99999999999996059914448324368242303560; table_log_2[45] = 99999999999998029957224162164715809087; table_log_2[46] = 99999999999999014978612081077506568870; table_log_2[47] = 99999999999999507489306040537540450517; table_log_2[48] = 99999999999999753744653020268467016779; table_log_2[49] = 99999999999999876872326510134157706270; table_log_2[50] = 99999999999999938436163255067059902605; table_log_2[51] = 99999999999999969218081627533525213670; table_log_2[52] = 99999999999999984609040813766761422427; table_log_2[53] = 99999999999999992304520406883380415111; table_log_2[54] = 99999999999999996152260203441690133530; table_log_2[55] = 99999999999999998076130101720845048259; table_log_2[56] = 99999999999999999038065050860422519503; table_log_2[57] = 99999999999999999519032525430211258595; table_log_2[58] = 99999999999999999759516262715105629008; table_log_2[59] = 99999999999999999879758131357552814432; table_log_2[60] = 99999999999999999939879065678776407198; table_log_2[61] = 99999999999999999969939532839388203594; table_log_2[62] = 99999999999999999984969766419694101796; table_log_2[63] = 99999999999999999992484883209847050898; table_log_2[64] = 99999999999999999996242441604923525449; table_log_2[65] = 99999999999999999998121220802461762724; table_log_2[66] = 99999999999999999999060610401230881362; table_log_2[67] = 99999999999999999999530305200615440681; table_log_2[68] = 99999999999999999999765152600307720341; table_log_2[69] = 99999999999999999999882576300153860170; table_log_2[70] = 99999999999999999999941288150076930085; table_log_2[71] = 99999999999999999999970644075038465043; table_log_2[72] = 99999999999999999999985322037519232521; table_log_2[73] = 99999999999999999999992661018759616261; table_log_2[74] = 99999999999999999999996330509379808130; table_log_2[75] = 99999999999999999999998165254689904065; table_log_2[76] = 99999999999999999999999082627344952033; table_log_2[77] = 99999999999999999999999541313672476016; table_log_2[78] = 99999999999999999999999770656836238008; table_log_2[79] = 99999999999999999999999885328418119004; table_log_2[80] = 99999999999999999999999942664209059502; table_log_2[81] = 99999999999999999999999971332104529751; table_log_2[82] = 99999999999999999999999985666052264876; table_log_2[83] = 99999999999999999999999992833026132438; table_log_2[84] = 99999999999999999999999996416513066219; table_log_2[85] = 99999999999999999999999998208256533109; table_log_2[86] = 99999999999999999999999999104128266555; table_log_2[87] = 99999999999999999999999999552064133277; table_log_2[88] = 99999999999999999999999999776032066639; table_log_2[89] = 99999999999999999999999999888016033319; table_log_2[90] = 99999999999999999999999999944008016660; table_log_2[91] = 99999999999999999999999999972004008330; table_log_2[92] = 99999999999999999999999999986002004165; table_log_2[93] = 99999999999999999999999999993001002082; table_log_2[94] = 99999999999999999999999999996500501041; table_log_2[95] = 99999999999999999999999999998250250521; table_log_2[96] = 99999999999999999999999999999125125260; table_log_2[97] = 99999999999999999999999999999562562630; table_log_2[98] = 99999999999999999999999999999781281315; table_log_2[99] = 99999999999999999999999999999890640658; LUT1_isSet = true; } // LUT2 for log_2(x). The i'th term is 1/(2^i) function setLUT2() public { table2_log_2[0] = 200000000000000000000000000000000000000; table2_log_2[1] = 50000000000000000000000000000000000000; table2_log_2[2] = 25000000000000000000000000000000000000; table2_log_2[3] = 12500000000000000000000000000000000000; table2_log_2[4] = 6250000000000000000000000000000000000; table2_log_2[5] = 3125000000000000000000000000000000000; table2_log_2[6] = 1562500000000000000000000000000000000; table2_log_2[7] = 781250000000000000000000000000000000; table2_log_2[8] = 390625000000000000000000000000000000; table2_log_2[9] = 195312500000000000000000000000000000; table2_log_2[10] = 97656250000000000000000000000000000; table2_log_2[11] = 48828125000000000000000000000000000; table2_log_2[12] = 24414062500000000000000000000000000; table2_log_2[13] = 12207031250000000000000000000000000; table2_log_2[14] = 6103515625000000000000000000000000; table2_log_2[15] = 3051757812500000000000000000000000; table2_log_2[16] = 1525878906250000000000000000000000; table2_log_2[17] = 762939453125000000000000000000000; table2_log_2[18] = 381469726562500000000000000000000; table2_log_2[19] = 190734863281250000000000000000000; table2_log_2[20] = 95367431640625000000000000000000; table2_log_2[21] = 47683715820312500000000000000000; table2_log_2[22] = 23841857910156250000000000000000; table2_log_2[23] = 11920928955078125000000000000000; table2_log_2[24] = 5960464477539062500000000000000; table2_log_2[25] = 2980232238769531250000000000000; table2_log_2[26] = 1490116119384765625000000000000; table2_log_2[27] = 745058059692382812500000000000; table2_log_2[28] = 372529029846191406250000000000; table2_log_2[29] = 186264514923095703125000000000; table2_log_2[30] = 93132257461547851562500000000; table2_log_2[31] = 46566128730773925781250000000; table2_log_2[32] = 23283064365386962890625000000; table2_log_2[33] = 11641532182693481445312500000; table2_log_2[34] = 5820766091346740722656250000; table2_log_2[35] = 2910383045673370361328125000; table2_log_2[36] = 1455191522836685180664062500; table2_log_2[37] = 727595761418342590332031250; table2_log_2[38] = 363797880709171295166015625; table2_log_2[39] = 181898940354585647583007812; table2_log_2[40] = 90949470177292823791503906; table2_log_2[41] = 45474735088646411895751953; table2_log_2[42] = 22737367544323205947875976; table2_log_2[43] = 11368683772161602973937988; table2_log_2[44] = 5684341886080801486968994; table2_log_2[45] = 2842170943040400743484497; table2_log_2[46] = 1421085471520200371742248; table2_log_2[47] = 710542735760100185871124; table2_log_2[48] = 355271367880050092935562; table2_log_2[49] = 177635683940025046467781; table2_log_2[50] = 88817841970012523233890; table2_log_2[51] = 44408920985006261616945; table2_log_2[52] = 22204460492503130808472; table2_log_2[53] = 11102230246251565404236; table2_log_2[54] = 5551115123125782702118; table2_log_2[55] = 2775557561562891351059; table2_log_2[56] = 1387778780781445675529; table2_log_2[57] = 693889390390722837764; table2_log_2[58] = 346944695195361418882; table2_log_2[59] = 173472347597680709441; table2_log_2[60] = 86736173798840354720; table2_log_2[61] = 43368086899420177360; table2_log_2[62] = 21684043449710088680; table2_log_2[63] = 10842021724855044340; table2_log_2[64] = 5421010862427522170; table2_log_2[65] = 2710505431213761085; table2_log_2[66] = 1355252715606880542; table2_log_2[67] = 677626357803440271; table2_log_2[68] = 338813178901720135; table2_log_2[69] = 169406589450860067; table2_log_2[70] = 84703294725430033; table2_log_2[71] = 42351647362715016; table2_log_2[72] = 21175823681357508; table2_log_2[73] = 10587911840678754; table2_log_2[74] = 5293955920339377; table2_log_2[75] = 2646977960169688; table2_log_2[76] = 1323488980084844; table2_log_2[77] = 661744490042422; table2_log_2[78] = 330872245021211; table2_log_2[79] = 165436122510605; table2_log_2[80] = 82718061255302; table2_log_2[81] = 41359030627651; table2_log_2[82] = 20679515313825; table2_log_2[83] = 10339757656912; table2_log_2[84] = 5169878828456; table2_log_2[85] = 2584939414228; table2_log_2[86] = 1292469707114; table2_log_2[87] = 646234853557; table2_log_2[88] = 323117426778; table2_log_2[89] = 161558713389; table2_log_2[90] = 80779356694; table2_log_2[91] = 40389678347; table2_log_2[92] = 20194839173; table2_log_2[93] = 10097419586; table2_log_2[94] = 5048709793; table2_log_2[95] = 2524354896; table2_log_2[96] = 1262177448; table2_log_2[97] = 631088724; table2_log_2[98] = 315544362; table2_log_2[99] = 157772181; LUT2_isSet = true; } /* LUT for pow2() function. Table contains 39 arrays, each array contains 10 uint slots. table_pow2[i][d] = (2^(1 / 10^(i + 1))) ** d. d ranges from 0 to 9. LUT-setting is split into four separate setter functions to keep gas costs under block limit. */ function setLUT3_1() public { table_pow2[0][0] = 100000000000000000000000000000000000000; table_pow2[0][1] = 107177346253629316421300632502334202291; table_pow2[0][2] = 114869835499703500679862694677792758944; table_pow2[0][3] = 123114441334491628449939306916774310988; table_pow2[0][4] = 131950791077289425937400197122964013303; table_pow2[0][5] = 141421356237309504880168872420969807857; table_pow2[0][6] = 151571656651039808234725980130644523868; table_pow2[0][7] = 162450479271247104521941876555056330257; table_pow2[0][8] = 174110112659224827827254003495949219796; table_pow2[0][9] = 186606598307361483196268653229988433405; table_pow2[1][0] = 100000000000000000000000000000000000000; table_pow2[1][1] = 100695555005671880883269821411323978545; table_pow2[1][2] = 101395947979002913869016599962823042584; table_pow2[1][3] = 102101212570719324976409517478306437354; table_pow2[1][4] = 102811382665606650934634495879263497655; table_pow2[1][5] = 103526492384137750434778819421124619773; table_pow2[1][6] = 104246576084112139095471141872690784007; table_pow2[1][7] = 104971668362306726904934732174028851665; table_pow2[1][8] = 105701804056138037449949421408611430989; table_pow2[1][9] = 106437018245335988793865835140404338206; table_pow2[2][0] = 100000000000000000000000000000000000000; table_pow2[2][1] = 100069338746258063253756863930385919571; table_pow2[2][2] = 100138725571133452908322477441877746756; table_pow2[2][3] = 100208160507963279436035132489114568295; table_pow2[2][4] = 100277643590107768843673305907248072983; table_pow2[2][5] = 100347174850950278700477431086959080340; table_pow2[2][6] = 100416754323897314177285298995922943429; table_pow2[2][7] = 100486382042378544096788794597976421668; table_pow2[2][8] = 100556058039846816994919680064517944020; table_pow2[2][9] = 100625782349778177193372141519657470417; table_pow2[3][0] = 100000000000000000000000000000000000000; table_pow2[3][1] = 100006931712037656919243991260264256542; table_pow2[3][2] = 100013863904561631568466376833067115945; table_pow2[3][3] = 100020796577605229875592540103010552992; table_pow2[3][4] = 100027729731201760077218879711834041246; table_pow2[3][5] = 100034663365384532718772839985089028270; table_pow2[3][6] = 100041597480186860654672952451661760537; table_pow2[3][7] = 100048532075642059048488888456913382370; table_pow2[3][8] = 100055467151783445373101522870206286485; table_pow2[3][9] = 100062402708644339410863008887585747065; table_pow2[4][0] = 100000000000000000000000000000000000000; table_pow2[4][1] = 100000693149582830565320908980056168150; table_pow2[4][2] = 100001386303970224572423685307245831542; table_pow2[4][3] = 100002079463162215324119782522433627138; table_pow2[4][4] = 100002772627158836123451492465145260129; table_pow2[4][5] = 100003465795960120273691946873622208121; table_pow2[4][6] = 100004158969566101078345118984887516084; table_pow2[4][7] = 100004852147976811841145825134822682163; table_pow2[4][8] = 100005545331192285866059726358255634403; table_pow2[4][9] = 100006238519212556457283329989059798485; table_pow2[5][0] = 100000000000000000000000000000000000000; table_pow2[5][1] = 100000069314742078650777263622740703038; table_pow2[5][2] = 100000138629532202636248826052225815048; table_pow2[5][3] = 100000207944370371989717187112633071811; table_pow2[5][4] = 100000277259256586744484869711682067979; table_pow2[5][5] = 100000346574190846933854419840650257373; table_pow2[5][6] = 100000415889173152591128406574388953292; table_pow2[5][7] = 100000485204203503749609422071339328833; table_pow2[5][8] = 100000554519281900442600081573548417222; table_pow2[5][9] = 100000623834408342703403023406685112154; table_pow2[6][0] = 100000000000000000000000000000000000000; table_pow2[6][1] = 100000006931472045825965603683996211583; table_pow2[6][2] = 100000013862944572104978428035962521332; table_pow2[6][3] = 100000020794417578837071775524560348874; table_pow2[6][4] = 100000027725891066022278948620759465140; table_pow2[6][5] = 100000034657365033660633249797837992529; table_pow2[6][6] = 100000041588839481752167981531382405066; table_pow2[6][7] = 100000048520314410296916446299287528561; table_pow2[6][8] = 100000055451789819294911946581756540768; table_pow2[6][9] = 100000062383265708746187784861300971552; table_pow2[7][0] = 100000000000000000000000000000000000000; table_pow2[7][1] = 100000000693147182962210384558650120894; table_pow2[7][2] = 100000001386294370728950941601779822006; table_pow2[7][3] = 100000002079441563300221704431854648481; table_pow2[7][4] = 100000002772588760676022706351340376300; table_pow2[7][5] = 100000003465735962856353980662703012279; table_pow2[7][6] = 100000004158883169841215560668408794069; table_pow2[7][7] = 100000004852030381630607479670924190156; table_pow2[7][8] = 100000005545177598224529770972715899860; table_pow2[7][9] = 100000006238324819622982467876250853339; table_pow2[8][0] = 100000000000000000000000000000000000000; table_pow2[8][1] = 100000000069314718080017181643183694247; table_pow2[8][2] = 100000000138629436208079664711489996172; table_pow2[8][3] = 100000000207944154384187449238221371011; table_pow2[8][4] = 100000000277258872608340535256680284018; table_pow2[8][5] = 100000000346573590880538922800169200474; table_pow2[8][6] = 100000000415888309200782611901990585682; table_pow2[8][7] = 100000000485203027569071602595446904968; table_pow2[8][8] = 100000000554517745985405894913840623680; table_pow2[8][9] = 100000000623832464449785488890474207190; table_pow2[9][0] = 100000000000000000000000000000000000000; table_pow2[9][1] = 100000000006931471805839679601136972338; table_pow2[9][2] = 100000000013862943612159812216225448565; table_pow2[9][3] = 100000000020794415418960397845298731148; table_pow2[9][4] = 100000000027725887226241436488390122551; table_pow2[9][5] = 100000000034657359034002928145532925240; table_pow2[9][6] = 100000000041588830842244872816760441679; table_pow2[9][7] = 100000000048520302650967270502105974334; table_pow2[9][8] = 100000000055451774460170121201602825670; table_pow2[9][9] = 100000000062383246269853424915284298153; table_pow2[10][0] = 100000000000000000000000000000000000000; table_pow2[10][1] = 100000000000693147180562347574486828679; table_pow2[10][2] = 100000000001386294361129499679112872675; table_pow2[10][3] = 100000000002079441541701456313878165290; table_pow2[10][4] = 100000000002772588722278217478782739826; table_pow2[10][5] = 100000000003465735902859783173826629587; table_pow2[10][6] = 100000000004158883083446153399009867874; table_pow2[10][7] = 100000000004852030264037328154332487990; table_pow2[10][8] = 100000000005545177444633307439794523238; table_pow2[10][9] = 100000000006238324625234091255396006920; LUT3_1_isSet = true; } function setLUT3_2() public { table_pow2[11][0] = 100000000000000000000000000000000000000; table_pow2[11][1] = 100000000000069314718056018553592419128; table_pow2[11][2] = 100000000000138629436112085152486230109; table_pow2[11][3] = 100000000000207944154168199796681432977; table_pow2[11][4] = 100000000000277258872224362486178027765; table_pow2[11][5] = 100000000000346573590280573220976014506; table_pow2[11][6] = 100000000000415888308336832001075393234; table_pow2[11][7] = 100000000000485203026393138826476163982; table_pow2[11][8] = 100000000000554517744449493697178326784; table_pow2[11][9] = 100000000000623832462505896613181881671; table_pow2[12][0] = 100000000000000000000000000000000000000; table_pow2[12][1] = 100000000000006931471805599693320679280; table_pow2[12][2] = 100000000000013862943611199867094372479; table_pow2[12][3] = 100000000000020794415416800521321079596; table_pow2[12][4] = 100000000000027725887222401656000800631; table_pow2[12][5] = 100000000000034657359028003271133535584; table_pow2[12][6] = 100000000000041588830833605366719284456; table_pow2[12][7] = 100000000000048520302639207942758047246; table_pow2[12][8] = 100000000000055451774444810999249823955; table_pow2[12][9] = 100000000000062383246250414536194614582; table_pow2[13][0] = 100000000000000000000000000000000000000; table_pow2[13][1] = 100000000000000693147180559947711682302; table_pow2[13][2] = 100000000000001386294361119900227894743; table_pow2[13][3] = 100000000000002079441541679857548637323; table_pow2[13][4] = 100000000000002772588722239819673910042; table_pow2[13][5] = 100000000000003465735902799786603712900; table_pow2[13][6] = 100000000000004158883083359758338045898; table_pow2[13][7] = 100000000000004852030263919734876909035; table_pow2[13][8] = 100000000000005545177444479716220302311; table_pow2[13][9] = 100000000000006238324625039702368225726; table_pow2[14][0] = 100000000000000000000000000000000000000; table_pow2[14][1] = 100000000000000069314718055994554964374; table_pow2[14][2] = 100000000000000138629436111989157974049; table_pow2[14][3] = 100000000000000207944154167983809029026; table_pow2[14][4] = 100000000000000277258872223978508129304; table_pow2[14][5] = 100000000000000346573590279973255274883; table_pow2[14][6] = 100000000000000415888308335968050465764; table_pow2[14][7] = 100000000000000485203026391962893701947; table_pow2[14][8] = 100000000000000554517744447957784983430; table_pow2[14][9] = 100000000000000623832462503952724310215; table_pow2[15][0] = 100000000000000000000000000000000000000; table_pow2[15][1] = 100000000000000006931471805599453334399; table_pow2[15][2] = 100000000000000013862943611198907149251; table_pow2[15][3] = 100000000000000020794415416798361444556; table_pow2[15][4] = 100000000000000027725887222397816220313; table_pow2[15][5] = 100000000000000034657359027997271476524; table_pow2[15][6] = 100000000000000041588830833596727213188; table_pow2[15][7] = 100000000000000048520302639196183430305; table_pow2[15][8] = 100000000000000055451774444795640127875; table_pow2[15][9] = 100000000000000062383246250395097305898; table_pow2[16][0] = 100000000000000000000000000000000000000; table_pow2[16][1] = 100000000000000000693147180559945311819; table_pow2[16][2] = 100000000000000001386294361119890628444; table_pow2[16][3] = 100000000000000002079441541679835949872; table_pow2[16][4] = 100000000000000002772588722239781276105; table_pow2[16][5] = 100000000000000003465735902799726607143; table_pow2[16][6] = 100000000000000004158883083359671942985; table_pow2[16][7] = 100000000000000004852030263919617283632; table_pow2[16][8] = 100000000000000005545177444479562629083; table_pow2[16][9] = 100000000000000006238324625039507979339; table_pow2[17][0] = 100000000000000000000000000000000000000; table_pow2[17][1] = 100000000000000000069314718055994530966; table_pow2[17][2] = 100000000000000000138629436111989061980; table_pow2[17][3] = 100000000000000000207944154167983593041; table_pow2[17][4] = 100000000000000000277258872223978124151; table_pow2[17][5] = 100000000000000000346573590279972655309; table_pow2[17][6] = 100000000000000000415888308335967186515; table_pow2[17][7] = 100000000000000000485203026391961717769; table_pow2[17][8] = 100000000000000000554517744447956249071; table_pow2[17][9] = 100000000000000000623832462503950780421; table_pow2[18][0] = 100000000000000000000000000000000000000; table_pow2[18][1] = 100000000000000000006931471805599453094; table_pow2[18][2] = 100000000000000000013862943611198906189; table_pow2[18][3] = 100000000000000000020794415416798359285; table_pow2[18][4] = 100000000000000000027725887222397812381; table_pow2[18][5] = 100000000000000000034657359027997265477; table_pow2[18][6] = 100000000000000000041588830833596718574; table_pow2[18][7] = 100000000000000000048520302639196171671; table_pow2[18][8] = 100000000000000000055451774444795624769; table_pow2[18][9] = 100000000000000000062383246250395077867; table_pow2[19][0] = 100000000000000000000000000000000000000; table_pow2[19][1] = 100000000000000000000693147180559945309; table_pow2[19][2] = 100000000000000000001386294361119890619; table_pow2[19][3] = 100000000000000000002079441541679835928; table_pow2[19][4] = 100000000000000000002772588722239781238; table_pow2[19][5] = 100000000000000000003465735902799726547; table_pow2[19][6] = 100000000000000000004158883083359671857; table_pow2[19][7] = 100000000000000000004852030263919617166; table_pow2[19][8] = 100000000000000000005545177444479562475; table_pow2[19][9] = 100000000000000000006238324625039507785; table_pow2[20][0] = 100000000000000000000000000000000000000; table_pow2[20][1] = 100000000000000000000069314718055994531; table_pow2[20][2] = 100000000000000000000138629436111989062; table_pow2[20][3] = 100000000000000000000207944154167983593; table_pow2[20][4] = 100000000000000000000277258872223978124; table_pow2[20][5] = 100000000000000000000346573590279972655; table_pow2[20][6] = 100000000000000000000415888308335967186; table_pow2[20][7] = 100000000000000000000485203026391961717; table_pow2[20][8] = 100000000000000000000554517744447956248; table_pow2[20][9] = 100000000000000000000623832462503950778; LUT3_2_isSet = true; } function setLUT3_3() public { table_pow2[21][0] = 100000000000000000000000000000000000000; table_pow2[21][1] = 100000000000000000000006931471805599453; table_pow2[21][2] = 100000000000000000000013862943611198906; table_pow2[21][3] = 100000000000000000000020794415416798359; table_pow2[21][4] = 100000000000000000000027725887222397812; table_pow2[21][5] = 100000000000000000000034657359027997265; table_pow2[21][6] = 100000000000000000000041588830833596719; table_pow2[21][7] = 100000000000000000000048520302639196172; table_pow2[21][8] = 100000000000000000000055451774444795625; table_pow2[21][9] = 100000000000000000000062383246250395078; table_pow2[22][0] = 100000000000000000000000000000000000000; table_pow2[22][1] = 100000000000000000000000693147180559945; table_pow2[22][2] = 100000000000000000000001386294361119891; table_pow2[22][3] = 100000000000000000000002079441541679836; table_pow2[22][4] = 100000000000000000000002772588722239781; table_pow2[22][5] = 100000000000000000000003465735902799727; table_pow2[22][6] = 100000000000000000000004158883083359672; table_pow2[22][7] = 100000000000000000000004852030263919617; table_pow2[22][8] = 100000000000000000000005545177444479562; table_pow2[22][9] = 100000000000000000000006238324625039508; table_pow2[23][0] = 100000000000000000000000000000000000000; table_pow2[23][1] = 100000000000000000000000069314718055995; table_pow2[23][2] = 100000000000000000000000138629436111989; table_pow2[23][3] = 100000000000000000000000207944154167984; table_pow2[23][4] = 100000000000000000000000277258872223978; table_pow2[23][5] = 100000000000000000000000346573590279973; table_pow2[23][6] = 100000000000000000000000415888308335967; table_pow2[23][7] = 100000000000000000000000485203026391962; table_pow2[23][8] = 100000000000000000000000554517744447956; table_pow2[23][9] = 100000000000000000000000623832462503951; table_pow2[24][0] = 100000000000000000000000000000000000000; table_pow2[24][1] = 100000000000000000000000006931471805599; table_pow2[24][2] = 100000000000000000000000013862943611199; table_pow2[24][3] = 100000000000000000000000020794415416798; table_pow2[24][4] = 100000000000000000000000027725887222398; table_pow2[24][5] = 100000000000000000000000034657359027997; table_pow2[24][6] = 100000000000000000000000041588830833597; table_pow2[24][7] = 100000000000000000000000048520302639196; table_pow2[24][8] = 100000000000000000000000055451774444796; table_pow2[24][9] = 100000000000000000000000062383246250395; table_pow2[25][0] = 100000000000000000000000000000000000000; table_pow2[25][1] = 100000000000000000000000000693147180560; table_pow2[25][2] = 100000000000000000000000001386294361120; table_pow2[25][3] = 100000000000000000000000002079441541680; table_pow2[25][4] = 100000000000000000000000002772588722240; table_pow2[25][5] = 100000000000000000000000003465735902800; table_pow2[25][6] = 100000000000000000000000004158883083360; table_pow2[25][7] = 100000000000000000000000004852030263920; table_pow2[25][8] = 100000000000000000000000005545177444480; table_pow2[25][9] = 100000000000000000000000006238324625040; table_pow2[26][0] = 100000000000000000000000000000000000000; table_pow2[26][1] = 100000000000000000000000000069314718056; table_pow2[26][2] = 100000000000000000000000000138629436112; table_pow2[26][3] = 100000000000000000000000000207944154168; table_pow2[26][4] = 100000000000000000000000000277258872224; table_pow2[26][5] = 100000000000000000000000000346573590280; table_pow2[26][6] = 100000000000000000000000000415888308336; table_pow2[26][7] = 100000000000000000000000000485203026392; table_pow2[26][8] = 100000000000000000000000000554517744448; table_pow2[26][9] = 100000000000000000000000000623832462504; table_pow2[27][0] = 100000000000000000000000000000000000000; table_pow2[27][1] = 100000000000000000000000000006931471806; table_pow2[27][2] = 100000000000000000000000000013862943611; table_pow2[27][3] = 100000000000000000000000000020794415417; table_pow2[27][4] = 100000000000000000000000000027725887222; table_pow2[27][5] = 100000000000000000000000000034657359028; table_pow2[27][6] = 100000000000000000000000000041588830834; table_pow2[27][7] = 100000000000000000000000000048520302639; table_pow2[27][8] = 100000000000000000000000000055451774445; table_pow2[27][9] = 100000000000000000000000000062383246250; table_pow2[28][0] = 100000000000000000000000000000000000000; table_pow2[28][1] = 100000000000000000000000000000693147181; table_pow2[28][2] = 100000000000000000000000000001386294361; table_pow2[28][3] = 100000000000000000000000000002079441542; table_pow2[28][4] = 100000000000000000000000000002772588722; table_pow2[28][5] = 100000000000000000000000000003465735903; table_pow2[28][6] = 100000000000000000000000000004158883083; table_pow2[28][7] = 100000000000000000000000000004852030264; table_pow2[28][8] = 100000000000000000000000000005545177444; table_pow2[28][9] = 100000000000000000000000000006238324625; table_pow2[29][0] = 100000000000000000000000000000000000000; table_pow2[29][1] = 100000000000000000000000000000069314718; table_pow2[29][2] = 100000000000000000000000000000138629436; table_pow2[29][3] = 100000000000000000000000000000207944154; table_pow2[29][4] = 100000000000000000000000000000277258872; table_pow2[29][5] = 100000000000000000000000000000346573590; table_pow2[29][6] = 100000000000000000000000000000415888308; table_pow2[29][7] = 100000000000000000000000000000485203026; table_pow2[29][8] = 100000000000000000000000000000554517744; table_pow2[29][9] = 100000000000000000000000000000623832463; table_pow2[30][0] = 100000000000000000000000000000000000000; table_pow2[30][1] = 100000000000000000000000000000006931472; table_pow2[30][2] = 100000000000000000000000000000013862944; table_pow2[30][3] = 100000000000000000000000000000020794415; table_pow2[30][4] = 100000000000000000000000000000027725887; table_pow2[30][5] = 100000000000000000000000000000034657359; table_pow2[30][6] = 100000000000000000000000000000041588831; table_pow2[30][7] = 100000000000000000000000000000048520303; table_pow2[30][8] = 100000000000000000000000000000055451774; table_pow2[30][9] = 100000000000000000000000000000062383246; LUT3_3_isSet = true; } function setLUT3_4() public { table_pow2[31][0] = 100000000000000000000000000000000000000; table_pow2[31][1] = 100000000000000000000000000000000693147; table_pow2[31][2] = 100000000000000000000000000000001386294; table_pow2[31][3] = 100000000000000000000000000000002079442; table_pow2[31][4] = 100000000000000000000000000000002772589; table_pow2[31][5] = 100000000000000000000000000000003465736; table_pow2[31][6] = 100000000000000000000000000000004158883; table_pow2[31][7] = 100000000000000000000000000000004852030; table_pow2[31][8] = 100000000000000000000000000000005545177; table_pow2[31][9] = 100000000000000000000000000000006238325; table_pow2[32][0] = 100000000000000000000000000000000000000; table_pow2[32][1] = 100000000000000000000000000000000069315; table_pow2[32][2] = 100000000000000000000000000000000138629; table_pow2[32][3] = 100000000000000000000000000000000207944; table_pow2[32][4] = 100000000000000000000000000000000277259; table_pow2[32][5] = 100000000000000000000000000000000346574; table_pow2[32][6] = 100000000000000000000000000000000415888; table_pow2[32][7] = 100000000000000000000000000000000485203; table_pow2[32][8] = 100000000000000000000000000000000554518; table_pow2[32][9] = 100000000000000000000000000000000623832; table_pow2[33][0] = 100000000000000000000000000000000000000; table_pow2[33][1] = 100000000000000000000000000000000006931; table_pow2[33][2] = 100000000000000000000000000000000013863; table_pow2[33][3] = 100000000000000000000000000000000020794; table_pow2[33][4] = 100000000000000000000000000000000027726; table_pow2[33][5] = 100000000000000000000000000000000034657; table_pow2[33][6] = 100000000000000000000000000000000041589; table_pow2[33][7] = 100000000000000000000000000000000048520; table_pow2[33][8] = 100000000000000000000000000000000055452; table_pow2[33][9] = 100000000000000000000000000000000062383; table_pow2[34][0] = 100000000000000000000000000000000000000; table_pow2[34][1] = 100000000000000000000000000000000000693; table_pow2[34][2] = 100000000000000000000000000000000001386; table_pow2[34][3] = 100000000000000000000000000000000002079; table_pow2[34][4] = 100000000000000000000000000000000002773; table_pow2[34][5] = 100000000000000000000000000000000003466; table_pow2[34][6] = 100000000000000000000000000000000004159; table_pow2[34][7] = 100000000000000000000000000000000004852; table_pow2[34][8] = 100000000000000000000000000000000005545; table_pow2[34][9] = 100000000000000000000000000000000006238; table_pow2[35][0] = 100000000000000000000000000000000000000; table_pow2[35][1] = 100000000000000000000000000000000000069; table_pow2[35][2] = 100000000000000000000000000000000000139; table_pow2[35][3] = 100000000000000000000000000000000000208; table_pow2[35][4] = 100000000000000000000000000000000000277; table_pow2[35][5] = 100000000000000000000000000000000000347; table_pow2[35][6] = 100000000000000000000000000000000000416; table_pow2[35][7] = 100000000000000000000000000000000000485; table_pow2[35][8] = 100000000000000000000000000000000000555; table_pow2[35][9] = 100000000000000000000000000000000000624; table_pow2[36][0] = 100000000000000000000000000000000000000; table_pow2[36][1] = 100000000000000000000000000000000000007; table_pow2[36][2] = 100000000000000000000000000000000000014; table_pow2[36][3] = 100000000000000000000000000000000000021; table_pow2[36][4] = 100000000000000000000000000000000000028; table_pow2[36][5] = 100000000000000000000000000000000000035; table_pow2[36][6] = 100000000000000000000000000000000000042; table_pow2[36][7] = 100000000000000000000000000000000000049; table_pow2[36][8] = 100000000000000000000000000000000000055; table_pow2[36][9] = 100000000000000000000000000000000000062; table_pow2[37][0] = 100000000000000000000000000000000000000; table_pow2[37][1] = 100000000000000000000000000000000000001; table_pow2[37][2] = 100000000000000000000000000000000000001; table_pow2[37][3] = 100000000000000000000000000000000000002; table_pow2[37][4] = 100000000000000000000000000000000000003; table_pow2[37][5] = 100000000000000000000000000000000000003; table_pow2[37][6] = 100000000000000000000000000000000000004; table_pow2[37][7] = 100000000000000000000000000000000000005; table_pow2[37][8] = 100000000000000000000000000000000000006; table_pow2[37][9] = 100000000000000000000000000000000000006; table_pow2[38][0] = 100000000000000000000000000000000000000; table_pow2[38][1] = 100000000000000000000000000000000000000; table_pow2[38][2] = 100000000000000000000000000000000000000; table_pow2[38][3] = 100000000000000000000000000000000000000; table_pow2[38][4] = 100000000000000000000000000000000000000; table_pow2[38][5] = 100000000000000000000000000000000000000; table_pow2[38][6] = 100000000000000000000000000000000000000; table_pow2[38][7] = 100000000000000000000000000000000000000; table_pow2[38][8] = 100000000000000000000000000000000000001; table_pow2[38][9] = 100000000000000000000000000000000000001; LUT3_4_isSet = true; } /***** MODIFIERS *****/ modifier _onlyLUT1andLUT2AreSet() { require(LUT1_isSet == true && LUT2_isSet == true, "Lookup tables 1 & 2 must first be set"); _; } modifier _onlyLUT3isSet() { require( LUT3_1_isSet == true && LUT3_2_isSet == true && LUT3_3_isSet == true && LUT3_4_isSet == true, "Lookup table 3 must first be set" ); _; } }
pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a, "SafeMath: subtraction overflow"); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, "SafeMath: division by zero"); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0, "SafeMath: modulo by zero"); return a % b; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"buyer","type":"address"},{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sUSDPaid","type":"uint256"},{"indexed":false,"internalType":"address","name":"susd","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"BoughtFromAmm","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"isPaused","type":"bool"}],"name":"PauseChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_manager","type":"address"}],"name":"SetBinaryOptionsMarketManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_capPerMarket","type":"uint256"}],"name":"SetCapPerMarket","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"asset","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_impliedVolatility","type":"uint256"}],"name":"SetImpliedVolatilityPerAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"SetMaxSpread","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"SetMinSpread","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"SetMinimalTimeLeftToMaturity","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_priceFeed","type":"address"}],"name":"SetPriceFeed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sUSD","type":"address"}],"name":"SetSUSD","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"seller","type":"address"},{"indexed":false,"internalType":"address","name":"market","type":"address"},{"indexed":false,"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"sUSDPaid","type":"uint256"},{"indexed":false,"internalType":"address","name":"susd","type":"address"},{"indexed":false,"internalType":"address","name":"asset","type":"address"}],"name":"SoldToAMM","type":"event"},{"constant":false,"inputs":[],"name":"acceptOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"availableToBuyFromAMM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"availableToSellToAMM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"}],"name":"buyFromAMM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buyFromAmmQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"buyPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint256","name":"price","type":"uint256"},{"internalType":"uint256","name":"strike","type":"uint256"},{"internalType":"uint256","name":"timeLeftInDays","type":"uint256"},{"internalType":"uint256","name":"volatility","type":"uint256"}],"name":"calculateOdds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"canExerciseMaturedMarket","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"capPerMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"deciMath","outputs":[{"internalType":"contract DeciMath","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"exerciseMaturedMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"impliedVolatilityPerAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"initNonReentrant","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"contract IPriceFeed","name":"_priceFeed","type":"address"},{"internalType":"contract IERC20","name":"_sUSD","type":"address"},{"internalType":"uint256","name":"_capPerMarket","type":"uint256"},{"internalType":"contract DeciMath","name":"_deciMath","type":"address"},{"internalType":"uint256","name":"_min_spread","type":"uint256"},{"internalType":"uint256","name":"_max_spread","type":"uint256"},{"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"initialize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"}],"name":"isMarketInAMMTrading","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lastPauseTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"manager","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"max_spread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"min_spread","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"minimalTimeLeftToMaturity","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"nominateNewOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"nominatedOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"priceFeed","outputs":[{"internalType":"contract IPriceFeed","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address payable","name":"account","type":"address"}],"name":"retrieveSUSD","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"sUSD","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sellPriceImpact","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"expectedPayout","type":"uint256"},{"internalType":"uint256","name":"additionalSlippage","type":"uint256"}],"name":"sellToAMM","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"sellToAmmQuote","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_manager","type":"address"}],"name":"setBinaryOptionsMarketManager","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_capPerMarket","type":"uint256"}],"name":"setCapPerMarket","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"asset","type":"bytes32"},{"internalType":"uint256","name":"_impliedVolatility","type":"uint256"}],"name":"setImpliedVolatilityPerAsset","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"setMaxSpread","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_spread","type":"uint256"}],"name":"setMinSpread","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_minimalTimeLeftToMaturity","type":"uint256"}],"name":"setMinimalTimeLeftToMaturity","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bool","name":"_paused","type":"bool"}],"name":"setPaused","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IPriceFeed","name":"_priceFeed","type":"address"}],"name":"setPriceFeed","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"_sUSD","type":"address"}],"name":"setSUSD","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"spentOnMarket","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b5061422d806100206000396000f3fe608060405234801561001057600080fd5b50600436106102695760003560e01c806379ba509711610151578063c2783f92116100c3578063ebc7977211610087578063ebc797721461076a578063efc1525114610772578063f502b003146107a1578063f598df82146107be578063f85de9fa146107db578063fb91d41c146107f857610269565b8063c2783f92146106c1578063c3b83f5f146106f0578063c4dc27d714610716578063ca1d578e1461073c578063df8974d01461076257610269565b80639324cac7116101155780639324cac7146105bb578063a8cd06e8146105c3578063a996798c146105f2578063ad18f0da14610618578063bef648db1461066f578063bf46c0b41461068c57610269565b806379ba509714610545578063851702091461054d5780638875eb841461056a5780638da5cb5b146105ab57806391b4ded9146105b357610269565b806351b9181f116101ea5780636aaa81b6116101ae5780636aaa81b6146104b25780636cfa636e146104ba5780636ed033f8146104c2578063724e78da146104f1578063741bef1a1461051757806375cdc2281461051f57610269565b806351b9181f1461041f57806353a47bb7146104455780635727a0f31461044d5780635c975abb146104875780635ef85b261461048f57610269565b806321ef44c61161023157806321ef44c614610357578063270e13ef1461037d578063316425c3146103b25780633ce1108d146103ba578063481c6a75146103fb57610269565b80630f13aae81461026e57806313af4035146102b55780631627540c146102dd57806316c38b3c146103035780631c37d04b14610322575b600080fd5b6102a36004803603606081101561028457600080fd5b506001600160a01b038135169060ff6020820135169060400135610800565b60408051918252519081900360200190f35b6102db600480360360208110156102cb57600080fd5b50356001600160a01b031661089b565b005b6102db600480360360208110156102f357600080fd5b50356001600160a01b03166109ae565b6102db6004803603602081101561031957600080fd5b50351515610a0a565b6102a36004803603606081101561033857600080fd5b506001600160a01b038135169060ff6020820135169060400135610a84565b6102db6004803603602081101561036d57600080fd5b50356001600160a01b0316610ab2565b6102a36004803603606081101561039357600080fd5b506001600160a01b038135169060ff6020820135169060400135610b14565b6102a3610b7e565b6102db600480360360a08110156103d057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135610b84565b610403611396565b604080516001600160a01b039092168252519081900360200190f35b6102db6004803603602081101561043557600080fd5b50356001600160a01b03166113a5565b6104036115e1565b6104736004803603602081101561046357600080fd5b50356001600160a01b03166115f0565b604080519115158252519081900360200190f35b61047361179c565b6102db600480360360408110156104a557600080fd5b50803590602001356117a5565b6102a36117fe565b610403611804565b6102a3600480360360408110156104d857600080fd5b5080356001600160a01b0316906020013560ff16611813565b6102db6004803603602081101561050757600080fd5b50356001600160a01b0316611a2b565b610403611a87565b6102db6004803603602081101561053557600080fd5b50356001600160a01b0316611a96565b6102db611c0a565b6102db6004803603602081101561056357600080fd5b5035611cc6565b6102db600480360360a081101561058057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611d07565b61040361243c565b6102a361244b565b610403612451565b6102a3600480360360808110156105d957600080fd5b5080359060208101359060408101359060600135612460565b6102db6004803603602081101561060857600080fd5b50356001600160a01b03166128c3565b6102db600480360361010081101561062f57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e0013561299a565b6102db6004803603602081101561068557600080fd5b5035612ab2565b6102a3600480360360608110156106a257600080fd5b506001600160a01b038135169060ff6020820135169060400135612af5565b6102a3600480360360408110156106d757600080fd5b5080356001600160a01b0316906020013560ff16612b1b565b6102db6004803603602081101561070657600080fd5b50356001600160a01b0316612df4565b6102a36004803603602081101561072c57600080fd5b50356001600160a01b0316612f13565b6104736004803603602081101561075257600080fd5b50356001600160a01b0316612f25565b6102a36131a1565b6102db6131a7565b6102a36004803603604081101561078857600080fd5b5080356001600160a01b0316906020013560ff1661320a565b6102a3600480360360208110156107b757600080fd5b50356133c2565b6102db600480360360208110156107d457600080fd5b50356133d4565b6102db600480360360208110156107f157600080fd5b5035613417565b6102a361345a565b600061080c8484612b1b565b82111561081b57506000610894565b60006108278585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a6108558c8c8c613460565b670de0b6b3a76400009063ffffffff61386016565b879063ffffffff6138bd16565b9063ffffffff61391616565b869063ffffffff6138bd16565b9150505b9392505050565b6001600160a01b0381166108f6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff161561093f5760405162461bcd60e51b81526004018080602001828103825260298152602001806141166029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b6109b6613980565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610a12613980565b60035460ff1615158115151415610a2857610a81565b6003805460ff1916821515179081905560ff1615610a4557426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6000610a908484612b1b565b821115610a9f57506000610894565b610aaa848484613460565b949350505050565b610aba613980565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b6000610b20848461320a565b821115610b2f57506000610894565b6000610b3b8585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a610b698c8c8c6139cb565b670de0b6b3a76400009063ffffffff613d6116565b603e5481565b600480546001019081905560035460ff1615610bd15760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b610bda866115f0565b610c2b576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000610c378787612b1b565b9050600081118015610c495750808511155b610c92576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000610c9f888888610800565b9050610cb9670de0b6b3a76400008563ffffffff613d6116565b610cd58261087788670de0b6b3a764000063ffffffff6138bd16565b1115610d1c576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015610d5757600080fd5b505afa158015610d6b573d6000803e3d6000fd5b505050506040513d6040811015610d8157600080fd5b50805160209091015190925090506000808a6001811115610d9e57fe5b14610da95781610dab565b825b604080516370a0823160e01b815233600482015290519192508a916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610df657600080fd5b505afa158015610e0a573d6000803e3d6000fd5b505050506040513d6020811015610e2057600080fd5b50511015610e75576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b158015610ec457600080fd5b505afa158015610ed8573d6000803e3d6000fd5b505050506040513d6020811015610eee57600080fd5b50511015610f33576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b604080516323b872dd60e01b8152336004820152306024820152604481018b905290516001600160a01b038316916323b872dd9160648083019260209291908290030181600087803b158015610f8857600080fd5b505af1158015610f9c573d6000803e3d6000fd5b505050506040513d6020811015610fb257600080fd5b5050604080516314edbee160e31b815230600482015290516000916001600160a01b038e169163a76df70891602480820192602092909190829003018186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190508015611086578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561106d57600080fd5b505af1158015611081573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d60208110156110fa57600080fd5b5051101561114f576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506040513d60208110156111cd57600080fd5b50506001600160a01b038c166000908152604160205260409020546111f8908663ffffffff613d6116565b6001600160a01b038d1660009081526041602052604090208190558110611237576001600160a01b038c1660009081526041602052604081205561127a565b6001600160a01b038c16600090815260416020526040902054611260908263ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050600454811461138e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6001816001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e057600080fd5b505afa1580156113f4573d6000803e3d6000fd5b505050506040513d602081101561140a57600080fd5b5051600281111561141757fe5b14611469576040805162461bcd60e51b815260206004820152601f60248201527f4d61726b6574206973206e6f7420696e204d6174757269747920706861736500604482015290519081900360640190fd5b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151919092169163e62b8889916024808301926020929190829003018186803b1580156114b657600080fd5b505afa1580156114ca573d6000803e3d6000fd5b505050506040513d60208110156114e057600080fd5b5051611524576040805162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881b585c9ad95d60921b604482015290519081900360640190fd5b61152d81612f25565b611577576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b257600080fd5b505af11580156115c6573d6000803e3d6000fd5b505050506040513d60208110156115dc57600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561164157600080fd5b505afa158015611655573d6000803e3d6000fd5b505050506040513d602081101561166b57600080fd5b5051156117935760008290506000806000836001600160a01b03166398508ecd6040518163ffffffff1660e01b815260040160606040518083038186803b1580156116b557600080fd5b505afa1580156116c9573d6000803e3d6000fd5b505050506040513d60608110156116df57600080fd5b5080516020808301516040938401516000848152603f90935293909120549195509350909150611716576000945050505050611797565b600080856001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561175157600080fd5b505afa158015611765573d6000803e3d6000fd5b505050506040513d604081101561177b57600080fd5b50516040544290910311965061179795505050505050565b5060005b919050565b60035460ff1681565b6117ad613980565b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b600061181e836115f0565b15611a21576000839050600080826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d604081101561188d57600080fd5b508051602090910151909250905042820360006118bf6201518061087784670de0b6b3a764000063ffffffff6138bd16565b90506000856001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b1580156118fc57600080fd5b505afa158015611910573d6000803e3d6000fd5b505050506040513d602081101561192657600080fd5b5051604080516398508ecd60e01b81529051919250600091829182916001600160a01b038b16916398508ecd916004808301926060929190829003018186803b15801561197257600080fd5b505afa158015611986573d6000803e3d6000fd5b505050506040513d606081101561199c57600080fd5b5080516020820151604090920151909450909250905060008b60018111156119c057fe5b14156119fa576119ea6064610877868589603f60008a815260200190815260200160002054612460565b9950505050505050505050611a25565b6119ea610855606461087787868a603f60008b815260200190815260200160002054612460565b5060005b92915050565b611a33613980565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b611a9e613980565b6001600160a01b03811615611b3257603a546040805163095ea7b360e01b81526001600160a01b038481166004830152600060248301819052925193169263095ea7b392604480840193602093929083900390910190829087803b158015611b0557600080fd5b505af1158015611b19573d6000803e3d6000fd5b505050506040513d6020811015611b2f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b505050506040513d6020811015611bc957600080fd5b5050604080516001600160a01b038316815290517fcea2aea50ed8fa12062e9ad0a16093152af67e7c46a0d706227f8e722e2793ca9181900360200190a150565b6001546001600160a01b03163314611c535760405162461bcd60e51b81526004018080602001828103825260358152602001806140e16035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611cce613980565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff1615611d545760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b611d5d866115f0565b611dae576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000611dba878761320a565b9050600081118015611dcc5750808511155b611e15576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611e22888888610b14565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611e7257600080fd5b505afa158015611e86573d6000803e3d6000fd5b505050506040513d6020811015611e9c57600080fd5b50511015611ef1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015611f4157600080fd5b505afa158015611f55573d6000803e3d6000fd5b505050506040513d6020811015611f6b57600080fd5b50511015611fb0576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b611fc8670de0b6b3a76400008563ffffffff613d6116565b611fe48661087784670de0b6b3a764000063ffffffff6138bd16565b111561202b576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561208557600080fd5b505af1158015612099573d6000803e3d6000fd5b505050506040513d60208110156120af57600080fd5b50600090506120bf898989613dbb565b9050801561223157603a54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561211157600080fd5b505afa158015612125573d6000803e3d6000fd5b505050506040513d602081101561213b57600080fd5b50511015612190576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156121d657600080fd5b505af11580156121ea573d6000803e3d6000fd5b5050506001600160a01b038a1660009081526041602052604090205461221791508263ffffffff613d6116565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561226c57600080fd5b505afa158015612280573d6000803e3d6000fd5b505050506040513d604081101561229657600080fd5b50805160209091015190925090506000808b60018111156122b357fe5b146122be57816122c0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b15801561231357600080fd5b505af1158015612327573d6000803e3d6000fd5b505050506040513d602081101561233d57600080fd5b50506001600160a01b038c16600090815260416020526040902054851061237c576001600160a01b038c166000908152604160205260408120556123bf565b6001600160a01b038c166000908152604160205260409020546123a5908663ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b6000546001600160a01b031681565b60025481565b603a546001600160a01b031681565b6000806124a5633b9aca006108776124886124838861016d63ffffffff61391616565b613dee565b61249987606463ffffffff61391616565b9063ffffffff6138bd16565b9050858510156000816124d3576124ce876108778a670de0b6b3a764000063ffffffff6138bd16565b6124ef565b6124ef8861087789670de0b6b3a764000063ffffffff6138bd16565b603854604080516344f7787f60e01b81526004810184905260636024820152905192935060009261259192879261087792670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b15801561255957600080fd5b505afa15801561256d573d6000803e3d6000fd5b505050506040513d602081101561258357600080fd5b50519063ffffffff6138bd16565b905060006125cd6125b5610b6962989680610877866223588363ffffffff6138bd16565b610877670de0b6b3a76400008063ffffffff6138bd16565b905060006125f0670de0b6b3a7640000610877600281878063ffffffff6138bd16565b9050600061260b62989680610877623cdfaf61249986613e3f565b60385460408051632e4c697f60e01b815260048101879052674563918244f400006024820152905192935060009261267a92620f4240926108779262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d900000602482015290519293506000926126e992620f42409261087792621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c00006024820152905192935060009261275892620f42409261087792621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec80000602482015290519293506000926127c792620f42409261087792620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b905060006127e5629896806108778a6230bbd763ffffffff6138bd16565b9050600061281b8361280f8781866128038c8b63ffffffff613d6116565b9063ffffffff613d6116565b9063ffffffff61386016565b9050600061283e610855670de0b6b3a76400006108778b8663ffffffff6138bd16565b9050600061286f61285683606463ffffffff6138bd16565b61280f670de0b6b3a7640000606463ffffffff6138bd16565b90508d1561288d579e50610aaa9d5050505050505050505050505050565b6128aa8161280f670de0b6b3a7640000606463ffffffff6138bd16565b9f50505050505050505050505050505050949350505050565b6128cb613980565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156115b257600080fd5b60055462010000900460ff16806129b457506129b4613e68565b806129c75750600554610100900460ff16155b612a025760405162461bcd60e51b815260040180806020018281038252602e81526020018061418f602e913960400191505060405180910390fd5b60055462010000900460ff16158015612a32576005805461ff001962ff0000199091166201000017166101001790555b612a3b8961089b565b612a436131a7565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612aa7576005805462ff0000191690555b505050505050505050565b612aba613980565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b6000612b01848461320a565b821115612b1057506000610894565b610aaa8484846139cb565b6000612b26836115f0565b15611a21576000612b378484611813565b905067016345785d8a000081111580612b585750670c7d713b49da00008110155b15612b67576000915050611a25565b6000612ba2670de0b6b3a7640000610877612b95603e54670de0b6b3a764000061386090919063ffffffff16565b859063ffffffff6138bd16565b905060008111612bf9576040805162461bcd60e51b815260206004820152601a60248201527f646976206279207a65726f2073656c6c5f6d61785f7072696365000000000000604482015290519081900360640190fd5b600080866001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015612c3457600080fd5b505afa158015612c48573d6000803e3d6000fd5b505050506040513d6040811015612c5e57600080fd5b5080516020909101519092509050600080876001811115612c7b57fe5b14612cf757604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015612cc657600080fd5b505afa158015612cda573d6000803e3d6000fd5b505050506040513d6020811015612cf057600080fd5b5051612d6a565b604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015612d3d57600080fd5b505afa158015612d51573d6000803e3d6000fd5b505050506040513d6020811015612d6757600080fd5b50515b90506000612d8a670de0b6b3a7640000610877848863ffffffff6138bd16565b6001600160a01b038a16600090815260416020526040812054603c549293509091612dc491849161280f919082908863ffffffff613d6116565b9050612de683612803670de0b6b3a7640000612499858b63ffffffff61391616565b975050505050505050611a25565b612dfc613980565b6001600160a01b038116612e49576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612e9e576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b158015612f7657600080fd5b505afa158015612f8a573d6000803e3d6000fd5b505050506040513d6020811015612fa057600080fd5b5051801561301d57506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b158015612fe457600080fd5b505afa158015612ff8573d6000803e3d6000fd5b505050506040513d602081101561300e57600080fd5b5051600281111561301b57fe5b145b1561179357600080836001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561305d57600080fd5b505afa158015613071573d6000803e3d6000fd5b505050506040513d604081101561308757600080fd5b508051602091820151604080516370a0823160e01b815230600482015290519295509093506000926001600160a01b038616926370a08231926024808201939291829003018186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505111806131875750604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561315957600080fd5b505afa15801561316d573d6000803e3d6000fd5b505050506040513d602081101561318357600080fd5b5051115b1561319757600192505050611797565b5050506000919050565b60405481565b60055460ff16156131f5576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b6000613215836115f0565b15611a215760006132268484611813565b905067016345785d8a0000811115806132475750670c7d713b49da00008110155b15613256576000915050611a25565b60006132628585613e6e565b90506000613292670de0b6b3a7640000610877610883603e54670de0b6b3a7640000613d6190919063ffffffff16565b90506132b3670de0b6b3a7640000662386f26fc1000063ffffffff61386016565b811015806132c85750662386f26fc100008111155b156132d95760009350505050611a25565b60006132f3670de0b6b3a76400008363ffffffff61386016565b90506000613313670de0b6b3a7640000610877868663ffffffff6138bd16565b6001600160a01b038916600090815260416020526040902054603c5491925090613343908363ffffffff613d6116565b1161335657600095505050505050611a25565b6001600160a01b038816600090815260416020526040812054603c54613387919061280f908563ffffffff613d6116565b90506133b56133a8670de0b6b3a7640000612499848763ffffffff61391616565b869063ffffffff613d6116565b9650505050505050611a25565b603f6020526000908152604090205481565b6133dc613980565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61341f613980565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603c5481565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561349d57600080fd5b505afa1580156134b1573d6000803e3d6000fd5b505050506040513d60408110156134c757600080fd5b50805160209091015190925090506000808660018111156134e457fe5b1461356057604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561352f57600080fd5b505afa158015613543573d6000803e3d6000fd5b505050506040513d602081101561355957600080fd5b50516135d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156135a657600080fd5b505afa1580156135ba573d6000803e3d6000fd5b505050506040513d60208110156135d057600080fd5b50515b90506000808760018111156135e457fe5b1461366057604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d602081101561365957600080fd5b50516136d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156136a657600080fd5b505afa1580156136ba573d6000803e3d6000fd5b505050506040513d60208110156136d057600080fd5b50515b905060006136e7838863ffffffff613d6116565b90506000613705670de0b6b3a76400006108778a6124998e8e613feb565b90508282101561371f57603d549650505050505050610894565b600061372b8b8b611813565b9050600061373f848663ffffffff61386016565b90506000821161378e576040805162461bcd60e51b8152602060048201526015602482015274646976206279207a65726f2062617365507269636560581b604482015290519081900360640190fd5b60006137b183610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b905060008111613808576040805162461bcd60e51b815260206004820152601b60248201527f646976206279207a65726f206d6178506f737369626c65536b65770000000000604482015290519081900360640190fd5b613850613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b603d54603e546124999163ffffffff61386016565b603d549063ffffffff613d6116565b9950505050505050505050610894565b6000828211156138b7576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826138cc57506000611a25565b828202828482816138d957fe5b04146108945760405162461bcd60e51b815260040180806020018281038252602181526020018061416e6021913960400191505060405180910390fd5b600080821161396c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161397757fe5b04949350505050565b6000546001600160a01b031633146139c95760405162461bcd60e51b815260040180806020018281038252602f81526020018061413f602f913960400191505060405180910390fd5b565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613a0857600080fd5b505afa158015613a1c573d6000803e3d6000fd5b505050506040513d6040811015613a3257600080fd5b5080516020909101519092509050600080866001811115613a4f57fe5b14613acb57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613a9a57600080fd5b505afa158015613aae573d6000803e3d6000fd5b505050506040513d6020811015613ac457600080fd5b5051613b3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613b1157600080fd5b505afa158015613b25573d6000803e3d6000fd5b505050506040513d6020811015613b3b57600080fd5b50515b9050600080876001811115613b4f57fe5b14613bcb57604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b158015613b9a57600080fd5b505afa158015613bae573d6000803e3d6000fd5b505050506040513d6020811015613bc457600080fd5b5051613c3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613c1157600080fd5b505afa158015613c25573d6000803e3d6000fd5b505050506040513d6020811015613c3b57600080fd5b50515b90506000868311613c50576000613c60565b613c60838863ffffffff61386016565b90506000878411613c9057613c8b613c7e898663ffffffff61386016565b849063ffffffff613d6116565b613c92565b825b90506000613cb0670de0b6b3a76400006108778b6124998f8f614023565b9050818310613cca57603d54975050505050505050610894565b6000613cf18c828d6001811115613cdd57fe5b14613ce9576000613cec565b60015b611813565b90506000613d05848663ffffffff61386016565b90506000613d2a83610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b9050613d50613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b9a5050505050505050505050610894565b600082820183811015610894576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080613dc88585613e6e565b90506000915082811015613de657610890838263ffffffff61386016565b509392505050565b60006003821115613e31575080600160028204015b81811015613e2b57809150600281828581613e1a57fe5b040181613e2357fe5b049050613e03565b50611797565b811561179757506001919050565b6000613e4a82614051565b6ec097ce7bc90715b34b9f100000000081613e6157fe5b0492915050565b303b1590565b6000806000846001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613eab57600080fd5b505afa158015613ebf573d6000803e3d6000fd5b505050506040513d6040811015613ed557600080fd5b5080516020909101519092509050600080856001811115613ef257fe5b14613f6e57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613f3d57600080fd5b505afa158015613f51573d6000803e3d6000fd5b505050506040513d6020811015613f6757600080fd5b5051613fe1565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613fb457600080fd5b505afa158015613fc8573d6000803e3d6000fd5b505050506040513d6020811015613fde57600080fd5b50515b9695505050505050565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a764000061386090919063ffffffff16565b6124998787611813565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a7640000613d6190919063ffffffff16565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156140ad57600080fd5b505afa1580156140c1573d6000803e3d6000fd5b505050506040513d60208110156140d757600080fd5b5051939250505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a723158201983215b1d3a52f153b1a33e58e0d676fb473dad00152b998b94ce1ec637121964736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106102695760003560e01c806379ba509711610151578063c2783f92116100c3578063ebc7977211610087578063ebc797721461076a578063efc1525114610772578063f502b003146107a1578063f598df82146107be578063f85de9fa146107db578063fb91d41c146107f857610269565b8063c2783f92146106c1578063c3b83f5f146106f0578063c4dc27d714610716578063ca1d578e1461073c578063df8974d01461076257610269565b80639324cac7116101155780639324cac7146105bb578063a8cd06e8146105c3578063a996798c146105f2578063ad18f0da14610618578063bef648db1461066f578063bf46c0b41461068c57610269565b806379ba509714610545578063851702091461054d5780638875eb841461056a5780638da5cb5b146105ab57806391b4ded9146105b357610269565b806351b9181f116101ea5780636aaa81b6116101ae5780636aaa81b6146104b25780636cfa636e146104ba5780636ed033f8146104c2578063724e78da146104f1578063741bef1a1461051757806375cdc2281461051f57610269565b806351b9181f1461041f57806353a47bb7146104455780635727a0f31461044d5780635c975abb146104875780635ef85b261461048f57610269565b806321ef44c61161023157806321ef44c614610357578063270e13ef1461037d578063316425c3146103b25780633ce1108d146103ba578063481c6a75146103fb57610269565b80630f13aae81461026e57806313af4035146102b55780631627540c146102dd57806316c38b3c146103035780631c37d04b14610322575b600080fd5b6102a36004803603606081101561028457600080fd5b506001600160a01b038135169060ff6020820135169060400135610800565b60408051918252519081900360200190f35b6102db600480360360208110156102cb57600080fd5b50356001600160a01b031661089b565b005b6102db600480360360208110156102f357600080fd5b50356001600160a01b03166109ae565b6102db6004803603602081101561031957600080fd5b50351515610a0a565b6102a36004803603606081101561033857600080fd5b506001600160a01b038135169060ff6020820135169060400135610a84565b6102db6004803603602081101561036d57600080fd5b50356001600160a01b0316610ab2565b6102a36004803603606081101561039357600080fd5b506001600160a01b038135169060ff6020820135169060400135610b14565b6102a3610b7e565b6102db600480360360a08110156103d057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135610b84565b610403611396565b604080516001600160a01b039092168252519081900360200190f35b6102db6004803603602081101561043557600080fd5b50356001600160a01b03166113a5565b6104036115e1565b6104736004803603602081101561046357600080fd5b50356001600160a01b03166115f0565b604080519115158252519081900360200190f35b61047361179c565b6102db600480360360408110156104a557600080fd5b50803590602001356117a5565b6102a36117fe565b610403611804565b6102a3600480360360408110156104d857600080fd5b5080356001600160a01b0316906020013560ff16611813565b6102db6004803603602081101561050757600080fd5b50356001600160a01b0316611a2b565b610403611a87565b6102db6004803603602081101561053557600080fd5b50356001600160a01b0316611a96565b6102db611c0a565b6102db6004803603602081101561056357600080fd5b5035611cc6565b6102db600480360360a081101561058057600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611d07565b61040361243c565b6102a361244b565b610403612451565b6102a3600480360360808110156105d957600080fd5b5080359060208101359060408101359060600135612460565b6102db6004803603602081101561060857600080fd5b50356001600160a01b03166128c3565b6102db600480360361010081101561062f57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e0013561299a565b6102db6004803603602081101561068557600080fd5b5035612ab2565b6102a3600480360360608110156106a257600080fd5b506001600160a01b038135169060ff6020820135169060400135612af5565b6102a3600480360360408110156106d757600080fd5b5080356001600160a01b0316906020013560ff16612b1b565b6102db6004803603602081101561070657600080fd5b50356001600160a01b0316612df4565b6102a36004803603602081101561072c57600080fd5b50356001600160a01b0316612f13565b6104736004803603602081101561075257600080fd5b50356001600160a01b0316612f25565b6102a36131a1565b6102db6131a7565b6102a36004803603604081101561078857600080fd5b5080356001600160a01b0316906020013560ff1661320a565b6102a3600480360360208110156107b757600080fd5b50356133c2565b6102db600480360360208110156107d457600080fd5b50356133d4565b6102db600480360360208110156107f157600080fd5b5035613417565b6102a361345a565b600061080c8484612b1b565b82111561081b57506000610894565b60006108278585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a6108558c8c8c613460565b670de0b6b3a76400009063ffffffff61386016565b879063ffffffff6138bd16565b9063ffffffff61391616565b869063ffffffff6138bd16565b9150505b9392505050565b6001600160a01b0381166108f6576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff161561093f5760405162461bcd60e51b81526004018080602001828103825260298152602001806141166029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b6109b6613980565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610a12613980565b60035460ff1615158115151415610a2857610a81565b6003805460ff1916821515179081905560ff1615610a4557426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b6000610a908484612b1b565b821115610a9f57506000610894565b610aaa848484613460565b949350505050565b610aba613980565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b6000610b20848461320a565b821115610b2f57506000610894565b6000610b3b8585611813565b9050610890670de0b6b3a7640000610877610883670de0b6b3a764000061087761086a610b698c8c8c6139cb565b670de0b6b3a76400009063ffffffff613d6116565b603e5481565b600480546001019081905560035460ff1615610bd15760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b610bda866115f0565b610c2b576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000610c378787612b1b565b9050600081118015610c495750808511155b610c92576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000610c9f888888610800565b9050610cb9670de0b6b3a76400008563ffffffff613d6116565b610cd58261087788670de0b6b3a764000063ffffffff6138bd16565b1115610d1c576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015610d5757600080fd5b505afa158015610d6b573d6000803e3d6000fd5b505050506040513d6040811015610d8157600080fd5b50805160209091015190925090506000808a6001811115610d9e57fe5b14610da95781610dab565b825b604080516370a0823160e01b815233600482015290519192508a916001600160a01b038416916370a08231916024808301926020929190829003018186803b158015610df657600080fd5b505afa158015610e0a573d6000803e3d6000fd5b505050506040513d6020811015610e2057600080fd5b50511015610e75576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b158015610ec457600080fd5b505afa158015610ed8573d6000803e3d6000fd5b505050506040513d6020811015610eee57600080fd5b50511015610f33576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b604080516323b872dd60e01b8152336004820152306024820152604481018b905290516001600160a01b038316916323b872dd9160648083019260209291908290030181600087803b158015610f8857600080fd5b505af1158015610f9c573d6000803e3d6000fd5b505050506040513d6020811015610fb257600080fd5b5050604080516314edbee160e31b815230600482015290516000916001600160a01b038e169163a76df70891602480820192602092909190829003018186803b158015610ffe57600080fd5b505afa158015611012573d6000803e3d6000fd5b505050506040513d602081101561102857600080fd5b505190508015611086578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561106d57600080fd5b505af1158015611081573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156110d057600080fd5b505afa1580156110e4573d6000803e3d6000fd5b505050506040513d60208110156110fa57600080fd5b5051101561114f576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b1580156111a357600080fd5b505af11580156111b7573d6000803e3d6000fd5b505050506040513d60208110156111cd57600080fd5b50506001600160a01b038c166000908152604160205260409020546111f8908663ffffffff613d6116565b6001600160a01b038d1660009081526041602052604090208190558110611237576001600160a01b038c1660009081526041602052604081205561127a565b6001600160a01b038c16600090815260416020526040902054611260908263ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050600454811461138e576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6001816001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156113e057600080fd5b505afa1580156113f4573d6000803e3d6000fd5b505050506040513d602081101561140a57600080fd5b5051600281111561141757fe5b14611469576040805162461bcd60e51b815260206004820152601f60248201527f4d61726b6574206973206e6f7420696e204d6174757269747920706861736500604482015290519081900360640190fd5b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151919092169163e62b8889916024808301926020929190829003018186803b1580156114b657600080fd5b505afa1580156114ca573d6000803e3d6000fd5b505050506040513d60208110156114e057600080fd5b5051611524576040805162461bcd60e51b815260206004820152600e60248201526d155b9adb9bdddb881b585c9ad95d60921b604482015290519081900360640190fd5b61152d81612f25565b611577576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b1580156115b257600080fd5b505af11580156115c6573d6000803e3d6000fd5b505050506040513d60208110156115dc57600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561164157600080fd5b505afa158015611655573d6000803e3d6000fd5b505050506040513d602081101561166b57600080fd5b5051156117935760008290506000806000836001600160a01b03166398508ecd6040518163ffffffff1660e01b815260040160606040518083038186803b1580156116b557600080fd5b505afa1580156116c9573d6000803e3d6000fd5b505050506040513d60608110156116df57600080fd5b5080516020808301516040938401516000848152603f90935293909120549195509350909150611716576000945050505050611797565b600080856001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561175157600080fd5b505afa158015611765573d6000803e3d6000fd5b505050506040513d604081101561177b57600080fd5b50516040544290910311965061179795505050505050565b5060005b919050565b60035460ff1681565b6117ad613980565b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b600061181e836115f0565b15611a21576000839050600080826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b15801561186357600080fd5b505afa158015611877573d6000803e3d6000fd5b505050506040513d604081101561188d57600080fd5b508051602090910151909250905042820360006118bf6201518061087784670de0b6b3a764000063ffffffff6138bd16565b90506000856001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b1580156118fc57600080fd5b505afa158015611910573d6000803e3d6000fd5b505050506040513d602081101561192657600080fd5b5051604080516398508ecd60e01b81529051919250600091829182916001600160a01b038b16916398508ecd916004808301926060929190829003018186803b15801561197257600080fd5b505afa158015611986573d6000803e3d6000fd5b505050506040513d606081101561199c57600080fd5b5080516020820151604090920151909450909250905060008b60018111156119c057fe5b14156119fa576119ea6064610877868589603f60008a815260200190815260200160002054612460565b9950505050505050505050611a25565b6119ea610855606461087787868a603f60008b815260200190815260200160002054612460565b5060005b92915050565b611a33613980565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b611a9e613980565b6001600160a01b03811615611b3257603a546040805163095ea7b360e01b81526001600160a01b038481166004830152600060248301819052925193169263095ea7b392604480840193602093929083900390910190829087803b158015611b0557600080fd5b505af1158015611b19573d6000803e3d6000fd5b505050506040513d6020811015611b2f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015611b9f57600080fd5b505af1158015611bb3573d6000803e3d6000fd5b505050506040513d6020811015611bc957600080fd5b5050604080516001600160a01b038316815290517fcea2aea50ed8fa12062e9ad0a16093152af67e7c46a0d706227f8e722e2793ca9181900360200190a150565b6001546001600160a01b03163314611c535760405162461bcd60e51b81526004018080602001828103825260358152602001806140e16035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b611cce613980565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff1615611d545760405162461bcd60e51b815260040180806020018281038252603c8152602001806141bd603c913960400191505060405180910390fd5b611d5d866115f0565b611dae576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000611dba878761320a565b9050600081118015611dcc5750808511155b611e15576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611e22888888610b14565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015611e7257600080fd5b505afa158015611e86573d6000803e3d6000fd5b505050506040513d6020811015611e9c57600080fd5b50511015611ef1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015611f4157600080fd5b505afa158015611f55573d6000803e3d6000fd5b505050506040513d6020811015611f6b57600080fd5b50511015611fb0576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b611fc8670de0b6b3a76400008563ffffffff613d6116565b611fe48661087784670de0b6b3a764000063ffffffff6138bd16565b111561202b576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54604080516323b872dd60e01b81523360048201523060248201526044810184905290516001600160a01b03909216916323b872dd916064808201926020929091908290030181600087803b15801561208557600080fd5b505af1158015612099573d6000803e3d6000fd5b505050506040513d60208110156120af57600080fd5b50600090506120bf898989613dbb565b9050801561223157603a54604080516370a0823160e01b8152306004820152905183926001600160a01b0316916370a08231916024808301926020929190829003018186803b15801561211157600080fd5b505afa158015612125573d6000803e3d6000fd5b505050506040513d602081101561213b57600080fd5b50511015612190576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156121d657600080fd5b505af11580156121ea573d6000803e3d6000fd5b5050506001600160a01b038a1660009081526041602052604090205461221791508263ffffffff613d6116565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561226c57600080fd5b505afa158015612280573d6000803e3d6000fd5b505050506040513d604081101561229657600080fd5b50805160209091015190925090506000808b60018111156122b357fe5b146122be57816122c0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b15801561231357600080fd5b505af1158015612327573d6000803e3d6000fd5b505050506040513d602081101561233d57600080fd5b50506001600160a01b038c16600090815260416020526040902054851061237c576001600160a01b038c166000908152604160205260408120556123bf565b6001600160a01b038c166000908152604160205260409020546123a5908663ffffffff61386016565b6001600160a01b038d166000908152604160205260409020555b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156112f757fe5b6000546001600160a01b031681565b60025481565b603a546001600160a01b031681565b6000806124a5633b9aca006108776124886124838861016d63ffffffff61391616565b613dee565b61249987606463ffffffff61391616565b9063ffffffff6138bd16565b9050858510156000816124d3576124ce876108778a670de0b6b3a764000063ffffffff6138bd16565b6124ef565b6124ef8861087789670de0b6b3a764000063ffffffff6138bd16565b603854604080516344f7787f60e01b81526004810184905260636024820152905192935060009261259192879261087792670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b15801561255957600080fd5b505afa15801561256d573d6000803e3d6000fd5b505050506040513d602081101561258357600080fd5b50519063ffffffff6138bd16565b905060006125cd6125b5610b6962989680610877866223588363ffffffff6138bd16565b610877670de0b6b3a76400008063ffffffff6138bd16565b905060006125f0670de0b6b3a7640000610877600281878063ffffffff6138bd16565b9050600061260b62989680610877623cdfaf61249986613e3f565b60385460408051632e4c697f60e01b815260048101879052674563918244f400006024820152905192935060009261267a92620f4240926108779262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d900000602482015290519293506000926126e992620f42409261087792621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c00006024820152905192935060009261275892620f42409261087792621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec80000602482015290519293506000926127c792620f42409261087792620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b15801561255957600080fd5b905060006127e5629896806108778a6230bbd763ffffffff6138bd16565b9050600061281b8361280f8781866128038c8b63ffffffff613d6116565b9063ffffffff613d6116565b9063ffffffff61386016565b9050600061283e610855670de0b6b3a76400006108778b8663ffffffff6138bd16565b9050600061286f61285683606463ffffffff6138bd16565b61280f670de0b6b3a7640000606463ffffffff6138bd16565b90508d1561288d579e50610aaa9d5050505050505050505050505050565b6128aa8161280f670de0b6b3a7640000606463ffffffff6138bd16565b9f50505050505050505050505050505050949350505050565b6128cb613980565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561291f57600080fd5b505afa158015612933573d6000803e3d6000fd5b505050506040513d602081101561294957600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b1580156115b257600080fd5b60055462010000900460ff16806129b457506129b4613e68565b806129c75750600554610100900460ff16155b612a025760405162461bcd60e51b815260040180806020018281038252602e81526020018061418f602e913960400191505060405180910390fd5b60055462010000900460ff16158015612a32576005805461ff001962ff0000199091166201000017166101001790555b612a3b8961089b565b612a436131a7565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612aa7576005805462ff0000191690555b505050505050505050565b612aba613980565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b6000612b01848461320a565b821115612b1057506000610894565b610aaa8484846139cb565b6000612b26836115f0565b15611a21576000612b378484611813565b905067016345785d8a000081111580612b585750670c7d713b49da00008110155b15612b67576000915050611a25565b6000612ba2670de0b6b3a7640000610877612b95603e54670de0b6b3a764000061386090919063ffffffff16565b859063ffffffff6138bd16565b905060008111612bf9576040805162461bcd60e51b815260206004820152601a60248201527f646976206279207a65726f2073656c6c5f6d61785f7072696365000000000000604482015290519081900360640190fd5b600080866001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015612c3457600080fd5b505afa158015612c48573d6000803e3d6000fd5b505050506040513d6040811015612c5e57600080fd5b5080516020909101519092509050600080876001811115612c7b57fe5b14612cf757604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015612cc657600080fd5b505afa158015612cda573d6000803e3d6000fd5b505050506040513d6020811015612cf057600080fd5b5051612d6a565b604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015612d3d57600080fd5b505afa158015612d51573d6000803e3d6000fd5b505050506040513d6020811015612d6757600080fd5b50515b90506000612d8a670de0b6b3a7640000610877848863ffffffff6138bd16565b6001600160a01b038a16600090815260416020526040812054603c549293509091612dc491849161280f919082908863ffffffff613d6116565b9050612de683612803670de0b6b3a7640000612499858b63ffffffff61391616565b975050505050505050611a25565b612dfc613980565b6001600160a01b038116612e49576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612e9e576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b158015612f7657600080fd5b505afa158015612f8a573d6000803e3d6000fd5b505050506040513d6020811015612fa057600080fd5b5051801561301d57506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b158015612fe457600080fd5b505afa158015612ff8573d6000803e3d6000fd5b505050506040513d602081101561300e57600080fd5b5051600281111561301b57fe5b145b1561179357600080836001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561305d57600080fd5b505afa158015613071573d6000803e3d6000fd5b505050506040513d604081101561308757600080fd5b508051602091820151604080516370a0823160e01b815230600482015290519295509093506000926001600160a01b038616926370a08231926024808201939291829003018186803b1580156130dc57600080fd5b505afa1580156130f0573d6000803e3d6000fd5b505050506040513d602081101561310657600080fd5b505111806131875750604080516370a0823160e01b815230600482015290516000916001600160a01b038416916370a0823191602480820192602092909190829003018186803b15801561315957600080fd5b505afa15801561316d573d6000803e3d6000fd5b505050506040513d602081101561318357600080fd5b5051115b1561319757600192505050611797565b5050506000919050565b60405481565b60055460ff16156131f5576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b6000613215836115f0565b15611a215760006132268484611813565b905067016345785d8a0000811115806132475750670c7d713b49da00008110155b15613256576000915050611a25565b60006132628585613e6e565b90506000613292670de0b6b3a7640000610877610883603e54670de0b6b3a7640000613d6190919063ffffffff16565b90506132b3670de0b6b3a7640000662386f26fc1000063ffffffff61386016565b811015806132c85750662386f26fc100008111155b156132d95760009350505050611a25565b60006132f3670de0b6b3a76400008363ffffffff61386016565b90506000613313670de0b6b3a7640000610877868663ffffffff6138bd16565b6001600160a01b038916600090815260416020526040902054603c5491925090613343908363ffffffff613d6116565b1161335657600095505050505050611a25565b6001600160a01b038816600090815260416020526040812054603c54613387919061280f908563ffffffff613d6116565b90506133b56133a8670de0b6b3a7640000612499848763ffffffff61391616565b869063ffffffff613d6116565b9650505050505050611a25565b603f6020526000908152604090205481565b6133dc613980565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61341f613980565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603c5481565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b15801561349d57600080fd5b505afa1580156134b1573d6000803e3d6000fd5b505050506040513d60408110156134c757600080fd5b50805160209091015190925090506000808660018111156134e457fe5b1461356057604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b15801561352f57600080fd5b505afa158015613543573d6000803e3d6000fd5b505050506040513d602081101561355957600080fd5b50516135d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156135a657600080fd5b505afa1580156135ba573d6000803e3d6000fd5b505050506040513d60208110156135d057600080fd5b50515b90506000808760018111156135e457fe5b1461366057604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b15801561362f57600080fd5b505afa158015613643573d6000803e3d6000fd5b505050506040513d602081101561365957600080fd5b50516136d3565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b1580156136a657600080fd5b505afa1580156136ba573d6000803e3d6000fd5b505050506040513d60208110156136d057600080fd5b50515b905060006136e7838863ffffffff613d6116565b90506000613705670de0b6b3a76400006108778a6124998e8e613feb565b90508282101561371f57603d549650505050505050610894565b600061372b8b8b611813565b9050600061373f848663ffffffff61386016565b90506000821161378e576040805162461bcd60e51b8152602060048201526015602482015274646976206279207a65726f2062617365507269636560581b604482015290519081900360640190fd5b60006137b183610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b905060008111613808576040805162461bcd60e51b815260206004820152601b60248201527f646976206279207a65726f206d6178506f737369626c65536b65770000000000604482015290519081900360640190fd5b613850613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b603d54603e546124999163ffffffff61386016565b603d549063ffffffff613d6116565b9950505050505050505050610894565b6000828211156138b7576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b6000826138cc57506000611a25565b828202828482816138d957fe5b04146108945760405162461bcd60e51b815260040180806020018281038252602181526020018061416e6021913960400191505060405180910390fd5b600080821161396c576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161397757fe5b04949350505050565b6000546001600160a01b031633146139c95760405162461bcd60e51b815260040180806020018281038252602f81526020018061413f602f913960400191505060405180910390fd5b565b6000806000856001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613a0857600080fd5b505afa158015613a1c573d6000803e3d6000fd5b505050506040513d6040811015613a3257600080fd5b5080516020909101519092509050600080866001811115613a4f57fe5b14613acb57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613a9a57600080fd5b505afa158015613aae573d6000803e3d6000fd5b505050506040513d6020811015613ac457600080fd5b5051613b3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613b1157600080fd5b505afa158015613b25573d6000803e3d6000fd5b505050506040513d6020811015613b3b57600080fd5b50515b9050600080876001811115613b4f57fe5b14613bcb57604080516370a0823160e01b815230600482015290516001600160a01b038616916370a08231916024808301926020929190829003018186803b158015613b9a57600080fd5b505afa158015613bae573d6000803e3d6000fd5b505050506040513d6020811015613bc457600080fd5b5051613c3e565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613c1157600080fd5b505afa158015613c25573d6000803e3d6000fd5b505050506040513d6020811015613c3b57600080fd5b50515b90506000868311613c50576000613c60565b613c60838863ffffffff61386016565b90506000878411613c9057613c8b613c7e898663ffffffff61386016565b849063ffffffff613d6116565b613c92565b825b90506000613cb0670de0b6b3a76400006108778b6124998f8f614023565b9050818310613cca57603d54975050505050505050610894565b6000613cf18c828d6001811115613cdd57fe5b14613ce9576000613cec565b60015b611813565b90506000613d05848663ffffffff61386016565b90506000613d2a83610877670de0b6b3a7640000603c546138bd90919063ffffffff16565b9050613d50613841670de0b6b3a764000061087761382c8582888563ffffffff6138bd16565b9a5050505050505050505050610894565b600082820183811015610894576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600080613dc88585613e6e565b90506000915082811015613de657610890838263ffffffff61386016565b509392505050565b60006003821115613e31575080600160028204015b81811015613e2b57809150600281828581613e1a57fe5b040181613e2357fe5b049050613e03565b50611797565b811561179757506001919050565b6000613e4a82614051565b6ec097ce7bc90715b34b9f100000000081613e6157fe5b0492915050565b303b1590565b6000806000846001600160a01b0316631069143a6040518163ffffffff1660e01b8152600401604080518083038186803b158015613eab57600080fd5b505afa158015613ebf573d6000803e3d6000fd5b505050506040513d6040811015613ed557600080fd5b5080516020909101519092509050600080856001811115613ef257fe5b14613f6e57604080516370a0823160e01b815230600482015290516001600160a01b038416916370a08231916024808301926020929190829003018186803b158015613f3d57600080fd5b505afa158015613f51573d6000803e3d6000fd5b505050506040513d6020811015613f6757600080fd5b5051613fe1565b604080516370a0823160e01b815230600482015290516001600160a01b038516916370a08231916024808301926020929190829003018186803b158015613fb457600080fd5b505afa158015613fc8573d6000803e3d6000fd5b505050506040513d6020811015613fde57600080fd5b50515b9695505050505050565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a764000061386090919063ffffffff16565b6124998787611813565b6000610894670de0b6b3a7640000610877614019603d54670de0b6b3a7640000613d6190919063ffffffff16565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156140ad57600080fd5b505afa1580156140c1573d6000803e3d6000fd5b505050506040513d60208110156140d757600080fd5b5051939250505056fe596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e747261637420697320706175736564a265627a7a723158201983215b1d3a52f153b1a33e58e0d676fb473dad00152b998b94ce1ec637121964736f6c63430005100032
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.