Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
0x60806040 | 9986243 | 1549 days ago | IN | 0 ETH | 0.02362297 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
10880608 | 1411 days ago | 9 wei | ||||
10880608 | 1411 days ago | 9 wei | ||||
10161483 | 1522 days ago | 3.66427421 ETH | ||||
10161483 | 1522 days ago | 3.66427421 ETH | ||||
10054222 | 1539 days ago | 1 ETH | ||||
10054222 | 1539 days ago | 1 ETH | ||||
10017510 | 1545 days ago | 2.8 ETH | ||||
10017510 | 1545 days ago | 2.8 ETH | ||||
10015948 | 1545 days ago | 0.25 ETH | ||||
10015948 | 1545 days ago | 0.25 ETH | ||||
10015942 | 1545 days ago | 0.25013667 ETH | ||||
10015942 | 1545 days ago | 0.25013667 ETH | ||||
10015338 | 1545 days ago | 0.5 ETH | ||||
10015338 | 1545 days ago | 0.5 ETH | ||||
10015048 | 1545 days ago | 0.5 ETH | ||||
10015048 | 1545 days ago | 0.5 ETH | ||||
10014876 | 1545 days ago | 89.77275885 ETH | ||||
10014876 | 1545 days ago | 26.97620337 ETH | ||||
10014876 | 1545 days ago | 62.79655547 ETH | ||||
10014821 | 1545 days ago | 1.36850539 ETH | ||||
10014821 | 1545 days ago | 1.36850539 ETH | ||||
10014805 | 1545 days ago | 1 ETH | ||||
10014805 | 1545 days ago | 1 ETH | ||||
10014797 | 1545 days ago | 4.77759621 ETH | ||||
10014797 | 1545 days ago | 4.77759621 ETH |
Loading...
Loading
Contract Name:
OneSplitWrap
Compiler Version
v0.5.17+commit.d19bba13
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2020-05-02 */ // File: @openzeppelin/contracts/token/ERC20/IERC20.sol pragma solidity ^0.5.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. Does not include * the optional functions; to access them see {ERC20Detailed}. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `recipient`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address recipient, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * 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 `sender` to `recipient` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); } // File: contracts/IOneSplit.sol pragma solidity ^0.5.0; // // || // || // \/ // +--------------+ // | OneSplitWrap | // +--------------+ // || // || (delegatecall) // \/ // +--------------+ // | OneSplit | // +--------------+ // // contract IOneSplitConsts { // flags = FLAG_DISABLE_UNISWAP + FLAG_DISABLE_KYBER + ... uint256 public constant FLAG_DISABLE_UNISWAP = 0x01; uint256 public constant FLAG_DISABLE_KYBER = 0x02; uint256 public constant FLAG_ENABLE_KYBER_UNISWAP_RESERVE = 0x100000000; // Turned off by default uint256 public constant FLAG_ENABLE_KYBER_OASIS_RESERVE = 0x200000000; // Turned off by default uint256 public constant FLAG_ENABLE_KYBER_BANCOR_RESERVE = 0x400000000; // Turned off by default uint256 public constant FLAG_DISABLE_BANCOR = 0x04; uint256 public constant FLAG_DISABLE_OASIS = 0x08; uint256 public constant FLAG_DISABLE_COMPOUND = 0x10; uint256 public constant FLAG_DISABLE_FULCRUM = 0x20; uint256 public constant FLAG_DISABLE_CHAI = 0x40; uint256 public constant FLAG_DISABLE_AAVE = 0x80; uint256 public constant FLAG_DISABLE_SMART_TOKEN = 0x100; uint256 public constant FLAG_ENABLE_MULTI_PATH_ETH = 0x200; // Turned off by default uint256 public constant FLAG_DISABLE_BDAI = 0x400; uint256 public constant FLAG_DISABLE_IEARN = 0x800; uint256 public constant FLAG_DISABLE_CURVE_COMPOUND = 0x1000; uint256 public constant FLAG_DISABLE_CURVE_USDT = 0x2000; uint256 public constant FLAG_DISABLE_CURVE_Y = 0x4000; uint256 public constant FLAG_DISABLE_CURVE_BINANCE = 0x8000; uint256 public constant FLAG_ENABLE_MULTI_PATH_DAI = 0x10000; // Turned off by default uint256 public constant FLAG_ENABLE_MULTI_PATH_USDC = 0x20000; // Turned off by default uint256 public constant FLAG_DISABLE_CURVE_SYNTHETIX = 0x40000; uint256 public constant FLAG_DISABLE_WETH = 0x80000; uint256 public constant FLAG_ENABLE_UNISWAP_COMPOUND = 0x100000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH uint256 public constant FLAG_ENABLE_UNISWAP_CHAI = 0x200000; // Works only when ETH<>DAI or FLAG_ENABLE_MULTI_PATH_ETH uint256 public constant FLAG_ENABLE_UNISWAP_AAVE = 0x400000; // Works only when one of assets is ETH or FLAG_ENABLE_MULTI_PATH_ETH uint256 public constant FLAG_DISABLE_IDLE = 0x800000; } contract IOneSplit is IOneSplitConsts { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ); function swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 minReturn, uint256[] memory distribution, uint256 flags ) public payable; } // File: @openzeppelin/contracts/math/SafeMath.sol pragma solidity ^0.5.0; /** * @dev Wrappers over Solidity's arithmetic operations with added overflow * checks. * * Arithmetic operations in Solidity wrap on overflow. This can easily result * in bugs, because programmers usually assume that an overflow raises an * error, which is the standard behavior in high level programming languages. * `SafeMath` restores this intuition by reverting the transaction when an * operation overflows. * * Using this library instead of the unchecked operations eliminates an entire * class of bugs, so it's recommended to use it always. */ library SafeMath { /** * @dev Returns the addition of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `+` operator. * * Requirements: * - Addition cannot overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a, "SafeMath: addition overflow"); return c; } /** * @dev Returns the subtraction of two unsigned integers, reverting on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { return sub(a, b, "SafeMath: subtraction overflow"); } /** * @dev Returns the subtraction of two unsigned integers, reverting with custom message on * overflow (when the result is negative). * * Counterpart to Solidity's `-` operator. * * Requirements: * - Subtraction cannot overflow. * * _Available since v2.4.0._ */ function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b <= a, errorMessage); uint256 c = a - b; return c; } /** * @dev Returns the multiplication of two unsigned integers, reverting on * overflow. * * Counterpart to Solidity's `*` operator. * * Requirements: * - Multiplication cannot overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) { return 0; } uint256 c = a * b; require(c / a == b, "SafeMath: multiplication overflow"); return c; } /** * @dev Returns the integer division of two unsigned integers. Reverts on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { return div(a, b, "SafeMath: division by zero"); } /** * @dev Returns the integer division of two unsigned integers. Reverts with custom message on * division by zero. The result is rounded towards zero. * * Counterpart to Solidity's `/` operator. Note: this function uses a * `revert` opcode (which leaves remaining gas untouched) while Solidity * uses an invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { // Solidity only automatically asserts when dividing by 0 require(b > 0, errorMessage); uint256 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { return mod(a, b, "SafeMath: modulo by zero"); } /** * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo), * Reverts with custom message when dividing by zero. * * Counterpart to Solidity's `%` operator. This function uses a `revert` * opcode (which leaves remaining gas untouched) while Solidity uses an * invalid opcode to revert (consuming all remaining gas). * * Requirements: * - The divisor cannot be zero. * * _Available since v2.4.0._ */ function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) { require(b != 0, errorMessage); return a % b; } } // File: contracts/interface/IUniswapExchange.sol pragma solidity ^0.5.0; interface IUniswapExchange { function getEthToTokenInputPrice(uint256 ethSold) external view returns (uint256 tokensBought); function getTokenToEthInputPrice(uint256 tokensSold) external view returns (uint256 ethBought); function ethToTokenSwapInput(uint256 minTokens, uint256 deadline) external payable returns (uint256 tokensBought); function tokenToEthSwapInput(uint256 tokensSold, uint256 minEth, uint256 deadline) external returns (uint256 ethBought); function tokenToTokenSwapInput( uint256 tokensSold, uint256 minTokensBought, uint256 minEthBought, uint256 deadline, address tokenAddr ) external returns (uint256 tokensBought); } // File: contracts/interface/IUniswapFactory.sol pragma solidity ^0.5.0; interface IUniswapFactory { function getExchange(IERC20 token) external view returns (IUniswapExchange exchange); } // File: contracts/interface/IKyberNetworkContract.sol pragma solidity ^0.5.0; interface IKyberNetworkContract { function searchBestRate(IERC20 src, IERC20 dest, uint256 srcAmount, bool usePermissionless) external view returns (address reserve, uint256 rate); } // File: contracts/interface/IKyberNetworkProxy.sol pragma solidity ^0.5.0; interface IKyberNetworkProxy { function getExpectedRate(IERC20 src, IERC20 dest, uint256 srcQty) external view returns (uint256 expectedRate, uint256 slippageRate); function tradeWithHint( IERC20 src, uint256 srcAmount, IERC20 dest, address destAddress, uint256 maxDestAmount, uint256 minConversionRate, address walletId, bytes calldata hint ) external payable returns (uint256); function kyberNetworkContract() external view returns (IKyberNetworkContract); // TODO: Limit usage by tx.gasPrice // function maxGasPrice() external view returns (uint256); // TODO: Limit usage by user cap // function getUserCapInWei(address user) external view returns (uint256); // function getUserCapInTokenWei(address user, IERC20 token) external view returns (uint256); } // File: contracts/interface/IKyberUniswapReserve.sol pragma solidity ^0.5.0; interface IKyberUniswapReserve { function uniswapFactory() external view returns (address); } // File: contracts/interface/IKyberOasisReserve.sol pragma solidity ^0.5.0; interface IKyberOasisReserve { function otc() external view returns (address); } // File: contracts/interface/IKyberBancorReserve.sol pragma solidity ^0.5.0; contract IKyberBancorReserve { function bancorEth() public view returns (address); } // File: contracts/interface/IBancorNetwork.sol pragma solidity ^0.5.0; interface IBancorNetwork { function getReturnByPath(address[] calldata path, uint256 amount) external view returns (uint256 returnAmount, uint256 conversionFee); function claimAndConvert(address[] calldata path, uint256 amount, uint256 minReturn) external returns (uint256); function convert(address[] calldata path, uint256 amount, uint256 minReturn) external payable returns (uint256); } // File: contracts/interface/IBancorContractRegistry.sol pragma solidity ^0.5.0; contract IBancorContractRegistry { function addressOf(bytes32 contractName) external view returns (address); } // File: contracts/interface/IBancorConverterRegistry.sol pragma solidity ^0.5.0; interface IBancorConverterRegistry { function getConvertibleTokenSmartTokenCount(IERC20 convertibleToken) external view returns(uint256); function getConvertibleTokenSmartTokens(IERC20 convertibleToken) external view returns(address[] memory); function getConvertibleTokenSmartToken(IERC20 convertibleToken, uint256 index) external view returns(address); function isConvertibleTokenSmartToken(IERC20 convertibleToken, address value) external view returns(bool); } // File: contracts/interface/IBancorEtherToken.sol pragma solidity ^0.5.0; contract IBancorEtherToken is IERC20 { function deposit() external payable; function withdraw(uint256 amount) external; } // File: contracts/interface/IOasisExchange.sol pragma solidity ^0.5.0; interface IOasisExchange { function getBuyAmount(IERC20 buyGem, IERC20 payGem, uint256 payAmt) external view returns (uint256 fillAmt); function sellAllAmount(IERC20 payGem, uint256 payAmt, IERC20 buyGem, uint256 minFillAmount) external returns (uint256 fillAmt); } // File: contracts/interface/IWETH.sol pragma solidity ^0.5.0; contract IWETH is IERC20 { function deposit() external payable; function withdraw(uint256 amount) external; } // File: contracts/interface/ICurve.sol pragma solidity ^0.5.0; interface ICurve { // solium-disable-next-line mixedcase function get_dy_underlying(int128 i, int128 j, uint256 dx) external view returns(uint256 dy); // solium-disable-next-line mixedcase function exchange_underlying(int128 i, int128 j, uint256 dx, uint256 minDy) external; } // File: contracts/interface/IChai.sol pragma solidity ^0.5.0; interface IPot { function dsr() external view returns (uint256); function chi() external view returns (uint256); function rho() external view returns (uint256); function drip() external returns (uint256); function join(uint256) external; function exit(uint256) external; } contract IChai is IERC20 { function POT() public view returns (IPot); function join(address dst, uint256 wad) external; function exit(address src, uint256 wad) external; } library ChaiHelper { IPot private constant POT = IPot(0x197E90f9FAD81970bA7976f33CbD77088E5D7cf7); uint256 private constant RAY = 10**27; function _mul(uint256 x, uint256 y) private pure returns (uint256 z) { require(y == 0 || (z = x * y) / y == x); } function _rmul(uint256 x, uint256 y) private pure returns (uint256 z) { // always rounds down z = _mul(x, y) / RAY; } function _rdiv(uint256 x, uint256 y) private pure returns (uint256 z) { // always rounds down z = _mul(x, RAY) / y; } function rpow(uint256 x, uint256 n, uint256 base) private pure returns (uint256 z) { // solium-disable-next-line security/no-inline-assembly assembly { switch x case 0 { switch n case 0 { z := base } default { z := 0 } } default { switch mod(n, 2) case 0 { z := base } default { z := x } let half := div(base, 2) // for rounding. for { n := div(n, 2) } n { n := div(n, 2) } { let xx := mul(x, x) if iszero(eq(div(xx, x), x)) { revert(0, 0) } let xxRound := add(xx, half) if lt(xxRound, xx) { revert(0, 0) } x := div(xxRound, base) if mod(n, 2) { let zx := mul(z, x) if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0, 0) } let zxRound := add(zx, half) if lt(zxRound, zx) { revert(0, 0) } z := div(zxRound, base) } } } } } function potDrip() private view returns (uint256) { return _rmul(rpow(POT.dsr(), now - POT.rho(), RAY), POT.chi()); } function daiToChai( IChai, /*chai*/ uint256 amount ) internal view returns (uint256) { uint256 chi = (now > POT.rho()) ? potDrip() : POT.chi(); return _rdiv(amount, chi); } function chaiToDai( IChai, /*chai*/ uint256 amount ) internal view returns (uint256) { uint256 chi = (now > POT.rho()) ? potDrip() : POT.chi(); return _rmul(chi, amount); } } // File: contracts/interface/ICompound.sol pragma solidity ^0.5.0; contract ICompound { function markets(address cToken) external view returns (bool isListed, uint256 collateralFactorMantissa); } contract ICompoundToken is IERC20 { function underlying() external view returns (address); function exchangeRateStored() external view returns (uint256); function mint(uint256 mintAmount) external returns (uint256); function redeem(uint256 redeemTokens) external returns (uint256); } contract ICompoundEther is IERC20 { function mint() external payable; function redeem(uint256 redeemTokens) external returns (uint256); } // File: contracts/interface/IAaveToken.sol pragma solidity ^0.5.0; contract IAaveToken is IERC20 { function underlyingAssetAddress() external view returns (IERC20); function redeem(uint256 amount) external; } interface IAaveLendingPool { function core() external view returns (address); function deposit(IERC20 token, uint256 amount, uint16 refCode) external payable; } // File: @openzeppelin/contracts/utils/Address.sol pragma solidity ^0.5.5; /** * @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 * ==== */ function isContract(address account) internal view returns (bool) { // According to EIP-1052, 0x0 is the value returned for not-yet created accounts // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned // for accounts without code, i.e. `keccak256('')` bytes32 codehash; bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470; // solhint-disable-next-line no-inline-assembly assembly { codehash := extcodehash(account) } return (codehash != accountHash && codehash != 0x0); } /** * @dev Converts an `address` into `address payable`. Note that this is * simply a type cast: the actual underlying value is not changed. * * _Available since v2.4.0._ */ function toPayable(address account) internal pure returns (address payable) { return address(uint160(account)); } /** * @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://diligence.consensys.net/posts/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.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. * * _Available since v2.4.0._ */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); // solhint-disable-next-line avoid-call-value (bool success, ) = recipient.call.value(amount)(""); require(success, "Address: unable to send value, recipient may have reverted"); } } // File: @openzeppelin/contracts/token/ERC20/SafeERC20.sol pragma solidity ^0.5.0; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using SafeMath for uint256; using Address for address; function safeTransfer(IERC20 token, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value)); } function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value)); } function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' // solhint-disable-next-line max-line-length require((value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value)); } function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).add(value); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero"); callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. // A Solidity high level call has three parts: // 1. The target address is checked to verify it contains contract code // 2. The call itself is made, and success asserted // 3. The return value is decoded, which in turn checks the size of the returned data. // solhint-disable-next-line max-line-length require(address(token).isContract(), "SafeERC20: call to non-contract"); // solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = address(token).call(data); require(success, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional // solhint-disable-next-line max-line-length require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } } // File: contracts/UniversalERC20.sol pragma solidity ^0.5.0; library UniversalERC20 { using SafeMath for uint256; using SafeERC20 for IERC20; IERC20 private constant ZERO_ADDRESS = IERC20(0x0000000000000000000000000000000000000000); IERC20 private constant ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); function universalTransfer(IERC20 token, address to, uint256 amount) internal returns(bool) { if (amount == 0) { return true; } if (isETH(token)) { address(uint160(to)).transfer(amount); } else { token.safeTransfer(to, amount); return true; } } function universalTransferFrom(IERC20 token, address from, address to, uint256 amount) internal { if (amount == 0) { return; } if (isETH(token)) { require(from == msg.sender && msg.value >= amount, "Wrong useage of ETH.universalTransferFrom()"); if (to != address(this)) { address(uint160(to)).transfer(amount); } if (msg.value > amount) { msg.sender.transfer(msg.value.sub(amount)); } } else { token.safeTransferFrom(from, to, amount); } } function universalTransferFromSenderToThis(IERC20 token, uint256 amount) internal { if (amount == 0) { return; } if (isETH(token)) { if (msg.value > amount) { // Return remainder if exist msg.sender.transfer(msg.value.sub(amount)); } } else { token.safeTransferFrom(msg.sender, address(this), amount); } } function universalApprove(IERC20 token, address to, uint256 amount) internal { if (!isETH(token)) { if (amount > 0 && token.allowance(address(this), to) > 0) { token.safeApprove(to, 0); } token.safeApprove(to, amount); } } function universalBalanceOf(IERC20 token, address who) internal view returns (uint256) { if (isETH(token)) { return who.balance; } else { return token.balanceOf(who); } } function universalDecimals(IERC20 token) internal view returns (uint256) { if (isETH(token)) { return 18; } (bool success, bytes memory data) = address(token).staticcall.gas(10000)( abi.encodeWithSignature("decimals()") ); if (!success || data.length == 0) { (success, data) = address(token).staticcall.gas(10000)( abi.encodeWithSignature("DECIMALS()") ); } return (success && data.length > 0) ? abi.decode(data, (uint256)) : 18; } function isETH(IERC20 token) internal pure returns(bool) { return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS)); } } // File: contracts/OneSplitBase.sol pragma solidity ^0.5.0; //import "./interface/IBancorNetworkPathFinder.sol"; contract IOneSplitView is IOneSplitConsts { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ); } library DisableFlags { function check(uint256 flags, uint256 flag) internal pure returns(bool) { return (flags & flag) != 0; } } contract OneSplitRoot { using SafeMath for uint256; using DisableFlags for uint256; using UniversalERC20 for IERC20; using UniversalERC20 for IWETH; using UniversalERC20 for IBancorEtherToken; using ChaiHelper for IChai; uint256 constant public DEXES_COUNT = 12; IERC20 constant public ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); IERC20 constant public dai = IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); IERC20 constant public bnt = IERC20(0x1F573D6Fb3F13d689FF844B4cE37794d79a7FF1C); IERC20 constant public usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); IERC20 constant public usdt = IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); IERC20 constant public tusd = IERC20(0x0000000000085d4780B73119b644AE5ecd22b376); IERC20 constant public busd = IERC20(0x4Fabb145d64652a948d72533023f6E7A623C7C53); IERC20 constant public susd = IERC20(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51); IWETH constant public wethToken = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2); IBancorEtherToken constant public bancorEtherToken = IBancorEtherToken(0xc0829421C1d260BD3cB3E0F06cfE2D52db2cE315); IChai constant public chai = IChai(0x06AF07097C9Eeb7fD685c692751D5C66dB49c215); IKyberNetworkProxy constant public kyberNetworkProxy = IKyberNetworkProxy(0x818E6FECD516Ecc3849DAf6845e3EC868087B755); IUniswapFactory constant public uniswapFactory = IUniswapFactory(0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95); IBancorContractRegistry constant public bancorContractRegistry = IBancorContractRegistry(0x52Ae12ABe5D8BD778BD5397F99cA900624CfADD4); //IBancorNetworkPathFinder constant public bancorNetworkPathFinder = IBancorNetworkPathFinder(0x6F0cD8C4f6F06eAB664C7E3031909452b4B72861); IBancorConverterRegistry constant public bancorConverterRegistry = IBancorConverterRegistry(0xf6E2D7F616B67E46D708e4410746E9AAb3a4C518); IOasisExchange constant public oasisExchange = IOasisExchange(0x794e6e91555438aFc3ccF1c5076A74F42133d08D); ICurve constant public curveCompound = ICurve(0xA2B47E3D5c44877cca798226B7B8118F9BFb7A56); ICurve constant public curveUsdt = ICurve(0x52EA46506B9CC5Ef470C5bf89f17Dc28bB35D85C); ICurve constant public curveY = ICurve(0x45F783CCE6B7FF23B2ab2D70e416cdb7D6055f51); ICurve constant public curveBinance = ICurve(0x79a8C46DeA5aDa233ABaFFD40F3A0A2B1e5A4F27); ICurve constant public curveSynthetix = ICurve(0xA5407eAE9Ba41422680e2e00537571bcC53efBfD); IAaveLendingPool constant public aave = IAaveLendingPool(0x398eC7346DcD622eDc5ae82352F02bE94C62d119); ICompound constant public compound = ICompound(0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B); ICompoundEther constant public cETH = ICompoundEther(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5); function _buildBancorPath( IERC20 fromToken, IERC20 toToken ) internal view returns(address[] memory path) { if (fromToken == toToken) { return new address[](0); } if (fromToken.isETH()) { fromToken = bancorEtherToken; } if (toToken.isETH()) { toToken = bancorEtherToken; } if (fromToken == bnt || toToken == bnt) { path = new address[](3); } else { path = new address[](5); } address fromConverter; address toConverter; if (fromToken != bnt) { (bool success, bytes memory data) = address(bancorConverterRegistry).staticcall.gas(10000)(abi.encodeWithSelector( bancorConverterRegistry.getConvertibleTokenSmartToken.selector, fromToken.isETH() ? bnt : fromToken, 0 )); if (!success) { return new address[](0); } fromConverter = abi.decode(data, (address)); if (fromConverter == address(0)) { return new address[](0); } } if (toToken != bnt) { (bool success, bytes memory data) = address(bancorConverterRegistry).staticcall.gas(10000)(abi.encodeWithSelector( bancorConverterRegistry.getConvertibleTokenSmartToken.selector, toToken.isETH() ? bnt : toToken, 0 )); if (!success) { return new address[](0); } toConverter = abi.decode(data, (address)); if (toConverter == address(0)) { return new address[](0); } } if (toToken == bnt) { path[0] = address(fromToken); path[1] = fromConverter; path[2] = address(bnt); return path; } if (fromToken == bnt) { path[0] = address(bnt); path[1] = toConverter; path[2] = address(toToken); return path; } path[0] = address(fromToken); path[1] = fromConverter; path[2] = address(bnt); path[3] = toConverter; path[4] = address(toToken); return path; } function _getCompoundToken(IERC20 token) internal pure returns(ICompoundToken) { if (token.isETH()) { // ETH return ICompoundToken(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5); } if (token == IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { // DAI return ICompoundToken(0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643); } if (token == IERC20(0x0D8775F648430679A709E98d2b0Cb6250d2887EF)) { // BAT return ICompoundToken(0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E); } if (token == IERC20(0x1985365e9f78359a9B6AD760e32412f4a445E862)) { // REP return ICompoundToken(0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1); } if (token == IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) { // USDC return ICompoundToken(0x39AA39c021dfbaE8faC545936693aC917d5E7563); } if (token == IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599)) { // WBTC return ICompoundToken(0xC11b1268C1A384e55C48c2391d8d480264A3A7F4); } if (token == IERC20(0xE41d2489571d322189246DaFA5ebDe1F4699F498)) { // ZRX return ICompoundToken(0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407); } if (token == IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7)) { // USDT return ICompoundToken(0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9); } return ICompoundToken(0); } function _getAaveToken(IERC20 token) internal pure returns(IAaveToken) { if (token.isETH()) { // ETH return IAaveToken(0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04); } if (token == IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F)) { // DAI return IAaveToken(0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d); } if (token == IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48)) { // USDC return IAaveToken(0x9bA00D6856a4eDF4665BcA2C2309936572473B7E); } if (token == IERC20(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51)) { // SUSD return IAaveToken(0x625aE63000f46200499120B906716420bd059240); } if (token == IERC20(0x4Fabb145d64652a948d72533023f6E7A623C7C53)) { // BUSD return IAaveToken(0x6Ee0f7BB50a54AB5253dA0667B0Dc2ee526C30a8); } if (token == IERC20(0x0000000000085d4780B73119b644AE5ecd22b376)) { // TUSD return IAaveToken(0x4DA9b813057D04BAef4e5800E36083717b4a0341); } if (token == IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7)) { // USDT return IAaveToken(0x71fc860F7D3A592A4a98740e39dB31d25db65ae8); } if (token == IERC20(0x0D8775F648430679A709E98d2b0Cb6250d2887EF)) { // BAT return IAaveToken(0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00); } if (token == IERC20(0xdd974D5C2e2928deA5F71b9825b8b646686BD200)) { // KNC return IAaveToken(0x9D91BE44C06d373a8a226E1f3b146956083803eB); } if (token == IERC20(0x80fB784B7eD66730e8b1DBd9820aFD29931aab03)) { // LEND return IAaveToken(0x7D2D3688Df45Ce7C552E19c27e007673da9204B8); } if (token == IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA)) { // LINK return IAaveToken(0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84); } if (token == IERC20(0x0F5D2fB29fb7d3CFeE444a200298f468908cC942)) { // MANA return IAaveToken(0x6FCE4A401B6B80ACe52baAefE4421Bd188e76F6f); } if (token == IERC20(0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2)) { // MKR return IAaveToken(0x7deB5e830be29F91E298ba5FF1356BB7f8146998); } if (token == IERC20(0x1985365e9f78359a9B6AD760e32412f4a445E862)) { // REP return IAaveToken(0x71010A9D003445aC60C4e6A7017c1E89A477B438); } if (token == IERC20(0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F)) { // SNX return IAaveToken(0x328C4c80BC7aCa0834Db37e6600A6c49E12Da4DE); } if (token == IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599)) { // WBTC return IAaveToken(0xFC4B8ED459e00e5400be803A9BB3954234FD50e3); } if (token == IERC20(0xE41d2489571d322189246DaFA5ebDe1F4699F498)) { // ZRX return IAaveToken(0x6Fb0855c404E09c47C3fBCA25f08d4E41f9F062f); } return IAaveToken(0); } function _infiniteApproveIfNeeded(IERC20 token, address to) internal { if (!token.isETH()) { if ((token.allowance(address(this), to) >> 255) == 0) { token.universalApprove(to, uint256(- 1)); } } } } contract OneSplitViewWrapBase is IOneSplitView, OneSplitRoot { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags // See constants in IOneSplit.sol ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return _getExpectedReturnFloor( fromToken, toToken, amount, parts, flags ); } function _getExpectedReturnFloor( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags // See constants in IOneSplit.sol ) internal view returns( uint256 returnAmount, uint256[] memory distribution ); } contract OneSplitView is IOneSplitView, OneSplitRoot { function log(uint256) external view { } function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags // See constants in IOneSplit.sol ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { distribution = new uint256[](DEXES_COUNT); if (fromToken == toToken) { return (amount, distribution); } function(IERC20,IERC20,uint256,uint256) view returns(uint256)[DEXES_COUNT] memory reserves = [ flags.check(FLAG_DISABLE_UNISWAP) ? _calculateNoReturn : calculateUniswapReturn, flags.check(FLAG_DISABLE_KYBER) ? _calculateNoReturn : calculateKyberReturn, flags.check(FLAG_DISABLE_BANCOR) ? _calculateNoReturn : calculateBancorReturn, flags.check(FLAG_DISABLE_OASIS) ? _calculateNoReturn : calculateOasisReturn, flags.check(FLAG_DISABLE_CURVE_COMPOUND) ? _calculateNoReturn : calculateCurveCompound, flags.check(FLAG_DISABLE_CURVE_USDT) ? _calculateNoReturn : calculateCurveUsdt, flags.check(FLAG_DISABLE_CURVE_Y) ? _calculateNoReturn : calculateCurveY, flags.check(FLAG_DISABLE_CURVE_BINANCE) ? _calculateNoReturn : calculateCurveBinance, flags.check(FLAG_DISABLE_CURVE_SYNTHETIX) ? _calculateNoReturn : calculateCurveSynthetix, !flags.check(FLAG_ENABLE_UNISWAP_COMPOUND) ? _calculateNoReturn : calculateUniswapCompound, !flags.check(FLAG_ENABLE_UNISWAP_CHAI) ? _calculateNoReturn : calculateUniswapChai, !flags.check(FLAG_ENABLE_UNISWAP_AAVE) ? _calculateNoReturn : calculateUniswapAave ]; uint256[DEXES_COUNT] memory rates; uint256[DEXES_COUNT] memory fullRates; for (uint i = 0; i < rates.length; i++) { rates[i] = reserves[i](fromToken, toToken, amount.div(parts), flags); this.log(rates[i]); fullRates[i] = rates[i]; } for (uint j = 0; j < parts; j++) { // Find best part uint256 bestIndex = 0; for (uint i = 1; i < rates.length; i++) { if (rates[i] > rates[bestIndex]) { bestIndex = i; } } // Add best part returnAmount = returnAmount.add(rates[bestIndex]); distribution[bestIndex]++; // Avoid CompilerError: Stack too deep uint256 srcAmount = amount; // Recalc part if needed if (j + 1 < parts) { uint256 newRate = reserves[bestIndex]( fromToken, toToken, srcAmount.mul(distribution[bestIndex] + 1).div(parts), flags ); if (newRate > fullRates[bestIndex]) { rates[bestIndex] = newRate.sub(fullRates[bestIndex]); } else { rates[bestIndex] = 0; } this.log(rates[bestIndex]); fullRates[bestIndex] = newRate; } } } // View Helpers function calculateCurveCompound( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0); if (i == 0 || j == 0) { return 0; } return curveCompound.get_dy_underlying(i - 1, j - 1, amount); } function calculateCurveUsdt( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0); if (i == 0 || j == 0) { return 0; } return curveUsdt.get_dy_underlying(i - 1, j - 1, amount); } function calculateCurveY( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == tusd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == tusd ? 4 : 0); if (i == 0 || j == 0) { return 0; } return curveY.get_dy_underlying(i - 1, j - 1, amount); } function calculateCurveBinance( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == busd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == busd ? 4 : 0); if (i == 0 || j == 0) { return 0; } return curveBinance.get_dy_underlying(i - 1, j - 1, amount); } function calculateCurveSynthetix( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == susd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == susd ? 4 : 0); if (i == 0 || j == 0) { return 0; } return curveSynthetix.get_dy_underlying(i - 1, j - 1, amount); } function calculateUniswapReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { uint256 returnAmount = amount; if (!fromToken.isETH()) { IUniswapExchange fromExchange = uniswapFactory.getExchange(fromToken); if (fromExchange != IUniswapExchange(0)) { (bool success, bytes memory data) = address(fromExchange).staticcall.gas(200000)( abi.encodeWithSelector( fromExchange.getTokenToEthInputPrice.selector, returnAmount ) ); if (success) { returnAmount = abi.decode(data, (uint256)); } else { returnAmount = 0; } } else { returnAmount = 0; } } if (!toToken.isETH()) { IUniswapExchange toExchange = uniswapFactory.getExchange(toToken); if (toExchange != IUniswapExchange(0)) { (bool success, bytes memory data) = address(toExchange).staticcall.gas(200000)( abi.encodeWithSelector( toExchange.getEthToTokenInputPrice.selector, returnAmount ) ); if (success) { returnAmount = abi.decode(data, (uint256)); } else { returnAmount = 0; } } else { returnAmount = 0; } } return returnAmount; } function calculateUniswapCompound( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 flags ) public view returns(uint256) { if (!fromToken.isETH() && !toToken.isETH()) { return 0; } if (!fromToken.isETH()) { ICompoundToken fromCompound = _getCompoundToken(fromToken); if (fromCompound != ICompoundToken(0)) { return calculateUniswapReturn( fromCompound, toToken, amount.mul(1e18).div(fromCompound.exchangeRateStored()), flags ); } } else { ICompoundToken toCompound = _getCompoundToken(toToken); if (toCompound != ICompoundToken(0)) { return calculateUniswapReturn( fromToken, toCompound, amount, flags ).mul(toCompound.exchangeRateStored()).div(1e18); } } return 0; } function calculateUniswapChai( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 flags ) public view returns(uint256) { if (fromToken == dai && toToken.isETH()) { return calculateUniswapReturn( chai, toToken, chai.daiToChai(amount), flags ); } if (fromToken.isETH() && toToken == dai) { return chai.chaiToDai(calculateUniswapReturn( fromToken, chai, amount, flags )); } return 0; } function calculateUniswapAave( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 flags ) public view returns(uint256) { if (!fromToken.isETH() && !toToken.isETH()) { return 0; } if (!fromToken.isETH()) { IAaveToken fromAave = _getAaveToken(fromToken); if (fromAave != IAaveToken(0)) { return calculateUniswapReturn( fromAave, toToken, amount, flags ); } } else { IAaveToken toAave = _getAaveToken(toToken); if (toAave != IAaveToken(0)) { return calculateUniswapReturn( fromToken, toAave, amount, flags ); } } return 0; } function calculateKyberReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 flags ) public view returns(uint256) { (bool success, bytes memory data) = address(kyberNetworkProxy).staticcall.gas(2300)(abi.encodeWithSelector( kyberNetworkProxy.kyberNetworkContract.selector )); if (!success) { return 0; } IKyberNetworkContract kyberNetworkContract = IKyberNetworkContract(abi.decode(data, (address))); if (fromToken.isETH() || toToken.isETH()) { return _calculateKyberReturnWithEth(kyberNetworkContract, fromToken, toToken, amount, flags); } uint256 value = _calculateKyberReturnWithEth(kyberNetworkContract, fromToken, ETH_ADDRESS, amount, flags); if (value == 0) { return 0; } return _calculateKyberReturnWithEth(kyberNetworkContract, ETH_ADDRESS, toToken, value, flags); } function _calculateKyberReturnWithEth( IKyberNetworkContract kyberNetworkContract, IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 flags ) public view returns(uint256) { require(fromToken.isETH() || toToken.isETH(), "One of the tokens should be ETH"); (bool success, bytes memory data) = address(kyberNetworkContract).staticcall.gas(1500000)(abi.encodeWithSelector( kyberNetworkContract.searchBestRate.selector, fromToken.isETH() ? ETH_ADDRESS : fromToken, toToken.isETH() ? ETH_ADDRESS : toToken, amount, true )); if (!success) { return 0; } (address reserve, uint256 rate) = abi.decode(data, (address,uint256)); if (rate == 0) { return 0; } if ((reserve == 0x31E085Afd48a1d6e51Cc193153d625e8f0514C7F && !flags.check(FLAG_ENABLE_KYBER_UNISWAP_RESERVE)) || (reserve == 0x1E158c0e93c30d24e918Ef83d1e0bE23595C3c0f && !flags.check(FLAG_ENABLE_KYBER_OASIS_RESERVE)) || (reserve == 0x053AA84FCC676113a57e0EbB0bD1913839874bE4 && !flags.check(FLAG_ENABLE_KYBER_BANCOR_RESERVE))) { return 0; } if (!flags.check(FLAG_ENABLE_KYBER_UNISWAP_RESERVE)) { (success,) = reserve.staticcall.gas(2300)(abi.encodeWithSelector( IKyberUniswapReserve(reserve).uniswapFactory.selector )); if (success) { return 0; } } if (!flags.check(FLAG_ENABLE_KYBER_OASIS_RESERVE)) { (success,) = reserve.staticcall.gas(2300)(abi.encodeWithSelector( IKyberOasisReserve(reserve).otc.selector )); if (success) { return 0; } } if (!flags.check(FLAG_ENABLE_KYBER_BANCOR_RESERVE)) { (success,) = reserve.staticcall.gas(2300)(abi.encodeWithSelector( IKyberBancorReserve(reserve).bancorEth.selector )); if (success) { return 0; } } return rate.mul(amount) .mul(10 ** IERC20(toToken).universalDecimals()) .div(10 ** IERC20(fromToken).universalDecimals()) .div(1e18); } function calculateBancorReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { IBancorNetwork bancorNetwork = IBancorNetwork(bancorContractRegistry.addressOf("BancorNetwork")); address[] memory path = _buildBancorPath(fromToken, toToken); (bool success, bytes memory data) = address(bancorNetwork).staticcall.gas(500000)( abi.encodeWithSelector( bancorNetwork.getReturnByPath.selector, path, amount ) ); if (!success) { return 0; } (uint256 returnAmount,) = abi.decode(data, (uint256,uint256)); return returnAmount; } function calculateOasisReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 /*flags*/ ) public view returns(uint256) { (bool success, bytes memory data) = address(oasisExchange).staticcall.gas(500000)( abi.encodeWithSelector( oasisExchange.getBuyAmount.selector, toToken.isETH() ? wethToken : toToken, fromToken.isETH() ? wethToken : fromToken, amount ) ); if (!success) { return 0; } return abi.decode(data, (uint256)); } function _calculateNoReturn( IERC20 /*fromToken*/, IERC20 /*toToken*/, uint256 /*amount*/, uint256 /*flags*/ ) internal view returns(uint256) { this; } } contract OneSplitBaseWrap is IOneSplit, OneSplitRoot { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags // See constants in IOneSplit.sol ) internal { if (fromToken == toToken) { return; } _swapFloor( fromToken, toToken, amount, distribution, flags ); } function _swapFloor( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 /*flags*/ // See constants in IOneSplit.sol ) internal; } contract OneSplit is IOneSplit, OneSplitRoot { IOneSplitView public oneSplitView; constructor(IOneSplitView _oneSplitView) public { oneSplitView = _oneSplitView; } function() external payable { // solium-disable-next-line security/no-tx-origin require(msg.sender != tx.origin); } function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return oneSplitView.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } function swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 /*minReturn*/, uint256[] memory distribution, uint256 /*flags*/ // See constants in IOneSplit.sol ) public payable { if (fromToken == toToken) { return; } function(IERC20,IERC20,uint256) returns(uint256)[DEXES_COUNT] memory reserves = [ _swapOnUniswap, _swapOnKyber, _swapOnBancor, _swapOnOasis, _swapOnCurveCompound, _swapOnCurveUsdt, _swapOnCurveY, _swapOnCurveBinance, _swapOnCurveSynthetix, _swapOnUniswapCompound, _swapOnUniswapChai, _swapOnUniswapAave ]; require(distribution.length <= reserves.length, "OneSplit: Distribution array should not exceed reserves array size"); uint256 parts = 0; uint256 lastNonZeroIndex = 0; for (uint i = 0; i < distribution.length; i++) { if (distribution[i] > 0) { parts = parts.add(distribution[i]); lastNonZeroIndex = i; } } require(parts > 0, "OneSplit: distribution should contain non-zeros"); uint256 remainingAmount = amount; for (uint i = 0; i < distribution.length; i++) { if (distribution[i] == 0) { continue; } uint256 swapAmount = amount.mul(distribution[i]).div(parts); if (i == lastNonZeroIndex) { swapAmount = remainingAmount; } remainingAmount -= swapAmount; reserves[i](fromToken, toToken, swapAmount); } } // Swap helpers function _swapOnCurveCompound( IERC20 fromToken, IERC20 destToken, uint256 amount ) internal returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0); if (i == 0 || j == 0) { return 0; } _infiniteApproveIfNeeded(fromToken, address(curveCompound)); curveCompound.exchange_underlying(i - 1, j - 1, amount, 0); } function _swapOnCurveUsdt( IERC20 fromToken, IERC20 destToken, uint256 amount ) internal returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0); if (i == 0 || j == 0) { return 0; } _infiniteApproveIfNeeded(fromToken, address(curveUsdt)); curveUsdt.exchange_underlying(i - 1, j - 1, amount, 0); } function _swapOnCurveY( IERC20 fromToken, IERC20 destToken, uint256 amount ) internal returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == tusd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == tusd ? 4 : 0); if (i == 0 || j == 0) { return 0; } _infiniteApproveIfNeeded(fromToken, address(curveY)); curveY.exchange_underlying(i - 1, j - 1, amount, 0); } function _swapOnCurveBinance( IERC20 fromToken, IERC20 destToken, uint256 amount ) internal returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == busd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == busd ? 4 : 0); if (i == 0 || j == 0) { return 0; } _infiniteApproveIfNeeded(fromToken, address(curveBinance)); curveBinance.exchange_underlying(i - 1, j - 1, amount, 0); } function _swapOnCurveSynthetix( IERC20 fromToken, IERC20 destToken, uint256 amount ) internal returns(uint256) { int128 i = (fromToken == dai ? 1 : 0) + (fromToken == usdc ? 2 : 0) + (fromToken == usdt ? 3 : 0) + (fromToken == susd ? 4 : 0); int128 j = (destToken == dai ? 1 : 0) + (destToken == usdc ? 2 : 0) + (destToken == usdt ? 3 : 0) + (destToken == susd ? 4 : 0); if (i == 0 || j == 0) { return 0; } _infiniteApproveIfNeeded(fromToken, address(curveSynthetix)); curveSynthetix.exchange_underlying(i - 1, j - 1, amount, 0); } function _swapOnUniswap( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { uint256 returnAmount = amount; if (!fromToken.isETH()) { IUniswapExchange fromExchange = uniswapFactory.getExchange(fromToken); if (fromExchange != IUniswapExchange(0)) { _infiniteApproveIfNeeded(fromToken, address(fromExchange)); returnAmount = fromExchange.tokenToEthSwapInput(returnAmount, 1, now); } } if (!toToken.isETH()) { IUniswapExchange toExchange = uniswapFactory.getExchange(toToken); if (toExchange != IUniswapExchange(0)) { returnAmount = toExchange.ethToTokenSwapInput.value(returnAmount)(1, now); } } return returnAmount; } function _swapOnUniswapCompound( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { if (!fromToken.isETH()) { ICompoundToken fromCompound = _getCompoundToken(fromToken); _infiniteApproveIfNeeded(fromToken, address(fromCompound)); fromCompound.mint(amount); return _swapOnUniswap(IERC20(fromCompound), toToken, IERC20(fromCompound).universalBalanceOf(address(this))); } if (!toToken.isETH()) { ICompoundToken toCompound = _getCompoundToken(toToken); uint256 compoundAmount = _swapOnUniswap(fromToken, IERC20(toCompound), amount); toCompound.redeem(compoundAmount); return toToken.universalBalanceOf(address(this)); } return 0; } function _swapOnUniswapChai( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { if (fromToken == dai) { _infiniteApproveIfNeeded(fromToken, address(chai)); chai.join(address(this), amount); return _swapOnUniswap(IERC20(chai), toToken, IERC20(chai).universalBalanceOf(address(this))); } if (toToken == dai) { uint256 chaiAmount = _swapOnUniswap(fromToken, IERC20(chai), amount); chai.exit(address(this), chaiAmount); return toToken.universalBalanceOf(address(this)); } return 0; } function _swapOnUniswapAave( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { if (!fromToken.isETH()) { IAaveToken fromAave = _getAaveToken(fromToken); _infiniteApproveIfNeeded(fromToken, address(fromAave)); aave.deposit(fromToken, amount, 1101); return _swapOnUniswap(IERC20(fromAave), toToken, IERC20(fromAave).universalBalanceOf(address(this))); } if (!toToken.isETH()) { IAaveToken toAave = _getAaveToken(toToken); uint256 aaveAmount = _swapOnUniswap(fromToken, IERC20(toAave), amount); toAave.redeem(aaveAmount); return aaveAmount; } return 0; } function _swapOnKyber( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { _infiniteApproveIfNeeded(fromToken, address(kyberNetworkProxy)); return kyberNetworkProxy.tradeWithHint.value(fromToken.isETH() ? amount : 0)( fromToken.isETH() ? ETH_ADDRESS : fromToken, amount, toToken.isETH() ? ETH_ADDRESS : toToken, address(this), 1 << 255, 0, 0x4D37f28D2db99e8d35A6C725a5f1749A085850a3, "" ); } function _swapOnBancor( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { if (fromToken.isETH()) { bancorEtherToken.deposit.value(amount)(); } IBancorNetwork bancorNetwork = IBancorNetwork(bancorContractRegistry.addressOf("BancorNetwork")); address[] memory path = _buildBancorPath(fromToken, toToken); _infiniteApproveIfNeeded(fromToken.isETH() ? bancorEtherToken : fromToken, address(bancorNetwork)); uint256 returnAmount = bancorNetwork.claimAndConvert(path, amount, 1); if (toToken.isETH()) { bancorEtherToken.withdraw(bancorEtherToken.balanceOf(address(this))); } return returnAmount; } function _swapOnOasis( IERC20 fromToken, IERC20 toToken, uint256 amount ) internal returns(uint256) { if (fromToken.isETH()) { wethToken.deposit.value(amount)(); } _infiniteApproveIfNeeded(fromToken.isETH() ? wethToken : fromToken, address(oasisExchange)); uint256 returnAmount = oasisExchange.sellAllAmount( fromToken.isETH() ? wethToken : fromToken, amount, toToken.isETH() ? wethToken : toToken, 1 ); if (toToken.isETH()) { wethToken.withdraw(wethToken.balanceOf(address(this))); } return returnAmount; } } // File: contracts/OneSplitMultiPath.sol pragma solidity ^0.5.0; contract OneSplitMultiPathView is OneSplitViewWrapBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns ( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!fromToken.isETH() && !toToken.isETH() && flags.check(FLAG_ENABLE_MULTI_PATH_ETH)) { (returnAmount, distribution) = super.getExpectedReturn( fromToken, ETH_ADDRESS, amount, parts, flags | FLAG_DISABLE_BANCOR | FLAG_DISABLE_CURVE_COMPOUND | FLAG_DISABLE_CURVE_USDT | FLAG_DISABLE_CURVE_Y | FLAG_DISABLE_CURVE_BINANCE ); uint256[] memory dist; (returnAmount, dist) = super.getExpectedReturn( ETH_ADDRESS, toToken, returnAmount, parts, flags | FLAG_DISABLE_BANCOR | FLAG_DISABLE_CURVE_COMPOUND | FLAG_DISABLE_CURVE_USDT | FLAG_DISABLE_CURVE_Y | FLAG_DISABLE_CURVE_BINANCE ); for (uint i = 0; i < distribution.length; i++) { distribution[i] = distribution[i].add(dist[i] << 8); } return (returnAmount, distribution); } if (fromToken != dai && toToken != dai && flags.check(FLAG_ENABLE_MULTI_PATH_DAI)) { (returnAmount, distribution) = super.getExpectedReturn( fromToken, dai, amount, parts, flags ); uint256[] memory dist; (returnAmount, dist) = super.getExpectedReturn( dai, toToken, returnAmount, parts, flags ); for (uint i = 0; i < distribution.length; i++) { distribution[i] = distribution[i].add(dist[i] << 8); } return (returnAmount, distribution); } if (fromToken != usdc && toToken != usdc && flags.check(FLAG_ENABLE_MULTI_PATH_USDC)) { (returnAmount, distribution) = super.getExpectedReturn( fromToken, usdc, amount, parts, flags ); uint256[] memory dist; (returnAmount, dist) = super.getExpectedReturn( usdc, toToken, returnAmount, parts, flags ); for (uint i = 0; i < distribution.length; i++) { distribution[i] = distribution[i].add(dist[i] << 8); } return (returnAmount, distribution); } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitMultiPath is OneSplitBaseWrap { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { if (!fromToken.isETH() && !toToken.isETH() && flags.check(FLAG_ENABLE_MULTI_PATH_ETH)) { uint256[] memory dist = new uint256[](distribution.length); for (uint i = 0; i < distribution.length; i++) { dist[i] = distribution[i] & 0xFF; } super._swap( fromToken, ETH_ADDRESS, amount, dist, flags ); for (uint i = 0; i < distribution.length; i++) { dist[i] = (distribution[i] >> 8) & 0xFF; } super._swap( ETH_ADDRESS, toToken, address(this).balance, dist, flags ); return; } if (fromToken != dai && toToken != dai && flags.check(FLAG_ENABLE_MULTI_PATH_DAI)) { uint256[] memory dist = new uint256[](distribution.length); for (uint i = 0; i < distribution.length; i++) { dist[i] = distribution[i] & 0xFF; } super._swap( fromToken, dai, amount, dist, flags ); for (uint i = 0; i < distribution.length; i++) { dist[i] = (distribution[i] >> 8) & 0xFF; } super._swap( dai, toToken, dai.balanceOf(address(this)), dist, flags ); return; } if (fromToken != usdc && toToken != usdc && flags.check(FLAG_ENABLE_MULTI_PATH_USDC)) { uint256[] memory dist = new uint256[](distribution.length); for (uint i = 0; i < distribution.length; i++) { dist[i] = distribution[i] & 0xFF; } super._swap( fromToken, usdc, amount, dist, flags ); for (uint i = 0; i < distribution.length; i++) { dist[i] = (distribution[i] >> 8) & 0xFF; } super._swap( usdc, toToken, usdc.balanceOf(address(this)), dist, flags ); return; } super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: contracts/OneSplitCompound.sol pragma solidity ^0.5.0; contract OneSplitCompoundBase { function _getCompoundUnderlyingToken(IERC20 token) internal pure returns(IERC20) { if (token == IERC20(0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5)) { // ETH return IERC20(0); } if (token == IERC20(0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643)) { // DAI return IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); } if (token == IERC20(0x6C8c6b02E7b2BE14d4fA6022Dfd6d75921D90E4E)) { // BAT return IERC20(0x0D8775F648430679A709E98d2b0Cb6250d2887EF); } if (token == IERC20(0x158079Ee67Fce2f58472A96584A73C7Ab9AC95c1)) { // REP return IERC20(0x1985365e9f78359a9B6AD760e32412f4a445E862); } if (token == IERC20(0x39AA39c021dfbaE8faC545936693aC917d5E7563)) { // USDC return IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); } if (token == IERC20(0xC11b1268C1A384e55C48c2391d8d480264A3A7F4)) { // WBTC return IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599); } if (token == IERC20(0xB3319f5D18Bc0D84dD1b4825Dcde5d5f7266d407)) { // ZRX return IERC20(0xE41d2489571d322189246DaFA5ebDe1F4699F498); } if (token == IERC20(0xf650C3d88D12dB855b8bf7D11Be6C55A4e07dCC9)) { // USDT return IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); } return IERC20(-1); } } contract OneSplitCompoundView is OneSplitViewWrapBase, OneSplitCompoundBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return _compoundGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _compoundGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) private view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!flags.check(FLAG_DISABLE_COMPOUND)) { IERC20 underlying = _getCompoundUnderlyingToken(fromToken); if (underlying != IERC20(-1)) { uint256 compoundRate = ICompoundToken(address(fromToken)).exchangeRateStored(); return _compoundGetExpectedReturn( underlying, toToken, amount.mul(compoundRate).div(1e18), parts, flags ); } underlying = _getCompoundUnderlyingToken(toToken); if (underlying != IERC20(-1)) { uint256 compoundRate = ICompoundToken(address(toToken)).exchangeRateStored(); (returnAmount, distribution) = super.getExpectedReturn( fromToken, underlying, amount, parts, flags ); returnAmount = returnAmount.mul(1e18).div(compoundRate); return (returnAmount, distribution); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitCompound is OneSplitBaseWrap, OneSplitCompoundBase { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _compundSwap( fromToken, toToken, amount, distribution, flags ); } function _compundSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) private { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_COMPOUND)) { IERC20 underlying = _getCompoundUnderlyingToken(fromToken); if (underlying != IERC20(-1)) { ICompoundToken(address(fromToken)).redeem(amount); uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); return _compundSwap( underlying, toToken, underlyingAmount, distribution, flags ); } underlying = _getCompoundUnderlyingToken(toToken); if (underlying != IERC20(-1)) { super._swap( fromToken, underlying, amount, distribution, flags ); uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); if (underlying.isETH()) { cETH.mint.value(underlyingAmount)(); } else { _infiniteApproveIfNeeded(underlying, address(toToken)); ICompoundToken(address(toToken)).mint(underlyingAmount); } return; } } return super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: @openzeppelin/contracts/token/ERC20/ERC20Detailed.sol pragma solidity ^0.5.0; /** * @dev Optional functions from the ERC20 standard. */ contract ERC20Detailed is IERC20 { string private _name; string private _symbol; uint8 private _decimals; /** * @dev Sets the values for `name`, `symbol`, and `decimals`. All three of * these values are immutable: they can only be set once during * construction. */ constructor (string memory name, string memory symbol, uint8 decimals) public { _name = name; _symbol = symbol; _decimals = decimals; } /** * @dev Returns the name of the token. */ function name() public view returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5,05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view returns (uint8) { return _decimals; } } // File: contracts/interface/IFulcrum.sol pragma solidity ^0.5.0; contract IFulcrumToken is IERC20 { function tokenPrice() external view returns (uint256); function loanTokenAddress() external view returns (address); function mintWithEther(address receiver) external payable returns (uint256 mintAmount); function mint(address receiver, uint256 depositAmount) external returns (uint256 mintAmount); function burnToEther(address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid); function burn(address receiver, uint256 burnAmount) external returns (uint256 loanAmountPaid); } // File: contracts/OneSplitFulcrum.sol pragma solidity ^0.5.0; contract OneSplitFulcrumBase { using UniversalERC20 for IERC20; function _isFulcrumToken(IERC20 token) public view returns(IERC20) { if (token.isETH()) { return IERC20(-1); } (bool success, bytes memory data) = address(token).staticcall.gas(5000)(abi.encodeWithSelector( ERC20Detailed(address(token)).name.selector )); if (!success) { return IERC20(-1); } bool foundBZX = false; for (uint i = 0; i + 6 < data.length; i++) { if (data[i + 0] == "F" && data[i + 1] == "u" && data[i + 2] == "l" && data[i + 3] == "c" && data[i + 4] == "r" && data[i + 5] == "u" && data[i + 6] == "m") { foundBZX = true; break; } } if (!foundBZX) { return IERC20(-1); } (success, data) = address(token).staticcall.gas(5000)(abi.encodeWithSelector( IFulcrumToken(address(token)).loanTokenAddress.selector )); if (!success) { return IERC20(-1); } return abi.decode(data, (IERC20)); } } contract OneSplitFulcrumView is OneSplitViewWrapBase, OneSplitFulcrumBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return _fulcrumGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _fulcrumGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) private view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!flags.check(FLAG_DISABLE_FULCRUM)) { IERC20 underlying = _isFulcrumToken(fromToken); if (underlying != IERC20(-1)) { uint256 fulcrumRate = IFulcrumToken(address(fromToken)).tokenPrice(); return _fulcrumGetExpectedReturn( underlying, toToken, amount.mul(fulcrumRate).div(1e18), parts, flags ); } underlying = _isFulcrumToken(toToken); if (underlying != IERC20(-1)) { uint256 fulcrumRate = IFulcrumToken(address(toToken)).tokenPrice(); (returnAmount, distribution) = super.getExpectedReturn( fromToken, underlying, amount, parts, flags ); returnAmount = returnAmount.mul(1e18).div(fulcrumRate); return (returnAmount, distribution); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitFulcrum is OneSplitBaseWrap, OneSplitFulcrumBase { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _fulcrumSwap( fromToken, toToken, amount, distribution, flags ); } function _fulcrumSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) private { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_FULCRUM)) { IERC20 underlying = _isFulcrumToken(fromToken); if (underlying != IERC20(-1)) { if (underlying.isETH()) { IFulcrumToken(address(fromToken)).burnToEther(address(this), amount); } else { IFulcrumToken(address(fromToken)).burn(address(this), amount); } uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); return super._swap( underlying, toToken, underlyingAmount, distribution, flags ); } underlying = _isFulcrumToken(toToken); if (underlying != IERC20(-1)) { super._swap( fromToken, underlying, amount, distribution, flags ); uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); if (underlying.isETH()) { IFulcrumToken(address(toToken)).mintWithEther.value(underlyingAmount)(address(this)); } else { _infiniteApproveIfNeeded(underlying, address(toToken)); IFulcrumToken(address(toToken)).mint(address(this), underlyingAmount); } return; } } return super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: contracts/OneSplitChai.sol pragma solidity ^0.5.0; contract OneSplitChaiView is OneSplitViewWrapBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!flags.check(FLAG_DISABLE_CHAI)) { if (fromToken == IERC20(chai)) { return super.getExpectedReturn( dai, toToken, chai.chaiToDai(amount), parts, flags ); } if (toToken == IERC20(chai)) { (returnAmount, distribution) = super.getExpectedReturn( fromToken, dai, amount, parts, flags ); return (chai.daiToChai(returnAmount), distribution); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitChai is OneSplitBaseWrap { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_CHAI)) { if (fromToken == IERC20(chai)) { chai.exit(address(this), amount); return super._swap( dai, toToken, dai.balanceOf(address(this)), distribution, flags ); } if (toToken == IERC20(chai)) { super._swap( fromToken, dai, amount, distribution, flags ); _infiniteApproveIfNeeded(dai, address(chai)); chai.join(address(this), dai.balanceOf(address(this))); return; } } return super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: contracts/interface/IBdai.sol pragma solidity ^0.5.0; contract IBdai is IERC20 { function join(uint256) external; function exit(uint256) external; } // File: contracts/OneSplitBdai.sol pragma solidity ^0.5.0; contract OneSplitBdaiBase { IBdai public bdai = IBdai(0x6a4FFAafa8DD400676Df8076AD6c724867b0e2e8); IERC20 public btu = IERC20(0xb683D83a532e2Cb7DFa5275eED3698436371cc9f); } contract OneSplitBdaiView is OneSplitViewWrapBase, OneSplitBdaiBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns (uint256 returnAmount, uint256[] memory distribution) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!flags.check(FLAG_DISABLE_BDAI)) { if (fromToken == IERC20(bdai)) { return super.getExpectedReturn( dai, toToken, amount, parts, flags ); } if (toToken == IERC20(bdai)) { return super.getExpectedReturn( fromToken, dai, amount, parts, flags ); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitBdai is OneSplitBaseWrap, OneSplitBdaiBase { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_BDAI)) { if (fromToken == IERC20(bdai)) { bdai.exit(amount); uint256 btuBalance = btu.balanceOf(address(this)); if (btuBalance > 0) { (,uint256[] memory btuDistribution) = getExpectedReturn( btu, toToken, btuBalance, 1, flags ); _swap( btu, toToken, btuBalance, btuDistribution, flags ); } return super._swap( dai, toToken, amount, distribution, flags ); } if (toToken == IERC20(bdai)) { super._swap(fromToken, dai, amount, distribution, flags); _infiniteApproveIfNeeded(dai, address(bdai)); bdai.join(dai.balanceOf(address(this))); return; } } return super._swap(fromToken, toToken, amount, distribution, flags); } } // File: contracts/interface/IIearn.sol pragma solidity ^0.5.0; contract IIearn is IERC20 { function token() external view returns(IERC20); function calcPoolValueInToken() external view returns(uint256); function deposit(uint256 _amount) external; function withdraw(uint256 _shares) external; } // File: contracts/OneSplitIearn.sol pragma solidity ^0.5.0; contract OneSplitIearnBase { function _yTokens() internal pure returns(IIearn[10] memory) { return [ IIearn(0x16de59092dAE5CcF4A1E6439D611fd0653f0Bd01), IIearn(0x04Aa51bbcB46541455cCF1B8bef2ebc5d3787EC9), IIearn(0x73a052500105205d34Daf004eAb301916DA8190f), IIearn(0x83f798e925BcD4017Eb265844FDDAbb448f1707D), IIearn(0xd6aD7a6750A7593E092a9B218d66C0A814a3436e), IIearn(0xF61718057901F84C4eEC4339EF8f0D86D2B45600), IIearn(0x04bC0Ab673d88aE9dbC9DA2380cB6B79C4BCa9aE), IIearn(0xC2cB1040220768554cf699b0d863A3cd4324ce32), IIearn(0xE6354ed5bC4b393a5Aad09f21c46E101e692d447), IIearn(0x26EA744E5B887E5205727f55dFBE8685e3b21951) ]; } } contract OneSplitIearnView is OneSplitViewWrapBase, OneSplitIearnBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns (uint256 returnAmount, uint256[] memory distribution) { return _iearnGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _iearnGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) private view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } IIearn[10] memory yTokens = _yTokens(); if (!flags.check(FLAG_DISABLE_IEARN)) { for (uint i = 0; i < yTokens.length; i++) { if (fromToken == IERC20(yTokens[i])) { return _iearnGetExpectedReturn( yTokens[i].token(), toToken, amount .mul(yTokens[i].calcPoolValueInToken()) .div(yTokens[i].totalSupply()), parts, flags ); } } for (uint i = 0; i < yTokens.length; i++) { if (toToken == IERC20(yTokens[i])) { (uint256 ret, uint256[] memory dist) = super.getExpectedReturn( fromToken, yTokens[i].token(), amount, parts, flags ); return ( ret .mul(yTokens[i].totalSupply()) .div(yTokens[i].calcPoolValueInToken()), dist ); } } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitIearn is OneSplitBaseWrap, OneSplitIearnBase { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _iearnSwap( fromToken, toToken, amount, distribution, flags ); } function _iearnSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) private { if (fromToken == toToken) { return; } IIearn[10] memory yTokens = _yTokens(); if (!flags.check(FLAG_DISABLE_IEARN)) { for (uint i = 0; i < yTokens.length; i++) { if (fromToken == IERC20(yTokens[i])) { IERC20 underlying = yTokens[i].token(); yTokens[i].withdraw(amount); _iearnSwap(underlying, toToken, underlying.balanceOf(address(this)), distribution, flags); return; } } for (uint i = 0; i < yTokens.length; i++) { if (toToken == IERC20(yTokens[i])) { IERC20 underlying = yTokens[i].token(); super._swap(fromToken, underlying, amount, distribution, flags); _infiniteApproveIfNeeded(underlying, address(yTokens[i])); yTokens[i].deposit(underlying.balanceOf(address(this))); return; } } } return super._swap(fromToken, toToken, amount, distribution, flags); } } // File: contracts/interface/IIdle.sol pragma solidity ^0.5.0; contract IIdle is IERC20 { function token() external view returns (IERC20); function tokenPrice() external view returns (uint256); function mintIdleToken(uint256 _amount, uint256[] calldata _clientProtocolAmounts) external returns (uint256 mintedTokens); function redeemIdleToken(uint256 _amount, bool _skipRebalance, uint256[] calldata _clientProtocolAmounts) external returns (uint256 redeemedTokens); } // File: contracts/OneSplitIdle.sol pragma solidity ^0.5.0; contract OneSplitIdleBase { function _idleTokens() internal pure returns(IIdle[2] memory) { return [ IIdle(0x10eC0D497824e342bCB0EDcE00959142aAa766dD), IIdle(0xeB66ACc3d011056B00ea521F8203580C2E5d3991) ]; } } contract OneSplitIdleView is OneSplitViewWrapBase, OneSplitIdleBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns (uint256 /*returnAmount*/, uint256[] memory /*distribution*/) { return _idleGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _idleGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) internal view returns (uint256 returnAmount, uint256[] memory distribution) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } IIdle[2] memory tokens = _idleTokens(); for (uint i = 0; i < tokens.length; i++) { if (fromToken == IERC20(tokens[i])) { return _idleGetExpectedReturn( tokens[i].token(), toToken, amount.mul(tokens[i].tokenPrice()).div(1e18), parts, flags ); } } for (uint i = 0; i < tokens.length; i++) { if (toToken == IERC20(tokens[i])) { (uint256 ret, uint256[] memory dist) = super.getExpectedReturn( fromToken, tokens[i].token(), amount, parts, flags ); return ( ret.mul(1e18).div(tokens[i].tokenPrice()), dist ); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitIdle is OneSplitBaseWrap, OneSplitIdleBase { function _superOneSplitIdleSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] calldata distribution, uint256 flags ) external { require(msg.sender == address(this)); return super._swap(fromToken, toToken, amount, distribution, flags); } function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _idleSwap( fromToken, toToken, amount, distribution, flags ); } function _idleSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) public payable { IIdle[2] memory tokens = _idleTokens(); for (uint i = 0; i < tokens.length; i++) { if (fromToken == IERC20(tokens[i])) { IERC20 underlying = tokens[i].token(); uint256 minted = tokens[i].redeemIdleToken(amount, true, new uint256[](0)); _idleSwap(underlying, toToken, minted, distribution, flags); return; } } for (uint i = 0; i < tokens.length; i++) { if (toToken == IERC20(tokens[i])) { IERC20 underlying = tokens[i].token(); super._swap(fromToken, underlying, amount, distribution, flags); _infiniteApproveIfNeeded(underlying, address(tokens[i])); tokens[i].mintIdleToken(underlying.balanceOf(address(this)), new uint256[](0)); return; } } return super._swap(fromToken, toToken, amount, distribution, flags); } } // File: contracts/OneSplitAave.sol pragma solidity ^0.5.0; contract OneSplitAaveBase { function _getAaveUnderlyingToken(IERC20 token) internal pure returns(IERC20) { if (token == IERC20(0x3a3A65aAb0dd2A17E3F1947bA16138cd37d08c04)) { // ETH return IERC20(0); } if (token == IERC20(0xfC1E690f61EFd961294b3e1Ce3313fBD8aa4f85d)) { // DAI return IERC20(0x6B175474E89094C44Da98b954EedeAC495271d0F); } if (token == IERC20(0x9bA00D6856a4eDF4665BcA2C2309936572473B7E)) { // USDC return IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); } if (token == IERC20(0x625aE63000f46200499120B906716420bd059240)) { // SUSD return IERC20(0x57Ab1ec28D129707052df4dF418D58a2D46d5f51); } if (token == IERC20(0x6Ee0f7BB50a54AB5253dA0667B0Dc2ee526C30a8)) { // BUSD return IERC20(0x4Fabb145d64652a948d72533023f6E7A623C7C53); } if (token == IERC20(0x4DA9b813057D04BAef4e5800E36083717b4a0341)) { // TUSD return IERC20(0x0000000000085d4780B73119b644AE5ecd22b376); } if (token == IERC20(0x71fc860F7D3A592A4a98740e39dB31d25db65ae8)) { // USDT return IERC20(0xdAC17F958D2ee523a2206206994597C13D831ec7); } if (token == IERC20(0xE1BA0FB44CCb0D11b80F92f4f8Ed94CA3fF51D00)) { // BAT return IERC20(0x0D8775F648430679A709E98d2b0Cb6250d2887EF); } if (token == IERC20(0x9D91BE44C06d373a8a226E1f3b146956083803eB)) { // KNC return IERC20(0xdd974D5C2e2928deA5F71b9825b8b646686BD200); } if (token == IERC20(0x7D2D3688Df45Ce7C552E19c27e007673da9204B8)) { // LEND return IERC20(0x80fB784B7eD66730e8b1DBd9820aFD29931aab03); } if (token == IERC20(0xA64BD6C70Cb9051F6A9ba1F163Fdc07E0DfB5F84)) { // LINK return IERC20(0x514910771AF9Ca656af840dff83E8264EcF986CA); } if (token == IERC20(0x6FCE4A401B6B80ACe52baAefE4421Bd188e76F6f)) { // MANA return IERC20(0x0F5D2fB29fb7d3CFeE444a200298f468908cC942); } if (token == IERC20(0x7deB5e830be29F91E298ba5FF1356BB7f8146998)) { // MKR return IERC20(0x9f8F72aA9304c8B593d555F12eF6589cC3A579A2); } if (token == IERC20(0x71010A9D003445aC60C4e6A7017c1E89A477B438)) { // REP return IERC20(0x1985365e9f78359a9B6AD760e32412f4a445E862); } if (token == IERC20(0x328C4c80BC7aCa0834Db37e6600A6c49E12Da4DE)) { // SNX return IERC20(0xC011a73ee8576Fb46F5E1c5751cA3B9Fe0af2a6F); } if (token == IERC20(0xFC4B8ED459e00e5400be803A9BB3954234FD50e3)) { // WBTC return IERC20(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599); } if (token == IERC20(0x6Fb0855c404E09c47C3fBCA25f08d4E41f9F062f)) { // ZRX return IERC20(0xE41d2489571d322189246DaFA5ebDe1F4699F498); } return IERC20(-1); } } contract OneSplitAaveView is OneSplitViewWrapBase, OneSplitAaveBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return _aaveGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _aaveGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) private view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, distribution); } if (!flags.check(FLAG_DISABLE_AAVE)) { IERC20 underlying = _getAaveUnderlyingToken(fromToken); if (underlying != IERC20(-1)) { return _aaveGetExpectedReturn( underlying, toToken, amount, parts, flags ); } underlying = _getAaveUnderlyingToken(toToken); if (underlying != IERC20(-1)) { return super.getExpectedReturn( fromToken, underlying, amount, parts, flags ); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitAave is OneSplitBaseWrap, OneSplitAaveBase { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _aaveSwap( fromToken, toToken, amount, distribution, flags ); } function _aaveSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) private { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_AAVE)) { IERC20 underlying = _getAaveUnderlyingToken(fromToken); if (underlying != IERC20(-1)) { IAaveToken(address(fromToken)).redeem(amount); return _aaveSwap( underlying, toToken, amount, distribution, flags ); } underlying = _getAaveUnderlyingToken(toToken); if (underlying != IERC20(-1)) { super._swap( fromToken, underlying, amount, distribution, flags ); uint256 underlyingAmount = underlying.universalBalanceOf(address(this)); _infiniteApproveIfNeeded(underlying, aave.core()); aave.deposit.value(underlying.isETH() ? underlyingAmount : 0)( underlying.isETH() ? ETH_ADDRESS : underlying, underlyingAmount, 1101 ); return; } } return super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: contracts/OneSplitWeth.sol pragma solidity ^0.5.0; contract OneSplitWethView is OneSplitViewWrapBase { function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { return _wethGetExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _wethGetExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) private view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } if (!flags.check(FLAG_DISABLE_WETH)) { if (fromToken == wethToken || fromToken == bancorEtherToken) { return super.getExpectedReturn(ETH_ADDRESS, toToken, amount, parts, flags); } if (toToken == wethToken || toToken == bancorEtherToken) { return super.getExpectedReturn(fromToken, ETH_ADDRESS, amount, parts, flags); } } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitWeth is OneSplitBaseWrap { function _swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { _wethSwap( fromToken, toToken, amount, distribution, flags ); } function _wethSwap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) private { if (fromToken == toToken) { return; } if (!flags.check(FLAG_DISABLE_WETH)) { if (fromToken == wethToken) { wethToken.withdraw(wethToken.balanceOf(address(this))); super._swap( ETH_ADDRESS, toToken, amount, distribution, flags ); return; } if (fromToken == bancorEtherToken) { bancorEtherToken.withdraw(bancorEtherToken.balanceOf(address(this))); super._swap( ETH_ADDRESS, toToken, amount, distribution, flags ); return; } if (toToken == wethToken) { _wethSwap( fromToken, ETH_ADDRESS, amount, distribution, flags ); wethToken.deposit.value(address(this).balance)(); return; } if (toToken == bancorEtherToken) { _wethSwap( fromToken, ETH_ADDRESS, amount, distribution, flags ); bancorEtherToken.deposit.value(address(this).balance)(); return; } } return super._swap( fromToken, toToken, amount, distribution, flags ); } } // File: contracts/OneSplit.sol pragma solidity ^0.5.0; //import "./OneSplitSmartToken.sol"; contract OneSplitViewWrap is OneSplitViewWrapBase, OneSplitMultiPathView, OneSplitChaiView, OneSplitBdaiView, OneSplitAaveView, OneSplitFulcrumView, OneSplitCompoundView, OneSplitIearnView, OneSplitIdleView, OneSplitWethView //OneSplitSmartTokenView { IOneSplitView public oneSplitView; constructor(IOneSplitView _oneSplit) public { oneSplitView = _oneSplit; } function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) public view returns( uint256 returnAmount, uint256[] memory distribution ) { if (fromToken == toToken) { return (amount, new uint256[](DEXES_COUNT)); } return super.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } function _getExpectedReturnFloor( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags ) internal view returns( uint256 returnAmount, uint256[] memory distribution ) { return oneSplitView.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } } contract OneSplitWrap is OneSplitBaseWrap, OneSplitMultiPath, OneSplitChai, OneSplitBdai, OneSplitAave, OneSplitFulcrum, OneSplitCompound, OneSplitIearn, OneSplitIdle, OneSplitWeth //OneSplitSmartToken { IOneSplitView public oneSplitView; IOneSplit public oneSplit; constructor(IOneSplitView _oneSplitView, IOneSplit _oneSplit) public { oneSplitView = _oneSplitView; oneSplit = _oneSplit; } function() external payable { // solium-disable-next-line security/no-tx-origin require(msg.sender != tx.origin); } function getExpectedReturn( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 parts, uint256 flags // 1 - Uniswap, 2 - Kyber, 4 - Bancor, 8 - Oasis, 16 - Compound, 32 - Fulcrum, 64 - Chai, 128 - Aave, 256 - SmartToken, 1024 - bDAI ) public view returns( uint256 /*returnAmount*/, uint256[] memory /*distribution*/ ) { return oneSplitView.getExpectedReturn( fromToken, toToken, amount, parts, flags ); } function swap( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256 minReturn, uint256[] memory distribution, // [Uniswap, Kyber, Bancor, Oasis] uint256 flags // 16 - Compound, 32 - Fulcrum, 64 - Chai, 128 - Aave, 256 - SmartToken, 1024 - bDAI ) public payable { fromToken.universalTransferFrom(msg.sender, address(this), amount); _swap(fromToken, toToken, amount, distribution, flags); uint256 returnAmount = toToken.universalBalanceOf(address(this)); require(returnAmount >= minReturn, "OneSplit: actual return amount is less than minReturn"); toToken.universalTransfer(msg.sender, returnAmount); fromToken.universalTransfer(msg.sender, fromToken.universalBalanceOf(address(this))); } function _swapFloor( IERC20 fromToken, IERC20 toToken, uint256 amount, uint256[] memory distribution, uint256 flags ) internal { (bool success, bytes memory data) = address(oneSplit).delegatecall( abi.encodeWithSelector( this.swap.selector, fromToken, toToken, amount, 0, distribution, flags ) ); assembly { switch success // delegatecall returns 0 on error. case 0 { revert(add(data, 32), returndatasize) } } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IOneSplitView","name":"_oneSplitView","type":"address"},{"internalType":"contract IOneSplit","name":"_oneSplit","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":true,"inputs":[],"name":"DEXES_COUNT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ETH_ADDRESS","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_AAVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_BANCOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_BDAI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CHAI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_COMPOUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CURVE_BINANCE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CURVE_COMPOUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CURVE_SYNTHETIX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CURVE_USDT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_CURVE_Y","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_FULCRUM","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_IDLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_IEARN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_KYBER","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_OASIS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_SMART_TOKEN","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_UNISWAP","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_DISABLE_WETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_KYBER_BANCOR_RESERVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_KYBER_OASIS_RESERVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_KYBER_UNISWAP_RESERVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_MULTI_PATH_DAI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_MULTI_PATH_ETH","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_MULTI_PATH_USDC","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_UNISWAP_AAVE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_UNISWAP_CHAI","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"FLAG_ENABLE_UNISWAP_COMPOUND","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"_idleSwap","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"token","type":"address"}],"name":"_isFulcrumToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"_superOneSplitIdleSwap","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"aave","outputs":[{"internalType":"contract IAaveLendingPool","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bancorContractRegistry","outputs":[{"internalType":"contract IBancorContractRegistry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bancorConverterRegistry","outputs":[{"internalType":"contract IBancorConverterRegistry","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bancorEtherToken","outputs":[{"internalType":"contract IBancorEtherToken","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bdai","outputs":[{"internalType":"contract IBdai","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"bnt","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"btu","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"busd","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"cETH","outputs":[{"internalType":"contract ICompoundEther","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"chai","outputs":[{"internalType":"contract IChai","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"compound","outputs":[{"internalType":"contract ICompound","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"curveBinance","outputs":[{"internalType":"contract ICurve","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"curveCompound","outputs":[{"internalType":"contract ICurve","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"curveSynthetix","outputs":[{"internalType":"contract ICurve","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"curveUsdt","outputs":[{"internalType":"contract ICurve","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"curveY","outputs":[{"internalType":"contract ICurve","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"dai","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256[]","name":"","type":"uint256[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"kyberNetworkProxy","outputs":[{"internalType":"contract IKyberNetworkProxy","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oasisExchange","outputs":[{"internalType":"contract IOasisExchange","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oneSplit","outputs":[{"internalType":"contract IOneSplit","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"oneSplitView","outputs":[{"internalType":"contract IOneSplitView","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"susd","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"toToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"minReturn","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"},{"internalType":"uint256","name":"flags","type":"uint256"}],"name":"swap","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"tusd","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"uniswapFactory","outputs":[{"internalType":"contract IUniswapFactory","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"usdc","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"usdt","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"wethToken","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600080546001600160a01b0319908116736a4ffaafa8dd400676df8076ad6c724867b0e2e8179091556001805490911673b683d83a532e2cb7dfa5275eed3698436371cc9f17905534801561005857600080fd5b5060405162004575380380620045758339818101604052604081101561007d57600080fd5b508051602090910151600280546001600160a01b039384166001600160a01b031991821617909155600380549390921692169190911790556144b080620000c56000396000f3fe6080604052600436106103a25760003560e01c806375a8b012116101e7578063c77b9de61161010d578063d70a2d1f116100a0578063f4b9fa751161006f578063f4b9fa7514610b26578063f56e281f14610b3b578063f69e204614610b50578063fbe4ed9514610b65576103a2565b8063d70a2d1f14610a1f578063d77366a414610a34578063dc1536b214610a49578063e2a7515e14610a5e576103a2565b8063cc26e9fc116100dc578063cc26e9fc14610945578063cede5f6a1461095a578063d1ae60631461096f578063d393c3e914610a0a576103a2565b8063c77b9de6146108f1578063c925777514610906578063c989b6671461091b578063c9b42c6714610930576103a2565b8063944a32e211610185578063b3bc784411610154578063b3bc78441461089d578063b69d0456146108b2578063c11f4f11146108c7578063c762a46c146108dc576103a2565b8063944a32e21461079b578063a1b4d0111461085e578063a734f06e14610873578063b0a7ef2914610888576103a2565b80637e09b9c2116101c15780637e09b9c214610747578063819faf7b1461075c578063851954fa146107715780638bdb2afa14610786576103a2565b806375a8b0121461070857806375b5be2d1461071d5780637a88bdbd14610732576103a2565b80634037f967116102cc57806351f1985c1161026a57806364ec4e5c1161023957806364ec4e5c146106b457806368e2a014146106c95780636b5a4ca2146106de5780636cbc4a6e146106f3576103a2565b806351f1985c146106605780635aa8fb48146106755780635ae51b821461068a5780635c0cb4791461069f576103a2565b806343ee21f0116102a657806343ee21f01461060c57806344211d62146106215780634a7101d5146106365780634b57b0be1461064b576103a2565b80634037f967146105af57806340ab7b8c146105e2578063423d03f9146105f7576103a2565b806322320c981161034457806334b4dabb1161031357806334b4dabb1461055b578063372a26cb146105705780633ca5b234146105855780633e413bee1461059a576103a2565b806322320c98146105075780632d3b52071461051c5780632e707bd2146105315780632f48ab7d14610546576103a2565b80631388b420116103805780631388b420146104b357806313989140146104c85780632113240d146104dd57806321a360f5146104f2576103a2565b806305d8aa0a146103b1578063085e2c5b146103d857806312dea16014610482575b333214156103af57600080fd5b005b3480156103bd57600080fd5b506103c6610b7a565b60408051918252519081900360200190f35b3480156103e457600080fd5b50610427600480360360a08110156103fb57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135610b81565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561046d578181015183820152602001610455565b50505050905001935050505060405180910390f35b34801561048e57600080fd5b50610497610cc9565b604080516001600160a01b039092168252519081900360200190f35b3480156104bf57600080fd5b50610497610ce1565b3480156104d457600080fd5b506103c6610cf9565b3480156104e957600080fd5b506103c6610cff565b3480156104fe57600080fd5b506103c6610d05565b34801561051357600080fd5b50610497610d0e565b34801561052857600080fd5b506103c6610d26565b34801561053d57600080fd5b506103c6610d2e565b34801561055257600080fd5b50610497610d33565b34801561056757600080fd5b506103c6610d4b565b34801561057c57600080fd5b50610497610d50565b34801561059157600080fd5b50610497610d68565b3480156105a657600080fd5b50610497610d80565b3480156105bb57600080fd5b50610497600480360360208110156105d257600080fd5b50356001600160a01b0316610d98565b3480156105ee57600080fd5b50610497611110565b34801561060357600080fd5b50610497611128565b34801561061857600080fd5b50610497611140565b34801561062d57600080fd5b506103c661114f565b34801561064257600080fd5b506103c6611154565b34801561065757600080fd5b50610497611159565b34801561066c57600080fd5b50610497611171565b34801561068157600080fd5b506103c6611189565b34801561069657600080fd5b506103c661118f565b3480156106ab57600080fd5b506103c6611195565b3480156106c057600080fd5b506103c661119a565b3480156106d557600080fd5b506103c66111a1565b3480156106ea57600080fd5b506104976111a8565b3480156106ff57600080fd5b506103c66111b7565b34801561071457600080fd5b506103c66111be565b34801561072957600080fd5b506104976111c4565b34801561073e57600080fd5b506103c66111d7565b34801561075357600080fd5b506103c66111dc565b34801561076857600080fd5b506104976111e3565b34801561077d57600080fd5b506104976111fb565b34801561079257600080fd5b50610497611213565b6103af600480360360a08110156107b157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156107eb57600080fd5b8201836020820111156107fd57600080fd5b803590602001918460208302840111600160201b8311171561081e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550509135925061122b915050565b34801561086a57600080fd5b50610497611667565b34801561087f57600080fd5b5061049761167f565b34801561089457600080fd5b506103c6611697565b3480156108a957600080fd5b506103c661169d565b3480156108be57600080fd5b506104976116a6565b3480156108d357600080fd5b506104976116be565b3480156108e857600080fd5b506103c66116cd565b3480156108fd57600080fd5b506103c66116d2565b34801561091257600080fd5b506104976116d8565b34801561092757600080fd5b506103c66116f0565b34801561093c57600080fd5b506103c66116f7565b34801561095157600080fd5b506103c66116fe565b34801561096657600080fd5b50610497611703565b34801561097b57600080fd5b506103af600480360360a081101561099257600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156109cc57600080fd5b8201836020820111156109de57600080fd5b803590602001918460208302840111600160201b831117156109ff57600080fd5b91935091503561171b565b348015610a1657600080fd5b506103c6611768565b348015610a2b57600080fd5b5061049761176f565b348015610a4057600080fd5b50610497611787565b348015610a5557600080fd5b506103c661179f565b6103af600480360360c0811015610a7457600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b811115610ab357600080fd5b820183602082011115610ac557600080fd5b803590602001918460208302840111600160201b83111715610ae657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506117a5915050565b348015610b3257600080fd5b50610497611882565b348015610b4757600080fd5b506103c6611894565b348015610b5c57600080fd5b50610497611899565b348015610b7157600080fd5b506104976118b1565b6220000081565b6002546040805163085e2c5b60e01b81526001600160a01b03888116600483015287811660248301526044820187905260648201869052608482018590529151600093606093169163085e2c5b9160a48083019287929190829003018186803b158015610bed57600080fd5b505afa158015610c01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015610c2a57600080fd5b815160208301805160405192949293830192919084600160201b821115610c5057600080fd5b908301906020820185811115610c6557600080fd5b82518660208202830111600160201b82111715610c8157600080fd5b82525081516020918201928201910280838360005b83811015610cae578181015183820152602001610c96565b50505050905001604052505050915091509550959350505050565b7352ae12abe5d8bd778bd5397f99ca900624cfadd481565b73794e6e91555438afc3ccf1c5076a74f42133d08d81565b61200081565b61800081565b64020000000081565b73a5407eae9ba41422680e2e00537571bcc53efbfd81565b600160201b81565b608081565b73dac17f958d2ee523a2206206994597c13d831ec781565b604081565b7379a8c46dea5ada233abaffd40f3a0a2b1e5a4f2781565b734fabb145d64652a948d72533023f6e7a623c7c5381565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6000610dac826001600160a01b03166118c0565b15610dba575060001961110b565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b178152915181516000936060936001600160a01b0388169361138893919290918291908083835b60208310610e255780518252601f199092019160209182019101610e06565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d8060008114610e86576040519150601f19603f3d011682016040523d82523d6000602084013e610e8b565b606091505b509150915081610ea1576000199250505061110b565b6000805b8251816006011015610ffa57828160000181518110610ec057fe5b6020910101516001600160f81b031916602360f91b148015610f035750828160010181518110610eec57fe5b6020910101516001600160f81b031916607560f81b145b8015610f305750828160020181518110610f1957fe5b6020910101516001600160f81b031916601b60fa1b145b8015610f5d5750828160030181518110610f4657fe5b6020910101516001600160f81b031916606360f81b145b8015610f8a5750828160040181518110610f7357fe5b6020910101516001600160f81b031916603960f91b145b8015610fb75750828160050181518110610fa057fe5b6020910101516001600160f81b031916607560f81b145b8015610fe45750828160060181518110610fcd57fe5b6020910101516001600160f81b031916606d60f81b145b15610ff25760019150610ffa565b600101610ea5565b508061100d57600019935050505061110b565b60408051600481526024810182526020810180516001600160e01b031663797bf38560e01b178152915181516001600160a01b038916936113889392918291908083835b602083106110705780518252601f199092019160209182019101611051565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d80600081146110d1576040519150601f19603f3d011682016040523d82523d6000602084013e6110d6565b606091505b509093509150826110ee57600019935050505061110b565b81806020019051602081101561110357600080fd5b505193505050505b919050565b731f573d6fb3f13d689ff844b4ce37794d79a7ff1c81565b7345f783cce6b7ff23b2ab2d70e416cdb7d6055f5181565b6003546001600160a01b031681565b601081565b602081565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b73a2b47e3d5c44877cca798226b7b8118f9bfb7a5681565b61400081565b61080081565b600881565b6202000081565b6210000081565b6001546001600160a01b031681565b6208000081565b61040081565b6e085d4780b73119b644ae5ecd22b37681565b600281565b6240000081565b73398ec7346dcd622edc5ae82352f02be94c62d11981565b73c0829421c1d260bd3cb3e0f06cfe2d52db2ce31581565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9581565b61123361435e565b61123b6118fa565b905060005b600281101561140e5781816002811061125557fe5b60200201516001600160a01b0316876001600160a01b0316141561140657600082826002811061128157fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112be57600080fd5b505afa1580156112d2573d6000803e3d6000fd5b505050506040513d60208110156112e857600080fd5b5051905060008383600281106112fa57fe5b60200201516001600160a01b031663c85c93aa886001600060405190808252806020026020018201604052801561133b578160200160208202803883390190505b506040518463ffffffff1660e01b8152600401808481526020018315151515815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561139b578181015183820152602001611383565b50505050905001945050505050602060405180830381600087803b1580156113c257600080fd5b505af11580156113d6573d6000803e3d6000fd5b505050506040513d60208110156113ec57600080fd5b505190506113fd828983898961122b565b50505050611660565b600101611240565b5060005b60028110156116505781816002811061142757fe5b60200201516001600160a01b0316866001600160a01b0316141561164857600082826002811061145357fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561149057600080fd5b505afa1580156114a4573d6000803e3d6000fd5b505050506040513d60208110156114ba57600080fd5b505190506114cb8882888888611941565b6114e5818484600281106114db57fe5b602002015161194e565b8282600281106114f157fe5b60200201516001600160a01b0316633cfcef64826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561155a57600080fd5b505afa15801561156e573d6000803e3d6000fd5b505050506040513d602081101561158457600080fd5b50516040805160008082526020820190925290506040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156115ed5781810151838201526020016115d5565b505050509050019350505050602060405180830381600087803b15801561161357600080fd5b505af1158015611627573d6000803e3d6000fd5b505050506040513d602081101561163d57600080fd5b506116609350505050565b600101611412565b5061165e8686868686611941565b505b5050505050565b734ddc2d193948926d02f9b1fe9e1daa0718270ed581565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b61100081565b64040000000081565b7306af07097c9eeb7fd685c692751d5c66db49c21581565b6000546001600160a01b031681565b600181565b61020081565b7357ab1ec28d129707052df4df418d58a2d46d5f5181565b6280000081565b6204000081565b600c81565b7352ea46506b9cc5ef470c5bf89f17dc28bb35d85c81565b33301461172757600080fd5b61165e868686868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250611941915050565b6201000081565b73f6e2d7f616b67e46d708e4410746e9aab3a4c51881565b73818e6fecd516ecc3849daf6845e3ec868087b75581565b61010081565b6117c06001600160a01b03871633308763ffffffff611a0716565b6117cd8686868585611b26565b60006117e86001600160a01b0387163063ffffffff611b3316565b9050838110156118295760405162461bcd60e51b815260040180806020018281038252603581526020018061439c6035913960400191505060405180910390fd5b6118436001600160a01b038716338363ffffffff611bdd16565b50611878336118616001600160a01b038a163063ffffffff611b3316565b6001600160a01b038a16919063ffffffff611bdd16565b5050505050505050565b6000805160206143d183398151915281565b600481565b733d9819210a31b4961b30ef54be2aed79b9c9cd3b81565b6002546001600160a01b031681565b60006001600160a01b03821615806118f457506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b61190261435e565b50604080518082019091527310ec0d497824e342bcb0edce00959142aaa766dd815273eb66acc3d011056b00ea521f8203580c2e5d3991602082015290565b6116608585858585611c5b565b611960826001600160a01b03166118c0565b611a035760408051636eb1769f60e11b81523060048201526001600160a01b038381166024830152915160ff9285169163dd62ed3e916044808301926020929190829003018186803b1580156119b557600080fd5b505afa1580156119c9573d6000803e3d6000fd5b505050506040513d60208110156119df57600080fd5b5051901c611a0357611a036001600160a01b0383168260001963ffffffff61204016565b5050565b80611a1157611b20565b611a1a846118c0565b15611b05576001600160a01b03831633148015611a375750803410155b611a725760405162461bcd60e51b815260040180806020018281038252602b8152602001806143f1602b913960400191505060405180910390fd5b6001600160a01b0382163014611aba576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611ab8573d6000803e3d6000fd5b505b80341115611b0057336108fc611ad6348463ffffffff61211616565b6040518115909202916000818181858888f19350505050158015611afe573d6000803e3d6000fd5b505b611b20565b611b206001600160a01b03851684848463ffffffff61215816565b50505050565b61166085858585856121b2565b6000611b3e836118c0565b15611b5457506001600160a01b038116316118f4565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611baa57600080fd5b505afa158015611bbe573d6000803e3d6000fd5b505050506040513d6020811015611bd457600080fd5b50519392505050565b600081611bec57506001611c54565b611bf5846118c0565b15611c36576040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015611c30573d6000803e3d6000fd5b50611c54565b611c506001600160a01b038516848463ffffffff6124e116565b5060015b9392505050565b836001600160a01b0316856001600160a01b03161415611c7a57611660565b611c8261437c565b611c8a612533565b9050611c9e8261080063ffffffff61264f16565b6120335760005b600a811015611e5d578181600a8110611cba57fe5b60200201516001600160a01b0316876001600160a01b03161415611e555760008282600a8110611ce657fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d2357600080fd5b505afa158015611d37573d6000803e3d6000fd5b505050506040513d6020811015611d4d57600080fd5b505190508282600a8110611d5d57fe5b60200201516001600160a01b0316632e1a7d4d876040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611da757600080fd5b505af1158015611dbb573d6000803e3d6000fd5b50505050611e4d8188836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611e1a57600080fd5b505afa158015611e2e573d6000803e3d6000fd5b505050506040513d6020811015611e4457600080fd5b50518888611c5b565b505050611660565b600101611ca5565b5060005b600a811015612031578181600a8110611e7657fe5b60200201516001600160a01b0316866001600160a01b031614156120295760008282600a8110611ea257fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611edf57600080fd5b505afa158015611ef3573d6000803e3d6000fd5b505050506040513d6020811015611f0957600080fd5b50519050611f1a8882888888612655565b611f2a818484600a81106114db57fe5b8282600a8110611f3657fe5b60200201516001600160a01b031663b6b55f25826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b505050506040513d6020811015611fc957600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561200957600080fd5b505af115801561201d573d6000803e3d6000fd5b50505050505050611660565b600101611e61565b505b61165e8686868686612655565b612049836118c0565b612111576000811180156120d7575060408051636eb1769f60e11b81523060048201526001600160a01b038481166024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b1580156120a957600080fd5b505afa1580156120bd573d6000803e3d6000fd5b505050506040513d60208110156120d357600080fd5b5051115b156120f7576120f76001600160a01b03841683600063ffffffff61266216565b6121116001600160a01b038416838363ffffffff61266216565b505050565b6000611c5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612775565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b2090859061280c565b836001600160a01b0316856001600160a01b031614156121d157611660565b6121e4816208000063ffffffff61264f16565b6124d4576001600160a01b03851673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561230e57604080516370a0823160e01b8152306004820152905173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561226657600080fd5b505afa15801561227a573d6000803e3d6000fd5b505050506040513d602081101561229057600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156122d057600080fd5b505af11580156122e4573d6000803e3d6000fd5b5050505061230973eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee858585856129c4565b611660565b6001600160a01b03851673c0829421c1d260bd3cb3e0f06cfe2d52db2ce315141561238c57604080516370a0823160e01b8152306004820152905173c0829421c1d260bd3cb3e0f06cfe2d52db2ce31591632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561226657600080fd5b6001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561243f576123d28573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8585856121b2565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b15801561242157600080fd5b505af1158015612435573d6000803e3d6000fd5b5050505050611660565b6001600160a01b03841673c0829421c1d260bd3cb3e0f06cfe2d52db2ce31514156124d4576124858573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8585856121b2565b73c0829421c1d260bd3cb3e0f06cfe2d52db2ce3156001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b15801561242157600080fd5b61166085858585856129c4565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261211190849061280c565b61253b61437c565b5060408051610140810182527316de59092dae5ccf4a1e6439d611fd0653f0bd0181527304aa51bbcb46541455ccf1b8bef2ebc5d3787ec960208201527373a052500105205d34daf004eab301916da8190f918101919091527383f798e925bcd4017eb265844fddabb448f1707d606082015273d6ad7a6750a7593e092a9b218d66c0a814a3436e608082015273f61718057901f84c4eec4339ef8f0d86d2b4560060a08201527304bc0ab673d88ae9dbc9da2380cb6b79c4bca9ae60c082015273c2cb1040220768554cf699b0d863a3cd4324ce3260e082015273e6354ed5bc4b393a5aad09f21c46e101e692d4476101008201527326ea744e5b887e5205727f55dfbe8685e3b2195161012082015290565b16151590565b61166085858585856129d1565b8015806126e8575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156126ba57600080fd5b505afa1580156126ce573d6000803e3d6000fd5b505050506040513d60208110156126e457600080fd5b5051155b6127235760405162461bcd60e51b81526004018080602001828103825260368152602001806144466036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261211190849061280c565b600081848411156128045760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156127c95781810151838201526020016127b1565b50505050905090810190601f1680156127f65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61281e826001600160a01b0316612c18565b61286f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106128ad5780518252601f19909201916020918201910161288e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461290f576040519150601f19603f3d011682016040523d82523d6000602084013e612914565b606091505b50915091508161296b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b205780806020019051602081101561298757600080fd5b5051611b205760405162461bcd60e51b815260040180806020018281038252602a81526020018061441c602a913960400191505060405180910390fd5b611660858585858561122b565b836001600160a01b0316856001600160a01b031614156129f057611660565b612a0181601063ffffffff61264f16565b612c0b576000612a1086612c54565b90506001600160a01b0380821614612ac657856001600160a01b031663db006a75856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612a6857600080fd5b505af1158015612a7c573d6000803e3d6000fd5b505050506040513d6020811015612a9257600080fd5b5060009050612ab06001600160a01b0383163063ffffffff611b3316565b9050612abf82878387876129d1565b5050611660565b612acf85612c54565b90506001600160a01b0380821614612c0957612aee8682868686612e46565b6000612b096001600160a01b0383163063ffffffff611b3316565b9050612b1d826001600160a01b03166118c0565b15612b8f57734ddc2d193948926d02f9b1fe9e1daa0718270ed56001600160a01b0316631249c58b826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612b7157600080fd5b505af1158015612b85573d6000803e3d6000fd5b5050505050612abf565b612b99828761194e565b856001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050506040513d60208110156113fd57600080fd5b505b6116608585858585612e46565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612c4c57508115155b949350505050565b60006001600160a01b038216734ddc2d193948926d02f9b1fe9e1daa0718270ed51415612c835750600061110b565b6001600160a01b038216735d3a536e4d6dbd6114cc1ead35777bab948e36431415612cbd57506000805160206143d183398151915261110b565b6001600160a01b038216736c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e1415612cfd5750730d8775f648430679a709e98d2b0cb6250d2887ef61110b565b6001600160a01b03821673158079ee67fce2f58472a96584a73c7ab9ac95c11415612d3d5750731985365e9f78359a9b6ad760e32412f4a445e86261110b565b6001600160a01b0382167339aa39c021dfbae8fac545936693ac917d5e75631415612d7d575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861110b565b6001600160a01b03821673c11b1268c1a384e55c48c2391d8d480264a3a7f41415612dbd5750732260fac5e5542a773aa44fbcfedf7c193bc2c59961110b565b6001600160a01b03821673b3319f5d18bc0d84dd1b4825dcde5d5f7266d4071415612dfd575073e41d2489571d322189246dafa5ebde1f4699f49861110b565b6001600160a01b03821673f650c3d88d12db855b8bf7d11be6c55a4e07dcc91415612e3d575073dac17f958d2ee523a2206206994597c13d831ec761110b565b50600019919050565b6116608585858585836001600160a01b0316856001600160a01b03161415612e6d57611660565b612e7e81602063ffffffff61264f16565b613111576000612e8d86610d98565b90506001600160a01b0380821614612fdd57612eb1816001600160a01b03166118c0565b15612f37576040805163081a6b2560e41b81523060048201526024810186905290516001600160a01b038816916381a6b2509160448083019260209291908290030181600087803b158015612f0557600080fd5b505af1158015612f19573d6000803e3d6000fd5b505050506040513d6020811015612f2f57600080fd5b50612fb39050565b60408051632770a7eb60e21b81523060048201526024810186905290516001600160a01b03881691639dc29fac9160448083019260209291908290030181600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b505050506040513d6020811015612fb057600080fd5b50505b6000612fce6001600160a01b0383163063ffffffff611b3316565b9050612abf828783878761311a565b612fe685610d98565b90506001600160a01b038082161461310f57613005868286868661311a565b60006130206001600160a01b0383163063ffffffff611b3316565b9050613034826001600160a01b03166118c0565b156130b65760408051638f6ede1f60e01b815230600482015290516001600160a01b03881691638f6ede1f91849160248082019260209290919082900301818588803b15801561308357600080fd5b505af1158015613097573d6000803e3d6000fd5b50505050506040513d60208110156130ae57600080fd5b50612abf9050565b6130c0828761194e565b604080516340c10f1960e01b81523060048201526024810183905290516001600160a01b038816916340c10f199160448083019260209291908290030181600087803b158015612bdf57600080fd5b505b61166085858585855b61166085858585855b836001600160a01b0316856001600160a01b0316141561314257611660565b61315381608063ffffffff61264f16565b61336e5760006131628661337b565b90506001600160a01b03808216146131e557856001600160a01b031663db006a75856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156131ba57600080fd5b505af11580156131ce573d6000803e3d6000fd5b505050506131df8186868686613123565b50611660565b6131ee8561337b565b90506001600160a01b038082161461336c5761320d868286868661379f565b60006132286001600160a01b0383163063ffffffff611b3316565b90506132ac8273398ec7346dcd622edc5ae82352f02be94c62d1196001600160a01b031663f2f4eb266040518163ffffffff1660e01b815260040160206040518083038186803b15801561327b57600080fd5b505afa15801561328f573d6000803e3d6000fd5b505050506040513d60208110156132a557600080fd5b505161194e565b73398ec7346dcd622edc5ae82352f02be94c62d11963d2d0e0666132d86001600160a01b0385166118c0565b6132e35760006132e5565b825b6132f7856001600160a01b03166118c0565b6133015784613317565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301526024820186905261044d604483015251606480830192600092919082900301818588803b15801561200957600080fd5b505b611660858585858561379f565b60006001600160a01b038216733a3a65aab0dd2a17e3f1947ba16138cd37d08c0414156133aa5750600061110b565b6001600160a01b03821673fc1e690f61efd961294b3e1ce3313fbd8aa4f85d14156133e457506000805160206143d183398151915261110b565b6001600160a01b038216739ba00d6856a4edf4665bca2c2309936572473b7e1415613424575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861110b565b6001600160a01b03821673625ae63000f46200499120b906716420bd059240141561346457507357ab1ec28d129707052df4df418d58a2d46d5f5161110b565b6001600160a01b038216736ee0f7bb50a54ab5253da0667b0dc2ee526c30a814156134a45750734fabb145d64652a948d72533023f6e7a623c7c5361110b565b6001600160a01b038216734da9b813057d04baef4e5800e36083717b4a034114156134df57506e085d4780b73119b644ae5ecd22b37661110b565b6001600160a01b0382167371fc860f7d3a592a4a98740e39db31d25db65ae8141561351f575073dac17f958d2ee523a2206206994597c13d831ec761110b565b6001600160a01b03821673e1ba0fb44ccb0d11b80f92f4f8ed94ca3ff51d00141561355f5750730d8775f648430679a709e98d2b0cb6250d2887ef61110b565b6001600160a01b038216739d91be44c06d373a8a226e1f3b146956083803eb141561359f575073dd974d5c2e2928dea5f71b9825b8b646686bd20061110b565b6001600160a01b038216737d2d3688df45ce7c552e19c27e007673da9204b814156135df57507380fb784b7ed66730e8b1dbd9820afd29931aab0361110b565b6001600160a01b03821673a64bd6c70cb9051f6a9ba1f163fdc07e0dfb5f84141561361f575073514910771af9ca656af840dff83e8264ecf986ca61110b565b6001600160a01b038216736fce4a401b6b80ace52baaefe4421bd188e76f6f141561365f5750730f5d2fb29fb7d3cfee444a200298f468908cc94261110b565b6001600160a01b038216737deb5e830be29f91e298ba5ff1356bb7f8146998141561369f5750739f8f72aa9304c8b593d555f12ef6589cc3a579a261110b565b6001600160a01b0382167371010a9d003445ac60c4e6a7017c1e89a477b43814156136df5750731985365e9f78359a9b6ad760e32412f4a445e86261110b565b6001600160a01b03821673328c4c80bc7aca0834db37e6600a6c49e12da4de141561371f575073c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f61110b565b6001600160a01b03821673fc4b8ed459e00e5400be803a9bb3954234fd50e3141561375f5750732260fac5e5542a773aa44fbcfedf7c193bc2c59961110b565b6001600160a01b038216736fb0855c404e09c47c3fbca25f08d4e41f9f062f1415612e3d575073e41d2489571d322189246dafa5ebde1f4699f49861110b565b836001600160a01b0316856001600160a01b031614156137be57611660565b6137d08161040063ffffffff61264f16565b613a59576000546001600160a01b0386811691161415613924576000805460408051637f8661a160e01b81526004810187905290516001600160a01b0390921692637f8661a19260248084019382900301818387803b15801561383257600080fd5b505af1158015613846573d6000803e3d6000fd5b5050600154604080516370a0823160e01b81523060048201529051600094506001600160a01b0390921692506370a08231916024808301926020929190829003018186803b15801561389757600080fd5b505afa1580156138ab573d6000803e3d6000fd5b505050506040513d60208110156138c157600080fd5b50519050801561390957600180546060916138ea916001600160a01b0316908890859087610b81565b60015490925061390791506001600160a01b031687848487611b26565b505b6131df6000805160206143d183398151915286868686613a62565b6000546001600160a01b0385811691161415613a5957613955856000805160206143d1833981519152858585613a62565b60005461397a906000805160206143d1833981519152906001600160a01b031661194e565b600054604080516370a0823160e01b815230600482015290516001600160a01b039092169163049878f3916000805160206143d1833981519152916370a0823191602480820192602092909190829003018186803b1580156139db57600080fd5b505afa1580156139ef573d6000803e3d6000fd5b505050506040513d6020811015613a0557600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b158015613a4557600080fd5b505af11580156113fd573d6000803e3d6000fd5b61166085858585855b836001600160a01b0316856001600160a01b03161415613a8157611660565b613a9281604063ffffffff61264f16565b613d04576001600160a01b0385167306af07097c9eeb7fd685c692751d5c66db49c2151415613bb3576040805163ef693bed60e01b81523060048201526024810185905290517306af07097c9eeb7fd685c692751d5c66db49c2159163ef693bed91604480830192600092919082900301818387803b158015613b1457600080fd5b505af1158015613b28573d6000803e3d6000fd5b5050604080516370a0823160e01b8152306004820152905161230993506000805160206143d18339815191529250879183916370a0823191602480820192602092909190829003018186803b158015613b8057600080fd5b505afa158015613b94573d6000803e3d6000fd5b505050506040513d6020811015613baa57600080fd5b50518585613d0d565b6001600160a01b0384167306af07097c9eeb7fd685c692751d5c66db49c2151415613d0457613bf3856000805160206143d1833981519152858585613d0d565b613c1f6000805160206143d18339815191527306af07097c9eeb7fd685c692751d5c66db49c21561194e565b604080516370a0823160e01b8152306004820181905291517306af07097c9eeb7fd685c692751d5c66db49c21592633b4da69f9290916000805160206143d1833981519152916370a08231916024808301926020929190829003018186803b158015613c8a57600080fd5b505afa158015613c9e573d6000803e3d6000fd5b505050506040513d6020811015613cb457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915251604480830192600092919082900301818387803b158015613a4557600080fd5b61166085858585855b613d1f856001600160a01b03166118c0565b158015613d3b5750613d39846001600160a01b03166118c0565b155b8015613d545750613d548161020063ffffffff61264f16565b15613e555760608251604051908082528060200260200182016040528015613d86578160200160208202803883390190505b50905060005b8351811015613dcb57838181518110613da157fe5b602002602001015160ff16828281518110613db857fe5b6020908102919091010152600101613d8c565b50613ded8673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8684866141b5565b60005b8351811015613e33576008848281518110613e0757fe5b6020026020010151901c60ff16828281518110613e2057fe5b6020908102919091010152600101613df0565b506131df73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee864784866141b5565b6001600160a01b0385166000805160206143d183398151915214801590613e9357506001600160a01b0384166000805160206143d183398151915214155b8015613ead5750613ead816201000063ffffffff61264f16565b1561400e5760608251604051908082528060200260200182016040528015613edf578160200160208202803883390190505b50905060005b8351811015613f2457838181518110613efa57fe5b602002602001015160ff16828281518110613f1157fe5b6020908102919091010152600101613ee5565b50613f40866000805160206143d18339815191528684866141b5565b60005b8351811015613f86576008848281518110613f5a57fe5b6020026020010151901c60ff16828281518110613f7357fe5b6020908102919091010152600101613f43565b50604080516370a0823160e01b815230600482015290516131df916000805160206143d183398151915291889183916370a0823191602480820192602092909190829003018186803b158015613fdb57600080fd5b505afa158015613fef573d6000803e3d6000fd5b505050506040513d602081101561400557600080fd5b505184866141b5565b6001600160a01b03851673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481480159061405857506001600160a01b03841673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4814155b80156140725750614072816202000063ffffffff61264f16565b156141ac57606082516040519080825280602002602001820160405280156140a4578160200160208202803883390190505b50905060005b83518110156140e9578381815181106140bf57fe5b602002602001015160ff168282815181106140d657fe5b60209081029190910101526001016140aa565b5061410b8673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488684866141b5565b60005b835181101561415157600884828151811061412557fe5b6020026020010151901c60ff1682828151811061413e57fe5b602090810291909101015260010161410e565b50604080516370a0823160e01b815230600482015290516131df9173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4891889183916370a0823191602480820192602092909190829003018186803b158015613fdb57600080fd5b61166085858585855b836001600160a01b0316856001600160a01b031614156141d457611660565b61166085858585856003546040516001600160a01b038781166024830190815287821660448401526064830187905260006084840181905260c4840186905260c060a48501908152875160e486015287519195606095941693637153a8af60e11b938c938c938c938a938d938d9391926101040190602080870191028083838a5b8381101561426d578181015183820152602001614255565b50505050905001975050505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518082805190602001908083835b602083106142df5780518252601f1990920191602091820191016142c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461433f576040519150601f19603f3d011682016040523d82523d6000602084013e614344565b606091505b5091509150816000811461435757611878565b3d60208301fd5b60405180604001604052806002906020820280388339509192915050565b604051806101400160405280600a90602082028038833950919291505056fe4f6e6553706c69743a2061637475616c2072657475726e20616d6f756e74206973206c657373207468616e206d696e52657475726e0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f57726f6e6720757365616765206f66204554482e756e6976657273616c5472616e7366657246726f6d28295361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a265627a7a72315820ed82bada9bab10e79931a19e6fa1964fdc8a989ef7bcfa86ce0538e0da99af6b64736f6c6343000511003200000000000000000000000034f359df4e0e5c5ca8f692300f6b273144de4696000000000000000000000000d2e0373e3bef55db21138c25cfe00bd421e759a7
Deployed Bytecode
0x6080604052600436106103a25760003560e01c806375a8b012116101e7578063c77b9de61161010d578063d70a2d1f116100a0578063f4b9fa751161006f578063f4b9fa7514610b26578063f56e281f14610b3b578063f69e204614610b50578063fbe4ed9514610b65576103a2565b8063d70a2d1f14610a1f578063d77366a414610a34578063dc1536b214610a49578063e2a7515e14610a5e576103a2565b8063cc26e9fc116100dc578063cc26e9fc14610945578063cede5f6a1461095a578063d1ae60631461096f578063d393c3e914610a0a576103a2565b8063c77b9de6146108f1578063c925777514610906578063c989b6671461091b578063c9b42c6714610930576103a2565b8063944a32e211610185578063b3bc784411610154578063b3bc78441461089d578063b69d0456146108b2578063c11f4f11146108c7578063c762a46c146108dc576103a2565b8063944a32e21461079b578063a1b4d0111461085e578063a734f06e14610873578063b0a7ef2914610888576103a2565b80637e09b9c2116101c15780637e09b9c214610747578063819faf7b1461075c578063851954fa146107715780638bdb2afa14610786576103a2565b806375a8b0121461070857806375b5be2d1461071d5780637a88bdbd14610732576103a2565b80634037f967116102cc57806351f1985c1161026a57806364ec4e5c1161023957806364ec4e5c146106b457806368e2a014146106c95780636b5a4ca2146106de5780636cbc4a6e146106f3576103a2565b806351f1985c146106605780635aa8fb48146106755780635ae51b821461068a5780635c0cb4791461069f576103a2565b806343ee21f0116102a657806343ee21f01461060c57806344211d62146106215780634a7101d5146106365780634b57b0be1461064b576103a2565b80634037f967146105af57806340ab7b8c146105e2578063423d03f9146105f7576103a2565b806322320c981161034457806334b4dabb1161031357806334b4dabb1461055b578063372a26cb146105705780633ca5b234146105855780633e413bee1461059a576103a2565b806322320c98146105075780632d3b52071461051c5780632e707bd2146105315780632f48ab7d14610546576103a2565b80631388b420116103805780631388b420146104b357806313989140146104c85780632113240d146104dd57806321a360f5146104f2576103a2565b806305d8aa0a146103b1578063085e2c5b146103d857806312dea16014610482575b333214156103af57600080fd5b005b3480156103bd57600080fd5b506103c6610b7a565b60408051918252519081900360200190f35b3480156103e457600080fd5b50610427600480360360a08110156103fb57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060800135610b81565b6040518083815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561046d578181015183820152602001610455565b50505050905001935050505060405180910390f35b34801561048e57600080fd5b50610497610cc9565b604080516001600160a01b039092168252519081900360200190f35b3480156104bf57600080fd5b50610497610ce1565b3480156104d457600080fd5b506103c6610cf9565b3480156104e957600080fd5b506103c6610cff565b3480156104fe57600080fd5b506103c6610d05565b34801561051357600080fd5b50610497610d0e565b34801561052857600080fd5b506103c6610d26565b34801561053d57600080fd5b506103c6610d2e565b34801561055257600080fd5b50610497610d33565b34801561056757600080fd5b506103c6610d4b565b34801561057c57600080fd5b50610497610d50565b34801561059157600080fd5b50610497610d68565b3480156105a657600080fd5b50610497610d80565b3480156105bb57600080fd5b50610497600480360360208110156105d257600080fd5b50356001600160a01b0316610d98565b3480156105ee57600080fd5b50610497611110565b34801561060357600080fd5b50610497611128565b34801561061857600080fd5b50610497611140565b34801561062d57600080fd5b506103c661114f565b34801561064257600080fd5b506103c6611154565b34801561065757600080fd5b50610497611159565b34801561066c57600080fd5b50610497611171565b34801561068157600080fd5b506103c6611189565b34801561069657600080fd5b506103c661118f565b3480156106ab57600080fd5b506103c6611195565b3480156106c057600080fd5b506103c661119a565b3480156106d557600080fd5b506103c66111a1565b3480156106ea57600080fd5b506104976111a8565b3480156106ff57600080fd5b506103c66111b7565b34801561071457600080fd5b506103c66111be565b34801561072957600080fd5b506104976111c4565b34801561073e57600080fd5b506103c66111d7565b34801561075357600080fd5b506103c66111dc565b34801561076857600080fd5b506104976111e3565b34801561077d57600080fd5b506104976111fb565b34801561079257600080fd5b50610497611213565b6103af600480360360a08110156107b157600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156107eb57600080fd5b8201836020820111156107fd57600080fd5b803590602001918460208302840111600160201b8311171561081e57600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929550509135925061122b915050565b34801561086a57600080fd5b50610497611667565b34801561087f57600080fd5b5061049761167f565b34801561089457600080fd5b506103c6611697565b3480156108a957600080fd5b506103c661169d565b3480156108be57600080fd5b506104976116a6565b3480156108d357600080fd5b506104976116be565b3480156108e857600080fd5b506103c66116cd565b3480156108fd57600080fd5b506103c66116d2565b34801561091257600080fd5b506104976116d8565b34801561092757600080fd5b506103c66116f0565b34801561093c57600080fd5b506103c66116f7565b34801561095157600080fd5b506103c66116fe565b34801561096657600080fd5b50610497611703565b34801561097b57600080fd5b506103af600480360360a081101561099257600080fd5b6001600160a01b03823581169260208101359091169160408201359190810190608081016060820135600160201b8111156109cc57600080fd5b8201836020820111156109de57600080fd5b803590602001918460208302840111600160201b831117156109ff57600080fd5b91935091503561171b565b348015610a1657600080fd5b506103c6611768565b348015610a2b57600080fd5b5061049761176f565b348015610a4057600080fd5b50610497611787565b348015610a5557600080fd5b506103c661179f565b6103af600480360360c0811015610a7457600080fd5b6001600160a01b03823581169260208101359091169160408201359160608101359181019060a081016080820135600160201b811115610ab357600080fd5b820183602082011115610ac557600080fd5b803590602001918460208302840111600160201b83111715610ae657600080fd5b91908080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525092955050913592506117a5915050565b348015610b3257600080fd5b50610497611882565b348015610b4757600080fd5b506103c6611894565b348015610b5c57600080fd5b50610497611899565b348015610b7157600080fd5b506104976118b1565b6220000081565b6002546040805163085e2c5b60e01b81526001600160a01b03888116600483015287811660248301526044820187905260648201869052608482018590529151600093606093169163085e2c5b9160a48083019287929190829003018186803b158015610bed57600080fd5b505afa158015610c01573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040908152811015610c2a57600080fd5b815160208301805160405192949293830192919084600160201b821115610c5057600080fd5b908301906020820185811115610c6557600080fd5b82518660208202830111600160201b82111715610c8157600080fd5b82525081516020918201928201910280838360005b83811015610cae578181015183820152602001610c96565b50505050905001604052505050915091509550959350505050565b7352ae12abe5d8bd778bd5397f99ca900624cfadd481565b73794e6e91555438afc3ccf1c5076a74f42133d08d81565b61200081565b61800081565b64020000000081565b73a5407eae9ba41422680e2e00537571bcc53efbfd81565b600160201b81565b608081565b73dac17f958d2ee523a2206206994597c13d831ec781565b604081565b7379a8c46dea5ada233abaffd40f3a0a2b1e5a4f2781565b734fabb145d64652a948d72533023f6e7a623c7c5381565b73a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4881565b6000610dac826001600160a01b03166118c0565b15610dba575060001961110b565b60408051600481526024810182526020810180516001600160e01b03166306fdde0360e01b178152915181516000936060936001600160a01b0388169361138893919290918291908083835b60208310610e255780518252601f199092019160209182019101610e06565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d8060008114610e86576040519150601f19603f3d011682016040523d82523d6000602084013e610e8b565b606091505b509150915081610ea1576000199250505061110b565b6000805b8251816006011015610ffa57828160000181518110610ec057fe5b6020910101516001600160f81b031916602360f91b148015610f035750828160010181518110610eec57fe5b6020910101516001600160f81b031916607560f81b145b8015610f305750828160020181518110610f1957fe5b6020910101516001600160f81b031916601b60fa1b145b8015610f5d5750828160030181518110610f4657fe5b6020910101516001600160f81b031916606360f81b145b8015610f8a5750828160040181518110610f7357fe5b6020910101516001600160f81b031916603960f91b145b8015610fb75750828160050181518110610fa057fe5b6020910101516001600160f81b031916607560f81b145b8015610fe45750828160060181518110610fcd57fe5b6020910101516001600160f81b031916606d60f81b145b15610ff25760019150610ffa565b600101610ea5565b508061100d57600019935050505061110b565b60408051600481526024810182526020810180516001600160e01b031663797bf38560e01b178152915181516001600160a01b038916936113889392918291908083835b602083106110705780518252601f199092019160209182019101611051565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303818686fa925050503d80600081146110d1576040519150601f19603f3d011682016040523d82523d6000602084013e6110d6565b606091505b509093509150826110ee57600019935050505061110b565b81806020019051602081101561110357600080fd5b505193505050505b919050565b731f573d6fb3f13d689ff844b4ce37794d79a7ff1c81565b7345f783cce6b7ff23b2ab2d70e416cdb7d6055f5181565b6003546001600160a01b031681565b601081565b602081565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b73a2b47e3d5c44877cca798226b7b8118f9bfb7a5681565b61400081565b61080081565b600881565b6202000081565b6210000081565b6001546001600160a01b031681565b6208000081565b61040081565b6e085d4780b73119b644ae5ecd22b37681565b600281565b6240000081565b73398ec7346dcd622edc5ae82352f02be94c62d11981565b73c0829421c1d260bd3cb3e0f06cfe2d52db2ce31581565b73c0a47dfe034b400b47bdad5fecda2621de6c4d9581565b61123361435e565b61123b6118fa565b905060005b600281101561140e5781816002811061125557fe5b60200201516001600160a01b0316876001600160a01b0316141561140657600082826002811061128157fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156112be57600080fd5b505afa1580156112d2573d6000803e3d6000fd5b505050506040513d60208110156112e857600080fd5b5051905060008383600281106112fa57fe5b60200201516001600160a01b031663c85c93aa886001600060405190808252806020026020018201604052801561133b578160200160208202803883390190505b506040518463ffffffff1660e01b8152600401808481526020018315151515815260200180602001828103825283818151815260200191508051906020019060200280838360005b8381101561139b578181015183820152602001611383565b50505050905001945050505050602060405180830381600087803b1580156113c257600080fd5b505af11580156113d6573d6000803e3d6000fd5b505050506040513d60208110156113ec57600080fd5b505190506113fd828983898961122b565b50505050611660565b600101611240565b5060005b60028110156116505781816002811061142757fe5b60200201516001600160a01b0316866001600160a01b0316141561164857600082826002811061145357fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561149057600080fd5b505afa1580156114a4573d6000803e3d6000fd5b505050506040513d60208110156114ba57600080fd5b505190506114cb8882888888611941565b6114e5818484600281106114db57fe5b602002015161194e565b8282600281106114f157fe5b60200201516001600160a01b0316633cfcef64826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561155a57600080fd5b505afa15801561156e573d6000803e3d6000fd5b505050506040513d602081101561158457600080fd5b50516040805160008082526020820190925290506040518363ffffffff1660e01b81526004018083815260200180602001828103825283818151815260200191508051906020019060200280838360005b838110156115ed5781810151838201526020016115d5565b505050509050019350505050602060405180830381600087803b15801561161357600080fd5b505af1158015611627573d6000803e3d6000fd5b505050506040513d602081101561163d57600080fd5b506116609350505050565b600101611412565b5061165e8686868686611941565b505b5050505050565b734ddc2d193948926d02f9b1fe9e1daa0718270ed581565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b61100081565b64040000000081565b7306af07097c9eeb7fd685c692751d5c66db49c21581565b6000546001600160a01b031681565b600181565b61020081565b7357ab1ec28d129707052df4df418d58a2d46d5f5181565b6280000081565b6204000081565b600c81565b7352ea46506b9cc5ef470c5bf89f17dc28bb35d85c81565b33301461172757600080fd5b61165e868686868680806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250889250611941915050565b6201000081565b73f6e2d7f616b67e46d708e4410746e9aab3a4c51881565b73818e6fecd516ecc3849daf6845e3ec868087b75581565b61010081565b6117c06001600160a01b03871633308763ffffffff611a0716565b6117cd8686868585611b26565b60006117e86001600160a01b0387163063ffffffff611b3316565b9050838110156118295760405162461bcd60e51b815260040180806020018281038252603581526020018061439c6035913960400191505060405180910390fd5b6118436001600160a01b038716338363ffffffff611bdd16565b50611878336118616001600160a01b038a163063ffffffff611b3316565b6001600160a01b038a16919063ffffffff611bdd16565b5050505050505050565b6000805160206143d183398151915281565b600481565b733d9819210a31b4961b30ef54be2aed79b9c9cd3b81565b6002546001600160a01b031681565b60006001600160a01b03821615806118f457506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee145b92915050565b61190261435e565b50604080518082019091527310ec0d497824e342bcb0edce00959142aaa766dd815273eb66acc3d011056b00ea521f8203580c2e5d3991602082015290565b6116608585858585611c5b565b611960826001600160a01b03166118c0565b611a035760408051636eb1769f60e11b81523060048201526001600160a01b038381166024830152915160ff9285169163dd62ed3e916044808301926020929190829003018186803b1580156119b557600080fd5b505afa1580156119c9573d6000803e3d6000fd5b505050506040513d60208110156119df57600080fd5b5051901c611a0357611a036001600160a01b0383168260001963ffffffff61204016565b5050565b80611a1157611b20565b611a1a846118c0565b15611b05576001600160a01b03831633148015611a375750803410155b611a725760405162461bcd60e51b815260040180806020018281038252602b8152602001806143f1602b913960400191505060405180910390fd5b6001600160a01b0382163014611aba576040516001600160a01b0383169082156108fc029083906000818181858888f19350505050158015611ab8573d6000803e3d6000fd5b505b80341115611b0057336108fc611ad6348463ffffffff61211616565b6040518115909202916000818181858888f19350505050158015611afe573d6000803e3d6000fd5b505b611b20565b611b206001600160a01b03851684848463ffffffff61215816565b50505050565b61166085858585856121b2565b6000611b3e836118c0565b15611b5457506001600160a01b038116316118f4565b826001600160a01b03166370a08231836040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611baa57600080fd5b505afa158015611bbe573d6000803e3d6000fd5b505050506040513d6020811015611bd457600080fd5b50519392505050565b600081611bec57506001611c54565b611bf5846118c0565b15611c36576040516001600160a01b0384169083156108fc029084906000818181858888f19350505050158015611c30573d6000803e3d6000fd5b50611c54565b611c506001600160a01b038516848463ffffffff6124e116565b5060015b9392505050565b836001600160a01b0316856001600160a01b03161415611c7a57611660565b611c8261437c565b611c8a612533565b9050611c9e8261080063ffffffff61264f16565b6120335760005b600a811015611e5d578181600a8110611cba57fe5b60200201516001600160a01b0316876001600160a01b03161415611e555760008282600a8110611ce657fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d2357600080fd5b505afa158015611d37573d6000803e3d6000fd5b505050506040513d6020811015611d4d57600080fd5b505190508282600a8110611d5d57fe5b60200201516001600160a01b0316632e1a7d4d876040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015611da757600080fd5b505af1158015611dbb573d6000803e3d6000fd5b50505050611e4d8188836001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611e1a57600080fd5b505afa158015611e2e573d6000803e3d6000fd5b505050506040513d6020811015611e4457600080fd5b50518888611c5b565b505050611660565b600101611ca5565b5060005b600a811015612031578181600a8110611e7657fe5b60200201516001600160a01b0316866001600160a01b031614156120295760008282600a8110611ea257fe5b60200201516001600160a01b031663fc0c546a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611edf57600080fd5b505afa158015611ef3573d6000803e3d6000fd5b505050506040513d6020811015611f0957600080fd5b50519050611f1a8882888888612655565b611f2a818484600a81106114db57fe5b8282600a8110611f3657fe5b60200201516001600160a01b031663b6b55f25826001600160a01b03166370a08231306040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015611f9f57600080fd5b505afa158015611fb3573d6000803e3d6000fd5b505050506040513d6020811015611fc957600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b15801561200957600080fd5b505af115801561201d573d6000803e3d6000fd5b50505050505050611660565b600101611e61565b505b61165e8686868686612655565b612049836118c0565b612111576000811180156120d7575060408051636eb1769f60e11b81523060048201526001600160a01b038481166024830152915160009286169163dd62ed3e916044808301926020929190829003018186803b1580156120a957600080fd5b505afa1580156120bd573d6000803e3d6000fd5b505050506040513d60208110156120d357600080fd5b5051115b156120f7576120f76001600160a01b03841683600063ffffffff61266216565b6121116001600160a01b038416838363ffffffff61266216565b505050565b6000611c5483836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250612775565b604080516001600160a01b0385811660248301528416604482015260648082018490528251808303909101815260849091019091526020810180516001600160e01b03166323b872dd60e01b179052611b2090859061280c565b836001600160a01b0316856001600160a01b031614156121d157611660565b6121e4816208000063ffffffff61264f16565b6124d4576001600160a01b03851673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561230e57604080516370a0823160e01b8152306004820152905173c02aaa39b223fe8d0a0e5c4f27ead9083c756cc291632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561226657600080fd5b505afa15801561227a573d6000803e3d6000fd5b505050506040513d602081101561229057600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b1580156122d057600080fd5b505af11580156122e4573d6000803e3d6000fd5b5050505061230973eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee858585856129c4565b611660565b6001600160a01b03851673c0829421c1d260bd3cb3e0f06cfe2d52db2ce315141561238c57604080516370a0823160e01b8152306004820152905173c0829421c1d260bd3cb3e0f06cfe2d52db2ce31591632e1a7d4d9183916370a08231916024808301926020929190829003018186803b15801561226657600080fd5b6001600160a01b03841673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2141561243f576123d28573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8585856121b2565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc26001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b15801561242157600080fd5b505af1158015612435573d6000803e3d6000fd5b5050505050611660565b6001600160a01b03841673c0829421c1d260bd3cb3e0f06cfe2d52db2ce31514156124d4576124858573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8585856121b2565b73c0829421c1d260bd3cb3e0f06cfe2d52db2ce3156001600160a01b031663d0e30db0476040518263ffffffff1660e01b81526004016000604051808303818588803b15801561242157600080fd5b61166085858585856129c4565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b17905261211190849061280c565b61253b61437c565b5060408051610140810182527316de59092dae5ccf4a1e6439d611fd0653f0bd0181527304aa51bbcb46541455ccf1b8bef2ebc5d3787ec960208201527373a052500105205d34daf004eab301916da8190f918101919091527383f798e925bcd4017eb265844fddabb448f1707d606082015273d6ad7a6750a7593e092a9b218d66c0a814a3436e608082015273f61718057901f84c4eec4339ef8f0d86d2b4560060a08201527304bc0ab673d88ae9dbc9da2380cb6b79c4bca9ae60c082015273c2cb1040220768554cf699b0d863a3cd4324ce3260e082015273e6354ed5bc4b393a5aad09f21c46e101e692d4476101008201527326ea744e5b887e5205727f55dfbe8685e3b2195161012082015290565b16151590565b61166085858585856129d1565b8015806126e8575060408051636eb1769f60e11b81523060048201526001600160a01b03848116602483015291519185169163dd62ed3e91604480820192602092909190829003018186803b1580156126ba57600080fd5b505afa1580156126ce573d6000803e3d6000fd5b505050506040513d60208110156126e457600080fd5b5051155b6127235760405162461bcd60e51b81526004018080602001828103825260368152602001806144466036913960400191505060405180910390fd5b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663095ea7b360e01b17905261211190849061280c565b600081848411156128045760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b838110156127c95781810151838201526020016127b1565b50505050905090810190601f1680156127f65780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b61281e826001600160a01b0316612c18565b61286f576040805162461bcd60e51b815260206004820152601f60248201527f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e747261637400604482015290519081900360640190fd5b60006060836001600160a01b0316836040518082805190602001908083835b602083106128ad5780518252601f19909201916020918201910161288e565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d806000811461290f576040519150601f19603f3d011682016040523d82523d6000602084013e612914565b606091505b50915091508161296b576040805162461bcd60e51b815260206004820181905260248201527f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564604482015290519081900360640190fd5b805115611b205780806020019051602081101561298757600080fd5b5051611b205760405162461bcd60e51b815260040180806020018281038252602a81526020018061441c602a913960400191505060405180910390fd5b611660858585858561122b565b836001600160a01b0316856001600160a01b031614156129f057611660565b612a0181601063ffffffff61264f16565b612c0b576000612a1086612c54565b90506001600160a01b0380821614612ac657856001600160a01b031663db006a75856040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612a6857600080fd5b505af1158015612a7c573d6000803e3d6000fd5b505050506040513d6020811015612a9257600080fd5b5060009050612ab06001600160a01b0383163063ffffffff611b3316565b9050612abf82878387876129d1565b5050611660565b612acf85612c54565b90506001600160a01b0380821614612c0957612aee8682868686612e46565b6000612b096001600160a01b0383163063ffffffff611b3316565b9050612b1d826001600160a01b03166118c0565b15612b8f57734ddc2d193948926d02f9b1fe9e1daa0718270ed56001600160a01b0316631249c58b826040518263ffffffff1660e01b81526004016000604051808303818588803b158015612b7157600080fd5b505af1158015612b85573d6000803e3d6000fd5b5050505050612abf565b612b99828761194e565b856001600160a01b031663a0712d68826040518263ffffffff1660e01b815260040180828152602001915050602060405180830381600087803b158015612bdf57600080fd5b505af1158015612bf3573d6000803e3d6000fd5b505050506040513d60208110156113fd57600080fd5b505b6116608585858585612e46565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590612c4c57508115155b949350505050565b60006001600160a01b038216734ddc2d193948926d02f9b1fe9e1daa0718270ed51415612c835750600061110b565b6001600160a01b038216735d3a536e4d6dbd6114cc1ead35777bab948e36431415612cbd57506000805160206143d183398151915261110b565b6001600160a01b038216736c8c6b02e7b2be14d4fa6022dfd6d75921d90e4e1415612cfd5750730d8775f648430679a709e98d2b0cb6250d2887ef61110b565b6001600160a01b03821673158079ee67fce2f58472a96584a73c7ab9ac95c11415612d3d5750731985365e9f78359a9b6ad760e32412f4a445e86261110b565b6001600160a01b0382167339aa39c021dfbae8fac545936693ac917d5e75631415612d7d575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861110b565b6001600160a01b03821673c11b1268c1a384e55c48c2391d8d480264a3a7f41415612dbd5750732260fac5e5542a773aa44fbcfedf7c193bc2c59961110b565b6001600160a01b03821673b3319f5d18bc0d84dd1b4825dcde5d5f7266d4071415612dfd575073e41d2489571d322189246dafa5ebde1f4699f49861110b565b6001600160a01b03821673f650c3d88d12db855b8bf7d11be6c55a4e07dcc91415612e3d575073dac17f958d2ee523a2206206994597c13d831ec761110b565b50600019919050565b6116608585858585836001600160a01b0316856001600160a01b03161415612e6d57611660565b612e7e81602063ffffffff61264f16565b613111576000612e8d86610d98565b90506001600160a01b0380821614612fdd57612eb1816001600160a01b03166118c0565b15612f37576040805163081a6b2560e41b81523060048201526024810186905290516001600160a01b038816916381a6b2509160448083019260209291908290030181600087803b158015612f0557600080fd5b505af1158015612f19573d6000803e3d6000fd5b505050506040513d6020811015612f2f57600080fd5b50612fb39050565b60408051632770a7eb60e21b81523060048201526024810186905290516001600160a01b03881691639dc29fac9160448083019260209291908290030181600087803b158015612f8657600080fd5b505af1158015612f9a573d6000803e3d6000fd5b505050506040513d6020811015612fb057600080fd5b50505b6000612fce6001600160a01b0383163063ffffffff611b3316565b9050612abf828783878761311a565b612fe685610d98565b90506001600160a01b038082161461310f57613005868286868661311a565b60006130206001600160a01b0383163063ffffffff611b3316565b9050613034826001600160a01b03166118c0565b156130b65760408051638f6ede1f60e01b815230600482015290516001600160a01b03881691638f6ede1f91849160248082019260209290919082900301818588803b15801561308357600080fd5b505af1158015613097573d6000803e3d6000fd5b50505050506040513d60208110156130ae57600080fd5b50612abf9050565b6130c0828761194e565b604080516340c10f1960e01b81523060048201526024810183905290516001600160a01b038816916340c10f199160448083019260209291908290030181600087803b158015612bdf57600080fd5b505b61166085858585855b61166085858585855b836001600160a01b0316856001600160a01b0316141561314257611660565b61315381608063ffffffff61264f16565b61336e5760006131628661337b565b90506001600160a01b03808216146131e557856001600160a01b031663db006a75856040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156131ba57600080fd5b505af11580156131ce573d6000803e3d6000fd5b505050506131df8186868686613123565b50611660565b6131ee8561337b565b90506001600160a01b038082161461336c5761320d868286868661379f565b60006132286001600160a01b0383163063ffffffff611b3316565b90506132ac8273398ec7346dcd622edc5ae82352f02be94c62d1196001600160a01b031663f2f4eb266040518163ffffffff1660e01b815260040160206040518083038186803b15801561327b57600080fd5b505afa15801561328f573d6000803e3d6000fd5b505050506040513d60208110156132a557600080fd5b505161194e565b73398ec7346dcd622edc5ae82352f02be94c62d11963d2d0e0666132d86001600160a01b0385166118c0565b6132e35760006132e5565b825b6132f7856001600160a01b03166118c0565b6133015784613317565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee5b604080516001600160e01b031960e086901b1681526001600160a01b0390921660048301526024820186905261044d604483015251606480830192600092919082900301818588803b15801561200957600080fd5b505b611660858585858561379f565b60006001600160a01b038216733a3a65aab0dd2a17e3f1947ba16138cd37d08c0414156133aa5750600061110b565b6001600160a01b03821673fc1e690f61efd961294b3e1ce3313fbd8aa4f85d14156133e457506000805160206143d183398151915261110b565b6001600160a01b038216739ba00d6856a4edf4665bca2c2309936572473b7e1415613424575073a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4861110b565b6001600160a01b03821673625ae63000f46200499120b906716420bd059240141561346457507357ab1ec28d129707052df4df418d58a2d46d5f5161110b565b6001600160a01b038216736ee0f7bb50a54ab5253da0667b0dc2ee526c30a814156134a45750734fabb145d64652a948d72533023f6e7a623c7c5361110b565b6001600160a01b038216734da9b813057d04baef4e5800e36083717b4a034114156134df57506e085d4780b73119b644ae5ecd22b37661110b565b6001600160a01b0382167371fc860f7d3a592a4a98740e39db31d25db65ae8141561351f575073dac17f958d2ee523a2206206994597c13d831ec761110b565b6001600160a01b03821673e1ba0fb44ccb0d11b80f92f4f8ed94ca3ff51d00141561355f5750730d8775f648430679a709e98d2b0cb6250d2887ef61110b565b6001600160a01b038216739d91be44c06d373a8a226e1f3b146956083803eb141561359f575073dd974d5c2e2928dea5f71b9825b8b646686bd20061110b565b6001600160a01b038216737d2d3688df45ce7c552e19c27e007673da9204b814156135df57507380fb784b7ed66730e8b1dbd9820afd29931aab0361110b565b6001600160a01b03821673a64bd6c70cb9051f6a9ba1f163fdc07e0dfb5f84141561361f575073514910771af9ca656af840dff83e8264ecf986ca61110b565b6001600160a01b038216736fce4a401b6b80ace52baaefe4421bd188e76f6f141561365f5750730f5d2fb29fb7d3cfee444a200298f468908cc94261110b565b6001600160a01b038216737deb5e830be29f91e298ba5ff1356bb7f8146998141561369f5750739f8f72aa9304c8b593d555f12ef6589cc3a579a261110b565b6001600160a01b0382167371010a9d003445ac60c4e6a7017c1e89a477b43814156136df5750731985365e9f78359a9b6ad760e32412f4a445e86261110b565b6001600160a01b03821673328c4c80bc7aca0834db37e6600a6c49e12da4de141561371f575073c011a73ee8576fb46f5e1c5751ca3b9fe0af2a6f61110b565b6001600160a01b03821673fc4b8ed459e00e5400be803a9bb3954234fd50e3141561375f5750732260fac5e5542a773aa44fbcfedf7c193bc2c59961110b565b6001600160a01b038216736fb0855c404e09c47c3fbca25f08d4e41f9f062f1415612e3d575073e41d2489571d322189246dafa5ebde1f4699f49861110b565b836001600160a01b0316856001600160a01b031614156137be57611660565b6137d08161040063ffffffff61264f16565b613a59576000546001600160a01b0386811691161415613924576000805460408051637f8661a160e01b81526004810187905290516001600160a01b0390921692637f8661a19260248084019382900301818387803b15801561383257600080fd5b505af1158015613846573d6000803e3d6000fd5b5050600154604080516370a0823160e01b81523060048201529051600094506001600160a01b0390921692506370a08231916024808301926020929190829003018186803b15801561389757600080fd5b505afa1580156138ab573d6000803e3d6000fd5b505050506040513d60208110156138c157600080fd5b50519050801561390957600180546060916138ea916001600160a01b0316908890859087610b81565b60015490925061390791506001600160a01b031687848487611b26565b505b6131df6000805160206143d183398151915286868686613a62565b6000546001600160a01b0385811691161415613a5957613955856000805160206143d1833981519152858585613a62565b60005461397a906000805160206143d1833981519152906001600160a01b031661194e565b600054604080516370a0823160e01b815230600482015290516001600160a01b039092169163049878f3916000805160206143d1833981519152916370a0823191602480820192602092909190829003018186803b1580156139db57600080fd5b505afa1580156139ef573d6000803e3d6000fd5b505050506040513d6020811015613a0557600080fd5b5051604080516001600160e01b031960e085901b168152600481019290925251602480830192600092919082900301818387803b158015613a4557600080fd5b505af11580156113fd573d6000803e3d6000fd5b61166085858585855b836001600160a01b0316856001600160a01b03161415613a8157611660565b613a9281604063ffffffff61264f16565b613d04576001600160a01b0385167306af07097c9eeb7fd685c692751d5c66db49c2151415613bb3576040805163ef693bed60e01b81523060048201526024810185905290517306af07097c9eeb7fd685c692751d5c66db49c2159163ef693bed91604480830192600092919082900301818387803b158015613b1457600080fd5b505af1158015613b28573d6000803e3d6000fd5b5050604080516370a0823160e01b8152306004820152905161230993506000805160206143d18339815191529250879183916370a0823191602480820192602092909190829003018186803b158015613b8057600080fd5b505afa158015613b94573d6000803e3d6000fd5b505050506040513d6020811015613baa57600080fd5b50518585613d0d565b6001600160a01b0384167306af07097c9eeb7fd685c692751d5c66db49c2151415613d0457613bf3856000805160206143d1833981519152858585613d0d565b613c1f6000805160206143d18339815191527306af07097c9eeb7fd685c692751d5c66db49c21561194e565b604080516370a0823160e01b8152306004820181905291517306af07097c9eeb7fd685c692751d5c66db49c21592633b4da69f9290916000805160206143d1833981519152916370a08231916024808301926020929190829003018186803b158015613c8a57600080fd5b505afa158015613c9e573d6000803e3d6000fd5b505050506040513d6020811015613cb457600080fd5b5051604080516001600160e01b031960e086901b1681526001600160a01b039093166004840152602483019190915251604480830192600092919082900301818387803b158015613a4557600080fd5b61166085858585855b613d1f856001600160a01b03166118c0565b158015613d3b5750613d39846001600160a01b03166118c0565b155b8015613d545750613d548161020063ffffffff61264f16565b15613e555760608251604051908082528060200260200182016040528015613d86578160200160208202803883390190505b50905060005b8351811015613dcb57838181518110613da157fe5b602002602001015160ff16828281518110613db857fe5b6020908102919091010152600101613d8c565b50613ded8673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8684866141b5565b60005b8351811015613e33576008848281518110613e0757fe5b6020026020010151901c60ff16828281518110613e2057fe5b6020908102919091010152600101613df0565b506131df73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee864784866141b5565b6001600160a01b0385166000805160206143d183398151915214801590613e9357506001600160a01b0384166000805160206143d183398151915214155b8015613ead5750613ead816201000063ffffffff61264f16565b1561400e5760608251604051908082528060200260200182016040528015613edf578160200160208202803883390190505b50905060005b8351811015613f2457838181518110613efa57fe5b602002602001015160ff16828281518110613f1157fe5b6020908102919091010152600101613ee5565b50613f40866000805160206143d18339815191528684866141b5565b60005b8351811015613f86576008848281518110613f5a57fe5b6020026020010151901c60ff16828281518110613f7357fe5b6020908102919091010152600101613f43565b50604080516370a0823160e01b815230600482015290516131df916000805160206143d183398151915291889183916370a0823191602480820192602092909190829003018186803b158015613fdb57600080fd5b505afa158015613fef573d6000803e3d6000fd5b505050506040513d602081101561400557600080fd5b505184866141b5565b6001600160a01b03851673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb481480159061405857506001600160a01b03841673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4814155b80156140725750614072816202000063ffffffff61264f16565b156141ac57606082516040519080825280602002602001820160405280156140a4578160200160208202803883390190505b50905060005b83518110156140e9578381815181106140bf57fe5b602002602001015160ff168282815181106140d657fe5b60209081029190910101526001016140aa565b5061410b8673a0b86991c6218b36c1d19d4a2e9eb0ce3606eb488684866141b5565b60005b835181101561415157600884828151811061412557fe5b6020026020010151901c60ff1682828151811061413e57fe5b602090810291909101015260010161410e565b50604080516370a0823160e01b815230600482015290516131df9173a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4891889183916370a0823191602480820192602092909190829003018186803b158015613fdb57600080fd5b61166085858585855b836001600160a01b0316856001600160a01b031614156141d457611660565b61166085858585856003546040516001600160a01b038781166024830190815287821660448401526064830187905260006084840181905260c4840186905260c060a48501908152875160e486015287519195606095941693637153a8af60e11b938c938c938c938a938d938d9391926101040190602080870191028083838a5b8381101561426d578181015183820152602001614255565b50505050905001975050505050505050604051602081830303815290604052906001600160e01b0319166020820180516001600160e01b0383818316178352505050506040518082805190602001908083835b602083106142df5780518252601f1990920191602091820191016142c0565b6001836020036101000a038019825116818451168082178552505050505050905001915050600060405180830381855af49150503d806000811461433f576040519150601f19603f3d011682016040523d82523d6000602084013e614344565b606091505b5091509150816000811461435757611878565b3d60208301fd5b60405180604001604052806002906020820280388339509192915050565b604051806101400160405280600a90602082028038833950919291505056fe4f6e6553706c69743a2061637475616c2072657475726e20616d6f756e74206973206c657373207468616e206d696e52657475726e0000000000000000000000006b175474e89094c44da98b954eedeac495271d0f57726f6e6720757365616765206f66204554482e756e6976657273616c5472616e7366657246726f6d28295361666545524332303a204552433230206f7065726174696f6e20646964206e6f7420737563636565645361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f20746f206e6f6e2d7a65726f20616c6c6f77616e6365a265627a7a72315820ed82bada9bab10e79931a19e6fa1964fdc8a989ef7bcfa86ce0538e0da99af6b64736f6c63430005110032
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000034f359df4e0e5c5ca8f692300f6b273144de4696000000000000000000000000d2e0373e3bef55db21138c25cfe00bd421e759a7
-----Decoded View---------------
Arg [0] : _oneSplitView (address): 0x34f359DF4e0e5C5ca8f692300f6b273144DE4696
Arg [1] : _oneSplit (address): 0xd2e0373e3BEF55DB21138c25cFe00Bd421e759a7
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 00000000000000000000000034f359df4e0e5c5ca8f692300f6b273144de4696
Arg [1] : 000000000000000000000000d2e0373e3bef55db21138c25cfe00bd421e759a7
Deployed Bytecode Sourcemap
120532:2783:0:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121132:10;121146:9;121132:23;;121124:32;;;;;;120532:2783;5018:59;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5018:59:0;;;:::i;:::-;;;;;;;;;;;;;;;;121172:615;;8:9:-1;5:2;;;30:1;27;20:12;5:2;121172:615:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;121172:615:0;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;121172:615:0;;;;;;;;;;;;;;;;;;33950:132;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33950:132:0;;;:::i;:::-;;;;-1:-1:-1;;;;;33950:132:0;;;;;;;;;;;;;;34375:105;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34375:105:0;;;:::i;4377:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4377:56:0;;;:::i;4500:59::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4500:59:0;;;:::i;3501:69::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3501:69:0;;;:::i;34859:90::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34859:90:0;;;:::i;3398:71::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3398:71:0;;;:::i;3989:48::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3989:48:0;;;:::i;33065:80::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33065:80:0;;;:::i;3934:48::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3934:48:0;;;:::i;34764:88::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34764:88:0;;;:::i;33239:80::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33239:80:0;;;:::i;32978:::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32978:80:0;;;:::i;85894:1205::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;85894:1205:0;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;85894:1205:0;-1:-1:-1;;;;;85894:1205:0;;:::i;32892:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32892:79:0;;;:::i;34675:82::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34675:82:0;;;:::i;120837:25::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;120837:25:0;;;:::i;3817:52::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3817:52:0;;;:::i;3876:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3876:51:0;;;:::i;33413:83::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33413:83:0;;;:::i;34487:89::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34487:89:0;;;:::i;4440:53::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4440:53:0;;;:::i;4253:50::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4253:50:0;;;:::i;3761:49::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3761:49:0;;;:::i;4658:61::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4658:61:0;;;:::i;4878:63::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4878:63:0;;;:::i;94822:70::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;94822:70:0;;;:::i;4820:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4820:51:0;;;:::i;4197:49::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4197:49:0;;;:::i;33152:80::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33152:80:0;;;:::i;3342:49::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3342:49:0;;;:::i;5142:59::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5142:59:0;;;:::i;34956:100::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34956:100:0;;;:::i;33503:114::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33503:114:0;;;:::i;33835:108::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33835:108:0;;;:::i;106837:1166::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;106837:1166:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;106837:1166:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;106837:1166:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;106837:1166:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;106837:1166:0;;-1:-1:-1;;106837:1166:0;;;-1:-1:-1;106837:1166:0;;-1:-1:-1;;106837:1166:0:i;35160:96::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;35160:96:0;;;:::i;32710:87::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32710:87:0;;;:::i;4310:60::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4310:60:0;;;:::i;3602:70::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3602:70:0;;;:::i;33624:78::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33624:78:0;;;:::i;94746:69::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;94746:69:0;;;:::i;3284:51::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3284:51:0;;;:::i;4107:58::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4107:58:0;;;:::i;33326:80::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33326:80:0;;;:::i;5278:52::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5278:52:0;;;:::i;4751:62::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4751:62:0;;;:::i;32663:40::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32663:40:0;;;:::i;34583:85::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34583:85:0;;;:::i;106158:338::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;106158:338:0;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;106158:338:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;106158:338:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;106158:338:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;106158:338:0;;-1:-1:-1;106158:338:0;-1:-1:-1;106158:338:0;;:::i;4566:60::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4566:60:0;;;:::i;34233:135::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34233:135:0;;;:::i;33711:117::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;33711:117:0;;;:::i;4044:56::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4044:56:0;;;:::i;121795:813::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;121795:813:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;5:28;;2:2;;;46:1;43;36:12;2:2;121795:813:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;121795:813:0;;;;;;101:9:-1;95:2;81:12;77:21;67:8;63:36;60:51;-1:-1;;;25:12;22:29;11:108;8:2;;;132:1;129;122:12;8:2;121795:813:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;121795:813:0;;-1:-1:-1;;121795:813:0;;;-1:-1:-1;121795:813:0;;-1:-1:-1;;121795:813:0:i;32806:79::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;32806:79:0;;;:::i;3704:50::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;3704:50:0;;;:::i;35063:90::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;35063:90:0;;;:::i;120797:33::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;120797:33:0;;;:::i;5018:59::-;5069:8;5018:59;:::o;121172:615::-;121631:12;;:148;;;-1:-1:-1;;;121631:148:0;;-1:-1:-1;;;;;121631:148:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;121524:7;;121563:16;;121631:12;;:30;;:148;;;;;121524:7;;121631:148;;;;;;;:12;:148;;;5:2:-1;;;;30:1;27;20:12;5:2;121631:148:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;121631:148:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;121631:148:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;;;5:11;;2:2;;;29:1;26;19:12;2:2;121631:148:0;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;11:20;;8:2;;;44:1;41;34:12;8:2;62:21;;;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;-1:-1;;;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;373:25;;-1:-1;121631:148:0;;421:4:-1;412:14;;;;121631:148:0;;;;;412:14:-1;121631:148:0;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;121631:148:0;;;;;;;;;;;121624:155;;;;121172:615;;;;;;;;:::o;33950:132::-;34039:42;33950:132;:::o;34375:105::-;34437:42;34375:105;:::o;4377:56::-;4427:6;4377:56;:::o;4500:59::-;4553:6;4500:59;:::o;3501:69::-;3559:11;3501:69;:::o;34859:90::-;34906:42;34859:90;:::o;3398:71::-;-1:-1:-1;;;3398:71:0;:::o;3989:48::-;4033:4;3989:48;:::o;33065:80::-;33102:42;33065:80;:::o;3934:48::-;3978:4;3934:48;:::o;34764:88::-;34809:42;34764:88;:::o;33239:80::-;33276:42;33239:80;:::o;32978:::-;33015:42;32978:80;:::o;85894:1205::-;85953:6;85976:13;:5;-1:-1:-1;;;;;85976:11:0;;:13::i;:::-;85972:63;;;-1:-1:-1;;;86006:17:0;;85972:63;86119:91;;;22:32:-1;6:49;;86119:91:0;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;86083:128:0;;;;86048:12;;86062:17;;-1:-1:-1;;;;;86083:25:0;;;86113:4;;86119:91;;86083:128;;;;25:18:-1;86083:128:0;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;86083:128:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;86047:164:0;;;;86227:7;86222:58;;-1:-1:-1;;86251:17:0;;;;;;86222:58;86292:13;;86324:414;86349:4;:11;86341:1;86345;86341:5;:19;86324:414;;;86386:4;86391:1;86395;86391:5;86386:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86386:11:0;-1:-1:-1;;;86386:18:0;:57;;;;;86425:4;86430:1;86434;86430:5;86425:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86425:11:0;-1:-1:-1;;;86425:18:0;86386:57;:96;;;;;86464:4;86469:1;86473;86469:5;86464:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86464:11:0;-1:-1:-1;;;86464:18:0;86386:96;:135;;;;;86503:4;86508:1;86512;86508:5;86503:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86503:11:0;-1:-1:-1;;;86503:18:0;86386:135;:174;;;;;86542:4;86547:1;86551;86547:5;86542:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86542:11:0;-1:-1:-1;;;86542:18:0;86386:174;:213;;;;;86581:4;86586:1;86590;86586:5;86581:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86581:11:0;-1:-1:-1;;;86581:18:0;86386:213;:252;;;;;86620:4;86625:1;86629;86625:5;86620:11;;;;;;;;;;;;;-1:-1:-1;;;;;;86620:11:0;-1:-1:-1;;;86620:18:0;86386:252;86382:345;;;86683:4;86672:15;;86706:5;;86382:345;86362:3;;86324:414;;;;86753:8;86748:59;;-1:-1:-1;;86778:17:0;;;;;;;86748:59;86873:103;;;22:32:-1;6:49;;86873:103:0;;;;;49:4:-1;25:18;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;86837:140:0;;;;-1:-1:-1;;;;;86837:25:0;;;86867:4;;86873:103;86837:140;;;25:18:-1;86837:140:0;;25:18:-1;36:153;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;86837:140:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;86819:158:0;;-1:-1:-1;86819:158:0;-1:-1:-1;86819:158:0;86988:58;;-1:-1:-1;;87017:17:0;;;;;;;86988:58;87076:4;87065:26;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;87065:26:0;;-1:-1:-1;;;;85894:1205:0;;;;:::o;32892:79::-;32928:42;32892:79;:::o;34675:82::-;34714:42;34675:82;:::o;120837:25::-;;;-1:-1:-1;;;;;120837:25:0;;:::o;3817:52::-;3865:4;3817:52;:::o;3876:51::-;3923:4;3876:51;:::o;33413:83::-;33453:42;33413:83;:::o;34487:89::-;34533:42;34487:89;:::o;4440:53::-;4487:6;4440:53;:::o;4253:50::-;4298:5;4253:50;:::o;3761:49::-;3806:4;3761:49;:::o;4658:61::-;4712:7;4658:61;:::o;4878:63::-;4933:8;4878:63;:::o;94822:70::-;;;-1:-1:-1;;;;;94822:70:0;;:::o;4820:51::-;4864:7;4820:51;:::o;4197:49::-;4241:5;4197:49;:::o;33152:80::-;33189:42;33152:80;:::o;3342:49::-;3387:4;3342:49;:::o;5142:59::-;5193:8;5142:59;:::o;34956:100::-;35013:42;34956:100;:::o;33503:114::-;33574:42;33503:114;:::o;33835:108::-;33900:42;33835:108;:::o;106837:1166::-;107030:22;;:::i;:::-;107055:13;:11;:13::i;:::-;107030:38;-1:-1:-1;107086:6:0;107081:371;107102:13;107098:1;:17;107081:371;;;107161:6;107168:1;107161:9;;;;;;;;;;;-1:-1:-1;;;;;107141:30:0;:9;-1:-1:-1;;;;;107141:30:0;;107137:304;;;107192:17;107212:6;107219:1;107212:9;;;;;;;;;;;-1:-1:-1;;;;;107212:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107212:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107212:17:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;107212:17:0;;-1:-1:-1;107248:14:0;107265:6;107272:1;107265:9;;;;;;;;;;;-1:-1:-1;;;;;107265:25:0;;107291:6;107299:4;107319:1;107305:16;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;107305:16:0;;107265:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;107265:57:0;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107265:57:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107265:57:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;107265:57:0;;-1:-1:-1;107341:59:0;107351:10;107363:7;107265:57;107380:12;107394:5;107341:9;:59::i;:::-;107419:7;;;;;;107137:304;107117:3;;107081:371;;;-1:-1:-1;107469:6:0;107464:452;107485:13;107481:1;:17;107464:452;;;107542:6;107549:1;107542:9;;;;;;;;;;;-1:-1:-1;;;;;107524:28:0;:7;-1:-1:-1;;;;;107524:28:0;;107520:385;;;107573:17;107593:6;107600:1;107593:9;;;;;;;;;;;-1:-1:-1;;;;;107593:15:0;;:17;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107593:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107593:17:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;107593:17:0;;-1:-1:-1;107629:63:0;107641:9;107593:17;107664:6;107672:12;107686:5;107629:11;:63::i;:::-;107711:56;107736:10;107756:6;107763:1;107756:9;;;;;;;;;;;107711:24;:56::i;:::-;107786:6;107793:1;107786:9;;;;;;;;;;;-1:-1:-1;;;;;107786:23:0;;107810:10;-1:-1:-1;;;;;107810:20:0;;107839:4;107810:35;;;;;;;;;;;;;-1:-1:-1;;;;;107810:35:0;-1:-1:-1;;;;;107810:35:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107810:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107810:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;107810:35:0;107847:16;;;107861:1;107847:16;;;107810:35;107847:16;;;;;;;107786:78;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;107786:78:0;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;107786:78:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;107786:78:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;107883:7:0;;-1:-1:-1;;;;107883:7:0;107520:385;107500:3;;107464:452;;;;107935:60;107947:9;107958:7;107967:6;107975:12;107989:5;107935:11;:60::i;:::-;107928:67;106837:1166;;;;;;:::o;35160:96::-;35213:42;35160:96;:::o;32710:87::-;32754:42;32710:87;:::o;4310:60::-;4364:6;4310:60;:::o;3602:70::-;3661:11;3602:70;:::o;33624:78::-;33659:42;33624:78;:::o;94746:69::-;;;-1:-1:-1;;;;;94746:69:0;;:::o;3284:51::-;3331:4;3284:51;:::o;4107:58::-;4160:5;4107:58;:::o;33326:80::-;33363:42;33326:80;:::o;5278:52::-;5322:8;5278:52;:::o;4751:62::-;4806:7;4751:62;:::o;32663:40::-;32701:2;32663:40;:::o;34583:85::-;34625:42;34583:85;:::o;106158:338::-;106382:10;106404:4;106382:27;106374:36;;;;;;106428:60;106440:9;106451:7;106460:6;106468:12;;106428:60;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;106482:5:0;;-1:-1:-1;106428:11:0;;-1:-1:-1;;106428:60:0:i;4566:::-;4619:7;4566:60;:::o;34233:135::-;34325:42;34233:135;:::o;33711:117::-;33785:42;33711:117;:::o;4044:56::-;4095:5;4044:56;:::o;121795:813::-;122131:66;-1:-1:-1;;;;;122131:31:0;;122163:10;122183:4;122190:6;122131:66;:31;:66;:::i;:::-;122210:54;122216:9;122227:7;122236:6;122244:12;122258:5;122210;:54::i;:::-;122277:20;122300:41;-1:-1:-1;;;;;122300:26:0;;122335:4;122300:41;:26;:41;:::i;:::-;122277:64;;122376:9;122360:12;:25;;122352:91;;;;-1:-1:-1;;;122352:91:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;122454:51;-1:-1:-1;;;;;122454:25:0;;122480:10;122492:12;122454:51;:25;:51;:::i;:::-;-1:-1:-1;122516:84:0;122544:10;122556:43;-1:-1:-1;;;;;122556:28:0;;122593:4;122556:43;:28;:43;:::i;:::-;-1:-1:-1;;;;;122516:27:0;;;:84;;:27;:84;:::i;:::-;;121795:813;;;;;;;:::o;32806:79::-;-1:-1:-1;;;;;;;;;;;32806:79:0;:::o;3704:50::-;3750:4;3704:50;:::o;35063:90::-;35110:42;35063:90;:::o;120797:33::-;;;-1:-1:-1;;;;;120797:33:0;;:::o;31562:166::-;31613:4;-1:-1:-1;;;;;31638:39:0;;;;:81;;-1:-1:-1;;;;;;31681:38:0;;28951:42;31681:38;31638:81;31630:90;31562:166;-1:-1:-1;;31562:166:0:o;103811:227::-;103856:15;;:::i;:::-;-1:-1:-1;103884:146:0;;;;;;;;;103912:42;103884:146;;103976:42;103884:146;;;;103811:227;:::o;101494:326::-;101677:135;101702:9;101726:7;101748:6;101769:12;101796:5;101677:10;:135::i;42102:262::-;42187:13;:5;-1:-1:-1;;;;;42187:11:0;;:13::i;:::-;42182:175;;42222:34;;;-1:-1:-1;;;42222:34:0;;42246:4;42222:34;;;;-1:-1:-1;;;;;42222:34:0;;;;;;;;;42260:3;;42222:15;;;;;:34;;;;;;;;;;;;;;:15;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;42222:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;42222:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;42222:34:0;:41;;42217:129;;42290:40;-1:-1:-1;;;;;42290:22:0;;42313:2;-1:-1:-1;;42290:40:0;:22;:40;:::i;:::-;42102:262;;:::o;29359:617::-;29470:11;29466:50;;29498:7;;29466:50;29532:12;29538:5;29532;:12::i;:::-;29528:441;;;-1:-1:-1;;;;;29569:18:0;;29577:10;29569:18;:41;;;;;29604:6;29591:9;:19;;29569:41;29561:97;;;;-1:-1:-1;;;29561:97:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;29677:19:0;;29691:4;29677:19;29673:97;;29717:37;;-1:-1:-1;;;;;29717:29:0;;;:37;;;;;29747:6;;29717:37;;;;29747:6;29717:29;:37;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29717:37:0;29673:97;29800:6;29788:9;:18;29784:101;;;29827:10;:42;29847:21;:9;29861:6;29847:21;:13;:21;:::i;:::-;29827:42;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29827:42:0;29784:101;29528:441;;;29917:40;-1:-1:-1;;;;;29917:22:0;;29940:4;29946:2;29950:6;29917:40;:22;:40;:::i;:::-;29359:617;;;;:::o;116604:325::-;116787:134;116811:9;116835:7;116857:6;116878:12;116905:5;116787:9;:134::i;30744:228::-;30822:7;30846:12;30852:5;30846;:12::i;:::-;30842:123;;;-1:-1:-1;;;;;;30882:11:0;;;30875:18;;30842:123;30933:5;-1:-1:-1;;;;;30933:15:0;;30949:3;30933:20;;;;;;;;;;;;;-1:-1:-1;;;;;30933:20:0;-1:-1:-1;;;;;30933:20:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;30933:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30933:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30933:20:0;;30744:228;-1:-1:-1;;;30744:228:0:o;29003:348::-;29089:4;29110:11;29106:55;;-1:-1:-1;29145:4:0;29138:11;;29106:55;29177:12;29183:5;29177;:12::i;:::-;29173:171;;;29206:37;;-1:-1:-1;;;;;29206:29:0;;;:37;;;;;29236:6;;29206:37;;;;29236:6;29206:29;:37;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29206:37:0;29173:171;;;29276:30;-1:-1:-1;;;;;29276:18:0;;29295:2;29299:6;29276:30;:18;:30;:::i;:::-;-1:-1:-1;29328:4:0;29173:171;29003:348;;;;;:::o;101828:1326::-;102032:7;-1:-1:-1;;;;;102019:20:0;:9;-1:-1:-1;;;;;102019:20:0;;102015:59;;;102056:7;;102015:59;102086:25;;:::i;:::-;102114:10;:8;:10::i;:::-;102086:38;-1:-1:-1;102142:31:0;:5;4298;102142:31;:11;:31;:::i;:::-;102137:930;;102195:6;102190:385;102211:14;102207:1;:18;102190:385;;;102275:7;102283:1;102275:10;;;;;;;;;;;-1:-1:-1;;;;;102255:31:0;:9;-1:-1:-1;;;;;102255:31:0;;102251:309;;;102311:17;102331:7;102339:1;102331:10;;;;;;;;;;;-1:-1:-1;;;;;102331:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102331:18:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102331:18:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;102331:18:0;;-1:-1:-1;102372:7:0;102380:1;102372:10;;;;;;;;;;;-1:-1:-1;;;;;102372:19:0;;102392:6;102372:27;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102372:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102372:27:0;;;;102422:89;102433:10;102445:7;102454:10;-1:-1:-1;;;;;102454:20:0;;102483:4;102454:35;;;;;;;;;;;;;-1:-1:-1;;;;;102454:35:0;-1:-1:-1;;;;;102454:35:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102454:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102454:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;102454:35:0;102491:12;102505:5;102422:10;:89::i;:::-;102534:7;;;;;102251:309;102227:3;;102190:385;;;-1:-1:-1;102596:6:0;102591:465;102612:14;102608:1;:18;102591:465;;;102674:7;102682:1;102674:10;;;;;;;;;;;-1:-1:-1;;;;;102656:29:0;:7;-1:-1:-1;;;;;102656:29:0;;102652:389;;;102710:17;102730:7;102738:1;102730:10;;;;;;;;;;;-1:-1:-1;;;;;102730:16:0;;:18;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102730:18:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102730:18:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;102730:18:0;;-1:-1:-1;102771:63:0;102783:9;102730:18;102806:6;102814:12;102828:5;102771:11;:63::i;:::-;102857:57;102882:10;102902:7;102910:1;102902:10;;;;;;102857:57;102937:7;102945:1;102937:10;;;;;;;;;;;-1:-1:-1;;;;;102937:18:0;;102956:10;-1:-1:-1;;;;;102956:20:0;;102985:4;102956:35;;;;;;;;;;;;;-1:-1:-1;;;;;102956:35:0;-1:-1:-1;;;;;102956:35:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;102956:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102956:35:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;102956:35:0;102937:55;;;-1:-1:-1;;;;;;102937:55:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;102937:55:0;;;;;;;-1:-1:-1;102937:55:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;102937:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;102937:55:0;;;;103015:7;;;;;102652:389;102628:3;;102591:465;;;;102137:930;103086:60;103098:9;103109:7;103118:6;103126:12;103140:5;103086:11;:60::i;30435:301::-;30528:12;30534:5;30528;:12::i;:::-;30523:206;;30570:1;30561:6;:10;:52;;;;-1:-1:-1;30575:34:0;;;-1:-1:-1;;;30575:34:0;;30599:4;30575:34;;;;-1:-1:-1;;;;;30575:34:0;;;;;;;;;30612:1;;30575:15;;;;;:34;;;;;;;;;;;;;;:15;:34;;;5:2:-1;;;;30:1;27;20:12;5:2;30575:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30575:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30575:34:0;:38;30561:52;30557:117;;;30634:24;-1:-1:-1;;;;;30634:17:0;;30652:2;30656:1;30634:24;:17;:24;:::i;:::-;30688:29;-1:-1:-1;;;;;30688:17:0;;30706:2;30710:6;30688:29;:17;:29;:::i;:::-;30435:301;;;:::o;7270:136::-;7328:7;7355:43;7359:1;7362;7355:43;;;;;;;;;;;;;;;;;:3;:43::i;25658:204::-;25785:68;;;-1:-1:-1;;;;;25785:68:0;;;;;;;;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;25785:68:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;25759:95:0;;25778:5;;25759:18;:95::i;116937:1938::-;117140:7;-1:-1:-1;;;;;117127:20:0;:9;-1:-1:-1;;;;;117127:20:0;;117123:59;;;117164:7;;117123:59;117199:30;:5;4864:7;117199:30;:11;:30;:::i;:::-;117194:1518;;-1:-1:-1;;;;;117250:22:0;;33453:42;117250:22;117246:347;;;117312:34;;;-1:-1:-1;;;117312:34:0;;117340:4;117312:34;;;;;;33453:42;;117293:18;;33453:42;;117312:19;;:34;;;;;;;;;;;;;;33453:42;117312:34;;;5:2:-1;;;;30:1;27;20:12;5:2;117312:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117312:34:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;117312:34:0;117293:54;;;-1:-1:-1;;;;;;117293:54:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;117293:54:0;;;;;;;-1:-1:-1;117293:54:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;117293:54:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;117293:54:0;;;;117366:186;32754:42;117434:7;117464:6;117493:12;117528:5;117366:11;:186::i;:::-;117571:7;;117246:347;-1:-1:-1;;;;;117613:29:0;;33574:42;117613:29;117609:368;;;117689:41;;;-1:-1:-1;;;117689:41:0;;117724:4;117689:41;;;;;;33574:42;;117663:25;;33574:42;;117689:26;;:41;;;;;;;;;;;;;;33574:42;117689:41;;;5:2:-1;;;;30:1;27;20:12;117609:368:0;-1:-1:-1;;;;;117997:20:0;;33453:42;117997:20;117993:339;;;118038:186;118070:9;32754:42;118136:6;118165:12;118200:5;118038:9;:186::i;:::-;33453:42;-1:-1:-1;;;;;118243:17:0;;118267:21;118243:48;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;118243:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;118243:48:0;;;;;118310:7;;117993:339;-1:-1:-1;;;;;118352:27:0;;33574:42;118352:27;118348:353;;;118400:186;118432:9;32754:42;118498:6;118527:12;118562:5;118400:9;:186::i;:::-;33574:42;-1:-1:-1;;;;;118605:24:0;;118636:21;118605:55;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;118348:353:0;118731:136;118757:9;118781:7;118803:6;118824:12;118851:5;118731:11;:136::i;25474:176::-;25583:58;;;-1:-1:-1;;;;;25583:58:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;25583:58:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;25557:85:0;;25576:5;;25557:18;:85::i;98240:748::-;98282:17;;:::i;:::-;-1:-1:-1;98312:668:0;;;;;;;;98341:42;98312:668;;98406:42;98312:668;;;;98471:42;98312:668;;;;;;;98536:42;98312:668;;;;98601:42;98312:668;;;;98666:42;98312:668;;;;98731:42;98312:668;;;;98796:42;98312:668;;;;98861:42;98312:668;;;;98926:42;98312:668;;;;98240:748;:::o;32277:117::-;32368:12;32367:19;;;32277:117::o;81331:328::-;81514:137;81541:9;81565:7;81587:6;81608:12;81635:5;81514:12;:137::i;25870:621::-;26240:10;;;26239:62;;-1:-1:-1;26256:39:0;;;-1:-1:-1;;;26256:39:0;;26280:4;26256:39;;;;-1:-1:-1;;;;;26256:39:0;;;;;;;;;:15;;;;;;:39;;;;;;;;;;;;;;;:15;:39;;;5:2:-1;;;;30:1;27;20:12;5:2;26256:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;26256:39:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;26256:39:0;:44;26239:62;26231:152;;;;-1:-1:-1;;;26231:152:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;26420:62;;;-1:-1:-1;;;;;26420:62:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;26420:62:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;182:15;-1:-1;;;179:29;160:49;;26394:89:0;;26413:5;;26394:18;:89::i;7743:192::-;7829:7;7865:12;7857:6;;;;7849:29;;;;-1:-1:-1;;;7849:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;7849:29:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7901:5:0;;;7743:192::o;27513:1114::-;28117:27;28125:5;-1:-1:-1;;;;;28117:25:0;;:27::i;:::-;28109:71;;;;;-1:-1:-1;;;28109:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;28254:12;28268:23;28303:5;-1:-1:-1;;;;;28295:19:0;28315:4;28295:25;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;28295:25:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;28253:67:0;;;;28339:7;28331:52;;;;;-1:-1:-1;;;28331:52:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28400:17;;:21;28396:224;;28542:10;28531:30;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28531:30:0;28523:85;;;;-1:-1:-1;;;28523:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;106504:325;106687:134;106711:9;106735:7;106757:6;106778:12;106805:5;106687:9;:134::i;81667:1743::-;81873:7;-1:-1:-1;;;;;81860:20:0;:9;-1:-1:-1;;;;;81860:20:0;;81856:59;;;81897:7;;81856:59;81932:34;:5;3865:4;81932:34;:11;:34;:::i;:::-;81927:1320;;81983:17;82003:38;82031:9;82003:27;:38::i;:::-;81983:58;-1:-1:-1;;;;;;82060:24:0;;;;82056:428;;82128:9;-1:-1:-1;;;;;82105:41:0;;82147:6;82105:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82105:49:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82105:49:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;82173:24:0;;-1:-1:-1;82200:44:0;-1:-1:-1;;;;;82200:29:0;;82238:4;82200:44;:29;:44;:::i;:::-;82173:71;;82272:196;82307:10;82340:7;82370:16;82409:12;82444:5;82272:12;:196::i;:::-;82265:203;;;;82056:428;82513:36;82541:7;82513:27;:36::i;:::-;82500:49;-1:-1:-1;;;;;;82568:24:0;;;;82564:672;;82613:187;82647:9;82679:10;82712:6;82741:12;82776:5;82613:11;:187::i;:::-;82821:24;82848:44;-1:-1:-1;;;;;82848:29:0;;82886:4;82848:44;:29;:44;:::i;:::-;82821:71;;82917:18;:10;-1:-1:-1;;;;;82917:16:0;;:18::i;:::-;82913:283;;;35213:42;-1:-1:-1;;;;;82960:9:0;;82976:16;82960:35;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;82960:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;82960:35:0;;;;;82913:283;;;83044:54;83069:10;83089:7;83044:24;:54::i;:::-;83144:7;-1:-1:-1;;;;;83121:37:0;;83159:16;83121:55;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;83121:55:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;83121:55:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;82564:672:0;81927:1320;;83266:136;83292:9;83316:7;83338:6;83359:12;83386:5;83266:11;:136::i;22503:619::-;22563:4;23031:20;;22874:66;23071:23;;;;;;:42;;-1:-1:-1;23098:15:0;;;23071:42;23063:51;22503:619;-1:-1:-1;;;;22503:619:0:o;77540:1409::-;77613:6;-1:-1:-1;;;;;77636:59:0;;77652:42;77636:59;77632:115;;;-1:-1:-1;77733:1:0;77719:16;;77632:115;-1:-1:-1;;;;;77761:59:0;;77777:42;77761:59;77757:156;;;-1:-1:-1;;;;;;;;;;;;77844:57:0;;77757:156;-1:-1:-1;;;;;77927:59:0;;77943:42;77927:59;77923:156;;;-1:-1:-1;78024:42:0;78010:57;;77923:156;-1:-1:-1;;;;;78093:59:0;;78109:42;78093:59;78089:156;;;-1:-1:-1;78190:42:0;78176:57;;78089:156;-1:-1:-1;;;;;78259:59:0;;78275:42;78259:59;78255:157;;;-1:-1:-1;78357:42:0;78343:57;;78255:157;-1:-1:-1;;;;;78426:59:0;;78442:42;78426:59;78422:157;;;-1:-1:-1;78524:42:0;78510:57;;78422:157;-1:-1:-1;;;;;78593:59:0;;78609:42;78593:59;78589:156;;;-1:-1:-1;78690:42:0;78676:57;;78589:156;-1:-1:-1;;;;;78759:59:0;;78775:42;78759:59;78755:157;;;-1:-1:-1;78857:42:0;78843:57;;78755:157;-1:-1:-1;;;77540:1409:0;;;:::o;89425:328::-;89608:137;89635:9;89659:7;89681:6;89702:12;89729:5;89967:7;-1:-1:-1;;;;;89954:20:0;:9;-1:-1:-1;;;;;89954:20:0;;89950:59;;;89991:7;;89950:59;90026:33;:5;3923:4;90026:33;:11;:33;:::i;:::-;90021:1554;;90076:17;90096:26;90112:9;90096:15;:26::i;:::-;90076:46;-1:-1:-1;;;;;;90141:24:0;;;;90137:624;;90190:18;:10;-1:-1:-1;;;;;90190:16:0;;:18::i;:::-;90186:245;;;90233:68;;;-1:-1:-1;;;90233:68:0;;90287:4;90233:68;;;;;;;;;;;;-1:-1:-1;;;;;90233:45:0;;;;;:68;;;;;;;;;;;;;;-1:-1:-1;90233:45:0;:68;;;5:2:-1;;;;30:1;27;20:12;5:2;90233:68:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;90233:68:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;90186:245:0;;-1:-1:-1;90186:245:0;;90350:61;;;-1:-1:-1;;;90350:61:0;;90397:4;90350:61;;;;;;;;;;;;-1:-1:-1;;;;;90350:38:0;;;;;:61;;;;;;;;;;;;;;-1:-1:-1;90350:38:0;:61;;;5:2:-1;;;;30:1;27;20:12;5:2;90350:61:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;90350:61:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;90186:245:0;90451:24;90478:44;-1:-1:-1;;;;;90478:29:0;;90516:4;90478:44;:29;:44;:::i;:::-;90451:71;;90550:195;90584:10;90617:7;90647:16;90686:12;90721:5;90550:11;:195::i;90137:624::-;90790:24;90806:7;90790:15;:24::i;:::-;90777:37;-1:-1:-1;;;;;;90833:24:0;;;;90829:735;;90878:187;90912:9;90944:10;90977:6;91006:12;91041:5;90878:11;:187::i;:::-;91086:24;91113:44;-1:-1:-1;;;;;91113:29:0;;91151:4;91113:44;:29;:44;:::i;:::-;91086:71;;91182:18;:10;-1:-1:-1;;;;;91182:16:0;;:18::i;:::-;91178:346;;;91225:84;;;-1:-1:-1;;;91225:84:0;;91303:4;91225:84;;;;;;-1:-1:-1;;;;;91225:45:0;;;;;91277:16;;91225:84;;;;;;;;;;;;;;;91277:16;91225:45;:84;;;5:2:-1;;;;30:1;27;20:12;5:2;91225:84:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;91225:84:0;;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;91178:346:0;;-1:-1:-1;91178:346:0;;91358:54;91383:10;91403:7;91358:24;:54::i;:::-;91435:69;;;-1:-1:-1;;;91435:69:0;;91480:4;91435:69;;;;;;;;;;;;-1:-1:-1;;;;;91435:36:0;;;;;:69;;;;;;;;;;;;;;-1:-1:-1;91435:36:0;:69;;;5:2:-1;;;;30:1;27;20:12;90829:735:0;90021:1554;;91594:136;91620:9;91644:7;91666:6;91687:12;91714:5;112970:325;113153:134;113177:9;113201:7;113223:6;113244:12;113271:5;113303:1621;113506:7;-1:-1:-1;;;;;113493:20:0;:9;-1:-1:-1;;;;;113493:20:0;;113489:59;;;113530:7;;113489:59;113565:30;:5;4033:4;113565:30;:11;:30;:::i;:::-;113560:1201;;113612:17;113632:34;113656:9;113632:23;:34::i;:::-;113612:54;-1:-1:-1;;;;;;113685:24:0;;;;113681:321;;113749:9;-1:-1:-1;;;;;113730:37:0;;113768:6;113730:45;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;113730:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;113730:45:0;;;;113803:183;113835:10;113868:7;113898:6;113927:12;113962:5;113803:9;:183::i;:::-;113796:190;;;113681:321;114031:32;114055:7;114031:23;:32::i;:::-;114018:45;-1:-1:-1;;;;;;114082:24:0;;;;114078:672;;114127:187;114161:9;114193:10;114226:6;114255:12;114290:5;114127:11;:187::i;:::-;114335:24;114362:44;-1:-1:-1;;;;;114362:29:0;;114400:4;114362:44;:29;:44;:::i;:::-;114335:71;;114427:49;114452:10;35013:42;-1:-1:-1;;;;;114464:9:0;;:11;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;114464:11:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;114464:11:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;114464:11:0;114427:24;:49::i;:::-;35013:42;114495:12;114514:18;-1:-1:-1;;;;;114514:16:0;;;:18::i;:::-;:41;;114554:1;114514:41;;;114535:16;114514:41;114579:18;:10;-1:-1:-1;;;;;114579:16:0;;:18::i;:::-;:45;;114614:10;114579:45;;;32754:42;114579:45;114495:214;;;-1:-1:-1;;;;;;114495:214:0;;;;;;;-1:-1:-1;;;;;114495:214:0;;;;;;;;;;;;;114686:4;114495:214;;;;;;;;;;-1:-1:-1;;114495:214:0;;;;;;;;;;;;5:2:-1;;;;30:1;27;20:12;114078:672:0;113560:1201;;114780:136;114806:9;114830:7;114852:6;114873:12;114900:5;114780:11;:136::i;108117:2905::-;108186:6;-1:-1:-1;;;;;108209:59:0;;108225:42;108209:59;108205:115;;;-1:-1:-1;108306:1:0;108292:16;;108205:115;-1:-1:-1;;;;;108334:59:0;;108350:42;108334:59;108330:156;;;-1:-1:-1;;;;;;;;;;;;108417:57:0;;108330:156;-1:-1:-1;;;;;108500:59:0;;108516:42;108500:59;108496:157;;;-1:-1:-1;108598:42:0;108584:57;;108496:157;-1:-1:-1;;;;;108667:59:0;;108683:42;108667:59;108663:157;;;-1:-1:-1;108765:42:0;108751:57;;108663:157;-1:-1:-1;;;;;108834:59:0;;108850:42;108834:59;108830:157;;;-1:-1:-1;108932:42:0;108918:57;;108830:157;-1:-1:-1;;;;;109001:59:0;;109017:42;109001:59;108997:157;;;-1:-1:-1;109099:42:0;109085:57;;108997:157;-1:-1:-1;;;;;109168:59:0;;109184:42;109168:59;109164:157;;;-1:-1:-1;109266:42:0;109252:57;;109164:157;-1:-1:-1;;;;;109335:59:0;;109351:42;109335:59;109331:156;;;-1:-1:-1;109432:42:0;109418:57;;109331:156;-1:-1:-1;;;;;109501:59:0;;109517:42;109501:59;109497:156;;;-1:-1:-1;109598:42:0;109584:57;;109497:156;-1:-1:-1;;;;;109667:59:0;;109683:42;109667:59;109663:157;;;-1:-1:-1;109765:42:0;109751:57;;109663:157;-1:-1:-1;;;;;109834:59:0;;109850:42;109834:59;109830:157;;;-1:-1:-1;109932:42:0;109918:57;;109830:157;-1:-1:-1;;;;;110001:59:0;;110017:42;110001:59;109997:157;;;-1:-1:-1;110099:42:0;110085:57;;109997:157;-1:-1:-1;;;;;110168:59:0;;110184:42;110168:59;110164:156;;;-1:-1:-1;110265:42:0;110251:57;;110164:156;-1:-1:-1;;;;;110334:59:0;;110350:42;110334:59;110330:156;;;-1:-1:-1;110431:42:0;110417:57;;110330:156;-1:-1:-1;;;;;110500:59:0;;110516:42;110500:59;110496:156;;;-1:-1:-1;110597:42:0;110583:57;;110496:156;-1:-1:-1;;;;;110666:59:0;;110682:42;110666:59;110662:157;;;-1:-1:-1;110764:42:0;110750:57;;110662:157;-1:-1:-1;;;;;110833:59:0;;110849:42;110833:59;110829:156;;;-1:-1:-1;110930:42:0;110916:57;;96196:1595;96396:7;-1:-1:-1;;;;;96383:20:0;:9;-1:-1:-1;;;;;96383:20:0;;96379:59;;;96420:7;;96379:59;96455:30;:5;4241;96455:30;:11;:30;:::i;:::-;96450:1254;;96526:4;;-1:-1:-1;;;;;96506:25:0;;;96526:4;;96506:25;96502:907;;;96552:4;;;:17;;;-1:-1:-1;;;96552:17:0;;;;;;;;;;-1:-1:-1;;;;;96552:4:0;;;;:9;;:17;;;;;;;;;;:4;;:17;;;5:2:-1;;;;30:1;27;20:12;5:2;96552:17:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;96611:3:0;;:28;;;-1:-1:-1;;;96611:28:0;;96633:4;96611:28;;;;;;96590:18;;-1:-1:-1;;;;;;96611:3:0;;;;-1:-1:-1;96611:13:0;;:28;;;;;;;;;;;;;;:3;:28;;;5:2:-1;;;;30:1;27;20:12;5:2;96611:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;96611:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;96611:28:0;;-1:-1:-1;96662:14:0;;96658:530;;96783:3;;;96703:32;;96739:201;;-1:-1:-1;;;;;96783:3:0;;96813:7;;96847:10;;96912:5;96739:17;:201::i;:::-;96997:3;;96701:239;;-1:-1:-1;96965:203:0;;-1:-1:-1;;;;;;96997:3:0;97027:7;97061:10;96701:239;97140:5;96965;:203::i;:::-;96658:530;;97215:178;-1:-1:-1;;;;;;;;;;;97275:7:0;97305:6;97334:12;97369:5;97215:11;:178::i;96502:907::-;97447:4;;-1:-1:-1;;;;;97429:23:0;;;97447:4;;97429:23;97425:268;;;97473:56;97485:9;-1:-1:-1;;;;;;;;;;;97501:6:0;97509:12;97523:5;97473:11;:56::i;:::-;97588:4;;97550:44;;-1:-1:-1;;;;;;;;;;;32842:42:0;-1:-1:-1;;;;;97588:4:0;97550:24;:44::i;:::-;97613:4;;97623:28;;;-1:-1:-1;;;97623:28:0;;97645:4;97623:28;;;;;;-1:-1:-1;;;;;97613:4:0;;;;:9;;-1:-1:-1;;;;;;;;;;;32842:42:0;97623:13;;:28;;;;;;;;;;;;;;;32842:42;97623:28;;;5:2:-1;;;;30:1;27;20:12;5:2;97623:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;97623:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;97623:28:0;97613:39;;;-1:-1:-1;;;;;;97613:39:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;97613:39:0;;;;;;;-1:-1:-1;97613:39:0;;;;5:2:-1;;;;30:1;27;20:12;5:2;97613:39:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;97425:268:0;97723:60;97735:9;97746:7;97755:6;97763:12;97777:5;93221:1229;93421:7;-1:-1:-1;;;;;93408:20:0;:9;-1:-1:-1;;;;;93408:20:0;;93404:59;;;93445:7;;93404:59;93480:30;:5;3978:4;93480:30;:11;:30;:::i;:::-;93475:812;;-1:-1:-1;;;;;93531:25:0;;33659:42;93531:25;93527:326;;;93577:32;;;-1:-1:-1;;;93577:32:0;;93595:4;93577:32;;;;;;;;;;;;33659:42;;93577:9;;:32;;;;;-1:-1:-1;;93577:32:0;;;;;;;-1:-1:-1;33659:42:0;93577:32;;;5:2:-1;;;;30:1;27;20:12;5:2;93577:32:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;93727:28:0;;;-1:-1:-1;;;93727:28:0;;93749:4;93727:28;;;;;;93637:200;;-1:-1:-1;;;;;;;;;;;;32842:42:0;-1:-1:-1;93697:7:0;;32842:42;;93727:13;;:28;;;;;;;;;;;;;;;32842:42;93727:28;;;5:2:-1;;;;30:1;27;20:12;5:2;93727:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;93727:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;93727:28:0;93778:12;93813:5;93637:11;:200::i;93527:326::-;-1:-1:-1;;;;;93873:23:0;;33659:42;93873:23;93869:407;;;93917:180;93951:9;-1:-1:-1;;;;;;;;;;;94009:6:0;94038:12;94073:5;93917:11;:180::i;:::-;94118:44;-1:-1:-1;;;;;;;;;;;33659:42:0;94118:24;:44::i;:::-;94206:28;;;-1:-1:-1;;;94206:28:0;;94199:4;94206:28;;;;;;;;33659:42;;94181:9;;94199:4;;-1:-1:-1;;;;;;;;;;;32842:42:0;94206:13;;:28;;;;;;;;;;;;;;32842:42;94206:28;;;5:2:-1;;;;30:1;27;20:12;5:2;94206:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;94206:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;94206:28:0;94181:54;;;-1:-1:-1;;;;;;94181:54:0;;;;;;;-1:-1:-1;;;;;94181:54:0;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;94181:54:0;;;;;;;-1:-1:-1;94181:54:0;;;;5:2:-1;;;;30:1;27;20:12;93869:407:0;94306:136;94332:9;94356:7;94378:6;94399:12;94426:5;74638:2782;74826:17;:9;-1:-1:-1;;;;;74826:15:0;;:17::i;:::-;74825:18;:38;;;;;74848:15;:7;-1:-1:-1;;;;;74848:13:0;;:15::i;:::-;74847:16;74825:38;:81;;;;-1:-1:-1;74867:39:0;:5;4160;74867:39;:11;:39;:::i;:::-;74821:813;;;74923:21;74961:12;:19;74947:34;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;74947:34:0;-1:-1:-1;74923:58:0;-1:-1:-1;75001:6:0;74996:114;75017:12;:19;75013:1;:23;74996:114;;;75072:12;75085:1;75072:15;;;;;;;;;;;;;;75090:4;75072:22;75062:4;75067:1;75062:7;;;;;;;;;;;;;;;;;:32;75038:3;;74996:114;;;;75124:156;75154:9;32754:42;75212:6;75237:4;75260:5;75124:11;:156::i;:::-;75302:6;75297:121;75318:12;:19;75314:1;:23;75297:121;;;75393:1;75374:12;75387:1;75374:15;;;;;;;;;;;;;;:20;;75398:4;75373:29;75363:4;75368:1;75363:7;;;;;;;;;;;;;;;;;:39;75339:3;;75297:121;;;;75432:169;32754:42;75492:7;75518:21;75558:4;75581:5;75432:11;:169::i;74821:813::-;-1:-1:-1;;;;;75650:16:0;;-1:-1:-1;;;;;;;;;;;75650:16:0;;;;:34;;-1:-1:-1;;;;;;75670:14:0;;-1:-1:-1;;;;;;;;;;;75670:14:0;;75650:34;:77;;;;-1:-1:-1;75688:39:0;:5;4619:7;75688:39;:11;:39;:::i;:::-;75646:800;;;75744:21;75782:12;:19;75768:34;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;75768:34:0;-1:-1:-1;75744:58:0;-1:-1:-1;75822:6:0;75817:114;75838:12;:19;75834:1;:23;75817:114;;;75893:12;75906:1;75893:15;;;;;;;;;;;;;;75911:4;75893:22;75883:4;75888:1;75883:7;;;;;;;;;;;;;;;;;:32;75859:3;;75817:114;;;;75945:148;75975:9;-1:-1:-1;;;;;;;;;;;76025:6:0;76050:4;76073:5;75945:11;:148::i;:::-;76115:6;76110:121;76131:12;:19;76127:1;:23;76110:121;;;76206:1;76187:12;76200:1;76187:15;;;;;;;;;;;;;;:20;;76211:4;76186:29;76176:4;76181:1;76176:7;;;;;;;;;;;;;;;;;:39;76152:3;;76110:121;;;-1:-1:-1;76323:28:0;;;-1:-1:-1;;;76323:28:0;;76345:4;76323:28;;;;;;76245:168;;-1:-1:-1;;;;;;;;;;;32842:42:0;76297:7;;32842:42;;76323:13;;:28;;;;;;;;;;;;;;;32842:42;76323:28;;;5:2:-1;;;;30:1;27;20:12;5:2;76323:28:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;76323:28:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;76323:28:0;76370:4;76393:5;76245:11;:168::i;75646:800::-;-1:-1:-1;;;;;76462:17:0;;33015:42;76462:17;;;;:36;;-1:-1:-1;;;;;;76483:15:0;;33015:42;76483:15;;76462:36;:80;;;;-1:-1:-1;76502:40:0;:5;4712:7;76502:40;:11;:40;:::i;:::-;76458:806;;;76559:21;76597:12;:19;76583:34;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;76583:34:0;-1:-1:-1;76559:58:0;-1:-1:-1;76637:6:0;76632:114;76653:12;:19;76649:1;:23;76632:114;;;76708:12;76721:1;76708:15;;;;;;;;;;;;;;76726:4;76708:22;76698:4;76703:1;76698:7;;;;;;;;;;;;;;;;;:32;76674:3;;76632:114;;;;76760:149;76790:9;33015:42;76841:6;76866:4;76889:5;76760:11;:149::i;:::-;76931:6;76926:121;76947:12;:19;76943:1;:23;76926:121;;;77022:1;77003:12;77016:1;77003:15;;;;;;;;;;;;;;:20;;77027:4;77002:29;76992:4;76997:1;76992:7;;;;;;;;;;;;;;;;;:39;76968:3;;76926:121;;;-1:-1:-1;77140:29:0;;;-1:-1:-1;;;77140:29:0;;77163:4;77140:29;;;;;;77061:170;;33015:42;;77114:7;;33015:42;;77140:14;;:29;;;;;;;;;;;;;;;33015:42;77140:29;;;5:2:-1;;;;30:1;27;20:12;76458:806:0;77276:136;77302:9;77326:7;77348:6;77369:12;77396:5;59464:431;59698:7;-1:-1:-1;;;;;59685:20:0;:9;-1:-1:-1;;;;;59685:20:0;;59681:59;;;59722:7;;59681:59;59752:135;59777:9;59801:7;59823:6;59844:12;59871:5;122848:8;;122885:228;;-1:-1:-1;;;;;122885:228:0;;;;;;;;;;;;;;;;;;;;;;122805:12;122885:228;;;;;;;;;;;;;;;;;;;;;;;;;;;122805:12;;122819:17;;122848:8;;;-1:-1:-1;;;122926:18:0;122963:9;;122991:7;;123017:6;;122805:12;;123062;;123093:5;;122885:228;;;;;;;;;;;;;;122805:12;8:100:-1;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;122885:228:0;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;122885:228:0;;;;-1:-1:-1;;;;;122885:228:0;;38:4:-1;29:7;25:18;67:10;61:17;-1:-1;;;;;199:8;192:4;186;182:15;179:29;167:10;160:49;0:215;;;122885:228:0;122840:284;;;;;;;;;;;;;36:153:-1;66:2;61:3;58:11;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;122840:284:0;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;122804:320:0;;;;123168:7;123251:1;123246:48;;;;123161:133;;123246:48;123277:14;123272:2;123266:4;123262:13;123255:37;120532:2783;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;120532:2783:0;;;-1:-1:-1;;120532:2783:0:o;:::-;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;-1:-1;120532:2783:0;;;-1:-1:-1;;120532:2783:0:o
Swarm Source
bzzr://ed82bada9bab10e79931a19e6fa1964fdc8a989ef7bcfa86ce0538e0da99af6b
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
BSC | 100.00% | $3 | 1 | $3 |
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.