Contract Overview
Balance:
0 ETH
EtherValue:
$0.00
My Name Tag:
Not Available, login to update
Txn Hash | Method |
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0xfbb671d41a3c15fb09d47cd549b0c7431327462dffaa10a202191007c03c8c29 | 0x60806040 | 10834746 | 660 days 3 hrs ago | Thales: Deployer | IN | Create: ThalesAMM | 0 ETH | 0.008227057344 |
[ Download CSV Export ]
View more zero value Internal Transactions in Advanced View mode
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)
// SPDX-License-Identifier: MIT pragma solidity ^0.5.16; import "openzeppelin-solidity-2.3.0/contracts/token/ERC20/SafeERC20.sol"; import "openzeppelin-solidity-2.3.0/contracts/math/SafeMath.sol"; import "openzeppelin-solidity-2.3.0/contracts/math/Math.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/IPositionalMarket.sol"; import "../interfaces/IPositionalMarketManager.sol"; import "../interfaces/IPosition.sol"; import "../interfaces/IStakingThales.sol"; import "../interfaces/IReferrals.sol"; import "./DeciMath.sol"; contract ThalesAMM is ProxyOwned, ProxyPausable, ProxyReentrancyGuard, Initializable { using SafeMath for uint; using SafeERC20 for IERC20; DeciMath public deciMath; uint private constant ONE = 1e18; uint private constant ONE_PERCENT = 1e16; 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; enum Position {Up, Down} mapping(address => uint) public spentOnMarket; address public safeBox; uint public safeBoxImpact; IStakingThales public stakingThales; uint public minSupportedPrice; uint public maxSupportedPrice; mapping(bytes32 => uint) private _capPerAsset; mapping(address => bool) public whitelistedAddresses; address public referrals; uint public referrerFee; address public previousManager; 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).add(min_spread); // ignore extremes return _availableToBuyFromAMMWithBasePrice(market, position, basePrice); } else { return 0; } } function _availableToBuyFromAMMWithBasePrice( address market, Position position, uint basePrice ) internal view returns (uint) { // ignore extremes if (basePrice <= minSupportedPrice || basePrice >= maxSupportedPrice) { return 0; } uint balance = _balanceOfPositionOnMarket(market, position); uint midImpactPriceIncrease = ONE.sub(basePrice).mul(max_spread.div(2)).div(ONE); uint divider_price = ONE.sub(basePrice.add(midImpactPriceIncrease)); uint additionalBufferFromSelling = balance.mul(basePrice).div(ONE); if (_capOnMarket(market).add(additionalBufferFromSelling) <= spentOnMarket[market]) { return 0; } uint availableUntilCapSUSD = _capOnMarket(market).add(additionalBufferFromSelling).sub(spentOnMarket[market]); return balance.add(availableUntilCapSUSD.mul(ONE).div(divider_price)); } function buyFromAmmQuote( address market, Position position, uint amount ) public view returns (uint) { uint basePrice = price(market, position).add(min_spread); return _buyFromAmmQuoteWithBasePrice(market, position, amount, basePrice); } function _buyFromAmmQuoteWithBasePrice( address market, Position position, uint amount, uint basePrice ) internal view returns (uint) { if (amount < 1 || amount > _availableToBuyFromAMMWithBasePrice(market, position, basePrice)) { return 0; } uint impactPriceIncrease = ONE.sub(basePrice).mul(_buyPriceImpact(market, position, amount)).div(ONE); // add 2% to the price increase to avoid edge cases on the extremes impactPriceIncrease = impactPriceIncrease.mul(ONE.add(ONE_PERCENT * 2)).div(ONE); uint tempAmount = amount.mul(basePrice.add(impactPriceIncrease)).div(ONE); uint returnQuote = tempAmount.mul(ONE.add(safeBoxImpact)).div(ONE); return IPositionalMarketManager(manager).transformCollateral(returnQuote); } function buyPriceImpact( address market, Position position, uint amount ) public view returns (uint) { if (amount < 1 || 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 sell_max_price = _getSellMaxPrice(market, position); if (sell_max_price == 0) { return 0; } (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); uint balanceOfTheOtherSide = position == Position.Up ? down.getBalanceOf(address(this)) : up.getBalanceOf(address(this)); // can burn straight away balanceOfTheOtherSide uint willPay = balanceOfTheOtherSide.mul(sell_max_price).div(ONE); if (_capOnMarket(market).add(balanceOfTheOtherSide) < spentOnMarket[market].add(willPay)) { return 0; } uint usdAvailable = _capOnMarket(market).add(balanceOfTheOtherSide).sub(spentOnMarket[market]).sub(willPay); return usdAvailable.div(sell_max_price).mul(ONE).add(balanceOfTheOtherSide); } else return 0; } function _getSellMaxPrice(address market, Position position) internal view returns (uint) { uint basePrice = price(market, position); // ignore extremes if (basePrice <= minSupportedPrice || basePrice >= maxSupportedPrice) { return 0; } uint sell_max_price = basePrice.sub(min_spread).mul(ONE.sub(max_spread.div(2))).div(ONE); return sell_max_price; } function sellToAmmQuote( address market, Position position, uint amount ) public view returns (uint) { if (amount > availableToSellToAMM(market, position)) { return 0; } uint basePrice = price(market, position).sub(min_spread); uint tempAmount = amount.mul(basePrice.mul(ONE.sub(_sellPriceImpact(market, position, amount))).div(ONE)).div(ONE); uint returnQuote = tempAmount.mul(ONE.sub(safeBoxImpact)).div(ONE); return IPositionalMarketManager(manager).transformCollateral(returnQuote); } 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 IPositionalMarket marketContract = IPositionalMarket(market); (uint maturity, ) = marketContract.times(); uint timeLeftToMaturity = maturity - block.timestamp; uint timeLeftToMaturityInDays = timeLeftToMaturity.mul(ONE).div(86400); uint oraclePrice = marketContract.oraclePrice(); (bytes32 key, uint strikePrice, ) = marketContract.getOracleDetails(); if (position == Position.Up) { 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 (IPositionalMarketManager(manager).isActiveMarket(market)) { IPositionalMarket marketContract = IPositionalMarket(market); (bytes32 key, , ) = marketContract.getOracleDetails(); //check if asset is supported if (impliedVolatilityPerAsset[key] == 0) { return false; } // add price calculation (uint maturity, ) = marketContract.times(); if (maturity < block.timestamp) { return false; } uint timeLeftToMaturity = maturity - block.timestamp; return timeLeftToMaturity > minimalTimeLeftToMaturity; } else { return false; } } function canExerciseMaturedMarket(address market) public view returns (bool) { if ( IPositionalMarketManager(manager).isKnownMarket(market) && (IPositionalMarket(market).phase() == IPositionalMarket.Phase.Maturity) ) { (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); if ((up.getBalanceOf(address(this)) > 0) || (down.getBalanceOf(address(this)) > 0)) { return true; } } return false; } function getCapPerAsset(bytes32 asset) public view returns (uint) { if (priceFeed.rateForCurrency(asset) == 0) { return 0; } if (_capPerAsset[asset] == 0) { return capPerMarket; } return _capPerAsset[asset]; } // write methods function buyFromAMMWithReferrer( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage, address _referrer ) public nonReentrant notPaused { IReferrals(referrals).setReferrer(_referrer, msg.sender); _buyFromAMM(market, position, amount, expectedPayout, additionalSlippage); } function buyFromAMM( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage ) public nonReentrant notPaused { _buyFromAMM(market, position, amount, expectedPayout, additionalSlippage); } function _buyFromAMM( address market, Position position, uint amount, uint expectedPayout, uint additionalSlippage ) internal { require(isMarketInAMMTrading(market), "Market is not in Trading phase"); uint basePrice = price(market, position).add(min_spread); uint availableToBuyFromAMMatm = _availableToBuyFromAMMWithBasePrice(market, position, basePrice); require(amount <= availableToBuyFromAMMatm, "Not enough liquidity."); uint sUSDPaid = _buyFromAmmQuoteWithBasePrice(market, position, amount, basePrice); 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.safeTransferFrom(msg.sender, address(this), sUSDPaid); uint toMint = _getMintableAmount(market, position, amount); if (toMint > 0) { require( sUSD.balanceOf(address(this)) >= IPositionalMarketManager(manager).transformCollateral(toMint), "Not enough sUSD in contract." ); IPositionalMarket(market).mint(toMint); spentOnMarket[market] = spentOnMarket[market].add(toMint); } (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); IPosition target = position == Position.Up ? up : down; IERC20(address(target)).transfer(msg.sender, amount); if (address(stakingThales) != address(0)) { stakingThales.updateVolume(msg.sender, sUSDPaid); } _updateSpentOnOnMarketOnBuy(market, sUSDPaid, msg.sender); 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"); (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); IPosition target = position == Position.Up ? up : down; require(target.getBalanceOf(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)).safeTransferFrom(msg.sender, address(this), amount); uint sUSDFromBurning = IPositionalMarketManager(manager).transformCollateral( IPositionalMarket(market).getMaximumBurnable(address(this)) ); if (sUSDFromBurning > 0) { IPositionalMarket(market).burnOptionsMaximum(); } require(sUSD.balanceOf(address(this)) >= pricePaid, "Not enough sUSD in contract."); sUSD.transfer(msg.sender, pricePaid); if (address(stakingThales) != address(0)) { stakingThales.updateVolume(msg.sender, pricePaid); } _updateSpentOnMarketOnSell(market, pricePaid, sUSDFromBurning, msg.sender); emit SoldToAMM(msg.sender, market, position, amount, pricePaid, address(sUSD), address(target)); } function exerciseMaturedMarket(address market) external { require(canExerciseMaturedMarket(market), "No options to exercise"); IPositionalMarket(market).exerciseOptions(); } // setters function setMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity) external onlyOwner { minimalTimeLeftToMaturity = _minimalTimeLeftToMaturity; emit SetMinimalTimeLeftToMaturity(_minimalTimeLeftToMaturity); } function setMinSpread(uint _spread) external onlyOwner { min_spread = _spread; emit SetMinSpread(_spread); } function setSafeBoxImpact(uint _safeBoxImpact) external onlyOwner { safeBoxImpact = _safeBoxImpact; emit SetSafeBoxImpact(_safeBoxImpact); } function setSafeBox(address _safeBox) external onlyOwner { safeBox = _safeBox; emit SetSafeBox(_safeBox); } function setMaxSpread(uint _spread) external onlyOwner { max_spread = _spread; emit SetMaxSpread(_spread); } function setMinSupportedPrice(uint _minSupportedPrice) external onlyOwner { minSupportedPrice = _minSupportedPrice; emit SetMinSupportedPrice(_minSupportedPrice); } function setMaxSupportedPrice(uint _maxSupportedPrice) external onlyOwner { maxSupportedPrice = _maxSupportedPrice; emit SetMaxSupportedPrice(_maxSupportedPrice); } function setImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility) external { require( whitelistedAddresses[msg.sender] || owner == msg.sender, "Only whitelisted addresses or owner can change IV!" ); require(_impliedVolatility > ONE.mul(60) && _impliedVolatility < ONE.mul(300), "IV outside min/max range!"); require(priceFeed.rateForCurrency(asset) != 0, "Asset has no price!"); impliedVolatilityPerAsset[asset] = _impliedVolatility; emit SetImpliedVolatilityPerAsset(asset, _impliedVolatility); } function setCapPerMarket(uint _capPerMarket) external onlyOwner { capPerMarket = _capPerMarket; emit SetCapPerMarket(_capPerMarket); } function setPriceFeed(IPriceFeed _priceFeed) external onlyOwner { priceFeed = _priceFeed; emit SetPriceFeed(address(_priceFeed)); } function setSUSD(IERC20 _sUSD) external onlyOwner { sUSD = _sUSD; emit SetSUSD(address(sUSD)); } function setStakingThales(IStakingThales _stakingThales) external onlyOwner { stakingThales = _stakingThales; emit SetStakingThales(address(_stakingThales)); } function setReferrals(address _referrals, uint _referrerFee) external onlyOwner { referrals = _referrals; referrerFee = _referrerFee; } function setPositionalMarketManager(address _manager) external onlyOwner { if (address(manager) != address(0)) { sUSD.approve(address(manager), 0); } manager = _manager; sUSD.approve(manager, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); emit SetPositionalMarketManager(_manager); } function setCapPerAsset(bytes32 asset, uint _cap) external onlyOwner { _capPerAsset[asset] = _cap; emit SetCapPerAsset(asset, _cap); } // Internal function _updateSpentOnMarketOnSell( address market, uint sUSDPaid, uint sUSDFromBurning, address seller ) internal { uint safeBoxShare = sUSDPaid.mul(ONE).div(ONE.sub(safeBoxImpact)).sub(sUSDPaid); if (safeBoxImpact > 0) { sUSD.transfer(safeBox, safeBoxShare); } else { safeBoxShare = 0; } spentOnMarket[market] = spentOnMarket[market].add( IPositionalMarketManager(manager).reverseTransformCollateral(sUSDPaid.add(safeBoxShare)) ); if (spentOnMarket[market] <= IPositionalMarketManager(manager).reverseTransformCollateral(sUSDFromBurning)) { spentOnMarket[market] = 0; } else { spentOnMarket[market] = spentOnMarket[market].sub( IPositionalMarketManager(manager).reverseTransformCollateral(sUSDFromBurning) ); } if (referrerFee > 0 && referrals != address(0)) { uint referrerShare = sUSDPaid.mul(ONE).div(ONE.sub(referrerFee)).sub(sUSDPaid); _handleReferrer(seller, referrerShare, sUSDPaid); } } function _updateSpentOnOnMarketOnBuy( address market, uint sUSDPaid, address buyer ) internal { uint safeBoxShare = sUSDPaid.sub(sUSDPaid.mul(ONE).div(ONE.add(safeBoxImpact))); if (safeBoxImpact > 0) { sUSD.transfer(safeBox, safeBoxShare); } else { safeBoxShare = 0; } if ( spentOnMarket[market] <= IPositionalMarketManager(manager).reverseTransformCollateral(sUSDPaid.sub(safeBoxShare)) ) { spentOnMarket[market] = 0; } else { spentOnMarket[market] = spentOnMarket[market].sub( IPositionalMarketManager(manager).reverseTransformCollateral(sUSDPaid.sub(safeBoxShare)) ); } if (referrerFee > 0 && referrals != address(0)) { uint referrerShare = sUSDPaid.sub(sUSDPaid.mul(ONE).div(ONE.add(referrerFee))); _handleReferrer(buyer, referrerShare, sUSDPaid); } } function _buyPriceImpact( address market, Position position, uint amount ) internal view returns (uint) { (uint balancePosition, uint balanceOtherSide) = _balanceOfPositionsOnMarket(market, position); uint balancePositionAfter = balancePosition > amount ? balancePosition.sub(amount) : 0; uint balanceOtherSideAfter = balancePosition > amount ? balanceOtherSide : balanceOtherSide.add(amount.sub(balancePosition)); if (balancePositionAfter >= balanceOtherSideAfter) { //minimal price impact as it will balance the AMM exposure return 0; } else { return _buyPriceImpactElse( market, position, amount, balanceOtherSide, balancePosition, balanceOtherSideAfter, balancePositionAfter ); } } function _buyPriceImpactElse( address market, Position position, uint amount, uint balanceOtherSide, uint balancePosition, uint balanceOtherSideAfter, uint balancePositionAfter ) internal view returns (uint) { uint maxPossibleSkew = balanceOtherSide.add(availableToBuyFromAMM(market, position)).sub(balancePosition); uint skew = balanceOtherSideAfter.sub(balancePositionAfter); uint newImpact = max_spread.mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE); if (balancePosition > 0) { uint newPriceForMintedOnes = newImpact.div(2); uint tempMultiplier = amount.sub(balancePosition).mul(newPriceForMintedOnes); return tempMultiplier.div(amount); } else { uint previousSkew = balanceOtherSide; uint previousImpact = max_spread.mul(previousSkew.mul(ONE).div(maxPossibleSkew)).div(ONE); return newImpact.add(previousImpact).div(2); } } function _handleReferrer( address buyer, uint referrerShare, uint volume ) internal { address referrer = IReferrals(referrals).referrals(buyer); if (referrer != address(0)) { if (referrerFee > 0) { sUSD.transfer(referrer, referrerShare); emit ReferrerPaid(referrer, buyer, referrerShare, volume); } } } function balancePosition(address market, Position position) public view returns (uint) { (uint _balancePosition, ) = _balanceOfPositionsOnMarket(market, position); return _balancePosition; } function _sellPriceImpact( address market, Position position, uint amount ) internal view returns (uint) { (uint _balancePosition, uint balanceOtherSide) = _balanceOfPositionsOnMarket(market, position); uint balancePositionAfter = _balancePosition > 0 ? _balancePosition.add(amount) : balanceOtherSide > amount ? 0 : amount.sub(balanceOtherSide); uint balanceOtherSideAfter = balanceOtherSide > amount ? balanceOtherSide.sub(amount) : 0; if (balancePositionAfter < balanceOtherSideAfter) { //minimal price impact as it will balance the AMM exposure return 0; } else { return _sellPriceImpactElse( market, position, amount, balanceOtherSide, _balancePosition, balanceOtherSideAfter, balancePositionAfter ); } } function _sellPriceImpactElse( address market, Position position, uint amount, uint balanceOtherSide, uint _balancePosition, uint balanceOtherSideAfter, uint balancePositionAfter ) internal view returns (uint) { uint maxPossibleSkew = _balancePosition.add(availableToSellToAMM(market, position)).sub(balanceOtherSide); uint skew = balancePositionAfter.sub(balanceOtherSideAfter); uint newImpact = max_spread.mul(skew.mul(ONE).div(maxPossibleSkew)).div(ONE); if (balanceOtherSide > 0) { uint newPriceForMintedOnes = newImpact.div(2); uint tempMultiplier = amount.sub(_balancePosition).mul(newPriceForMintedOnes); return tempMultiplier.div(amount); } else { uint previousSkew = _balancePosition; uint previousImpact = max_spread.mul(previousSkew.mul(ONE).div(maxPossibleSkew)).div(ONE); return newImpact.add(previousImpact).div(2); } } 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 _balanceOfPositionOnMarket(address market, Position position) internal view returns (uint) { (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); uint balance = position == Position.Up ? up.getBalanceOf(address(this)) : down.getBalanceOf(address(this)); return balance; } function _balanceOfPositionsOnMarket(address market, Position position) internal view returns (uint, uint) { (IPosition up, IPosition down) = IPositionalMarket(market).getOptions(); uint balance = position == Position.Up ? up.getBalanceOf(address(this)) : down.getBalanceOf(address(this)); uint balanceOtherSide = position == Position.Up ? down.getBalanceOf(address(this)) : up.getBalanceOf(address(this)); return (balance, balanceOtherSide); } function _capOnMarket(address market) internal view returns (uint) { (bytes32 key, , ) = IPositionalMarket(market).getOracleDetails(); return getCapPerAsset(key); } 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))); } function retrieveSUSDAmount(address payable account, uint amount) external onlyOwner { sUSD.transfer(account, amount); } function setWhitelistedAddress(address _address, bool enabled) external onlyOwner { whitelistedAddresses[_address] = enabled; } // 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 SetPositionalMarketManager(address _manager); event SetSUSD(address sUSD); event SetPriceFeed(address _priceFeed); event SetCapPerMarket(uint _capPerMarket); event SetImpliedVolatilityPerAsset(bytes32 asset, uint _impliedVolatility); event SetCapPerAsset(bytes32 asset, uint _cap); event SetMaxSpread(uint _spread); event SetMinSpread(uint _spread); event SetSafeBoxImpact(uint _safeBoxImpact); event SetSafeBox(address _safeBox); event SetMinimalTimeLeftToMaturity(uint _minimalTimeLeftToMaturity); event SetStakingThales(address _stakingThales); event SetMinSupportedPrice(uint _spread); event SetMaxSupportedPrice(uint _spread); event ReferrerPaid(address refferer, address trader, uint amount, uint volume); }
pragma solidity ^0.5.0; import "./IERC20.sol"; import "../../math/SafeMath.sol"; import "../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
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; } }
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); } }
// 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; }
// SPDX-License-Identifier: MIT 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"); } }
// SPDX-License-Identifier: MIT 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); }
// SPDX-License-Identifier: MIT 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 = block.timestamp; } // 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.5.16; 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 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); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "../interfaces/IPositionalMarketManager.sol"; import "../interfaces/IPosition.sol"; import "../interfaces/IPriceFeed.sol"; interface IPositionalMarket { /* ========== TYPES ========== */ enum Phase {Trading, Maturity, Expiry} enum Side {Up, Down} /* ========== VIEWS / VARIABLES ========== */ function getOptions() external view returns (IPosition up, IPosition down); function times() external view returns (uint maturity, uint destructino); function getOracleDetails() 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 up, uint down); function totalSupplies() external view returns (uint up, uint down); 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; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "../interfaces/IPositionalMarket.sol"; interface IPositionalMarketManager { /* ========== VIEWS / VARIABLES ========== */ function durations() external view returns (uint expiryDuration, uint maxTimeToMaturity); function capitalRequirement() external view returns (uint); function marketCreationEnabled() external view returns (bool); function transformCollateral(uint value) external view returns (uint); function reverseTransformCollateral(uint value) external view returns (uint); 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 (IPositionalMarket); function resolveMarket(address market) external; function expireMarkets(address[] calldata market) external; function transferSusdTo( address sender, address receiver, uint amount ) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; import "./IPositionalMarket.sol"; interface IPosition { /* ========== VIEWS / VARIABLES ========== */ function getBalanceOf(address account) external view returns (uint); function getTotalSupply() external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; interface IStakingThales { function updateVolume(address account, uint amount) external; /* ========== VIEWS / VARIABLES ========== */ function totalStakedAmount() external view returns (uint); function stakedBalanceOf(address account) external view returns (uint); function currentPeriodRewards() external view returns (uint); function currentPeriodFees() external view returns (uint); function getLastPeriodOfClaimedRewards(address account) external view returns (uint); function getRewardsAvailable(address account) external view returns (uint); function getRewardFeesAvailable(address account) external view returns (uint); function getAlreadyClaimedRewards(address account) external view returns (uint); function getAlreadyClaimedFees(address account) external view returns (uint); function getContractRewardFunds() external view returns (uint); function getContractFeeFunds() external view returns (uint); }
// SPDX-License-Identifier: MIT pragma solidity >=0.5.16; interface IReferrals { function referrals(address) external view returns (address); function setReferrer(address, address) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.5.16; 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 pure 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 /* 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 Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see `ERC20Detailed`. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a `Transfer` event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through `transferFrom`. This is * zero by default. * * This value changes when `approve` or `transferFrom` are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * > Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an `Approval` event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a `Transfer` event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to `approve`. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
pragma solidity ^0.5.0; /** * @dev Collection of functions related to the address type, */ library Address { /** * @dev Returns true if `account` is a contract. * * This test is non-exhaustive, and there may be false-negatives: during the * execution of a contract's constructor, its address will be reported as * not containing a contract. * * > It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. */ function isContract(address account) internal view returns (bool) { // This method relies in extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution. uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "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":"refferer","type":"address"},{"indexed":false,"internalType":"address","name":"trader","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"volume","type":"uint256"}],"name":"ReferrerPaid","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"asset","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"SetCapPerAsset","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":"SetMaxSupportedPrice","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":"_spread","type":"uint256"}],"name":"SetMinSupportedPrice","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":"_manager","type":"address"}],"name":"SetPositionalMarketManager","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":"_safeBox","type":"address"}],"name":"SetSafeBox","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_safeBoxImpact","type":"uint256"}],"name":"SetSafeBoxImpact","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_stakingThales","type":"address"}],"name":"SetStakingThales","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":true,"inputs":[{"internalType":"address","name":"market","type":"address"},{"internalType":"enum ThalesAMM.Position","name":"position","type":"uint8"}],"name":"balancePosition","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":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"},{"internalType":"address","name":"_referrer","type":"address"}],"name":"buyFromAMMWithReferrer","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":"asset","type":"bytes32"}],"name":"getCapPerAsset","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","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":"maxSupportedPrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":"minSupportedPrice","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":[],"name":"previousManager","outputs":[{"internalType":"address","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"}],"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":true,"inputs":[],"name":"referrals","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"referrerFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"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":false,"inputs":[{"internalType":"address payable","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"retrieveSUSDAmount","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":[],"name":"safeBox","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"safeBoxImpact","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":"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":"bytes32","name":"asset","type":"bytes32"},{"internalType":"uint256","name":"_cap","type":"uint256"}],"name":"setCapPerAsset","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":"_maxSupportedPrice","type":"uint256"}],"name":"setMaxSupportedPrice","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":"_minSupportedPrice","type":"uint256"}],"name":"setMinSupportedPrice","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":"address","name":"_manager","type":"address"}],"name":"setPositionalMarketManager","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":"address","name":"_referrals","type":"address"},{"internalType":"uint256","name":"_referrerFee","type":"uint256"}],"name":"setReferrals","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":false,"inputs":[{"internalType":"address","name":"_safeBox","type":"address"}],"name":"setSafeBox","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint256","name":"_safeBoxImpact","type":"uint256"}],"name":"setSafeBoxImpact","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IStakingThales","name":"_stakingThales","type":"address"}],"name":"setStakingThales","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"bool","name":"enabled","type":"bool"}],"name":"setWhitelistedAddress","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":true,"inputs":[],"name":"stakingThales","outputs":[{"internalType":"contract IStakingThales","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"proxyAddress","type":"address"}],"name":"transferOwnershipAtInit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedAddresses","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b506155aa806100206000396000f3fe608060405234801561001057600080fd5b50600436106103d05760003560e01c80638a249778116101ff578063c4dc27d71161011a578063efb1fe35116100ad578063f85de9fa1161007c578063f85de9fa14610b64578063f8debeb714610b81578063fb91d41c14610b9e578063fd8a8cc614610ba6576103d0565b8063efb1fe3514610acf578063efc1525114610afb578063f502b00314610b2a578063f598df8214610b47576103d0565b8063d3dc7539116100e9578063d3dc753914610aaf578063d69fb66814610ab7578063df8974d014610abf578063ebc7977214610ac7576103d0565b8063c4dc27d714610a11578063ca1d578e14610a37578063ce696e5114610a5d578063d162492414610a8c576103d0565b8063a996798c11610192578063bf996ae311610161578063bf996ae314610970578063c2783f9214610996578063c3b83f5f146109c5578063c402055f146109eb576103d0565b8063a996798c146108a1578063ad18f0da146108c7578063bef648db1461091e578063bf46c0b41461093b576103d0565b8063931b2040116101ce578063931b2040146108195780639324cac7146108215780639f916c9f14610829578063a8cd06e814610872576103d0565b80638a249778146107c05780638da5cb5b146107ec5780638f816652146107f457806391b4ded914610811576103d0565b806353a47bb7116102ef578063724e78da116102825780637f852582116102515780637f8525821461071f578063808226d31461074557806385170209146107625780638875eb841461077f576103d0565b8063724e78da146106bb578063741bef1a146106e157806379ba5097146106e95780637b337a36146106f1576103d0565b80636aaa81b6116102be5780636aaa81b6146106745780636cfa636e1461067c5780636e88a7bd146106845780636ed033f81461068c576103d0565b806353a47bb71461061b5780635727a0f3146106235780635c975abb146106495780635ef85b2614610651576103d0565b80631c37d04b116103675780633ce1108d116103365780633ce1108d146105a4578063481c6a75146105e557806348663e95146105ed57806351b9181f146105f5576103d0565b80631c37d04b1461050c57806321ef44c614610541578063270e13ef14610567578063316425c31461059c576103d0565b806313af4035116103a357806313af4035146104995780631627540c146104bf57806316c38b3c146104e557806319b844a614610504576103d0565b806306c933d8146103d557806306f58fe41461040f5780630d0c8ca7146104335780630f13aae814610452575b600080fd5b6103fb600480360360208110156103eb57600080fd5b50356001600160a01b0316610bae565b604080519115158252519081900360200190f35b610417610bc3565b604080516001600160a01b039092168252519081900360200190f35b6104506004803603602081101561044957600080fd5b5035610bd2565b005b6104876004803603606081101561046857600080fd5b506001600160a01b038135169060ff6020820135169060400135610c15565b60408051918252519081900360200190f35b610450600480360360208110156104af57600080fd5b50356001600160a01b0316610d7e565b610450600480360360208110156104d557600080fd5b50356001600160a01b0316610e91565b610450600480360360208110156104fb57600080fd5b50351515610eed565b610487610f67565b6104876004803603606081101561052257600080fd5b506001600160a01b038135169060ff6020820135169060400135610f6d565b6104506004803603602081101561055757600080fd5b50356001600160a01b0316610f9b565b6104876004803603606081101561057d57600080fd5b506001600160a01b038135169060ff6020820135169060400135610ffd565b610487611033565b610450600480360360a08110156105ba57600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611039565b61041761185b565b61041761186a565b6104506004803603602081101561060b57600080fd5b50356001600160a01b0316611879565b610417611936565b6103fb6004803603602081101561063957600080fd5b50356001600160a01b0316611945565b6103fb611aeb565b6104506004803603604081101561066757600080fd5b5080359060200135611af4565b610487611cf7565b610417611cfd565b610487611d0c565b610487600480360360408110156106a257600080fd5b5080356001600160a01b0316906020013560ff16611d12565b610450600480360360208110156106d157600080fd5b50356001600160a01b0316611f14565b610417611f70565b610450611f7f565b6104506004803603604081101561070757600080fd5b506001600160a01b038135169060200135151561203b565b6104506004803603602081101561073557600080fd5b50356001600160a01b031661206e565b6104506004803603602081101561075b57600080fd5b50356120ca565b6104506004803603602081101561077857600080fd5b503561210d565b610450600480360360a081101561079557600080fd5b506001600160a01b038135169060ff602082013516906040810135906060810135906080013561214e565b610450600480360360408110156107d657600080fd5b506001600160a01b0381351690602001356121fe565b61041761222c565b6104506004803603602081101561080a57600080fd5b503561223b565b61048761227e565b610487612284565b61041761228a565b610450600480360360c081101561083f57600080fd5b506001600160a01b03813581169160ff6020820135169160408201359160608101359160808201359160a0013516612299565b6104876004803603608081101561088857600080fd5b50803590602081013590604081013590606001356123be565b610450600480360360208110156108b757600080fd5b50356001600160a01b031661281e565b61045060048036036101008110156108de57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e001356128f5565b6104506004803603602081101561093457600080fd5b5035612a0d565b6104876004803603606081101561095157600080fd5b506001600160a01b038135169060ff6020820135169060400135612a50565b6104506004803603602081101561098657600080fd5b50356001600160a01b0316612a81565b610487600480360360408110156109ac57600080fd5b5080356001600160a01b0316906020013560ff16612bfa565b610450600480360360208110156109db57600080fd5b50356001600160a01b0316612e62565b61045060048036036020811015610a0157600080fd5b50356001600160a01b0316612f81565b61048760048036036020811015610a2757600080fd5b50356001600160a01b0316612fdd565b6103fb60048036036020811015610a4d57600080fd5b50356001600160a01b0316612fef565b61048760048036036040811015610a7357600080fd5b5080356001600160a01b0316906020013560ff1661326b565b61045060048036036040811015610aa257600080fd5b5080359060200135613281565b6104176132da565b6104876132e9565b6104876132ef565b6104506132f5565b61045060048036036040811015610ae557600080fd5b506001600160a01b038135169060200135613358565b61048760048036036040811015610b1157600080fd5b5080356001600160a01b0316906020013560ff166133e6565b61048760048036036020811015610b4057600080fd5b503561341d565b61045060048036036020811015610b5d57600080fd5b503561342f565b61045060048036036020811015610b7a57600080fd5b5035613472565b61048760048036036020811015610b9757600080fd5b50356134b5565b610487613568565b61041761356e565b60486020526000908152604090205460ff1681565b604b546001600160a01b031681565b610bda61357d565b60458190556040805182815290517fa36b45ea010fcb2e70d33048b7d3f27c265915709bf40fc7e239459424933d9f9181900360200190a150565b6000610c218484612bfa565b821115610c3057506000610d77565b6000610c4e603d54610c428787611d12565b9063ffffffff6135c816565b90506000610cb9670de0b6b3a7640000610ca0610cac670de0b6b3a7640000610ca0610c93610c7e8d8d8d613625565b670de0b6b3a76400009063ffffffff6135c816565b889063ffffffff6136c816565b9063ffffffff61372116565b879063ffffffff6136c816565b90506000610cf6670de0b6b3a7640000610ca0610ce9604354670de0b6b3a76400006135c890919063ffffffff16565b859063ffffffff6136c816565b603b546040805163edc892e160e01b81526004810184905290519293506001600160a01b039091169163edc892e191602480820192602092909190829003018186803b158015610d4557600080fd5b505afa158015610d59573d6000803e3d6000fd5b505050506040513d6020811015610d6f57600080fd5b505193505050505b9392505050565b6001600160a01b038116610dd9576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff1615610e225760405162461bcd60e51b81526004018080602001828103825260298152602001806154696029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b610e9961357d565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610ef561357d565b60035460ff1615158115151415610f0b57610f64565b6003805460ff1916821515179081905560ff1615610f2857426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60465481565b6000610f798484612bfa565b821115610f8857506000610d77565b610f93848484613625565b949350505050565b610fa361357d565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b60008061101c603d546110108787611d12565b9063ffffffff61378b16565b905061102a858585846137e5565b95945050505050565b603e5481565b600480546001019081905560035460ff16156110865760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b61108f86611945565b6110e0576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b60006110ec8787612bfa565b90506000811180156110fe5750808511155b611147576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611154888888610c15565b905061116e670de0b6b3a76400008563ffffffff61378b16565b61118a82610ca088670de0b6b3a764000063ffffffff6136c816565b11156111d1576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561120c57600080fd5b505afa158015611220573d6000803e3d6000fd5b505050506040513d604081101561123657600080fd5b50805160209091015190925090506000808a600181111561125357fe5b1461125e5781611260565b825b60408051634dcb776760e11b815233600482015290519192508a916001600160a01b03841691639b96eece916024808301926020929190829003018186803b1580156112ab57600080fd5b505afa1580156112bf573d6000803e3d6000fd5b505050506040513d60208110156112d557600080fd5b5051101561132a576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b15801561137957600080fd5b505afa15801561138d573d6000803e3d6000fd5b505050506040513d60208110156113a357600080fd5b505110156113e8576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b6114036001600160a01b03821633308c63ffffffff61394f16565b6000603b60009054906101000a90046001600160a01b03166001600160a01b031663edc892e18d6001600160a01b031663a76df708306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561147f57600080fd5b505afa158015611493573d6000803e3d6000fd5b505050506040513d60208110156114a957600080fd5b5051604080516001600160e01b031960e085901b1681526004810192909252516024808301926020929190829003018186803b1580156114e857600080fd5b505afa1580156114fc573d6000803e3d6000fd5b505050506040513d602081101561151257600080fd5b505190508015611570578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156115ba57600080fd5b505afa1580156115ce573d6000803e3d6000fd5b505050506040513d60208110156115e457600080fd5b50511015611639576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561168d57600080fd5b505af11580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50506044546001600160a01b0316156117335760448054604080516302c7739b60e01b81523360048201526024810189905290516001600160a01b03909216926302c7739b92828201926000929082900301818387803b15801561171a57600080fd5b505af115801561172e573d6000803e3d6000fd5b505050505b61173f8c8683336139a9565b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156117bc57fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a15050505050506004548114611853576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6042546001600160a01b031681565b61188281612fef565b6118cc576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561190757600080fd5b505af115801561191b573d6000803e3d6000fd5b505050506040513d602081101561193157600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561199657600080fd5b505afa1580156119aa573d6000803e3d6000fd5b505050506040513d60208110156119c057600080fd5b505115611ae25760008290506000816001600160a01b03166341bc7b1f6040518163ffffffff1660e01b815260040160606040518083038186803b158015611a0757600080fd5b505afa158015611a1b573d6000803e3d6000fd5b505050506040513d6060811015611a3157600080fd5b50516000818152603f6020526040902054909150611a5457600092505050611ae6565b6000826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b158015611a8e57600080fd5b505afa158015611aa2573d6000803e3d6000fd5b505050506040513d6040811015611ab857600080fd5b5051905042811015611ad05760009350505050611ae6565b60405442909103119250611ae6915050565b5060005b919050565b60035460ff1681565b3360009081526048602052604090205460ff1680611b1c57506000546001600160a01b031633145b611b575760405162461bcd60e51b81526004018080602001828103825260328152602001806154026032913960400191505060405180910390fd5b611b70670de0b6b3a7640000603c63ffffffff6136c816565b81118015611b965750611b93670de0b6b3a764000061012c63ffffffff6136c816565b81105b611be7576040805162461bcd60e51b815260206004820152601960248201527f4956206f757473696465206d696e2f6d61782072616e67652100000000000000604482015290519081900360640190fd5b603954604080516315905ec160e31b81526004810185905290516001600160a01b039092169163ac82f60891602480820192602092909190829003018186803b158015611c3357600080fd5b505afa158015611c47573d6000803e3d6000fd5b505050506040513d6020811015611c5d57600080fd5b5051611ca6576040805162461bcd60e51b8152602060048201526013602482015272417373657420686173206e6f2070726963652160681b604482015290519081900360640190fd5b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b604a5481565b6000611d1d83611945565b15611f0a5760008390506000816001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d6040811015611d8b57600080fd5b505190504281036000611db362015180610ca084670de0b6b3a764000063ffffffff6136c816565b90506000846001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b158015611df057600080fd5b505afa158015611e04573d6000803e3d6000fd5b505050506040513d6020811015611e1a57600080fd5b5051604080516341bc7b1f60e01b8152905191925060009182916001600160a01b038916916341bc7b1f91600480820192606092909190829003018186803b158015611e6557600080fd5b505afa158015611e79573d6000803e3d6000fd5b505050506040513d6060811015611e8f57600080fd5b50805160209091015190925090506000896001811115611eab57fe5b1415611ee357611ed56064610ca0858488603f6000898152602001908152602001600020546123be565b975050505050505050611f0e565b611ed5610c7e6064610ca0868589603f60008a8152602001908152602001600020546123be565b5060005b92915050565b611f1c61357d565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b6001546001600160a01b03163314611fc85760405162461bcd60e51b81526004018080602001828103825260358152602001806154346035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b61204361357d565b6001600160a01b03919091166000908152604860205260409020805460ff1916911515919091179055565b61207661357d565b604480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f475a2179b9b6a155e7ba3f46a461beb6798279b265026364944e38dcb4bacafe9181900360200190a150565b6120d261357d565b60468190556040805182815290517fafb2511d843afc28083da6c608f400d0262aef83b3cd885abd205b3e64f544bb9181900360200190a150565b61211561357d565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff161561219b5760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b6121a88686868686613d1a565b6004548114611853576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b61220661357d565b604980546001600160a01b0319166001600160a01b039390931692909217909155604a55565b6000546001600160a01b031681565b61224361357d565b60438190556040805182815290517f01edd423db862fb00774918e3b06d9c1dd3db9a99b5a194c439d2f141876f4449181900360200190a150565b60025481565b60455481565b603a546001600160a01b031681565b600480546001019081905560035460ff16156122e65760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b6049546040805163bbddaca360e01b81526001600160a01b0385811660048301523360248301529151919092169163bbddaca391604480830192600092919082900301818387803b15801561233a57600080fd5b505af115801561234e573d6000803e3d6000fd5b5050505061235f8787878787613d1a565b60045481146123b5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50505050505050565b600080612403633b9aca00610ca06123e66123e18861016d63ffffffff61372116565b61446a565b6123f787606463ffffffff61372116565b9063ffffffff6136c816565b9050858510156000816124315761242c87610ca08a670de0b6b3a764000063ffffffff6136c816565b61244d565b61244d88610ca089670de0b6b3a764000063ffffffff6136c816565b603854604080516344f7787f60e01b8152600481018490526063602482015290519293506000926124ef928792610ca092670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b1580156124b757600080fd5b505afa1580156124cb573d6000803e3d6000fd5b505050506040513d60208110156124e157600080fd5b50519063ffffffff6136c816565b9050600061254061252861251362989680610ca0866223588363ffffffff6136c816565b670de0b6b3a76400009063ffffffff61378b16565b610ca0670de0b6b3a76400008063ffffffff6136c816565b90506000612563670de0b6b3a7640000610ca0600281878063ffffffff6136c816565b9050600061257e62989680610ca0623cdfaf6123f7866144bb565b60385460408051632e4c697f60e01b815260048101879052674563918244f40000602482015290519293506000926125ed92620f424092610ca09262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d9000006024820152905192935060009261265c92620f424092610ca092621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c0000602482015290519293506000926126cb92620f424092610ca092621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec800006024820152905192935060009261273a92620f424092610ca092620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b9050600061275862989680610ca08a6230bbd763ffffffff6136c816565b9050600061277683610c428781866110108c8b63ffffffff61378b16565b90506000612799610c7e670de0b6b3a7640000610ca08b8663ffffffff6136c816565b905060006127ca6127b183606463ffffffff6136c816565b610c42670de0b6b3a7640000606463ffffffff6136c816565b90508d156127e8579e50610f939d5050505050505050505050505050565b61280581610c42670de0b6b3a7640000606463ffffffff6136c816565b9f50505050505050505050505050505050949350505050565b61282661357d565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561287a57600080fd5b505afa15801561288e573d6000803e3d6000fd5b505050506040513d60208110156128a457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b15801561190757600080fd5b60055462010000900460ff168061290f575061290f6144e4565b806129225750600554610100900460ff16155b61295d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e2602e913960400191505060405180910390fd5b60055462010000900460ff1615801561298d576005805461ff001962ff0000199091166201000017166101001790555b61299689610d7e565b61299e6132f5565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612a02576005805462ff0000191690555b505050505050505050565b612a1561357d565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b60006001821080612a695750612a6684846133e6565b82115b15612a7657506000610d77565b610f938484846144ea565b612a8961357d565b603b546001600160a01b031615612b2257603a54603b546040805163095ea7b360e01b81526001600160a01b0392831660048201526000602482018190529151929093169263095ea7b39260448083019360209383900390910190829087803b158015612af557600080fd5b505af1158015612b09573d6000803e3d6000fd5b505050506040513d6020811015612b1f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015612b8f57600080fd5b505af1158015612ba3573d6000803e3d6000fd5b505050506040513d6020811015612bb957600080fd5b5050604080516001600160a01b038316815290517f9987372437ace1af79923f26b948aa04afef92b2b7786144c5aae621ea84eb0a9181900360200190a150565b6000612c0583611945565b15611f0a576000612c168484614574565b905080612c27576000915050611f0e565b600080856001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b158015612c6257600080fd5b505afa158015612c76573d6000803e3d6000fd5b505050506040513d6040811015612c8c57600080fd5b5080516020909101519092509050600080866001811115612ca957fe5b14612d255760408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b158015612cf457600080fd5b505afa158015612d08573d6000803e3d6000fd5b505050506040513d6020811015612d1e57600080fd5b5051612d98565b60408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b158015612d6b57600080fd5b505afa158015612d7f573d6000803e3d6000fd5b505050506040513d6020811015612d9557600080fd5b50515b90506000612db8670de0b6b3a7640000610ca0848863ffffffff6136c816565b6001600160a01b038916600090815260416020526040902054909150612de4908263ffffffff61378b16565b612df1836110108b6145e3565b1015612e0557600095505050505050611f0e565b6001600160a01b038816600090815260416020526040812054612e33908390610c429081876110108f6145e3565b9050612e5583611010670de0b6b3a76400006123f7858b63ffffffff61372116565b9650505050505050611f0e565b612e6a61357d565b6001600160a01b038116612eb7576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612f0c576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b612f8961357d565b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f49a4e3b1ee2ad2bfb1455dfad2d72e84e71a35c756d2c8296f305f12e1828bf59181900360200190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b15801561304057600080fd5b505afa158015613054573d6000803e3d6000fd5b505050506040513d602081101561306a57600080fd5b505180156130e757506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156130ae57600080fd5b505afa1580156130c2573d6000803e3d6000fd5b505050506040513d60208110156130d857600080fd5b505160028111156130e557fe5b145b15611ae257600080836001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561312757600080fd5b505afa15801561313b573d6000803e3d6000fd5b505050506040513d604081101561315157600080fd5b50805160209182015160408051634dcb776760e11b815230600482015290519295509093506000926001600160a01b03861692639b96eece926024808201939291829003018186803b1580156131a657600080fd5b505afa1580156131ba573d6000803e3d6000fd5b505050506040513d60208110156131d057600080fd5b50511180613251575060408051634dcb776760e11b815230600482015290516000916001600160a01b03841691639b96eece91602480820192602092909190829003018186803b15801561322357600080fd5b505afa158015613237573d6000803e3d6000fd5b505050506040513d602081101561324d57600080fd5b5051115b1561326157600192505050611ae6565b5050506000919050565b6000806132788484614656565b50949350505050565b61328961357d565b600082815260476020908152604091829020839055815184815290810183905281517f5af395595015797b4d0f26b77c38dd4831298dabc7906ee3d62b80fa75d35c1e929181900390910190a15050565b6049546001600160a01b031681565b60435481565b60405481565b60055460ff1615613343576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b61336061357d565b603a546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156133b657600080fd5b505af11580156133ca573d6000803e3d6000fd5b505050506040513d60208110156133e057600080fd5b50505050565b60006133f183611945565b15611f0a576000613408603d546110108686611d12565b90506134158484836148d9565b915050611f0e565b603f6020526000908152604090205481565b61343761357d565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61347a61357d565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603954604080516315905ec160e31b81526004810184905290516000926001600160a01b03169163ac82f608916024808301926020929190829003018186803b15801561350157600080fd5b505afa158015613515573d6000803e3d6000fd5b505050506040513d602081101561352b57600080fd5b505161353957506000611ae6565b6000828152604760205260409020546135555750603c54611ae6565b5060009081526047602052604090205490565b603c5481565b6044546001600160a01b031681565b6000546001600160a01b031633146135c65760405162461bcd60e51b815260040180806020018281038252602f815260200180615492602f913960400191505060405180910390fd5b565b60008282111561361f576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008060006136348686614656565b9150915060008083116136655784821161365d57613658858363ffffffff6135c816565b613660565b60005b613675565b613675838663ffffffff61378b16565b90506000858311613687576000613697565b613697838763ffffffff6135c816565b9050808210156136ae576000945050505050610d77565b6136bd88888886888688614a1f565b945050505050610d77565b6000826136d757506000611f0e565b828202828482816136e457fe5b0414610d775760405162461bcd60e51b81526004018080602001828103825260218152602001806154c16021913960400191505060405180910390fd5b6000808211613777576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161378257fe5b04949350505050565b600082820183811015610d77576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600060018310806137ff57506137fc8585846148d9565b83115b1561380c57506000610f93565b6000613840670de0b6b3a7640000610ca06138288989896144ea565b6123f7670de0b6b3a76400008863ffffffff6135c816565b9050613875670de0b6b3a7640000610ca06138688266470de4df82000063ffffffff61378b16565b849063ffffffff6136c816565b90506000613898670de0b6b3a7640000610ca0610c93878663ffffffff61378b16565b905060006138c8670de0b6b3a7640000610ca0610ce9604354670de0b6b3a764000061378b90919063ffffffff16565b603b546040805163edc892e160e01b81526004810184905290519293506001600160a01b039091169163edc892e191602480820192602092909190829003018186803b15801561391757600080fd5b505afa15801561392b573d6000803e3d6000fd5b505050506040513d602081101561394157600080fd5b505198975050505050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526133e0908590614b1f565b60006139e784610c426139cf604354670de0b6b3a76400006135c890919063ffffffff16565b610ca088670de0b6b3a764000063ffffffff6136c816565b60435490915015613a7d57603a546042546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b158015613a4b57600080fd5b505af1158015613a5f573d6000803e3d6000fd5b505050506040513d6020811015613a7557600080fd5b50613a819050565b5060005b603b54613b2b906001600160a01b03166317fd849a613aa6878563ffffffff61378b16565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613ada57600080fd5b505afa158015613aee573d6000803e3d6000fd5b505050506040513d6020811015613b0457600080fd5b50516001600160a01b0387166000908152604160205260409020549063ffffffff61378b16565b6001600160a01b0380871660009081526041602090815260409182902093909355603b548151630bfec24d60e11b81526004810188905291519216926317fd849a92602480840193829003018186803b158015613b8757600080fd5b505afa158015613b9b573d6000803e3d6000fd5b505050506040513d6020811015613bb157600080fd5b50516001600160a01b03861660009081526041602052604090205411613bef576001600160a01b038516600090815260416020526040812055613ca7565b603b5460408051630bfec24d60e11b8152600481018690529051613c8d926001600160a01b0316916317fd849a916024808301926020929190829003018186803b158015613c3c57600080fd5b505afa158015613c50573d6000803e3d6000fd5b505050506040513d6020811015613c6657600080fd5b50516001600160a01b0387166000908152604160205260409020549063ffffffff6135c816565b6001600160a01b0386166000908152604160205260409020555b6000604a54118015613cc357506049546001600160a01b031615155b15613d13576000613d0685610c42613cee604a54670de0b6b3a76400006135c890919063ffffffff16565b610ca089670de0b6b3a764000063ffffffff6136c816565b9050611853838287614cd7565b5050505050565b613d2385611945565b613d74576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000613d86603d546110108888611d12565b90506000613d958787846148d9565b905080851115613de4576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000613df2888888866137e5565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015613e4257600080fd5b505afa158015613e56573d6000803e3d6000fd5b505050506040513d6020811015613e6c57600080fd5b50511015613ec1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015613f1157600080fd5b505afa158015613f25573d6000803e3d6000fd5b505050506040513d6020811015613f3b57600080fd5b50511015613f80576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b613f98670de0b6b3a76400008563ffffffff61378b16565b613fb486610ca084670de0b6b3a764000063ffffffff6136c816565b1115613ffb576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54614019906001600160a01b031633308463ffffffff61394f16565b6000614026898989614e46565b9050801561421157603b546040805163edc892e160e01b81526004810184905290516001600160a01b039092169163edc892e191602480820192602092909190829003018186803b15801561407a57600080fd5b505afa15801561408e573d6000803e3d6000fd5b505050506040513d60208110156140a457600080fd5b5051603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156140f157600080fd5b505afa158015614105573d6000803e3d6000fd5b505050506040513d602081101561411b57600080fd5b50511015614170576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156141b657600080fd5b505af11580156141ca573d6000803e3d6000fd5b5050506001600160a01b038a166000908152604160205260409020546141f791508263ffffffff61378b16565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561424c57600080fd5b505afa158015614260573d6000803e3d6000fd5b505050506040513d604081101561427657600080fd5b50805160209091015190925090506000808b600181111561429357fe5b1461429e57816142a0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b1580156142f357600080fd5b505af1158015614307573d6000803e3d6000fd5b505050506040513d602081101561431d57600080fd5b50506044546001600160a01b0316156143995760448054604080516302c7739b60e01b81523360048201526024810189905290516001600160a01b03909216926302c7739b92828201926000929082900301818387803b15801561438057600080fd5b505af1158015614394573d6000803e3d6000fd5b505050505b6143a48c8633614e79565b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b0316815260200186600181111561442157fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050505050505050565b600060038211156144ad575080600160028204015b818110156144a75780915060028182858161449657fe5b04018161449f57fe5b04905061447f565b50611ae6565b8115611ae657506001919050565b60006144c682615156565b6ec097ce7bc90715b34b9f1000000000816144dd57fe5b0492915050565b303b1590565b60008060006144f98686614656565b91509150600084831161450d57600061451d565b61451d838663ffffffff6135c816565b9050600085841161454d5761454861453b878663ffffffff6135c816565b849063ffffffff61378b16565b61454f565b825b9050808210614565576000945050505050610d77565b6136bd888888868886886151e5565b6000806145818484611d12565b90506045548111158061459657506046548110155b156145a5576000915050611f0e565b600061102a670de0b6b3a7640000610ca06145cf610c7e6002603e5461372190919063ffffffff16565b603d546123f790879063ffffffff6135c816565b600080826001600160a01b03166341bc7b1f6040518163ffffffff1660e01b815260040160606040518083038186803b15801561461f57600080fd5b505afa158015614633573d6000803e3d6000fd5b505050506040513d606081101561464957600080fd5b50519050610d77816134b5565b600080600080856001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561469457600080fd5b505afa1580156146a8573d6000803e3d6000fd5b505050506040513d60408110156146be57600080fd5b50805160209091015190925090506000808660018111156146db57fe5b146147575760408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b15801561472657600080fd5b505afa15801561473a573d6000803e3d6000fd5b505050506040513d602081101561475057600080fd5b50516147ca565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b15801561479d57600080fd5b505afa1580156147b1573d6000803e3d6000fd5b505050506040513d60208110156147c757600080fd5b50515b90506000808760018111156147db57fe5b146148575760408051634dcb776760e11b815230600482015290516001600160a01b03861691639b96eece916024808301926020929190829003018186803b15801561482657600080fd5b505afa15801561483a573d6000803e3d6000fd5b505050506040513d602081101561485057600080fd5b50516148ca565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b15801561489d57600080fd5b505afa1580156148b1573d6000803e3d6000fd5b505050506040513d60208110156148c757600080fd5b50515b91989197509095505050505050565b6000604554821115806148ee57506046548210155b156148fb57506000610d77565b6000614907858561527e565b90506000614948670de0b6b3a7640000610ca06149306002603e5461372190919063ffffffff16565b6123f7670de0b6b3a76400008963ffffffff6135c816565b9050600061495f610c7e868463ffffffff61378b16565b9050600061497f670de0b6b3a7640000610ca0868963ffffffff6136c816565b6001600160a01b0389166000908152604160205260409020549091506149a8826110108b6145e3565b116149ba576000945050505050610d77565b6001600160a01b0388166000908152604160205260408120546149e490610c42846110108d6145e3565b9050614a12614a0584610ca084670de0b6b3a764000063ffffffff6136c816565b869063ffffffff61378b16565b9998505050505050505050565b600080614a4086610c42614a338c8c612bfa565b889063ffffffff61378b16565b90506000614a54848663ffffffff6135c816565b90506000614a88670de0b6b3a7640000610ca0614a798682878563ffffffff6136c816565b603e549063ffffffff6136c816565b90508715614ad9576000614aa382600263ffffffff61372116565b90506000614abb826123f78d8c63ffffffff6135c816565b9050614acd818c63ffffffff61372116565b95505050505050614b14565b866000614afd670de0b6b3a7640000610ca0614a798882878563ffffffff6136c816565b9050614acd6002610ca0858463ffffffff61378b16565b979650505050505050565b614b31826001600160a01b03166153fb565b614b82576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614bc05780518252601f199092019160209182019101614ba1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614c22576040519150601f19603f3d011682016040523d82523d6000602084013e614c27565b606091505b509150915081614c7e576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156133e057808060200190516020811015614c9a57600080fd5b50516133e05760405162461bcd60e51b815260040180806020018281038252602a81526020018061554c602a913960400191505060405180910390fd5b60495460408051639ca423b360e01b81526001600160a01b03868116600483015291516000939290921691639ca423b391602480820192602092909190829003018186803b158015614d2857600080fd5b505afa158015614d3c573d6000803e3d6000fd5b505050506040513d6020811015614d5257600080fd5b505190506001600160a01b038116156133e057604a54156133e057603a546040805163a9059cbb60e01b81526001600160a01b038481166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015614dc357600080fd5b505af1158015614dd7573d6000803e3d6000fd5b505050506040513d6020811015614ded57600080fd5b5050604080516001600160a01b038084168252861660208201528082018590526060810184905290517f8fa68a6a8e2fc9ff758a6e64afba8bc2f66fb082999a2c5225c8c49633faded49181900360800190a150505050565b600080614e53858561527e565b90506000915082811015614e715761102a838263ffffffff6135c816565b509392505050565b6000614ec3614eb6614e9e604354670de0b6b3a764000061378b90919063ffffffff16565b610ca086670de0b6b3a764000063ffffffff6136c816565b849063ffffffff6135c816565b60435490915015614f5957603a546042546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b158015614f2757600080fd5b505af1158015614f3b573d6000803e3d6000fd5b505050506040513d6020811015614f5157600080fd5b50614f5d9050565b5060005b603b546001600160a01b03166317fd849a614f7e858463ffffffff6135c816565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614fb257600080fd5b505afa158015614fc6573d6000803e3d6000fd5b505050506040513d6020811015614fdc57600080fd5b50516001600160a01b0385166000908152604160205260409020541161501a576001600160a01b0384166000908152604160205260408120556150de565b603b546150c4906001600160a01b03166317fd849a61503f868563ffffffff6135c816565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561507357600080fd5b505afa158015615087573d6000803e3d6000fd5b505050506040513d602081101561509d57600080fd5b50516001600160a01b0386166000908152604160205260409020549063ffffffff6135c816565b6001600160a01b0385166000908152604160205260409020555b6000604a541180156150fa57506049546001600160a01b031615155b156133e057600061514961513c615124604a54670de0b6b3a764000061378b90919063ffffffff16565b610ca087670de0b6b3a764000063ffffffff6136c816565b859063ffffffff6135c816565b9050613d13838286614cd7565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156151b257600080fd5b505afa1580156151c6573d6000803e3d6000fd5b505050506040513d60208110156151dc57600080fd5b50519392505050565b60008061520685610c426151f98c8c6133e6565b899063ffffffff61378b16565b9050600061521a858563ffffffff6135c816565b9050600061523f670de0b6b3a7640000610ca0614a798682878563ffffffff6136c816565b9050861561525a576000614aa382600263ffffffff61372116565b876000614afd670de0b6b3a7640000610ca0614a798882878563ffffffff6136c816565b6000806000846001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b1580156152bb57600080fd5b505afa1580156152cf573d6000803e3d6000fd5b505050506040513d60408110156152e557600080fd5b508051602090910151909250905060008085600181111561530257fe5b1461537e5760408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b15801561534d57600080fd5b505afa158015615361573d6000803e3d6000fd5b505050506040513d602081101561537757600080fd5b50516153f1565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b1580156153c457600080fd5b505afa1580156153d8573d6000803e3d6000fd5b505050506040513d60208110156153ee57600080fd5b50515b9695505050505050565b3b15159056fe4f6e6c792077686974656c697374656420616464726573736573206f72206f776e65722063616e206368616e676520495621596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a7231582034e1e06e9bbdf270fd11894e3ce3fcf42b01429e9ff746b38a58496abf1592d564736f6c63430005100032
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106103d05760003560e01c80638a249778116101ff578063c4dc27d71161011a578063efb1fe35116100ad578063f85de9fa1161007c578063f85de9fa14610b64578063f8debeb714610b81578063fb91d41c14610b9e578063fd8a8cc614610ba6576103d0565b8063efb1fe3514610acf578063efc1525114610afb578063f502b00314610b2a578063f598df8214610b47576103d0565b8063d3dc7539116100e9578063d3dc753914610aaf578063d69fb66814610ab7578063df8974d014610abf578063ebc7977214610ac7576103d0565b8063c4dc27d714610a11578063ca1d578e14610a37578063ce696e5114610a5d578063d162492414610a8c576103d0565b8063a996798c11610192578063bf996ae311610161578063bf996ae314610970578063c2783f9214610996578063c3b83f5f146109c5578063c402055f146109eb576103d0565b8063a996798c146108a1578063ad18f0da146108c7578063bef648db1461091e578063bf46c0b41461093b576103d0565b8063931b2040116101ce578063931b2040146108195780639324cac7146108215780639f916c9f14610829578063a8cd06e814610872576103d0565b80638a249778146107c05780638da5cb5b146107ec5780638f816652146107f457806391b4ded914610811576103d0565b806353a47bb7116102ef578063724e78da116102825780637f852582116102515780637f8525821461071f578063808226d31461074557806385170209146107625780638875eb841461077f576103d0565b8063724e78da146106bb578063741bef1a146106e157806379ba5097146106e95780637b337a36146106f1576103d0565b80636aaa81b6116102be5780636aaa81b6146106745780636cfa636e1461067c5780636e88a7bd146106845780636ed033f81461068c576103d0565b806353a47bb71461061b5780635727a0f3146106235780635c975abb146106495780635ef85b2614610651576103d0565b80631c37d04b116103675780633ce1108d116103365780633ce1108d146105a4578063481c6a75146105e557806348663e95146105ed57806351b9181f146105f5576103d0565b80631c37d04b1461050c57806321ef44c614610541578063270e13ef14610567578063316425c31461059c576103d0565b806313af4035116103a357806313af4035146104995780631627540c146104bf57806316c38b3c146104e557806319b844a614610504576103d0565b806306c933d8146103d557806306f58fe41461040f5780630d0c8ca7146104335780630f13aae814610452575b600080fd5b6103fb600480360360208110156103eb57600080fd5b50356001600160a01b0316610bae565b604080519115158252519081900360200190f35b610417610bc3565b604080516001600160a01b039092168252519081900360200190f35b6104506004803603602081101561044957600080fd5b5035610bd2565b005b6104876004803603606081101561046857600080fd5b506001600160a01b038135169060ff6020820135169060400135610c15565b60408051918252519081900360200190f35b610450600480360360208110156104af57600080fd5b50356001600160a01b0316610d7e565b610450600480360360208110156104d557600080fd5b50356001600160a01b0316610e91565b610450600480360360208110156104fb57600080fd5b50351515610eed565b610487610f67565b6104876004803603606081101561052257600080fd5b506001600160a01b038135169060ff6020820135169060400135610f6d565b6104506004803603602081101561055757600080fd5b50356001600160a01b0316610f9b565b6104876004803603606081101561057d57600080fd5b506001600160a01b038135169060ff6020820135169060400135610ffd565b610487611033565b610450600480360360a08110156105ba57600080fd5b506001600160a01b038135169060ff6020820135169060408101359060608101359060800135611039565b61041761185b565b61041761186a565b6104506004803603602081101561060b57600080fd5b50356001600160a01b0316611879565b610417611936565b6103fb6004803603602081101561063957600080fd5b50356001600160a01b0316611945565b6103fb611aeb565b6104506004803603604081101561066757600080fd5b5080359060200135611af4565b610487611cf7565b610417611cfd565b610487611d0c565b610487600480360360408110156106a257600080fd5b5080356001600160a01b0316906020013560ff16611d12565b610450600480360360208110156106d157600080fd5b50356001600160a01b0316611f14565b610417611f70565b610450611f7f565b6104506004803603604081101561070757600080fd5b506001600160a01b038135169060200135151561203b565b6104506004803603602081101561073557600080fd5b50356001600160a01b031661206e565b6104506004803603602081101561075b57600080fd5b50356120ca565b6104506004803603602081101561077857600080fd5b503561210d565b610450600480360360a081101561079557600080fd5b506001600160a01b038135169060ff602082013516906040810135906060810135906080013561214e565b610450600480360360408110156107d657600080fd5b506001600160a01b0381351690602001356121fe565b61041761222c565b6104506004803603602081101561080a57600080fd5b503561223b565b61048761227e565b610487612284565b61041761228a565b610450600480360360c081101561083f57600080fd5b506001600160a01b03813581169160ff6020820135169160408201359160608101359160808201359160a0013516612299565b6104876004803603608081101561088857600080fd5b50803590602081013590604081013590606001356123be565b610450600480360360208110156108b757600080fd5b50356001600160a01b031661281e565b61045060048036036101008110156108de57600080fd5b506001600160a01b038135811691602081013582169160408201358116916060810135916080820135169060a08101359060c08101359060e001356128f5565b6104506004803603602081101561093457600080fd5b5035612a0d565b6104876004803603606081101561095157600080fd5b506001600160a01b038135169060ff6020820135169060400135612a50565b6104506004803603602081101561098657600080fd5b50356001600160a01b0316612a81565b610487600480360360408110156109ac57600080fd5b5080356001600160a01b0316906020013560ff16612bfa565b610450600480360360208110156109db57600080fd5b50356001600160a01b0316612e62565b61045060048036036020811015610a0157600080fd5b50356001600160a01b0316612f81565b61048760048036036020811015610a2757600080fd5b50356001600160a01b0316612fdd565b6103fb60048036036020811015610a4d57600080fd5b50356001600160a01b0316612fef565b61048760048036036040811015610a7357600080fd5b5080356001600160a01b0316906020013560ff1661326b565b61045060048036036040811015610aa257600080fd5b5080359060200135613281565b6104176132da565b6104876132e9565b6104876132ef565b6104506132f5565b61045060048036036040811015610ae557600080fd5b506001600160a01b038135169060200135613358565b61048760048036036040811015610b1157600080fd5b5080356001600160a01b0316906020013560ff166133e6565b61048760048036036020811015610b4057600080fd5b503561341d565b61045060048036036020811015610b5d57600080fd5b503561342f565b61045060048036036020811015610b7a57600080fd5b5035613472565b61048760048036036020811015610b9757600080fd5b50356134b5565b610487613568565b61041761356e565b60486020526000908152604090205460ff1681565b604b546001600160a01b031681565b610bda61357d565b60458190556040805182815290517fa36b45ea010fcb2e70d33048b7d3f27c265915709bf40fc7e239459424933d9f9181900360200190a150565b6000610c218484612bfa565b821115610c3057506000610d77565b6000610c4e603d54610c428787611d12565b9063ffffffff6135c816565b90506000610cb9670de0b6b3a7640000610ca0610cac670de0b6b3a7640000610ca0610c93610c7e8d8d8d613625565b670de0b6b3a76400009063ffffffff6135c816565b889063ffffffff6136c816565b9063ffffffff61372116565b879063ffffffff6136c816565b90506000610cf6670de0b6b3a7640000610ca0610ce9604354670de0b6b3a76400006135c890919063ffffffff16565b859063ffffffff6136c816565b603b546040805163edc892e160e01b81526004810184905290519293506001600160a01b039091169163edc892e191602480820192602092909190829003018186803b158015610d4557600080fd5b505afa158015610d59573d6000803e3d6000fd5b505050506040513d6020811015610d6f57600080fd5b505193505050505b9392505050565b6001600160a01b038116610dd9576040805162461bcd60e51b815260206004820152601960248201527f4f776e657220616464726573732063616e6e6f74206265203000000000000000604482015290519081900360640190fd5b600154600160a01b900460ff1615610e225760405162461bcd60e51b81526004018080602001828103825260298152602001806154696029913960400191505060405180910390fd5b6001805460ff60a01b1916600160a01b179055600080546001600160a01b0383166001600160a01b03199091168117825560408051928352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b610e9961357d565b600180546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce229181900360200190a150565b610ef561357d565b60035460ff1615158115151415610f0b57610f64565b6003805460ff1916821515179081905560ff1615610f2857426002555b6003546040805160ff90921615158252517f8fb6c181ee25a520cf3dd6565006ef91229fcfe5a989566c2a3b8c115570cec59181900360200190a15b50565b60465481565b6000610f798484612bfa565b821115610f8857506000610d77565b610f93848484613625565b949350505050565b610fa361357d565b603a80546001600160a01b0319166001600160a01b03838116919091179182905560408051929091168252517f74a8764fc8d62d2d844c8c54426bd94ad034e0e92abdf5280ff75e2cbd678fb6916020908290030190a150565b60008061101c603d546110108787611d12565b9063ffffffff61378b16565b905061102a858585846137e5565b95945050505050565b603e5481565b600480546001019081905560035460ff16156110865760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b61108f86611945565b6110e0576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b60006110ec8787612bfa565b90506000811180156110fe5750808511155b611147576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000611154888888610c15565b905061116e670de0b6b3a76400008563ffffffff61378b16565b61118a82610ca088670de0b6b3a764000063ffffffff6136c816565b11156111d1576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b600080896001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561120c57600080fd5b505afa158015611220573d6000803e3d6000fd5b505050506040513d604081101561123657600080fd5b50805160209091015190925090506000808a600181111561125357fe5b1461125e5781611260565b825b60408051634dcb776760e11b815233600482015290519192508a916001600160a01b03841691639b96eece916024808301926020929190829003018186803b1580156112ab57600080fd5b505afa1580156112bf573d6000803e3d6000fd5b505050506040513d60208110156112d557600080fd5b5051101561132a576040805162461bcd60e51b815260206004820152601d60248201527f596f7520646f6e74206861766520656e6f756768206f7074696f6e732e000000604482015290519081900360640190fd5b60408051636eb1769f60e11b815233600482015230602482015290518a916001600160a01b0384169163dd62ed3e91604480820192602092909190829003018186803b15801561137957600080fd5b505afa15801561138d573d6000803e3d6000fd5b505050506040513d60208110156113a357600080fd5b505110156113e8576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b6114036001600160a01b03821633308c63ffffffff61394f16565b6000603b60009054906101000a90046001600160a01b03166001600160a01b031663edc892e18d6001600160a01b031663a76df708306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561147f57600080fd5b505afa158015611493573d6000803e3d6000fd5b505050506040513d60208110156114a957600080fd5b5051604080516001600160e01b031960e085901b1681526004810192909252516024808301926020929190829003018186803b1580156114e857600080fd5b505afa1580156114fc573d6000803e3d6000fd5b505050506040513d602081101561151257600080fd5b505190508015611570578b6001600160a01b031663f5571beb6040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561155757600080fd5b505af115801561156b573d6000803e3d6000fd5b505050505b603a54604080516370a0823160e01b8152306004820152905187926001600160a01b0316916370a08231916024808301926020929190829003018186803b1580156115ba57600080fd5b505afa1580156115ce573d6000803e3d6000fd5b505050506040513d60208110156115e457600080fd5b50511015611639576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b603a546040805163a9059cbb60e01b81523360048201526024810188905290516001600160a01b039092169163a9059cbb916044808201926020929091908290030181600087803b15801561168d57600080fd5b505af11580156116a1573d6000803e3d6000fd5b505050506040513d60208110156116b757600080fd5b50506044546001600160a01b0316156117335760448054604080516302c7739b60e01b81523360048201526024810189905290516001600160a01b03909216926302c7739b92828201926000929082900301818387803b15801561171a57600080fd5b505af115801561172e573d6000803e3d6000fd5b505050505b61173f8c8683336139a9565b7f1d6ff70c632edb1e6aba7fbc0148db68c8392e30f9dfaadae2543a2543757cf6338d8d8d89603a60009054906101000a90046001600160a01b03168860405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b031681526020018660018111156117bc57fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a15050505050506004548114611853576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b505050505050565b603b546001600160a01b031681565b6042546001600160a01b031681565b61188281612fef565b6118cc576040805162461bcd60e51b81526020600482015260166024820152754e6f206f7074696f6e7320746f20657865726369736560501b604482015290519081900360640190fd5b806001600160a01b031663851492586040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561190757600080fd5b505af115801561191b573d6000803e3d6000fd5b505050506040513d602081101561193157600080fd5b505050565b6001546001600160a01b031681565b603b5460408051633761c52760e11b81526001600160a01b03848116600483015291516000939290921691636ec38a4e91602480820192602092909190829003018186803b15801561199657600080fd5b505afa1580156119aa573d6000803e3d6000fd5b505050506040513d60208110156119c057600080fd5b505115611ae25760008290506000816001600160a01b03166341bc7b1f6040518163ffffffff1660e01b815260040160606040518083038186803b158015611a0757600080fd5b505afa158015611a1b573d6000803e3d6000fd5b505050506040513d6060811015611a3157600080fd5b50516000818152603f6020526040902054909150611a5457600092505050611ae6565b6000826001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b158015611a8e57600080fd5b505afa158015611aa2573d6000803e3d6000fd5b505050506040513d6040811015611ab857600080fd5b5051905042811015611ad05760009350505050611ae6565b60405442909103119250611ae6915050565b5060005b919050565b60035460ff1681565b3360009081526048602052604090205460ff1680611b1c57506000546001600160a01b031633145b611b575760405162461bcd60e51b81526004018080602001828103825260328152602001806154026032913960400191505060405180910390fd5b611b70670de0b6b3a7640000603c63ffffffff6136c816565b81118015611b965750611b93670de0b6b3a764000061012c63ffffffff6136c816565b81105b611be7576040805162461bcd60e51b815260206004820152601960248201527f4956206f757473696465206d696e2f6d61782072616e67652100000000000000604482015290519081900360640190fd5b603954604080516315905ec160e31b81526004810185905290516001600160a01b039092169163ac82f60891602480820192602092909190829003018186803b158015611c3357600080fd5b505afa158015611c47573d6000803e3d6000fd5b505050506040513d6020811015611c5d57600080fd5b5051611ca6576040805162461bcd60e51b8152602060048201526013602482015272417373657420686173206e6f2070726963652160681b604482015290519081900360640190fd5b6000828152603f6020908152604091829020839055815184815290810183905281517f715e0a52c0b74c77d2d2012a363ac95b494302ad2abb78ac7406ec93451f1adb929181900390910190a15050565b603d5481565b6038546001600160a01b031681565b604a5481565b6000611d1d83611945565b15611f0a5760008390506000816001600160a01b0316639e3b34bf6040518163ffffffff1660e01b8152600401604080518083038186803b158015611d6157600080fd5b505afa158015611d75573d6000803e3d6000fd5b505050506040513d6040811015611d8b57600080fd5b505190504281036000611db362015180610ca084670de0b6b3a764000063ffffffff6136c816565b90506000846001600160a01b031663668aa8246040518163ffffffff1660e01b815260040160206040518083038186803b158015611df057600080fd5b505afa158015611e04573d6000803e3d6000fd5b505050506040513d6020811015611e1a57600080fd5b5051604080516341bc7b1f60e01b8152905191925060009182916001600160a01b038916916341bc7b1f91600480820192606092909190829003018186803b158015611e6557600080fd5b505afa158015611e79573d6000803e3d6000fd5b505050506040513d6060811015611e8f57600080fd5b50805160209091015190925090506000896001811115611eab57fe5b1415611ee357611ed56064610ca0858488603f6000898152602001908152602001600020546123be565b975050505050505050611f0e565b611ed5610c7e6064610ca0868589603f60008a8152602001908152602001600020546123be565b5060005b92915050565b611f1c61357d565b603980546001600160a01b0383166001600160a01b0319909116811790915560408051918252517ff724a45d041687842411f2b977ef22ab8f43c8f1104f4592b42a00f9b34a643d9181900360200190a150565b6039546001600160a01b031681565b6001546001600160a01b03163314611fc85760405162461bcd60e51b81526004018080602001828103825260358152602001806154346035913960400191505060405180910390fd5b600054600154604080516001600160a01b03938416815292909116602083015280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a160018054600080546001600160a01b03199081166001600160a01b03841617909155169055565b61204361357d565b6001600160a01b03919091166000908152604860205260409020805460ff1916911515919091179055565b61207661357d565b604480546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f475a2179b9b6a155e7ba3f46a461beb6798279b265026364944e38dcb4bacafe9181900360200190a150565b6120d261357d565b60468190556040805182815290517fafb2511d843afc28083da6c608f400d0262aef83b3cd885abd205b3e64f544bb9181900360200190a150565b61211561357d565b6040818155805182815290517fdc469b5583fa9b7ebd3245e1665334cd758c4bef4c5a132c62baca85effacfec9181900360200190a150565b600480546001019081905560035460ff161561219b5760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b6121a88686868686613d1a565b6004548114611853576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b61220661357d565b604980546001600160a01b0319166001600160a01b039390931692909217909155604a55565b6000546001600160a01b031681565b61224361357d565b60438190556040805182815290517f01edd423db862fb00774918e3b06d9c1dd3db9a99b5a194c439d2f141876f4449181900360200190a150565b60025481565b60455481565b603a546001600160a01b031681565b600480546001019081905560035460ff16156122e65760405162461bcd60e51b815260040180806020018281038252603c815260200180615510603c913960400191505060405180910390fd5b6049546040805163bbddaca360e01b81526001600160a01b0385811660048301523360248301529151919092169163bbddaca391604480830192600092919082900301818387803b15801561233a57600080fd5b505af115801561234e573d6000803e3d6000fd5b5050505061235f8787878787613d1a565b60045481146123b5576040805162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604482015290519081900360640190fd5b50505050505050565b600080612403633b9aca00610ca06123e66123e18861016d63ffffffff61372116565b61446a565b6123f787606463ffffffff61372116565b9063ffffffff6136c816565b9050858510156000816124315761242c87610ca08a670de0b6b3a764000063ffffffff6136c816565b61244d565b61244d88610ca089670de0b6b3a764000063ffffffff6136c816565b603854604080516344f7787f60e01b8152600481018490526063602482015290519293506000926124ef928792610ca092670de0b6b3a7640000926001600160a01b0316916344f7787f916044808301926020929190829003018186803b1580156124b757600080fd5b505afa1580156124cb573d6000803e3d6000fd5b505050506040513d60208110156124e157600080fd5b50519063ffffffff6136c816565b9050600061254061252861251362989680610ca0866223588363ffffffff6136c816565b670de0b6b3a76400009063ffffffff61378b16565b610ca0670de0b6b3a76400008063ffffffff6136c816565b90506000612563670de0b6b3a7640000610ca0600281878063ffffffff6136c816565b9050600061257e62989680610ca0623cdfaf6123f7866144bb565b60385460408051632e4c697f60e01b815260048101879052674563918244f40000602482015290519293506000926125ed92620f424092610ca09262144c62926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b815260048101889052673782dace9d9000006024820152905192935060009261265c92620f424092610ca092621bca48926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b8152600481018990526729a2241af62c0000602482015290519293506000926126cb92620f424092610ca092621b2ee6926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b60385460408051632e4c697f60e01b8152600481018a9052671bc16d674ec800006024820152905192935060009261273a92620f424092610ca092620570ba926001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156124b757600080fd5b9050600061275862989680610ca08a6230bbd763ffffffff6136c816565b9050600061277683610c428781866110108c8b63ffffffff61378b16565b90506000612799610c7e670de0b6b3a7640000610ca08b8663ffffffff6136c816565b905060006127ca6127b183606463ffffffff6136c816565b610c42670de0b6b3a7640000606463ffffffff6136c816565b90508d156127e8579e50610f939d5050505050505050505050505050565b61280581610c42670de0b6b3a7640000606463ffffffff6136c816565b9f50505050505050505050505050505050949350505050565b61282661357d565b603a54604080516370a0823160e01b815230600482015290516001600160a01b039092169163a9059cbb91849184916370a08231916024808301926020929190829003018186803b15801561287a57600080fd5b505afa15801561288e573d6000803e3d6000fd5b505050506040513d60208110156128a457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b03909316600484015260248301919091525160448083019260209291908290030181600087803b15801561190757600080fd5b60055462010000900460ff168061290f575061290f6144e4565b806129225750600554610100900460ff16155b61295d5760405162461bcd60e51b815260040180806020018281038252602e8152602001806154e2602e913960400191505060405180910390fd5b60055462010000900460ff1615801561298d576005805461ff001962ff0000199091166201000017166101001790555b61299689610d7e565b61299e6132f5565b603980546001600160a01b03808b166001600160a01b031992831617909255603a80548a8416908316179055603c8890556038805492881692909116919091179055603d849055603e83905560408290558015612a02576005805462ff0000191690555b505050505050505050565b612a1561357d565b603e8190556040805182815290517f4af6d03c4624e0a6b868b8f6453e047f23f3ea15e9d08c938bd4c445d7ef19b39181900360200190a150565b60006001821080612a695750612a6684846133e6565b82115b15612a7657506000610d77565b610f938484846144ea565b612a8961357d565b603b546001600160a01b031615612b2257603a54603b546040805163095ea7b360e01b81526001600160a01b0392831660048201526000602482018190529151929093169263095ea7b39260448083019360209383900390910190829087803b158015612af557600080fd5b505af1158015612b09573d6000803e3d6000fd5b505050506040513d6020811015612b1f57600080fd5b50505b603b80546001600160a01b0319166001600160a01b038381169190911791829055603a546040805163095ea7b360e01b8152938316600485015260001960248501525191169163095ea7b39160448083019260209291908290030181600087803b158015612b8f57600080fd5b505af1158015612ba3573d6000803e3d6000fd5b505050506040513d6020811015612bb957600080fd5b5050604080516001600160a01b038316815290517f9987372437ace1af79923f26b948aa04afef92b2b7786144c5aae621ea84eb0a9181900360200190a150565b6000612c0583611945565b15611f0a576000612c168484614574565b905080612c27576000915050611f0e565b600080856001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b158015612c6257600080fd5b505afa158015612c76573d6000803e3d6000fd5b505050506040513d6040811015612c8c57600080fd5b5080516020909101519092509050600080866001811115612ca957fe5b14612d255760408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b158015612cf457600080fd5b505afa158015612d08573d6000803e3d6000fd5b505050506040513d6020811015612d1e57600080fd5b5051612d98565b60408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b158015612d6b57600080fd5b505afa158015612d7f573d6000803e3d6000fd5b505050506040513d6020811015612d9557600080fd5b50515b90506000612db8670de0b6b3a7640000610ca0848863ffffffff6136c816565b6001600160a01b038916600090815260416020526040902054909150612de4908263ffffffff61378b16565b612df1836110108b6145e3565b1015612e0557600095505050505050611f0e565b6001600160a01b038816600090815260416020526040812054612e33908390610c429081876110108f6145e3565b9050612e5583611010670de0b6b3a76400006123f7858b63ffffffff61372116565b9650505050505050611f0e565b612e6a61357d565b6001600160a01b038116612eb7576040805162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015290519081900360640190fd5b600154600160a81b900460ff1615612f0c576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481d1c985b9cd9995c9c9959606a1b604482015290519081900360640190fd5b600080546001600160a01b038084166001600160a01b03199092168217928390556001805460ff60a81b1916600160a81b17905560408051939091168352602083019190915280517fb532073b38c83145e3e5135377a08bf9aab55bc0fd7c1179cd4fb995d2a5159c9281900390910190a150565b612f8961357d565b604280546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f49a4e3b1ee2ad2bfb1455dfad2d72e84e71a35c756d2c8296f305f12e1828bf59181900360200190a150565b60416020526000908152604090205481565b603b546040805163e62b888960e01b81526001600160a01b0384811660048301529151600093929092169163e62b888991602480820192602092909190829003018186803b15801561304057600080fd5b505afa158015613054573d6000803e3d6000fd5b505050506040513d602081101561306a57600080fd5b505180156130e757506001826001600160a01b031663b1c9fe6e6040518163ffffffff1660e01b815260040160206040518083038186803b1580156130ae57600080fd5b505afa1580156130c2573d6000803e3d6000fd5b505050506040513d60208110156130d857600080fd5b505160028111156130e557fe5b145b15611ae257600080836001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561312757600080fd5b505afa15801561313b573d6000803e3d6000fd5b505050506040513d604081101561315157600080fd5b50805160209182015160408051634dcb776760e11b815230600482015290519295509093506000926001600160a01b03861692639b96eece926024808201939291829003018186803b1580156131a657600080fd5b505afa1580156131ba573d6000803e3d6000fd5b505050506040513d60208110156131d057600080fd5b50511180613251575060408051634dcb776760e11b815230600482015290516000916001600160a01b03841691639b96eece91602480820192602092909190829003018186803b15801561322357600080fd5b505afa158015613237573d6000803e3d6000fd5b505050506040513d602081101561324d57600080fd5b5051115b1561326157600192505050611ae6565b5050506000919050565b6000806132788484614656565b50949350505050565b61328961357d565b600082815260476020908152604091829020839055815184815290810183905281517f5af395595015797b4d0f26b77c38dd4831298dabc7906ee3d62b80fa75d35c1e929181900390910190a15050565b6049546001600160a01b031681565b60435481565b60405481565b60055460ff1615613343576040805162461bcd60e51b8152602060048201526013602482015272105b1c9958591e481a5b9a5d1a585b1a5e9959606a1b604482015290519081900360640190fd5b6005805460ff19166001908117909155600455565b61336061357d565b603a546040805163a9059cbb60e01b81526001600160a01b038581166004830152602482018590529151919092169163a9059cbb9160448083019260209291908290030181600087803b1580156133b657600080fd5b505af11580156133ca573d6000803e3d6000fd5b505050506040513d60208110156133e057600080fd5b50505050565b60006133f183611945565b15611f0a576000613408603d546110108686611d12565b90506134158484836148d9565b915050611f0e565b603f6020526000908152604090205481565b61343761357d565b603c8190556040805182815290517fcc72495e91bfc45ec11465a752fc2866b8a5ef8960b0925774ede927ee7cbdbe9181900360200190a150565b61347a61357d565b603d8190556040805182815290517f1e6a338a58debcc786781a079c4459466b102ad0156cc84f51d25ef7dd8cb9b09181900360200190a150565b603954604080516315905ec160e31b81526004810184905290516000926001600160a01b03169163ac82f608916024808301926020929190829003018186803b15801561350157600080fd5b505afa158015613515573d6000803e3d6000fd5b505050506040513d602081101561352b57600080fd5b505161353957506000611ae6565b6000828152604760205260409020546135555750603c54611ae6565b5060009081526047602052604090205490565b603c5481565b6044546001600160a01b031681565b6000546001600160a01b031633146135c65760405162461bcd60e51b815260040180806020018281038252602f815260200180615492602f913960400191505060405180910390fd5b565b60008282111561361f576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b60008060006136348686614656565b9150915060008083116136655784821161365d57613658858363ffffffff6135c816565b613660565b60005b613675565b613675838663ffffffff61378b16565b90506000858311613687576000613697565b613697838763ffffffff6135c816565b9050808210156136ae576000945050505050610d77565b6136bd88888886888688614a1f565b945050505050610d77565b6000826136d757506000611f0e565b828202828482816136e457fe5b0414610d775760405162461bcd60e51b81526004018080602001828103825260218152602001806154c16021913960400191505060405180910390fd5b6000808211613777576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b600082848161378257fe5b04949350505050565b600082820183811015610d77576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600060018310806137ff57506137fc8585846148d9565b83115b1561380c57506000610f93565b6000613840670de0b6b3a7640000610ca06138288989896144ea565b6123f7670de0b6b3a76400008863ffffffff6135c816565b9050613875670de0b6b3a7640000610ca06138688266470de4df82000063ffffffff61378b16565b849063ffffffff6136c816565b90506000613898670de0b6b3a7640000610ca0610c93878663ffffffff61378b16565b905060006138c8670de0b6b3a7640000610ca0610ce9604354670de0b6b3a764000061378b90919063ffffffff16565b603b546040805163edc892e160e01b81526004810184905290519293506001600160a01b039091169163edc892e191602480820192602092909190829003018186803b15801561391757600080fd5b505afa15801561392b573d6000803e3d6000fd5b505050506040513d602081101561394157600080fd5b505198975050505050505050565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b1790526133e0908590614b1f565b60006139e784610c426139cf604354670de0b6b3a76400006135c890919063ffffffff16565b610ca088670de0b6b3a764000063ffffffff6136c816565b60435490915015613a7d57603a546042546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b158015613a4b57600080fd5b505af1158015613a5f573d6000803e3d6000fd5b505050506040513d6020811015613a7557600080fd5b50613a819050565b5060005b603b54613b2b906001600160a01b03166317fd849a613aa6878563ffffffff61378b16565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015613ada57600080fd5b505afa158015613aee573d6000803e3d6000fd5b505050506040513d6020811015613b0457600080fd5b50516001600160a01b0387166000908152604160205260409020549063ffffffff61378b16565b6001600160a01b0380871660009081526041602090815260409182902093909355603b548151630bfec24d60e11b81526004810188905291519216926317fd849a92602480840193829003018186803b158015613b8757600080fd5b505afa158015613b9b573d6000803e3d6000fd5b505050506040513d6020811015613bb157600080fd5b50516001600160a01b03861660009081526041602052604090205411613bef576001600160a01b038516600090815260416020526040812055613ca7565b603b5460408051630bfec24d60e11b8152600481018690529051613c8d926001600160a01b0316916317fd849a916024808301926020929190829003018186803b158015613c3c57600080fd5b505afa158015613c50573d6000803e3d6000fd5b505050506040513d6020811015613c6657600080fd5b50516001600160a01b0387166000908152604160205260409020549063ffffffff6135c816565b6001600160a01b0386166000908152604160205260409020555b6000604a54118015613cc357506049546001600160a01b031615155b15613d13576000613d0685610c42613cee604a54670de0b6b3a76400006135c890919063ffffffff16565b610ca089670de0b6b3a764000063ffffffff6136c816565b9050611853838287614cd7565b5050505050565b613d2385611945565b613d74576040805162461bcd60e51b815260206004820152601e60248201527f4d61726b6574206973206e6f7420696e2054726164696e672070686173650000604482015290519081900360640190fd5b6000613d86603d546110108888611d12565b90506000613d958787846148d9565b905080851115613de4576040805162461bcd60e51b81526020600482015260156024820152742737ba1032b737bab3b4103634b8bab4b234ba3c9760591b604482015290519081900360640190fd5b6000613df2888888866137e5565b603a54604080516370a0823160e01b8152336004820152905192935083926001600160a01b03909216916370a0823191602480820192602092909190829003018186803b158015613e4257600080fd5b505afa158015613e56573d6000803e3d6000fd5b505050506040513d6020811015613e6c57600080fd5b50511015613ec1576040805162461bcd60e51b815260206004820152601a60248201527f596f7520646f6e74206861766520656e6f75676820735553442e000000000000604482015290519081900360640190fd5b603a5460408051636eb1769f60e11b8152336004820152306024820152905183926001600160a01b03169163dd62ed3e916044808301926020929190829003018186803b158015613f1157600080fd5b505afa158015613f25573d6000803e3d6000fd5b505050506040513d6020811015613f3b57600080fd5b50511015613f80576040805162461bcd60e51b815260206004820152600d60248201526c27379030b63637bbb0b731b29760991b604482015290519081900360640190fd5b613f98670de0b6b3a76400008563ffffffff61378b16565b613fb486610ca084670de0b6b3a764000063ffffffff6136c816565b1115613ffb576040805162461bcd60e51b81526020600482015260116024820152700a6d8d2e0e0c2ceca40e8dede40d0d2ced607b1b604482015290519081900360640190fd5b603a54614019906001600160a01b031633308463ffffffff61394f16565b6000614026898989614e46565b9050801561421157603b546040805163edc892e160e01b81526004810184905290516001600160a01b039092169163edc892e191602480820192602092909190829003018186803b15801561407a57600080fd5b505afa15801561408e573d6000803e3d6000fd5b505050506040513d60208110156140a457600080fd5b5051603a54604080516370a0823160e01b815230600482015290516001600160a01b03909216916370a0823191602480820192602092909190829003018186803b1580156140f157600080fd5b505afa158015614105573d6000803e3d6000fd5b505050506040513d602081101561411b57600080fd5b50511015614170576040805162461bcd60e51b815260206004820152601c60248201527f4e6f7420656e6f756768207355534420696e20636f6e74726163742e00000000604482015290519081900360640190fd5b886001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156141b657600080fd5b505af11580156141ca573d6000803e3d6000fd5b5050506001600160a01b038a166000908152604160205260409020546141f791508263ffffffff61378b16565b6001600160a01b038a166000908152604160205260409020555b6000808a6001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561424c57600080fd5b505afa158015614260573d6000803e3d6000fd5b505050506040513d604081101561427657600080fd5b50805160209091015190925090506000808b600181111561429357fe5b1461429e57816142a0565b825b6040805163a9059cbb60e01b8152336004820152602481018d905290519192506001600160a01b0383169163a9059cbb916044808201926020929091908290030181600087803b1580156142f357600080fd5b505af1158015614307573d6000803e3d6000fd5b505050506040513d602081101561431d57600080fd5b50506044546001600160a01b0316156143995760448054604080516302c7739b60e01b81523360048201526024810189905290516001600160a01b03909216926302c7739b92828201926000929082900301818387803b15801561438057600080fd5b505af1158015614394573d6000803e3d6000fd5b505050505b6143a48c8633614e79565b7ff3bfbc0822d1ed667a2b298e71e0304f2c1f4685398189d7c39e412f733150f4338d8d8d89603a60009054906101000a90046001600160a01b03168760405180886001600160a01b03166001600160a01b03168152602001876001600160a01b03166001600160a01b0316815260200186600181111561442157fe5b60ff1681526020810195909552506040808501939093526001600160a01b039182166060850152166080830152519081900360a0019350915050a1505050505050505050505050565b600060038211156144ad575080600160028204015b818110156144a75780915060028182858161449657fe5b04018161449f57fe5b04905061447f565b50611ae6565b8115611ae657506001919050565b60006144c682615156565b6ec097ce7bc90715b34b9f1000000000816144dd57fe5b0492915050565b303b1590565b60008060006144f98686614656565b91509150600084831161450d57600061451d565b61451d838663ffffffff6135c816565b9050600085841161454d5761454861453b878663ffffffff6135c816565b849063ffffffff61378b16565b61454f565b825b9050808210614565576000945050505050610d77565b6136bd888888868886886151e5565b6000806145818484611d12565b90506045548111158061459657506046548110155b156145a5576000915050611f0e565b600061102a670de0b6b3a7640000610ca06145cf610c7e6002603e5461372190919063ffffffff16565b603d546123f790879063ffffffff6135c816565b600080826001600160a01b03166341bc7b1f6040518163ffffffff1660e01b815260040160606040518083038186803b15801561461f57600080fd5b505afa158015614633573d6000803e3d6000fd5b505050506040513d606081101561464957600080fd5b50519050610d77816134b5565b600080600080856001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b15801561469457600080fd5b505afa1580156146a8573d6000803e3d6000fd5b505050506040513d60408110156146be57600080fd5b50805160209091015190925090506000808660018111156146db57fe5b146147575760408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b15801561472657600080fd5b505afa15801561473a573d6000803e3d6000fd5b505050506040513d602081101561475057600080fd5b50516147ca565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b15801561479d57600080fd5b505afa1580156147b1573d6000803e3d6000fd5b505050506040513d60208110156147c757600080fd5b50515b90506000808760018111156147db57fe5b146148575760408051634dcb776760e11b815230600482015290516001600160a01b03861691639b96eece916024808301926020929190829003018186803b15801561482657600080fd5b505afa15801561483a573d6000803e3d6000fd5b505050506040513d602081101561485057600080fd5b50516148ca565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b15801561489d57600080fd5b505afa1580156148b1573d6000803e3d6000fd5b505050506040513d60208110156148c757600080fd5b50515b91989197509095505050505050565b6000604554821115806148ee57506046548210155b156148fb57506000610d77565b6000614907858561527e565b90506000614948670de0b6b3a7640000610ca06149306002603e5461372190919063ffffffff16565b6123f7670de0b6b3a76400008963ffffffff6135c816565b9050600061495f610c7e868463ffffffff61378b16565b9050600061497f670de0b6b3a7640000610ca0868963ffffffff6136c816565b6001600160a01b0389166000908152604160205260409020549091506149a8826110108b6145e3565b116149ba576000945050505050610d77565b6001600160a01b0388166000908152604160205260408120546149e490610c42846110108d6145e3565b9050614a12614a0584610ca084670de0b6b3a764000063ffffffff6136c816565b869063ffffffff61378b16565b9998505050505050505050565b600080614a4086610c42614a338c8c612bfa565b889063ffffffff61378b16565b90506000614a54848663ffffffff6135c816565b90506000614a88670de0b6b3a7640000610ca0614a798682878563ffffffff6136c816565b603e549063ffffffff6136c816565b90508715614ad9576000614aa382600263ffffffff61372116565b90506000614abb826123f78d8c63ffffffff6135c816565b9050614acd818c63ffffffff61372116565b95505050505050614b14565b866000614afd670de0b6b3a7640000610ca0614a798882878563ffffffff6136c816565b9050614acd6002610ca0858463ffffffff61378b16565b979650505050505050565b614b31826001600160a01b03166153fb565b614b82576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b60208310614bc05780518252601f199092019160209182019101614ba1565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114614c22576040519150601f19603f3d011682016040523d82523d6000602084013e614c27565b606091505b509150915081614c7e576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b8051156133e057808060200190516020811015614c9a57600080fd5b50516133e05760405162461bcd60e51b815260040180806020018281038252602a81526020018061554c602a913960400191505060405180910390fd5b60495460408051639ca423b360e01b81526001600160a01b03868116600483015291516000939290921691639ca423b391602480820192602092909190829003018186803b158015614d2857600080fd5b505afa158015614d3c573d6000803e3d6000fd5b505050506040513d6020811015614d5257600080fd5b505190506001600160a01b038116156133e057604a54156133e057603a546040805163a9059cbb60e01b81526001600160a01b038481166004830152602482018790529151919092169163a9059cbb9160448083019260209291908290030181600087803b158015614dc357600080fd5b505af1158015614dd7573d6000803e3d6000fd5b505050506040513d6020811015614ded57600080fd5b5050604080516001600160a01b038084168252861660208201528082018590526060810184905290517f8fa68a6a8e2fc9ff758a6e64afba8bc2f66fb082999a2c5225c8c49633faded49181900360800190a150505050565b600080614e53858561527e565b90506000915082811015614e715761102a838263ffffffff6135c816565b509392505050565b6000614ec3614eb6614e9e604354670de0b6b3a764000061378b90919063ffffffff16565b610ca086670de0b6b3a764000063ffffffff6136c816565b849063ffffffff6135c816565b60435490915015614f5957603a546042546040805163a9059cbb60e01b81526001600160a01b039283166004820152602481018590529051919092169163a9059cbb9160448083019260209291908290030181600087803b158015614f2757600080fd5b505af1158015614f3b573d6000803e3d6000fd5b505050506040513d6020811015614f5157600080fd5b50614f5d9050565b5060005b603b546001600160a01b03166317fd849a614f7e858463ffffffff6135c816565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b158015614fb257600080fd5b505afa158015614fc6573d6000803e3d6000fd5b505050506040513d6020811015614fdc57600080fd5b50516001600160a01b0385166000908152604160205260409020541161501a576001600160a01b0384166000908152604160205260408120556150de565b603b546150c4906001600160a01b03166317fd849a61503f868563ffffffff6135c816565b6040518263ffffffff1660e01b81526004018082815260200191505060206040518083038186803b15801561507357600080fd5b505afa158015615087573d6000803e3d6000fd5b505050506040513d602081101561509d57600080fd5b50516001600160a01b0386166000908152604160205260409020549063ffffffff6135c816565b6001600160a01b0385166000908152604160205260409020555b6000604a541180156150fa57506049546001600160a01b031615155b156133e057600061514961513c615124604a54670de0b6b3a764000061378b90919063ffffffff16565b610ca087670de0b6b3a764000063ffffffff6136c816565b859063ffffffff6135c816565b9050613d13838286614cd7565b60385460408051632e4c697f60e01b81526725b94542080c8000600482018190526024820185905291516000936001600160a01b031691632e4c697f916044808301926020929190829003018186803b1580156151b257600080fd5b505afa1580156151c6573d6000803e3d6000fd5b505050506040513d60208110156151dc57600080fd5b50519392505050565b60008061520685610c426151f98c8c6133e6565b899063ffffffff61378b16565b9050600061521a858563ffffffff6135c816565b9050600061523f670de0b6b3a7640000610ca0614a798682878563ffffffff6136c816565b9050861561525a576000614aa382600263ffffffff61372116565b876000614afd670de0b6b3a7640000610ca0614a798882878563ffffffff6136c816565b6000806000846001600160a01b031663cc2ee1966040518163ffffffff1660e01b8152600401604080518083038186803b1580156152bb57600080fd5b505afa1580156152cf573d6000803e3d6000fd5b505050506040513d60408110156152e557600080fd5b508051602090910151909250905060008085600181111561530257fe5b1461537e5760408051634dcb776760e11b815230600482015290516001600160a01b03841691639b96eece916024808301926020929190829003018186803b15801561534d57600080fd5b505afa158015615361573d6000803e3d6000fd5b505050506040513d602081101561537757600080fd5b50516153f1565b60408051634dcb776760e11b815230600482015290516001600160a01b03851691639b96eece916024808301926020929190829003018186803b1580156153c457600080fd5b505afa1580156153d8573d6000803e3d6000fd5b505050506040513d60208110156153ee57600080fd5b50515b9695505050505050565b3b15159056fe4f6e6c792077686974656c697374656420616464726573736573206f72206f776e65722063616e206368616e676520495621596f75206d757374206265206e6f6d696e61746564206265666f726520796f752063616e20616363657074206f776e657273686970416c726561647920696e697469616c697a65642c20757365206e6f6d696e6174654e65774f776e65724f6e6c792074686520636f6e7472616374206f776e6572206d617920706572666f726d207468697320616374696f6e536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f77436f6e747261637420696e7374616e63652068617320616c7265616479206265656e20696e697469616c697a65645468697320616374696f6e2063616e6e6f7420626520706572666f726d6564207768696c652074686520636f6e7472616374206973207061757365645361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564a265627a7a7231582034e1e06e9bbdf270fd11894e3ce3fcf42b01429e9ff746b38a58496abf1592d564736f6c63430005100032
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.