Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- TWAP_Oracle
- Optimization enabled
- true
- Compiler version
- v0.6.6+commit.6c089d02
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2022-08-19T04:05:26.729561Z
Contract source code
// File @uniswap/lib/contracts/libraries/FullMath.sol@v2.1.0 // SPDX-License-Identifier: CC-BY-4.0 AND GPL-3.0-or-later pragma solidity >=0.4.0; // taken from https://medium.com/coinmonks/math-in-solidity-part-3-percents-and-proportions-4db014e080b1 // license is CC-BY-4.0 library FullMath { function fullMul(uint256 x, uint256 y) private pure returns (uint256 l, uint256 h) { uint256 mm = mulmod(x, y, uint256(-1)); l = x * y; h = mm - l; if (mm < l) h -= 1; } function fullDiv( uint256 l, uint256 h, uint256 d ) private pure returns (uint256) { uint256 pow2 = d & -d; d /= pow2; l /= pow2; l += h * ((-pow2) / pow2 + 1); uint256 r = 1; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; r *= 2 - d * r; return l * r; } function mulDiv( uint256 x, uint256 y, uint256 d ) internal pure returns (uint256) { (uint256 l, uint256 h) = fullMul(x, y); uint256 mm = mulmod(x, y, d); if (mm > l) h -= 1; l -= mm; require(h < d, 'FullMath: FULLDIV_OVERFLOW'); return fullDiv(l, h, d); } } // File @uniswap/lib/contracts/libraries/Babylonian.sol@v2.1.0 pragma solidity >=0.4.0; // computes square roots using the babylonian method // https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method library Babylonian { function sqrt(uint256 y) internal pure returns (uint256 z) { if (y > 3) { z = y; uint256 x = y / 2 + 1; while (x < z) { z = x; x = (y / x + x) / 2; } } else if (y != 0) { z = 1; } // else z = 0 } } // File @uniswap/lib/contracts/libraries/BitMath.sol@v2.1.0 pragma solidity >=0.5.0; library BitMath { function mostSignificantBit(uint256 x) internal pure returns (uint8 r) { require(x > 0, 'BitMath: ZERO'); if (x >= 0x100000000000000000000000000000000) { x >>= 128; r += 128; } if (x >= 0x10000000000000000) { x >>= 64; r += 64; } if (x >= 0x100000000) { x >>= 32; r += 32; } if (x >= 0x10000) { x >>= 16; r += 16; } if (x >= 0x100) { x >>= 8; r += 8; } if (x >= 0x10) { x >>= 4; r += 4; } if (x >= 0x4) { x >>= 2; r += 2; } if (x >= 0x2) r += 1; } } // File @uniswap/lib/contracts/libraries/FixedPoint.sol@v2.1.0 pragma solidity >=0.4.0; // a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format)) library FixedPoint { // range: [0, 2**112 - 1] // resolution: 1 / 2**112 struct uq112x112 { uint224 _x; } // range: [0, 2**144 - 1] // resolution: 1 / 2**112 struct uq144x112 { uint256 _x; } uint8 private constant RESOLUTION = 112; uint256 private constant Q112 = 0x10000000000000000000000000000; uint256 private constant Q224 = 0x100000000000000000000000000000000000000000000000000000000; uint256 private constant LOWER_MASK = 0xffffffffffffffffffffffffffff; // decimal of UQ*x112 (lower 112 bits) // encode a uint112 as a UQ112x112 function encode(uint112 x) internal pure returns (uq112x112 memory) { return uq112x112(uint224(x) << RESOLUTION); } // encodes a uint144 as a UQ144x112 function encode144(uint144 x) internal pure returns (uq144x112 memory) { return uq144x112(uint256(x) << RESOLUTION); } // decode a UQ112x112 into a uint112 by truncating after the radix point function decode(uq112x112 memory self) internal pure returns (uint112) { return uint112(self._x >> RESOLUTION); } // decode a UQ144x112 into a uint144 by truncating after the radix point function decode144(uq144x112 memory self) internal pure returns (uint144) { return uint144(self._x >> RESOLUTION); } // multiply a UQ112x112 by a uint, returning a UQ144x112 // reverts on overflow function mul(uq112x112 memory self, uint256 y) internal pure returns (uq144x112 memory) { uint256 z = 0; require(y == 0 || (z = self._x * y) / y == self._x, 'FixedPoint: MUL_OVERFLOW'); return uq144x112(z); } // multiply a UQ112x112 by an int and decode, returning an int // reverts on overflow function muli(uq112x112 memory self, int256 y) internal pure returns (int256) { uint256 z = FullMath.mulDiv(self._x, uint256(y < 0 ? -y : y), Q112); require(z < 2**255, 'FixedPoint: MULI_OVERFLOW'); return y < 0 ? -int256(z) : int256(z); } // multiply a UQ112x112 by a UQ112x112, returning a UQ112x112 // lossy function muluq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { if (self._x == 0 || other._x == 0) { return uq112x112(0); } uint112 upper_self = uint112(self._x >> RESOLUTION); // * 2^0 uint112 lower_self = uint112(self._x & LOWER_MASK); // * 2^-112 uint112 upper_other = uint112(other._x >> RESOLUTION); // * 2^0 uint112 lower_other = uint112(other._x & LOWER_MASK); // * 2^-112 // partial products uint224 upper = uint224(upper_self) * upper_other; // * 2^0 uint224 lower = uint224(lower_self) * lower_other; // * 2^-224 uint224 uppers_lowero = uint224(upper_self) * lower_other; // * 2^-112 uint224 uppero_lowers = uint224(upper_other) * lower_self; // * 2^-112 // so the bit shift does not overflow require(upper <= uint112(-1), 'FixedPoint: MULUQ_OVERFLOW_UPPER'); // this cannot exceed 256 bits, all values are 224 bits uint256 sum = uint256(upper << RESOLUTION) + uppers_lowero + uppero_lowers + (lower >> RESOLUTION); // so the cast does not overflow require(sum <= uint224(-1), 'FixedPoint: MULUQ_OVERFLOW_SUM'); return uq112x112(uint224(sum)); } // divide a UQ112x112 by a UQ112x112, returning a UQ112x112 function divuq(uq112x112 memory self, uq112x112 memory other) internal pure returns (uq112x112 memory) { require(other._x > 0, 'FixedPoint: DIV_BY_ZERO_DIVUQ'); if (self._x == other._x) { return uq112x112(uint224(Q112)); } if (self._x <= uint144(-1)) { uint256 value = (uint256(self._x) << RESOLUTION) / other._x; require(value <= uint224(-1), 'FixedPoint: DIVUQ_OVERFLOW'); return uq112x112(uint224(value)); } uint256 result = FullMath.mulDiv(Q112, self._x, other._x); require(result <= uint224(-1), 'FixedPoint: DIVUQ_OVERFLOW'); return uq112x112(uint224(result)); } // returns a UQ112x112 which represents the ratio of the numerator to the denominator // lossy function fraction(uint112 numerator, uint112 denominator) internal pure returns (uq112x112 memory) { require(denominator > 0, 'FixedPoint: DIV_BY_ZERO_FRACTION'); return uq112x112((uint224(numerator) << RESOLUTION) / denominator); } // take the reciprocal of a UQ112x112 // reverts on overflow // lossy function reciprocal(uq112x112 memory self) internal pure returns (uq112x112 memory) { require(self._x > 1, 'FixedPoint: DIV_BY_ZERO_RECIPROCAL_OR_OVERFLOW'); return uq112x112(uint224(Q224 / self._x)); } // square root of a UQ112x112 // lossy between 0/1 and 40 bits function sqrt(uq112x112 memory self) internal pure returns (uq112x112 memory) { if (self._x <= uint144(-1)) { return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << 112))); } uint8 safeShiftBits = 255 - BitMath.mostSignificantBit(self._x); safeShiftBits -= safeShiftBits % 2; return uq112x112(uint224(Babylonian.sqrt(uint256(self._x) << safeShiftBits) << ((112 - safeShiftBits) / 2))); } } // File @uniswap/v2-core/contracts/interfaces/IUniswapV2Pair.sol@v1.0.0 pragma solidity >=0.5.0; interface IUniswapV2Pair { event Approval(address indexed owner, address indexed spender, uint value); event Transfer(address indexed from, address indexed to, uint value); function name() external pure returns (string memory); function symbol() external pure returns (string memory); function decimals() external pure returns (uint8); function totalSupply() external view returns (uint); function balanceOf(address owner) external view returns (uint); function allowance(address owner, address spender) external view returns (uint); function approve(address spender, uint value) external returns (bool); function transfer(address to, uint value) external returns (bool); function transferFrom(address from, address to, uint value) external returns (bool); function DOMAIN_SEPARATOR() external view returns (bytes32); function PERMIT_TYPEHASH() external pure returns (bytes32); function nonces(address owner) external view returns (uint); function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external; event Mint(address indexed sender, uint amount0, uint amount1); event Burn(address indexed sender, uint amount0, uint amount1, address indexed to); event Swap( address indexed sender, uint amount0In, uint amount1In, uint amount0Out, uint amount1Out, address indexed to ); event Sync(uint112 reserve0, uint112 reserve1); function MINIMUM_LIQUIDITY() external pure returns (uint); function factory() external view returns (address); function token0() external view returns (address); function token1() external view returns (address); function getReserves() external view returns (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast); function price0CumulativeLast() external view returns (uint); function price1CumulativeLast() external view returns (uint); function kLast() external view returns (uint); function mint(address to) external returns (uint liquidity); function burn(address to) external returns (uint amount0, uint amount1); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; function initialize(address, address) external; } // File @uniswap/v2-periphery/contracts/libraries/UniswapV2OracleLibrary.sol@v1.1.0-beta.0 pragma solidity >=0.5.0; // library with helper methods for oracles that are concerned with computing average prices library UniswapV2OracleLibrary { using FixedPoint for *; // helper function that returns the current block timestamp within the range of uint32, i.e. [0, 2**32 - 1] function currentBlockTimestamp() internal view returns (uint32) { return uint32(block.timestamp % 2 ** 32); } // produces the cumulative price using counterfactuals to save gas and avoid a call to sync. function currentCumulativePrices( address pair ) internal view returns (uint price0Cumulative, uint price1Cumulative, uint32 blockTimestamp) { blockTimestamp = currentBlockTimestamp(); price0Cumulative = IUniswapV2Pair(pair).price0CumulativeLast(); price1Cumulative = IUniswapV2Pair(pair).price1CumulativeLast(); // if time has elapsed since the last update on the pair, mock the accumulated price values (uint112 reserve0, uint112 reserve1, uint32 blockTimestampLast) = IUniswapV2Pair(pair).getReserves(); if (blockTimestampLast != blockTimestamp) { // subtraction overflow is desired uint32 timeElapsed = blockTimestamp - blockTimestampLast; // addition overflow is desired // counterfactual price0Cumulative += uint(FixedPoint.fraction(reserve1, reserve0)._x) * timeElapsed; // counterfactual price1Cumulative += uint(FixedPoint.fraction(reserve0, reserve1)._x) * timeElapsed; } } } // File contracts/TWAP_Oracle.sol //based on: https://github.com/Uniswap/uniswap-v2-periphery/tree/master/contracts/examples pragma solidity =0.6.6; pragma experimental ABIEncoderV2; //import "@openzeppelin/contracts/access/Ownable.sol"; //copy of Ownable contract to avoid conflicts for not satisfying compiler requirements in OpenZeppelin's latest version contract Ownable { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); constructor() public { _owner = msg.sender; emit OwnershipTransferred(address(0), msg.sender); } function owner() public view virtual returns (address) { return _owner; } modifier onlyOwner() { require(owner() == msg.sender, "Ownable: caller is not the owner"); _; } function renounceOwnership() public virtual onlyOwner { emit OwnershipTransferred(_owner, address(0)); _owner = address(0); } function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } // fixed window oracle that recomputes the average price for the entire period once every period // note that the price average is only guaranteed to be over at least 1 period, but may be over a longer period contract TWAP_Oracle is Ownable { using FixedPoint for *; struct Observation { uint256 timestamp; uint256 price0CumulativeLast; uint256 price1CumulativeLast; FixedPoint.uq112x112 price0Average; FixedPoint.uq112x112 price1Average; } uint256 public constant PERIOD = 24 hours; //pangolin factory address public DEFAULT_FACTORY = 0xc08BAEA14C14f25bcafe3e3E05550715505eF3dE; //0x4FD2c40c25Dd40e9Bf0CE8479bA384178b8671b5 //Photon //0xc08BAEA14C14f25bcafe3e3E05550715505eF3dE; //Jupiter // 0x4FD2c40c25Dd40e9Bf0CE8479bA384178b8671b5; //Photon //stored price/trading observations mapping(address => Observation) public observations; //used for tokens that need a factory other than the default mapping(address => mapping(address => address)) public factories; //used for mapping factories to their pair init code hashes, used for calculating token pairs mapping(address => bytes) public factoryInitCodes; constructor() public { //PhotonSwap setFactoryInitCode(0x4FD2c40c25Dd40e9Bf0CE8479bA384178b8671b5, hex'01429e880a7972ebfbba904a5bbe32a816e78273e4b38ffa6bdeaebce8adba7c'); //SurfSwap setFactoryInitCode(0x9Ad6C38BE94206cA50bb0d90783181662f0Cfa10, hex'264c1de3eeed2e504a9ab050bbf99605f60533201a80002288df57d4ef5303af'); //Jupiter setFactoryInitCode(0xc08BAEA14C14f25bcafe3e3E05550715505eF3dE, hex'fdf760493f1e4ae13158510dc320f5b0d7766fc0017d7bbac0bb4116485b3db9'); } // calculates the CREATE2 address for a pair without making any external calls function pairFor(address factory, address tokenA, address tokenB) public view returns (address pair) { (address token0, address token1) = sortTokens(tokenA, tokenB); pair = address(uint(keccak256(abi.encodePacked( hex"ff", factory, keccak256(abi.encodePacked(token0, token1)), factoryInitCodes[factory] // init code hash )))); } // note this will always return 0 before update has been called successfully for the first time for the pair. function consult(address tokenA, address tokenB, address tokenIn, uint256 amountIn) public view returns (uint256 amountOut) { address factory = _getFactory(tokenA, tokenB); address pair = pairFor(factory, tokenA, tokenB); address token0 = IUniswapV2Pair(pair).token0(); address token1 = IUniswapV2Pair(pair).token1(); if (tokenIn == token0) { amountOut = observations[pair].price0Average.mul(amountIn).decode144(); } else { require(tokenIn == token1, 'TWAP_Oracle: invalid tokenIn'); amountOut = observations[pair].price1Average.mul(amountIn).decode144(); } } function consultWithUpdate(address tokenA, address tokenB, address tokenIn, uint256 amountIn) external returns (uint256 amountOut) { update(tokenA, tokenB); return consult(tokenA, tokenB, tokenIn, amountIn); } // update the cumulative price for the observation at the current timestamp. each observation is updated at most // once per epoch period. function update(address tokenA, address tokenB) public { address factory = _getFactory(tokenA, tokenB); address pair = pairFor(factory, tokenA, tokenB); // we only want to commit updates once per period (i.e. windowSize / granularity) uint256 timeElapsed = block.timestamp - observations[pair].timestamp; if (timeElapsed > PERIOD) { //PERIOD (uint256 price0Cumulative, uint256 price1Cumulative,) = UniswapV2OracleLibrary.currentCumulativePrices(pair); // leave price as zero if this is the first observation if (timeElapsed < block.timestamp) { // overflow is desired, casting never truncates // cumulative price is in (uq112x112 price * seconds) units so we simply wrap it after division by time elapsed observations[pair].price0Average = FixedPoint.uq112x112(uint224((price0Cumulative - observations[pair].price0CumulativeLast) / timeElapsed)); observations[pair].price1Average = FixedPoint.uq112x112(uint224((price1Cumulative - observations[pair].price1CumulativeLast) / timeElapsed)); } observations[pair].timestamp = block.timestamp; observations[pair].price0CumulativeLast = price0Cumulative; observations[pair].price1CumulativeLast = price1Cumulative; } } function setFactoryInitCode(address factory, bytes memory initCode) public onlyOwner { factoryInitCodes[factory] = initCode; } function setFactory(address tokenA, address tokenB, address factory) public onlyOwner { factories[tokenA][tokenB] = factory; factories[tokenB][tokenA] = factory; //update observation for pair while leaving price the same as before, in case we have switched back to this factory from another factory address pair = pairFor(factory, tokenA, tokenB); (uint256 price0Cumulative, uint256 price1Cumulative,) = UniswapV2OracleLibrary.currentCumulativePrices(pair); observations[pair].timestamp = block.timestamp; observations[pair].price0CumulativeLast = price0Cumulative; observations[pair].price1CumulativeLast = price1Cumulative; } function massSetFactory(address[] calldata tokenAs, address[] calldata tokenBs, address factory) external onlyOwner { require(tokenAs.length == tokenBs.length, "input length mismatch"); for (uint256 i = 0; i < tokenAs.length; i++) { setFactory(tokenAs[i], tokenBs[i], factory); } } function _getFactory(address tokenA, address tokenB) internal view returns(address) { if(factories[tokenA][tokenB] == address(0)) { return DEFAULT_FACTORY; } else { return factories[tokenA][tokenB]; } } // returns sorted token addresses, used to handle return values from pairs sorted in this order function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) { require(tokenA != tokenB, 'UniswapV2Library: IDENTICAL_ADDRESSES'); (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); require(token0 != address(0), 'UniswapV2Library: ZERO_ADDRESS'); } }
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[]},{"type":"event","name":"OwnershipTransferred","inputs":[{"type":"address","name":"previousOwner","internalType":"address","indexed":true},{"type":"address","name":"newOwner","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"DEFAULT_FACTORY","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"PERIOD","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"consult","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"amountOut","internalType":"uint256"}],"name":"consultWithUpdate","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"tokenIn","internalType":"address"},{"type":"uint256","name":"amountIn","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factories","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"factoryInitCodes","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"massSetFactory","inputs":[{"type":"address[]","name":"tokenAs","internalType":"address[]"},{"type":"address[]","name":"tokenBs","internalType":"address[]"},{"type":"address","name":"factory","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"},{"type":"uint256","name":"price0CumulativeLast","internalType":"uint256"},{"type":"uint256","name":"price1CumulativeLast","internalType":"uint256"},{"type":"tuple","name":"price0Average","internalType":"struct FixedPoint.uq112x112","components":[{"type":"uint224","name":"_x","internalType":"uint224"}]},{"type":"tuple","name":"price1Average","internalType":"struct FixedPoint.uq112x112","components":[{"type":"uint224","name":"_x","internalType":"uint224"}]}],"name":"observations","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"owner","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"pair","internalType":"address"}],"name":"pairFor","inputs":[{"type":"address","name":"factory","internalType":"address"},{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"renounceOwnership","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFactory","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"},{"type":"address","name":"factory","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setFactoryInitCode","inputs":[{"type":"address","name":"factory","internalType":"address"},{"type":"bytes","name":"initCode","internalType":"bytes"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"transferOwnership","inputs":[{"type":"address","name":"newOwner","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"update","inputs":[{"type":"address","name":"tokenA","internalType":"address"},{"type":"address","name":"tokenB","internalType":"address"}]}]
Contract Creation Code
0x6080604052600180546001600160a01b03191673c08baea14c14f25bcafe3e3e05550715505ef3de1790553480156200003757600080fd5b50600080546001600160a01b0319163390811782556040519091907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a3620000d2734fd2c40c25dd40e9bf0ce8479ba384178b8671b56040518060400160405280602081526020017f01429e880a7972ebfbba904a5bbe32a816e78273e4b38ffa6bdeaebce8adba7c8152506200018e60201b60201c565b6200012d739ad6c38be94206ca50bb0d90783181662f0cfa106040518060400160405280602081526020017f264c1de3eeed2e504a9ab050bbf99605f60533201a80002288df57d4ef5303af8152506200018e60201b60201c565b6200018873c08baea14c14f25bcafe3e3e05550715505ef3de6040518060400160405280602081526020017ffdf760493f1e4ae13158510dc320f5b0d7766fc0017d7bbac0bb4116485b3db98152506200018e60201b60201c565b620002eb565b33620001a26001600160e01b036200020416565b6001600160a01b031614620001d45760405162461bcd60e51b8152600401620001cb90620002b6565b60405180910390fd5b6001600160a01b03821660009081526004602090815260409091208251620001ff9284019062000214565b505050565b6000546001600160a01b03165b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200025757805160ff191683800117855562000287565b8280016001018555821562000287579182015b82811115620002875782518255916020019190600101906200026a565b506200029592915062000299565b5090565b6200021191905b80821115620002955760008155600101620002a0565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6115ad80620002fb6000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80639653020e11610097578063b4d1d79511610066578063b4d1d795146101ed578063c640752d146101f5578063d92b006414610208578063f2fde38b1461021b576100f5565b80639653020e146101a157806396e6c337146101b4578063a94fabc5146101c7578063acb0211b146101da576100f5565b80636d91c0e2116100d35780636d91c0e214610158578063715018a61461016b5780638a04ff3c146101755780638da5cb5b14610199576100f5565b806329f468fc146100fa57806352cefcd0146101235780635ad8960d14610143575b600080fd5b61010d61010836600461101c565b61022e565b60405161011a91906114f7565b60405180910390f35b610136610131366004610f5b565b610449565b60405161011a91906112db565b61014b6104e4565b60405161011a91906112c7565b61014b610166366004610fd2565b6104f3565b610173610578565b005b610188610183366004610f5b565b6105f1565b60405161011a959493929190611500565b61014b61063f565b61014b6101af366004610f9a565b61064f565b61010d6101c236600461101c565b610675565b6101736101d5366004610fd2565b610696565b6101736101e836600461106c565b610768565b61010d6107c5565b610173610203366004610f9a565b6107cc565b61017361021636600461111c565b61093e565b610173610229366004610f5b565b6109f2565b60008061023b8686610aa2565b9050600061024a8288886104f3565b90506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561028757600080fd5b505afa15801561029b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102bf9190610f7e565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156102fc57600080fd5b505afa158015610310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103349190610f7e565b9050816001600160a01b0316876001600160a01b031614156103ae576001600160a01b03831660009081526002602090815260409182902082519182019092526003909101546001600160e01b0316815261039e90610399908863ffffffff610b1216565b610b71565b6001600160901b0316945061043d565b806001600160a01b0316876001600160a01b0316146103e85760405162461bcd60e51b81526004016103df906113a3565b60405180910390fd5b6001600160a01b03831660009081526002602090815260409182902082519182019092526004909101546001600160e01b0316815261043190610399908863ffffffff610b1216565b6001600160901b031694505b50505050949350505050565b60046020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156104dc5780601f106104b1576101008083540402835291602001916104dc565b820191906000526020600020905b8154815290600101906020018083116104bf57829003601f168201915b505050505081565b6001546001600160a01b031681565b60008060006105028585610b78565b9150915085828260405160200161051a9291906111fe565b60408051601f1981840301815282825280516020918201206001600160a01b038b16600090815260048352929092206105569493909101611225565b60408051601f1981840301815291905280516020909101209695505050505050565b3361058161063f565b6001600160a01b0316146105a75760405162461bcd60e51b81526004016103df9061141f565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60026020818152600092835260409283902080546001820154938201548551808501875260038401546001600160e01b03908116825287519586019097526004909301549095168352939185565b6000546001600160a01b03165b90565b60036020908152600092835260408084209091529082529020546001600160a01b031681565b600061068185856107cc565b61068d8585858561022e565b95945050505050565b3361069f61063f565b6001600160a01b0316146106c55760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b0380841660008181526003602081815260408084208887168552825280842080549688166001600160a01b0319978816811790915592825280842094845293905291812080549093169091179091556107268285856104f3565b905060008061073483610c02565b506001600160a01b039094166000908152600260208190526040909120428155600181019290925501929092555050505050565b3361077161063f565b6001600160a01b0316146107975760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b038216600090815260046020908152604090912082516107c092840190610e5c565b505050565b6201518081565b60006107d88383610aa2565b905060006107e78285856104f3565b6001600160a01b0381166000908152600260205260409020549091504203620151808111156109375760008061081c84610c02565b50915091504283101561090b5760405180602001604052808460026000886001600160a01b03166001600160a01b031681526020019081526020016000206001015485038161086757fe5b046001600160e01b039081169091526001600160a01b03861660009081526002602081815260409283902094516003860180546001600160e01b031916919095161790935581519283019091529190910154819085908403816108c657fe5b046001600160e01b039081169091526001600160a01b03861660009081526002602052604090209151600490920180546001600160e01b031916929091169190911790555b6001600160a01b0384166000908152600260208190526040909120428155600181019390935591909101555b5050505050565b3361094761063f565b6001600160a01b03161461096d5760405162461bcd60e51b81526004016103df9061141f565b83821461098c5760405162461bcd60e51b81526004016103df9061132e565b60005b848110156109ea576109e28686838181106109a657fe5b90506020020160208101906109bb9190610f5b565b8585848181106109c757fe5b90506020020160208101906109dc9190610f5b565b84610696565b60010161098f565b505050505050565b336109fb61063f565b6001600160a01b031614610a215760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b038116610a475760405162461bcd60e51b81526004016103df9061135d565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382811660009081526003602090815260408083208585168452909152812054909116610ae257506001546001600160a01b0316610b0c565b506001600160a01b0380831660009081526003602090815260408083208585168452909152902054165b92915050565b610b1a610eda565b6000821580610b4057505082516001600160e01b031682810290838281610b3d57fe5b04145b610b5c5760405162461bcd60e51b81526004016103df90611454565b60408051602081019091529081529392505050565b5160701c90565b600080826001600160a01b0316846001600160a01b03161415610bad5760405162461bcd60e51b81526004016103df906113da565b826001600160a01b0316846001600160a01b031610610bcd578284610bd0565b83835b90925090506001600160a01b038216610bfb5760405162461bcd60e51b81526004016103df906114c0565b9250929050565b6000806000610c0f610dd7565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8291906111e6565b9250836001600160a01b0316635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b158015610cbd57600080fd5b505afa158015610cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf591906111e6565b91506000806000866001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015610d3557600080fd5b505afa158015610d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6d919061119d565b9250925092508363ffffffff168163ffffffff1614610dcd5780840363ffffffff8116610d9a8486610de1565b516001600160e01b031602969096019563ffffffff8116610dbb8585610de1565b516001600160e01b0316029590950194505b5050509193909250565b63ffffffff421690565b610de9610eed565b6000826001600160701b031611610e125760405162461bcd60e51b81526004016103df9061148b565b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b1681610e4757fe5b046001600160e01b0316815250905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e9d57805160ff1916838001178555610eca565b82800160010185558215610eca579182015b82811115610eca578251825591602001919060010190610eaf565b50610ed6929150610eff565b5090565b6040518060200160405280600081525090565b60408051602081019091526000815290565b61064c91905b80821115610ed65760008155600101610f05565b60008083601f840112610f2a578182fd5b50813567ffffffffffffffff811115610f41578182fd5b6020830191508360208083028501011115610bfb57600080fd5b600060208284031215610f6c578081fd5b8135610f778161154a565b9392505050565b600060208284031215610f8f578081fd5b8151610f778161154a565b60008060408385031215610fac578081fd5b8235610fb78161154a565b91506020830135610fc78161154a565b809150509250929050565b600080600060608486031215610fe6578081fd5b8335610ff18161154a565b925060208401356110018161154a565b915060408401356110118161154a565b809150509250925092565b60008060008060808587031215611031578081fd5b843561103c8161154a565b9350602085013561104c8161154a565b9250604085013561105c8161154a565b9396929550929360600135925050565b6000806040838503121561107e578182fd5b82356110898161154a565b9150602083013567ffffffffffffffff808211156110a5578283fd5b81850186601f8201126110b6578384fd5b80359250818311156110c6578384fd5b604051601f8401601f1916810160200183811182821017156110e6578586fd5b6040528381528184016020018810156110fd578485fd5b61110e84602083016020850161153e565b809450505050509250929050565b600080600080600060608688031215611133578081fd5b853567ffffffffffffffff8082111561114a578283fd5b61115689838a01610f19565b9097509550602088013591508082111561116e578283fd5b5061117b88828901610f19565b909450925050604086013561118f8161154a565b809150509295509295909350565b6000806000606084860312156111b1578283fd5b83516111bc81611562565b60208501519093506111cd81611562565b604085015190925063ffffffff81168114611011578182fd5b6000602082840312156111f7578081fd5b5051919050565b6bffffffffffffffffffffffff19606093841b811682529190921b16601482015260280190565b600060ff60f81b825260016bffffffffffffffffffffffff198660601b168184015284601584015260358285548381166000811461126a5760018114611285576112b9565b60ff1982168785015260028204607f168701840192506112b9565b6002820461129289611532565b875b828110156112b05781548a820188015290870190602001611294565b50508701840192505b509098975050505050505050565b6001600160a01b0391909116815260200190565b6000602080835283518082850152825b81811015611307578581018301518582016040015282016112eb565b818111156113185783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601590820152740d2dce0eae840d8cadccee8d040dad2e6dac2e8c6d605b1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f545741505f4f7261636c653a20696e76616c696420746f6b656e496e00000000604082015260600190565b60208082526025908201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604082015264455353455360d81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526018908201527f4669786564506f696e743a204d554c5f4f564552464c4f570000000000000000604082015260600190565b6020808252818101527f4669786564506f696e743a204449565f42595f5a45524f5f4652414354494f4e604082015260600190565b6020808252601e908201527f556e697377617056324c6962726172793a205a45524f5f414444524553530000604082015260600190565b90815260200190565b94855260208501939093526040840191909152516001600160e01b039081166060840152905116608082015260a00190565b60009081526020902090565b82818337506000910152565b6001600160a01b038116811461155f57600080fd5b50565b6001600160701b038116811461155f57600080fdfea2646970667358221220543723287cebef83a901d174eeffc6d7cbfd44f8c8d6424a6b10cbc72af1596b64736f6c63430006060033
Deployed ByteCode
0x608060405234801561001057600080fd5b50600436106100f55760003560e01c80639653020e11610097578063b4d1d79511610066578063b4d1d795146101ed578063c640752d146101f5578063d92b006414610208578063f2fde38b1461021b576100f5565b80639653020e146101a157806396e6c337146101b4578063a94fabc5146101c7578063acb0211b146101da576100f5565b80636d91c0e2116100d35780636d91c0e214610158578063715018a61461016b5780638a04ff3c146101755780638da5cb5b14610199576100f5565b806329f468fc146100fa57806352cefcd0146101235780635ad8960d14610143575b600080fd5b61010d61010836600461101c565b61022e565b60405161011a91906114f7565b60405180910390f35b610136610131366004610f5b565b610449565b60405161011a91906112db565b61014b6104e4565b60405161011a91906112c7565b61014b610166366004610fd2565b6104f3565b610173610578565b005b610188610183366004610f5b565b6105f1565b60405161011a959493929190611500565b61014b61063f565b61014b6101af366004610f9a565b61064f565b61010d6101c236600461101c565b610675565b6101736101d5366004610fd2565b610696565b6101736101e836600461106c565b610768565b61010d6107c5565b610173610203366004610f9a565b6107cc565b61017361021636600461111c565b61093e565b610173610229366004610f5b565b6109f2565b60008061023b8686610aa2565b9050600061024a8288886104f3565b90506000816001600160a01b0316630dfe16816040518163ffffffff1660e01b815260040160206040518083038186803b15801561028757600080fd5b505afa15801561029b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102bf9190610f7e565b90506000826001600160a01b031663d21220a76040518163ffffffff1660e01b815260040160206040518083038186803b1580156102fc57600080fd5b505afa158015610310573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103349190610f7e565b9050816001600160a01b0316876001600160a01b031614156103ae576001600160a01b03831660009081526002602090815260409182902082519182019092526003909101546001600160e01b0316815261039e90610399908863ffffffff610b1216565b610b71565b6001600160901b0316945061043d565b806001600160a01b0316876001600160a01b0316146103e85760405162461bcd60e51b81526004016103df906113a3565b60405180910390fd5b6001600160a01b03831660009081526002602090815260409182902082519182019092526004909101546001600160e01b0316815261043190610399908863ffffffff610b1216565b6001600160901b031694505b50505050949350505050565b60046020908152600091825260409182902080548351601f6002600019610100600186161502019093169290920491820184900484028101840190945280845290918301828280156104dc5780601f106104b1576101008083540402835291602001916104dc565b820191906000526020600020905b8154815290600101906020018083116104bf57829003601f168201915b505050505081565b6001546001600160a01b031681565b60008060006105028585610b78565b9150915085828260405160200161051a9291906111fe565b60408051601f1981840301815282825280516020918201206001600160a01b038b16600090815260048352929092206105569493909101611225565b60408051601f1981840301815291905280516020909101209695505050505050565b3361058161063f565b6001600160a01b0316146105a75760405162461bcd60e51b81526004016103df9061141f565b600080546040516001600160a01b03909116907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908390a3600080546001600160a01b0319169055565b60026020818152600092835260409283902080546001820154938201548551808501875260038401546001600160e01b03908116825287519586019097526004909301549095168352939185565b6000546001600160a01b03165b90565b60036020908152600092835260408084209091529082529020546001600160a01b031681565b600061068185856107cc565b61068d8585858561022e565b95945050505050565b3361069f61063f565b6001600160a01b0316146106c55760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b0380841660008181526003602081815260408084208887168552825280842080549688166001600160a01b0319978816811790915592825280842094845293905291812080549093169091179091556107268285856104f3565b905060008061073483610c02565b506001600160a01b039094166000908152600260208190526040909120428155600181019290925501929092555050505050565b3361077161063f565b6001600160a01b0316146107975760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b038216600090815260046020908152604090912082516107c092840190610e5c565b505050565b6201518081565b60006107d88383610aa2565b905060006107e78285856104f3565b6001600160a01b0381166000908152600260205260409020549091504203620151808111156109375760008061081c84610c02565b50915091504283101561090b5760405180602001604052808460026000886001600160a01b03166001600160a01b031681526020019081526020016000206001015485038161086757fe5b046001600160e01b039081169091526001600160a01b03861660009081526002602081815260409283902094516003860180546001600160e01b031916919095161790935581519283019091529190910154819085908403816108c657fe5b046001600160e01b039081169091526001600160a01b03861660009081526002602052604090209151600490920180546001600160e01b031916929091169190911790555b6001600160a01b0384166000908152600260208190526040909120428155600181019390935591909101555b5050505050565b3361094761063f565b6001600160a01b03161461096d5760405162461bcd60e51b81526004016103df9061141f565b83821461098c5760405162461bcd60e51b81526004016103df9061132e565b60005b848110156109ea576109e28686838181106109a657fe5b90506020020160208101906109bb9190610f5b565b8585848181106109c757fe5b90506020020160208101906109dc9190610f5b565b84610696565b60010161098f565b505050505050565b336109fb61063f565b6001600160a01b031614610a215760405162461bcd60e51b81526004016103df9061141f565b6001600160a01b038116610a475760405162461bcd60e51b81526004016103df9061135d565b600080546040516001600160a01b03808516939216917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e091a3600080546001600160a01b0319166001600160a01b0392909216919091179055565b6001600160a01b0382811660009081526003602090815260408083208585168452909152812054909116610ae257506001546001600160a01b0316610b0c565b506001600160a01b0380831660009081526003602090815260408083208585168452909152902054165b92915050565b610b1a610eda565b6000821580610b4057505082516001600160e01b031682810290838281610b3d57fe5b04145b610b5c5760405162461bcd60e51b81526004016103df90611454565b60408051602081019091529081529392505050565b5160701c90565b600080826001600160a01b0316846001600160a01b03161415610bad5760405162461bcd60e51b81526004016103df906113da565b826001600160a01b0316846001600160a01b031610610bcd578284610bd0565b83835b90925090506001600160a01b038216610bfb5760405162461bcd60e51b81526004016103df906114c0565b9250929050565b6000806000610c0f610dd7565b9050836001600160a01b0316635909c0d56040518163ffffffff1660e01b815260040160206040518083038186803b158015610c4a57600080fd5b505afa158015610c5e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c8291906111e6565b9250836001600160a01b0316635a3d54936040518163ffffffff1660e01b815260040160206040518083038186803b158015610cbd57600080fd5b505afa158015610cd1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf591906111e6565b91506000806000866001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b158015610d3557600080fd5b505afa158015610d49573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6d919061119d565b9250925092508363ffffffff168163ffffffff1614610dcd5780840363ffffffff8116610d9a8486610de1565b516001600160e01b031602969096019563ffffffff8116610dbb8585610de1565b516001600160e01b0316029590950194505b5050509193909250565b63ffffffff421690565b610de9610eed565b6000826001600160701b031611610e125760405162461bcd60e51b81526004016103df9061148b565b6040805160208101909152806001600160701b0384166dffffffffffffffffffffffffffff60701b607087901b1681610e4757fe5b046001600160e01b0316815250905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10610e9d57805160ff1916838001178555610eca565b82800160010185558215610eca579182015b82811115610eca578251825591602001919060010190610eaf565b50610ed6929150610eff565b5090565b6040518060200160405280600081525090565b60408051602081019091526000815290565b61064c91905b80821115610ed65760008155600101610f05565b60008083601f840112610f2a578182fd5b50813567ffffffffffffffff811115610f41578182fd5b6020830191508360208083028501011115610bfb57600080fd5b600060208284031215610f6c578081fd5b8135610f778161154a565b9392505050565b600060208284031215610f8f578081fd5b8151610f778161154a565b60008060408385031215610fac578081fd5b8235610fb78161154a565b91506020830135610fc78161154a565b809150509250929050565b600080600060608486031215610fe6578081fd5b8335610ff18161154a565b925060208401356110018161154a565b915060408401356110118161154a565b809150509250925092565b60008060008060808587031215611031578081fd5b843561103c8161154a565b9350602085013561104c8161154a565b9250604085013561105c8161154a565b9396929550929360600135925050565b6000806040838503121561107e578182fd5b82356110898161154a565b9150602083013567ffffffffffffffff808211156110a5578283fd5b81850186601f8201126110b6578384fd5b80359250818311156110c6578384fd5b604051601f8401601f1916810160200183811182821017156110e6578586fd5b6040528381528184016020018810156110fd578485fd5b61110e84602083016020850161153e565b809450505050509250929050565b600080600080600060608688031215611133578081fd5b853567ffffffffffffffff8082111561114a578283fd5b61115689838a01610f19565b9097509550602088013591508082111561116e578283fd5b5061117b88828901610f19565b909450925050604086013561118f8161154a565b809150509295509295909350565b6000806000606084860312156111b1578283fd5b83516111bc81611562565b60208501519093506111cd81611562565b604085015190925063ffffffff81168114611011578182fd5b6000602082840312156111f7578081fd5b5051919050565b6bffffffffffffffffffffffff19606093841b811682529190921b16601482015260280190565b600060ff60f81b825260016bffffffffffffffffffffffff198660601b168184015284601584015260358285548381166000811461126a5760018114611285576112b9565b60ff1982168785015260028204607f168701840192506112b9565b6002820461129289611532565b875b828110156112b05781548a820188015290870190602001611294565b50508701840192505b509098975050505050505050565b6001600160a01b0391909116815260200190565b6000602080835283518082850152825b81811015611307578581018301518582016040015282016112eb565b818111156113185783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601590820152740d2dce0eae840d8cadccee8d040dad2e6dac2e8c6d605b1b604082015260600190565b60208082526026908201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160408201526564647265737360d01b606082015260800190565b6020808252601c908201527f545741505f4f7261636c653a20696e76616c696420746f6b656e496e00000000604082015260600190565b60208082526025908201527f556e697377617056324c6962726172793a204944454e544943414c5f41444452604082015264455353455360d81b606082015260800190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526018908201527f4669786564506f696e743a204d554c5f4f564552464c4f570000000000000000604082015260600190565b6020808252818101527f4669786564506f696e743a204449565f42595f5a45524f5f4652414354494f4e604082015260600190565b6020808252601e908201527f556e697377617056324c6962726172793a205a45524f5f414444524553530000604082015260600190565b90815260200190565b94855260208501939093526040840191909152516001600160e01b039081166060840152905116608082015260a00190565b60009081526020902090565b82818337506000910152565b6001600160a01b038116811461155f57600080fd5b50565b6001600160701b038116811461155f57600080fdfea2646970667358221220543723287cebef83a901d174eeffc6d7cbfd44f8c8d6424a6b10cbc72af1596b64736f6c63430006060033