Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- VaraOracle
- Optimization enabled
- true
- Compiler version
- v0.8.19+commit.7dd6d404
- Optimization runs
- 200
- EVM Version
- default
- Verified at
- 2023-10-05T15:52:25.549713Z
Constructor Arguments
0x000000000000000000000000a138fafc30f6ec6980aad22656f2f11c38b56a95000000000000000000000000d63e8629773477bdc40287e4ec5282f927af1990031cd3e3daf9dda040eef58b332d44d2350e6ed8c98227e0ba96b741474db068
Arg [0] (address) : 0xa138fafc30f6ec6980aad22656f2f11c38b56a95
Arg [1] (address) : 0xd63e8629773477bdc40287e4ec5282f927af1990
Arg [2] (bytes32) : 031cd3e3daf9dda040eef58b332d44d2350e6ed8c98227e0ba96b741474db068
contracts/VaraOracle.sol
pragma solidity ^0.8.13; import { IPool } from "./interfaces/IPool.sol"; import { IPoolFactory } from "./interfaces/factories/IPoolFactory.sol"; import { IERC20, IERC20Metadata } from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { Clones } from "@openzeppelin/contracts/proxy/Clones.sol"; contract VaraOracle { address public immutable factoryV1; address public immutable factoryV2; bytes32 public immutable initcodeHashV1; uint8 constant maxHop = 10; constructor(address _factoryV1, address _factoryV2, bytes32 _initcodeHashV1) { factoryV1 = _factoryV1; factoryV2 = _factoryV2; initcodeHashV1 = _initcodeHashV1; } struct BalanceInfo { uint256 bal0; uint256 bal1; bool isStable; bool isV1; } struct Path { uint8 to_i; uint256 rate; } struct ReturnVal { bool mod; bool isStable; bool isV1; uint256 bal0; uint256 bal1; } struct Arrays { uint256[] rates; Path[] paths; int[] decimals; uint8[] visited; } struct IterVars { uint256 cur_rate; uint256 rate; uint8 from_i; uint8 to_i; bool seen; } function _get_bal( IERC20 from, IERC20 to, uint256 in_bal0 ) internal view returns (ReturnVal memory out) { bool b0_v1; bool b2_v1; (uint256 b0, uint256 b1) = _getBalances(from, to, false, false); (uint256 temp0, uint256 temp1) = _getBalances(from, to, false, true); if (b0 < temp0) { (b0, b1) = (temp0, temp1); b0_v1 = true; } (uint256 b2, uint256 b3) = _getBalances(from, to, true, false); (temp0, temp1) = _getBalances(from, to, true, true); if (b2 < temp0) { (b2, b3) = (temp0, temp1); b2_v1 = true; } if (b0 > in_bal0 || b2 > in_bal0) { out.mod = true; if (b0 > b2) { (out.bal0, out.bal1, out.isStable, out.isV1) = (b0, b1, false, b0_v1); } else { (out.bal0, out.bal1, out.isStable, out.isV1) = (b2, b3, true, b2_v1); } } } function getManyRatesWithConnectors( uint8 src_len, IERC20Metadata[] memory connectors ) external view returns (uint256[] memory rates) { uint8 j_max = min(maxHop, uint8(connectors.length - src_len)); Arrays memory arr; arr.rates = new uint256[](src_len); arr.paths = new Path[]((connectors.length - src_len)); arr.decimals = new int[](connectors.length); // Caching decimals of all connector tokens { for (uint8 i = 0; i < connectors.length; i++) { arr.decimals[i] = int(uint(connectors[i].decimals())); } } // Iterating through srcTokens for (uint8 src = 0; src < src_len; src++) { IterVars memory vars; vars.cur_rate = 1; vars.from_i = src; arr.visited = new uint8[](connectors.length - src_len); // Counting hops for (uint8 j = 0; j < j_max; j++) { BalanceInfo memory balInfo = BalanceInfo(0, 0, false, false); vars.to_i = 0; // Going through all connectors for (uint8 i = src_len; i < connectors.length; i++) { // Check if the current connector has been used to prevent cycles vars.seen = false; { for (uint8 c = 0; c < j; c++) { if (arr.visited[c] == i) { vars.seen = true; break; } } } if (vars.seen) { continue; } ReturnVal memory out = _get_bal(connectors[vars.from_i], connectors[i], balInfo.bal0); if (out.mod) { balInfo.isStable = out.isStable; balInfo.bal0 = out.bal0; balInfo.bal1 = out.bal1; balInfo.isV1 = out.isV1; vars.to_i = i; } } if (vars.to_i == 0) { arr.rates[src] = 0; break; } if (balInfo.isStable) { vars.rate = _stableRate( connectors[vars.from_i], connectors[vars.to_i], arr.decimals[vars.from_i] - arr.decimals[vars.to_i], balInfo.isV1 ); } else { vars.rate = _volatileRate( balInfo.bal0, balInfo.bal1, arr.decimals[vars.from_i] - arr.decimals[vars.to_i] ); } vars.cur_rate *= vars.rate; if (j > 0) { vars.cur_rate /= 1e18; } // If from_i points to a connector, cache swap rate for connectors[from_i] : connectors[to_i] if (vars.from_i >= src_len) { arr.paths[vars.from_i - src_len] = Path(vars.to_i, vars.rate); } // If from_i points to a srcToken, check if to_i is a connector which has already been expanded. // If so, directly follow the cached path to dstToken to get the final rate. else { if (arr.paths[vars.to_i - src_len].rate > 0) { while (true) { vars.cur_rate = (vars.cur_rate * arr.paths[vars.to_i - src_len].rate) / 1e18; vars.to_i = arr.paths[vars.to_i - src_len].to_i; if (vars.to_i == connectors.length - 1) { arr.rates[src] = vars.cur_rate; break; } } } } arr.visited[j] = vars.to_i; // Next token is dstToken, stop if (vars.to_i == connectors.length - 1) { arr.rates[src] = vars.cur_rate; break; } vars.from_i = vars.to_i; } } return arr.rates; } function _volatileRate( uint256 b0, uint256 b1, int dec_diff ) internal pure returns (uint256 rate) { // b0 has less 0s if (dec_diff < 0) { rate = (1e18 * b1) / (b0 * 10 ** (uint(-dec_diff))); } // b0 has more 0s else { rate = (1e18 * 10 ** (uint(dec_diff)) * b1) / b0; } } function _stableRate( IERC20Metadata t0, IERC20 t1, int dec_diff, bool isV1 ) internal view returns (uint256 rate) { uint256 t0_dec = t0.decimals(); address currentPair = _orderedPairFor(t0, t1, true, isV1); // newOut in t1 uint256 newOut = IPool(currentPair).getAmountOut((10 ** t0_dec), address(t0)); // t0 has less 0s if (dec_diff < 0) { rate = (1e18 * newOut) / (10 ** t0_dec * 10 ** (uint(-dec_diff))); } // t0 has more 0s else { rate = (1e18 * (newOut * 10 ** (uint(dec_diff)))) / (10 ** t0_dec); } } // calculates the CREATE2 address for a pair without making any external calls function _pairFor( IERC20 tokenA, IERC20 tokenB, bool stable, bool v1 ) private view returns (address pair) { if (v1) { pair = address( uint160( uint256( keccak256( abi.encodePacked( hex"ff", factoryV1, keccak256(abi.encodePacked(tokenA, tokenB, stable)), initcodeHashV1 ) ) ) ) ); } else { bytes32 salt = keccak256(abi.encodePacked(tokenA, tokenB, stable)); pair = Clones.predictDeterministicAddress( IPoolFactory(factoryV2).implementation(), salt, factoryV2 ); } } // returns the reserves of a pool if it exists, preserving the order of srcToken and dstToken function _getBalances( IERC20 srcToken, IERC20 dstToken, bool stable, bool v1 ) internal view returns (uint256 srcBalance, uint256 dstBalance) { (IERC20 token0, IERC20 token1) = srcToken < dstToken ? (srcToken, dstToken) : (dstToken, srcToken); address pairAddress = _pairFor(token0, token1, stable, v1); // if the pair doesn't exist, return 0 if (!Address.isContract(pairAddress)) { srcBalance = 0; dstBalance = 0; } else { (uint256 reserve0, uint256 reserve1, ) = IPool(pairAddress).getReserves(); (srcBalance, dstBalance) = srcToken == token0 ? (reserve0, reserve1) : (reserve1, reserve0); } } // fetch pair from tokens using correct order function _orderedPairFor( IERC20 tokenA, IERC20 tokenB, bool stable, bool isV1 ) internal view returns (address pairAddress) { (IERC20 token0, IERC20 token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA); pairAddress = _pairFor(token0, token1, stable, isV1); } function min(uint8 a, uint8 b) internal pure returns (uint8) { return a < b ? a : b; } }
@openzeppelin/contracts/proxy/Clones.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol) pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(0, 0x09, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(0, 0x09, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := keccak256(add(ptr, 0x43), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` 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 from, address to, uint256 amount) external returns (bool); }
@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
contracts/interfaces/IPool.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPool { error DepositsNotEqual(); error BelowMinimumK(); error FactoryAlreadySet(); error InsufficientLiquidity(); error InsufficientLiquidityMinted(); error InsufficientLiquidityBurned(); error InsufficientOutputAmount(); error InsufficientInputAmount(); error IsPaused(); error InvalidTo(); error K(); error NotEmergencyCouncil(); event Fees(address indexed sender, uint256 amount0, uint256 amount1); event Mint(address indexed sender, uint256 amount0, uint256 amount1); event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1); event Swap( address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out ); event Sync(uint256 reserve0, uint256 reserve1); event Claim(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1); function metadata() external view returns (uint256 dec0, uint256 dec1, uint256 r0, uint256 r1, bool st, address t0, address t1); function claimFees() external returns (uint256, uint256); function tokens() external view returns (address, address); function token0() external view returns (address); function token1() external view returns (address); function stable() external view returns (bool); function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; function burn(address to) external returns (uint256 amount0, uint256 amount1); function mint(address to) external returns (uint256 liquidity); function getReserves() external view returns (uint256 _reserve0, uint256 _reserve1, uint256 _blockTimestampLast); function getAmountOut(uint256, address) external view returns (uint256); function skim(address to) external; function initialize(address _token0, address _token1, bool _stable) external; }
contracts/interfaces/factories/IPoolFactory.sol
pragma solidity ^0.8.0; interface IPoolFactory { event SetFeeManager(address feeManager); event SetPauser(address pauser); event SetPauseState(bool state); event SetVoter(address voter); event PoolCreated( address indexed token0, address indexed token1, bool indexed stable, address pool, uint256 ); event SetCustomFee(address indexed pool, uint256 fee); error FeeInvalid(); error FeeTooHigh(); error InvalidPool(); error NotFeeManager(); error NotPauser(); error NotSinkConverter(); error NotVoter(); error PoolAlreadyExists(); error SameAddress(); error ZeroFee(); error ZeroAddress(); /// @notice returns the number of pools created from this factory function allPoolsLength() external view returns (uint256); /// @notice Is a valid pool created by this factory. /// @param . function isPool(address pool) external view returns (bool); /// @notice Support for Velodrome v1 which wraps around isPool(pool); /// @param . function isPair(address pool) external view returns (bool); /// @notice Return address of pool created by this factory /// @param tokenA . /// @param tokenB . /// @param stable True if stable, false if volatile function getPool(address tokenA, address tokenB, bool stable) external view returns (address); /// @notice Support for v3-style pools which wraps around getPool(tokenA,tokenB,stable) /// @dev fee is converted to stable boolean. /// @param tokenA . /// @param tokenB . /// @param fee 1 if stable, 0 if volatile, else returns address(0) function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address); /// @notice Support for Velodrome v1 pools as a "pool" was previously referenced as "pair" /// @notice Wraps around getPool(tokenA,tokenB,stable) function getPair(address tokenA, address tokenB, bool stable) external view returns (address); /// @dev Only called once to set to Voter.sol - Voter does not have a function /// to call this contract method, so once set it's immutable. /// This also follows convention of setVoterAndDistributor() in VotingEscrow.sol /// @param _voter . function setVoter(address _voter) external; function setSinkConverter(address _sinkConvert, address _vara, address _varaV2) external; function setPauser(address _pauser) external; function setPauseState(bool _state) external; function setFeeManager(address _feeManager) external; /// @notice Set default fee for stable and volatile pools. /// @dev Throws if higher than maximum fee. /// Throws if fee is zero. /// @param _stable Stable or volatile pool. /// @param _fee . function setFee(bool _stable, uint256 _fee) external; /// @notice Set overriding fee for a pool from the default /// @dev A custom fee of zero means the default fee will be used. function setCustomFee(address _pool, uint256 _fee) external; /// @notice Returns fee for a pool, as custom fees are possible. function getFee(address _pool, bool _stable) external view returns (uint256); /// @notice Create a pool given two tokens and if they're stable/volatile /// @dev token order does not matter /// @param tokenA . /// @param tokenB . /// @param stable . function createPool(address tokenA, address tokenB, bool stable) external returns (address pool); /// @notice Support for v3-style pools which wraps around createPool(tokena,tokenB,stable) /// @dev fee is converted to stable boolean /// @dev token order does not matter /// @param tokenA . /// @param tokenB . /// @param fee 1 if stable, 0 if volatile, else revert function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); /// @notice Support for Velodrome v1 which wraps around createPool(tokenA,tokenB,stable) function createPair(address tokenA, address tokenB, bool stable) external returns (address pool); function isPaused() external view returns (bool); function vara() external view returns (address); function varaV2() external view returns (address); function voter() external view returns (address); function sinkConverter() external view returns (address); function implementation() external view returns (address); }
@openzeppelin/contracts/proxy/Clones.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (proxy/Clones.sol) pragma solidity ^0.8.0; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[EIP 1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. * * _Available since v3.4._ */ library Clones { /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(0, 0x09, 0x37) } require(instance != address(0), "ERC1167: create failed"); } /** * @dev Deploys and returns the address of a clone that mimics the behaviour of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple time will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { /// @solidity memory-safe-assembly assembly { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(0, 0x09, 0x37, salt) } require(instance != address(0), "ERC1167: create2 failed"); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := keccak256(add(ptr, 0x43), 0x55) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } }
@openzeppelin/contracts/token/ERC20/IERC20.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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 `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` 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 from, address to, uint256 amount) external returns (bool); }
@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC20 standard. * * _Available since v4.1._ */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
@openzeppelin/contracts/utils/Address.sol
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
contracts/interfaces/IPool.sol
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IPool { error DepositsNotEqual(); error BelowMinimumK(); error FactoryAlreadySet(); error InsufficientLiquidity(); error InsufficientLiquidityMinted(); error InsufficientLiquidityBurned(); error InsufficientOutputAmount(); error InsufficientInputAmount(); error IsPaused(); error InvalidTo(); error K(); error NotEmergencyCouncil(); event Fees(address indexed sender, uint256 amount0, uint256 amount1); event Mint(address indexed sender, uint256 amount0, uint256 amount1); event Burn(address indexed sender, address indexed to, uint256 amount0, uint256 amount1); event Swap( address indexed sender, address indexed to, uint256 amount0In, uint256 amount1In, uint256 amount0Out, uint256 amount1Out ); event Sync(uint256 reserve0, uint256 reserve1); event Claim(address indexed sender, address indexed recipient, uint256 amount0, uint256 amount1); function metadata() external view returns (uint256 dec0, uint256 dec1, uint256 r0, uint256 r1, bool st, address t0, address t1); function claimFees() external returns (uint256, uint256); function tokens() external view returns (address, address); function token0() external view returns (address); function token1() external view returns (address); function stable() external view returns (bool); function swap(uint256 amount0Out, uint256 amount1Out, address to, bytes calldata data) external; function burn(address to) external returns (uint256 amount0, uint256 amount1); function mint(address to) external returns (uint256 liquidity); function getReserves() external view returns (uint256 _reserve0, uint256 _reserve1, uint256 _blockTimestampLast); function getAmountOut(uint256, address) external view returns (uint256); function skim(address to) external; function initialize(address _token0, address _token1, bool _stable) external; }
contracts/interfaces/factories/IPoolFactory.sol
pragma solidity ^0.8.0; interface IPoolFactory { event SetFeeManager(address feeManager); event SetPauser(address pauser); event SetPauseState(bool state); event SetVoter(address voter); event PoolCreated( address indexed token0, address indexed token1, bool indexed stable, address pool, uint256 ); event SetCustomFee(address indexed pool, uint256 fee); error FeeInvalid(); error FeeTooHigh(); error InvalidPool(); error NotFeeManager(); error NotPauser(); error NotSinkConverter(); error NotVoter(); error PoolAlreadyExists(); error SameAddress(); error ZeroFee(); error ZeroAddress(); /// @notice returns the number of pools created from this factory function allPoolsLength() external view returns (uint256); /// @notice Is a valid pool created by this factory. /// @param . function isPool(address pool) external view returns (bool); /// @notice Support for Velodrome v1 which wraps around isPool(pool); /// @param . function isPair(address pool) external view returns (bool); /// @notice Return address of pool created by this factory /// @param tokenA . /// @param tokenB . /// @param stable True if stable, false if volatile function getPool(address tokenA, address tokenB, bool stable) external view returns (address); /// @notice Support for v3-style pools which wraps around getPool(tokenA,tokenB,stable) /// @dev fee is converted to stable boolean. /// @param tokenA . /// @param tokenB . /// @param fee 1 if stable, 0 if volatile, else returns address(0) function getPool(address tokenA, address tokenB, uint24 fee) external view returns (address); /// @notice Support for Velodrome v1 pools as a "pool" was previously referenced as "pair" /// @notice Wraps around getPool(tokenA,tokenB,stable) function getPair(address tokenA, address tokenB, bool stable) external view returns (address); /// @dev Only called once to set to Voter.sol - Voter does not have a function /// to call this contract method, so once set it's immutable. /// This also follows convention of setVoterAndDistributor() in VotingEscrow.sol /// @param _voter . function setVoter(address _voter) external; function setSinkConverter(address _sinkConvert, address _vara, address _varaV2) external; function setPauser(address _pauser) external; function setPauseState(bool _state) external; function setFeeManager(address _feeManager) external; /// @notice Set default fee for stable and volatile pools. /// @dev Throws if higher than maximum fee. /// Throws if fee is zero. /// @param _stable Stable or volatile pool. /// @param _fee . function setFee(bool _stable, uint256 _fee) external; /// @notice Set overriding fee for a pool from the default /// @dev A custom fee of zero means the default fee will be used. function setCustomFee(address _pool, uint256 _fee) external; /// @notice Returns fee for a pool, as custom fees are possible. function getFee(address _pool, bool _stable) external view returns (uint256); /// @notice Create a pool given two tokens and if they're stable/volatile /// @dev token order does not matter /// @param tokenA . /// @param tokenB . /// @param stable . function createPool(address tokenA, address tokenB, bool stable) external returns (address pool); /// @notice Support for v3-style pools which wraps around createPool(tokena,tokenB,stable) /// @dev fee is converted to stable boolean /// @dev token order does not matter /// @param tokenA . /// @param tokenB . /// @param fee 1 if stable, 0 if volatile, else revert function createPool(address tokenA, address tokenB, uint24 fee) external returns (address pool); /// @notice Support for Velodrome v1 which wraps around createPool(tokenA,tokenB,stable) function createPair(address tokenA, address tokenB, bool stable) external returns (address pool); function isPaused() external view returns (bool); function vara() external view returns (address); function varaV2() external view returns (address); function voter() external view returns (address); function sinkConverter() external view returns (address); function implementation() external view returns (address); }
Compiler Settings
{"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers"]}},"optimizer":{"runs":200,"enabled":true},"libraries":{}}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_factoryV1","internalType":"address"},{"type":"address","name":"_factoryV2","internalType":"address"},{"type":"bytes32","name":"_initcodeHashV1","internalType":"bytes32"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factoryV1","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"factoryV2","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256[]","name":"rates","internalType":"uint256[]"}],"name":"getManyRatesWithConnectors","inputs":[{"type":"uint8","name":"src_len","internalType":"uint8"},{"type":"address[]","name":"connectors","internalType":"contract IERC20Metadata[]"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"initcodeHashV1","inputs":[]}]
Contract Creation Code
0x60e060405234801561001057600080fd5b506040516114ab3803806114ab83398101604081905261002f91610066565b6001600160a01b03928316608052911660a05260c0526100a2565b80516001600160a01b038116811461006157600080fd5b919050565b60008060006060848603121561007b57600080fd5b6100848461004a565b92506100926020850161004a565b9150604084015190509250925092565b60805160a05160c0516113c16100ea6000396000818160c10152610dcb015260008181609a01528181610e830152610f0801526000818160560152610d7f01526113c16000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80633957f4531461005157806368e0d4e114610095578063aaa60f7c146100bc578063fe6b9b4c146100f1575b600080fd5b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b6100787f000000000000000000000000000000000000000000000000000000000000000081565b6100e37f000000000000000000000000000000000000000000000000000000000000000081565b60405190815260200161008c565b6101046100ff366004610fd6565b610111565b60405161008c91906110b0565b6060600061012f600a8560ff16855161012a919061110a565b6108e0565b905061015c6040518060800160405280606081526020016060815260200160608152602001606081525090565b8460ff1667ffffffffffffffff81111561017857610178610f9b565b6040519080825280602002602001820160405280156101a1578160200160208202803683370190505b50815283516101b49060ff87169061110a565b67ffffffffffffffff8111156101cc576101cc610f9b565b60405190808252806020026020018201604052801561021157816020015b60408051808201909152600080825260208201528152602001906001900390816101ea5790505b506020820152835167ffffffffffffffff81111561023157610231610f9b565b60405190808252806020026020018201604052801561025a578160200160208202803683370190505b50604082015260005b84518160ff16101561032657848160ff16815181106102845761028461111d565b60200260200101516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ed9190611133565b60ff1682604001518260ff16815181106103095761030961111d565b60209081029190910101528061031e81611150565b915050610263565b5060005b8560ff168160ff1610156108d4576040805160a0810182526000602082018190526060820181905260808201526001815260ff8381169282019290925286519091610378919089169061110a565b67ffffffffffffffff81111561039057610390610f9b565b6040519080825280602002602001820160405280156103b9578160200160208202803683370190505b50606084015260005b8460ff168160ff1610156108bf57604080516080810182526000808252602082018190529181018290526060808201839052840191909152885b88518160ff161015610517576000608085018190525b8360ff168160ff16101561046b578160ff1687606001518260ff168151811061043d5761043d61111d565b602002602001015160ff1603610459576001608086015261046b565b8061046381611150565b915050610412565b5083608001516105055760006104c28a866040015160ff16815181106104935761049361111d565b60200260200101518b8460ff16815181106104b0576104b061111d565b602002602001015185600001516108fe565b805190915015610503576020808201511515604080860191909152606080840151865260808401519286019290925282015115158185015260ff8316908601525b505b8061050f81611150565b9150506103fc565b50826060015160ff1660000361055457600085600001518560ff16815181106105425761054261111d565b602002602001018181525050506108bf565b80604001511561060b5761060188846040015160ff168151811061057a5761057a61111d565b602002602001015189856060015160ff168151811061059b5761059b61111d565b60200260200101518760400151866060015160ff16815181106105c0576105c061111d565b60200260200101518860400151876040015160ff16815181106105e5576105e561111d565b60200260200101516105f7919061116f565b8460600151610a0b565b6020840152610677565b610671816000015182602001518760400151866060015160ff16815181106106355761063561111d565b60200260200101518860400151876040015160ff168151811061065a5761065a61111d565b602002602001015161066c919061116f565b610bb2565b60208401525b60208301518351849061068b908390611196565b90525060ff8216156106b557670de0b6b3a7640000836000018181516106b191906111ad565b9052505b8860ff16836040015160ff161061071e576040518060400160405280846060015160ff168152602001846020015181525085602001518a85604001516106fb91906111cf565b60ff168151811061070e5761070e61111d565b6020026020010181905250610839565b600085602001518a856060015161073591906111cf565b60ff16815181106107485761074861111d565b6020026020010151602001511115610839575b670de0b6b3a764000085602001518a856060015161077991906111cf565b60ff168151811061078c5761078c61111d565b60200260200101516020015184600001516107a79190611196565b6107b191906111ad565b8352602085015160608401516107c8908b906111cf565b60ff16815181106107db576107db61111d565b60209081029190910101515160ff16606084015287516107fd9060019061110a565b836060015160ff16036108345782518551805160ff87169081106108235761082361111d565b602002602001018181525050610839565b61075b565b826060015185606001518360ff16815181106108575761085761111d565b602002602001019060ff16908160ff168152505060018851610879919061110a565b836060015160ff160361089f5782518551805160ff87169081106105425761054261111d565b50606082015160ff166040830152806108b781611150565b9150506103c2565b505080806108cc90611150565b91505061032a565b50519150505b92915050565b60008160ff168360ff16106108f557816108f7565b825b9392505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081018290529080808061093888888380610c38565b9150915060008061094d8a8a60006001610c38565b91509150818410156109655760019550909250905081815b6000806109768c8c60016000610c38565b915091506109878c8c600180610c38565b90945092508382101561099e575060019550829050815b898611806109ab57508982115b156109fc5760018952818611156109de5787151560408a0152600060208a015260808901859052606089018690526109fc565b86151560408a0152600160208a015260808901819052606089018290525b50505050505050509392505050565b600080856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a709190611133565b60ff1690506000610a848787600187610d32565b905060006001600160a01b03821663f140a35a610aa285600a6112cc565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038b166024820152604401602060405180830381865afa158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1191906112d8565b90506000861215610b6857610b25866112f1565b610b3090600a6112cc565b610b3b84600a6112cc565b610b459190611196565b610b5782670de0b6b3a7640000611196565b610b6191906111ad565b9350610ba7565b610b7383600a6112cc565b610b7e87600a6112cc565b610b889083611196565b610b9a90670de0b6b3a7640000611196565b610ba491906111ad565b93505b505050949350505050565b600080821215610bfd57610bc5826112f1565b610bd090600a6112cc565b610bda9085611196565b610bec84670de0b6b3a7640000611196565b610bf691906111ad565b90506108f7565b8383610c0a84600a6112cc565b610c1c90670de0b6b3a7640000611196565b610c269190611196565b610c3091906111ad565b949350505050565b600080600080866001600160a01b0316886001600160a01b031610610c5e578688610c61565b87875b915091506000610c7383838989610d75565b90506001600160a01b0381163b610c91576000945060009350610d26565b600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf6919061130d565b5091509150846001600160a01b03168b6001600160a01b031614610d1b578082610d1e565b81815b909750955050505b50505094509492505050565b6000806000856001600160a01b0316876001600160a01b031610610d57578587610d5a565b86865b91509150610d6a82828787610d75565b979650505050505050565b60008115610e4f577f0000000000000000000000000000000000000000000000000000000000000000858585604051602001610db39392919061133b565b604051602081830303815290604052805190602001207f0000000000000000000000000000000000000000000000000000000000000000604051602001610e2f939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b6040516020818303038152906040528051906020012060001c9050610c30565b6000858585604051602001610e669392919061133b565b604051602081830303815290604052805190602001209050610f7f7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f03919061136e565b6040517f000000000000000000000000000000000000000000000000000000000000000060388201526f5af43d82803e903d91602b57fd5bf3ff60248201526014810191909152733d602d80600a3d3981f3363d3d373d3d3d363d738152605881018390526037600c8201206078820152605560439091012090565b9695505050505050565b60ff81168114610f9857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610f9857600080fd5b8035610fd181610fb1565b919050565b60008060408385031215610fe957600080fd5b8235610ff481610f89565b915060208381013567ffffffffffffffff8082111561101257600080fd5b818601915086601f83011261102657600080fd5b81358181111561103857611038610f9b565b8060051b604051601f19603f8301168101818110858211171561105d5761105d610f9b565b60405291825284820192508381018501918983111561107b57600080fd5b938501935b828510156110a05761109185610fc6565b84529385019392850192611080565b8096505050505050509250929050565b6020808252825182820181905260009190848201906040850190845b818110156110e8578351835292840192918401916001016110cc565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108da576108da6110f4565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561114557600080fd5b81516108f781610f89565b600060ff821660ff8103611166576111666110f4565b60010192915050565b818103600083128015838313168383128216171561118f5761118f6110f4565b5092915050565b80820281158282048414176108da576108da6110f4565b6000826111ca57634e487b7160e01b600052601260045260246000fd5b500490565b60ff82811682821603908111156108da576108da6110f4565b600181815b80851115611223578160001904821115611209576112096110f4565b8085161561121657918102915b93841c93908002906111ed565b509250929050565b60008261123a575060016108da565b81611247575060006108da565b816001811461125d576002811461126757611283565b60019150506108da565b60ff841115611278576112786110f4565b50506001821b6108da565b5060208310610133831016604e8410600b84101617156112a6575081810a6108da565b6112b083836111e8565b80600019048211156112c4576112c46110f4565b029392505050565b60006108f7838361122b565b6000602082840312156112ea57600080fd5b5051919050565b6000600160ff1b8201611306576113066110f4565b5060000390565b60008060006060848603121561132257600080fd5b8351925060208401519150604084015190509250925092565b6bffffffffffffffffffffffff19606094851b811682529290931b9091166014830152151560f81b602882015260290190565b60006020828403121561138057600080fd5b81516108f781610fb156fea264697066735822122048b592e647347a8b95197381d56cc356537e8ac1df64dc267c70fe0d7cfda52064736f6c63430008130033000000000000000000000000a138fafc30f6ec6980aad22656f2f11c38b56a95000000000000000000000000d63e8629773477bdc40287e4ec5282f927af1990031cd3e3daf9dda040eef58b332d44d2350e6ed8c98227e0ba96b741474db068
Deployed ByteCode
0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80633957f4531461005157806368e0d4e114610095578063aaa60f7c146100bc578063fe6b9b4c146100f1575b600080fd5b6100787f000000000000000000000000a138fafc30f6ec6980aad22656f2f11c38b56a9581565b6040516001600160a01b0390911681526020015b60405180910390f35b6100787f000000000000000000000000d63e8629773477bdc40287e4ec5282f927af199081565b6100e37f031cd3e3daf9dda040eef58b332d44d2350e6ed8c98227e0ba96b741474db06881565b60405190815260200161008c565b6101046100ff366004610fd6565b610111565b60405161008c91906110b0565b6060600061012f600a8560ff16855161012a919061110a565b6108e0565b905061015c6040518060800160405280606081526020016060815260200160608152602001606081525090565b8460ff1667ffffffffffffffff81111561017857610178610f9b565b6040519080825280602002602001820160405280156101a1578160200160208202803683370190505b50815283516101b49060ff87169061110a565b67ffffffffffffffff8111156101cc576101cc610f9b565b60405190808252806020026020018201604052801561021157816020015b60408051808201909152600080825260208201528152602001906001900390816101ea5790505b506020820152835167ffffffffffffffff81111561023157610231610f9b565b60405190808252806020026020018201604052801561025a578160200160208202803683370190505b50604082015260005b84518160ff16101561032657848160ff16815181106102845761028461111d565b60200260200101516001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa1580156102c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102ed9190611133565b60ff1682604001518260ff16815181106103095761030961111d565b60209081029190910101528061031e81611150565b915050610263565b5060005b8560ff168160ff1610156108d4576040805160a0810182526000602082018190526060820181905260808201526001815260ff8381169282019290925286519091610378919089169061110a565b67ffffffffffffffff81111561039057610390610f9b565b6040519080825280602002602001820160405280156103b9578160200160208202803683370190505b50606084015260005b8460ff168160ff1610156108bf57604080516080810182526000808252602082018190529181018290526060808201839052840191909152885b88518160ff161015610517576000608085018190525b8360ff168160ff16101561046b578160ff1687606001518260ff168151811061043d5761043d61111d565b602002602001015160ff1603610459576001608086015261046b565b8061046381611150565b915050610412565b5083608001516105055760006104c28a866040015160ff16815181106104935761049361111d565b60200260200101518b8460ff16815181106104b0576104b061111d565b602002602001015185600001516108fe565b805190915015610503576020808201511515604080860191909152606080840151865260808401519286019290925282015115158185015260ff8316908601525b505b8061050f81611150565b9150506103fc565b50826060015160ff1660000361055457600085600001518560ff16815181106105425761054261111d565b602002602001018181525050506108bf565b80604001511561060b5761060188846040015160ff168151811061057a5761057a61111d565b602002602001015189856060015160ff168151811061059b5761059b61111d565b60200260200101518760400151866060015160ff16815181106105c0576105c061111d565b60200260200101518860400151876040015160ff16815181106105e5576105e561111d565b60200260200101516105f7919061116f565b8460600151610a0b565b6020840152610677565b610671816000015182602001518760400151866060015160ff16815181106106355761063561111d565b60200260200101518860400151876040015160ff168151811061065a5761065a61111d565b602002602001015161066c919061116f565b610bb2565b60208401525b60208301518351849061068b908390611196565b90525060ff8216156106b557670de0b6b3a7640000836000018181516106b191906111ad565b9052505b8860ff16836040015160ff161061071e576040518060400160405280846060015160ff168152602001846020015181525085602001518a85604001516106fb91906111cf565b60ff168151811061070e5761070e61111d565b6020026020010181905250610839565b600085602001518a856060015161073591906111cf565b60ff16815181106107485761074861111d565b6020026020010151602001511115610839575b670de0b6b3a764000085602001518a856060015161077991906111cf565b60ff168151811061078c5761078c61111d565b60200260200101516020015184600001516107a79190611196565b6107b191906111ad565b8352602085015160608401516107c8908b906111cf565b60ff16815181106107db576107db61111d565b60209081029190910101515160ff16606084015287516107fd9060019061110a565b836060015160ff16036108345782518551805160ff87169081106108235761082361111d565b602002602001018181525050610839565b61075b565b826060015185606001518360ff16815181106108575761085761111d565b602002602001019060ff16908160ff168152505060018851610879919061110a565b836060015160ff160361089f5782518551805160ff87169081106105425761054261111d565b50606082015160ff166040830152806108b781611150565b9150506103c2565b505080806108cc90611150565b91505061032a565b50519150505b92915050565b60008160ff168360ff16106108f557816108f7565b825b9392505050565b6040805160a08101825260008082526020820181905291810182905260608101829052608081018290529080808061093888888380610c38565b9150915060008061094d8a8a60006001610c38565b91509150818410156109655760019550909250905081815b6000806109768c8c60016000610c38565b915091506109878c8c600180610c38565b90945092508382101561099e575060019550829050815b898611806109ab57508982115b156109fc5760018952818611156109de5787151560408a0152600060208a015260808901859052606089018690526109fc565b86151560408a0152600160208a015260808901819052606089018290525b50505050505050509392505050565b600080856001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610a4c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a709190611133565b60ff1690506000610a848787600187610d32565b905060006001600160a01b03821663f140a35a610aa285600a6112cc565b6040516001600160e01b031960e084901b16815260048101919091526001600160a01b038b166024820152604401602060405180830381865afa158015610aed573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b1191906112d8565b90506000861215610b6857610b25866112f1565b610b3090600a6112cc565b610b3b84600a6112cc565b610b459190611196565b610b5782670de0b6b3a7640000611196565b610b6191906111ad565b9350610ba7565b610b7383600a6112cc565b610b7e87600a6112cc565b610b889083611196565b610b9a90670de0b6b3a7640000611196565b610ba491906111ad565b93505b505050949350505050565b600080821215610bfd57610bc5826112f1565b610bd090600a6112cc565b610bda9085611196565b610bec84670de0b6b3a7640000611196565b610bf691906111ad565b90506108f7565b8383610c0a84600a6112cc565b610c1c90670de0b6b3a7640000611196565b610c269190611196565b610c3091906111ad565b949350505050565b600080600080866001600160a01b0316886001600160a01b031610610c5e578688610c61565b87875b915091506000610c7383838989610d75565b90506001600160a01b0381163b610c91576000945060009350610d26565b600080826001600160a01b0316630902f1ac6040518163ffffffff1660e01b8152600401606060405180830381865afa158015610cd2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cf6919061130d565b5091509150846001600160a01b03168b6001600160a01b031614610d1b578082610d1e565b81815b909750955050505b50505094509492505050565b6000806000856001600160a01b0316876001600160a01b031610610d57578587610d5a565b86865b91509150610d6a82828787610d75565b979650505050505050565b60008115610e4f577f000000000000000000000000a138fafc30f6ec6980aad22656f2f11c38b56a95858585604051602001610db39392919061133b565b604051602081830303815290604052805190602001207f031cd3e3daf9dda040eef58b332d44d2350e6ed8c98227e0ba96b741474db068604051602001610e2f939291906001600160f81b0319815260609390931b6bffffffffffffffffffffffff191660018401526015830191909152603582015260550190565b6040516020818303038152906040528051906020012060001c9050610c30565b6000858585604051602001610e669392919061133b565b604051602081830303815290604052805190602001209050610f7f7f000000000000000000000000d63e8629773477bdc40287e4ec5282f927af19906001600160a01b0316635c60da1b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610edf573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f03919061136e565b6040517f000000000000000000000000d63e8629773477bdc40287e4ec5282f927af199060388201526f5af43d82803e903d91602b57fd5bf3ff60248201526014810191909152733d602d80600a3d3981f3363d3d373d3d3d363d738152605881018390526037600c8201206078820152605560439091012090565b9695505050505050565b60ff81168114610f9857600080fd5b50565b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610f9857600080fd5b8035610fd181610fb1565b919050565b60008060408385031215610fe957600080fd5b8235610ff481610f89565b915060208381013567ffffffffffffffff8082111561101257600080fd5b818601915086601f83011261102657600080fd5b81358181111561103857611038610f9b565b8060051b604051601f19603f8301168101818110858211171561105d5761105d610f9b565b60405291825284820192508381018501918983111561107b57600080fd5b938501935b828510156110a05761109185610fc6565b84529385019392850192611080565b8096505050505050509250929050565b6020808252825182820181905260009190848201906040850190845b818110156110e8578351835292840192918401916001016110cc565b50909695505050505050565b634e487b7160e01b600052601160045260246000fd5b818103818111156108da576108da6110f4565b634e487b7160e01b600052603260045260246000fd5b60006020828403121561114557600080fd5b81516108f781610f89565b600060ff821660ff8103611166576111666110f4565b60010192915050565b818103600083128015838313168383128216171561118f5761118f6110f4565b5092915050565b80820281158282048414176108da576108da6110f4565b6000826111ca57634e487b7160e01b600052601260045260246000fd5b500490565b60ff82811682821603908111156108da576108da6110f4565b600181815b80851115611223578160001904821115611209576112096110f4565b8085161561121657918102915b93841c93908002906111ed565b509250929050565b60008261123a575060016108da565b81611247575060006108da565b816001811461125d576002811461126757611283565b60019150506108da565b60ff841115611278576112786110f4565b50506001821b6108da565b5060208310610133831016604e8410600b84101617156112a6575081810a6108da565b6112b083836111e8565b80600019048211156112c4576112c46110f4565b029392505050565b60006108f7838361122b565b6000602082840312156112ea57600080fd5b5051919050565b6000600160ff1b8201611306576113066110f4565b5060000390565b60008060006060848603121561132257600080fd5b8351925060208401519150604084015190509250925092565b6bffffffffffffffffffffffff19606094851b811682529290931b9091166014830152151560f81b602882015260290190565b60006020828403121561138057600080fd5b81516108f781610fb156fea264697066735822122048b592e647347a8b95197381d56cc356537e8ac1df64dc267c70fe0d7cfda52064736f6c63430008130033