Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Loading...
Loading
Contract Name:
SwitchView
Compiler Version
v0.8.9+commit.e5eed63a
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "../core/SwitchRoot.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; contract SwitchView is SwitchRoot { using UniversalERC20 for IERC20; using UniswapExchangeLib for IUniswapExchange; function(CalculateArgs memory args) view returns(uint256[] memory)[] pathFunctions; constructor( address _weth, address _otherToken, uint256 _pathCount, uint256 _pathSplit, address[] memory _factories ) SwitchRoot(_weth, _otherToken, _pathCount, _pathSplit, _factories) public { if (_pathCount == 2) { pathFunctions.push(calculate); pathFunctions.push(calculateETH); } else if (_pathCount == 3) { pathFunctions.push(calculate); pathFunctions.push(calculateETH); pathFunctions.push(calculateOtherToken); } else { revert("path count needs to be either 2 or 3"); } } // function(CalculateArgs memory args) view returns(uint256[] memory)[PATHS_COUNT] pathFunctions = [ // calculate, // calculateETH, // calculateRealETH // ]; function getExpectedReturn( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 parts ) public override view returns ( uint256 returnAmount, uint256[] memory distribution ) { (returnAmount, distribution) = _getExpectedReturn( ReturnArgs({ fromToken: fromToken, destToken: destToken, amount: amount, parts: parts }) ); } function _getExpectedReturn( ReturnArgs memory returnArgs ) internal view returns ( uint256 returnAmount, uint256[] memory mergedDistribution ) { uint256[] memory distribution = new uint256[](dexCount*pathCount*pathSplit); mergedDistribution = new uint256[](dexCount*pathCount); if (returnArgs.fromToken == returnArgs.destToken) { return (returnArgs.amount, distribution); } int256[][] memory matrix = new int256[][](dexCount*pathCount*pathSplit); bool atLeastOnePositive = false; for (uint l = 0; l < dexCount; l++) { uint256[] memory rets; for (uint m = 0; m < pathCount; m++) { rets = pathFunctions[m](CalculateArgs({ fromToken:returnArgs.fromToken, destToken:returnArgs.destToken, factory:IUniswapFactory(factories[l]), amount:returnArgs.amount, parts:returnArgs.parts })); for (uint k = 0; k < pathSplit; k++) { uint256 i = l*pathCount*pathSplit+m*pathSplit+k; // Prepend zero matrix[i] = new int256[](returnArgs.parts + 1); for (uint j = 0; j < rets.length; j++) { matrix[i][j + 1] = int256(rets[j]); atLeastOnePositive = atLeastOnePositive || (matrix[i][j + 1] > 0); } } } } if (!atLeastOnePositive) { for (uint i = 0; i < dexCount*pathCount*pathSplit;) { for (uint j = 1; j < returnArgs.parts + 1; j++) { if (matrix[i][j] == 0) { matrix[i][j] = VERY_NEGATIVE_VALUE; } } unchecked { i++; } } } (, distribution) = _findBestDistribution(returnArgs.parts, matrix); returnAmount = _getReturnByDistribution(matrix, distribution); for (uint i = 0; i < dexCount*pathCount*pathSplit;) { mergedDistribution[i/pathSplit] += distribution[i]; unchecked { i++; } } return (returnAmount, mergedDistribution); } struct Args { IERC20 fromToken; IERC20 destToken; uint256 amount; uint256 parts; uint256[] distribution; int256[][] matrix; function(CalculateArgs memory) view returns(uint256[] memory) pathFunctions; IUniswapFactory[] dexes; } function _getReturnByDistribution(int256[][] memory matrix, uint256[] memory distribution) internal view returns(uint256 returnAmount) { for (uint i = 0; i < dexCount*pathCount*pathSplit;) { if (distribution[i] > 0) { int256 value = matrix[i][distribution[i]]; returnAmount += uint256( (value == VERY_NEGATIVE_VALUE ? int256(0) : value) ); } unchecked { i++; } } } // View Helpers struct Balances { uint256 src; uint256 dst; } function _calculateUniswapFormula( uint256 fromBalance, uint256 toBalance, uint256 amount ) internal pure returns (uint256) { if (amount == 0) { return 0; } return amount * toBalance * 997 / ( fromBalance * 1000 + amount *997 ); } function calculate(CalculateArgs memory args) public view returns(uint256[] memory rets) { return _calculate( args.fromToken, args.destToken, args.factory, _linearInterpolation(args.amount, args.parts) ); } function calculateETH(CalculateArgs memory args) internal view returns(uint256[] memory rets) { if (args.fromToken.isETH() || args.fromToken == weth || args.destToken.isETH() || args.destToken == weth) { return new uint256[](args.parts); } return _calculateOverMidToken( args.fromToken, weth, args.destToken, args.factory, args.amount, args.parts ); } function calculateOtherToken(CalculateArgs memory args) internal view returns(uint256[] memory rets) { if (args.fromToken == otherToken || args.destToken == otherToken) { return new uint256[](args.parts); } return _calculateOverMidToken( args.fromToken, otherToken, args.destToken, args.factory, args.amount, args.parts ); } function _calculate( IERC20 fromToken, IERC20 destToken, IUniswapFactory factory, uint256[] memory amounts ) internal view returns (uint256[] memory rets) { rets = new uint256[](amounts.length); IERC20 fromTokenReal = fromToken.isETH() ? weth : fromToken; IERC20 destTokenReal = destToken.isETH() ? weth : destToken; IUniswapExchange exchange = factory.getPair(fromTokenReal, destTokenReal); if (address(exchange) != address(0)) { uint256 fromTokenBalance = fromTokenReal.universalBalanceOf(address(exchange)); uint256 destTokenBalance = destTokenReal.universalBalanceOf(address(exchange)); for (uint i = 0; i < amounts.length; i++) { rets[i] = _calculateUniswapFormula(fromTokenBalance, destTokenBalance, amounts[i]); } return rets; } } function _calculateOverMidToken( IERC20 fromToken, IERC20 midToken, IERC20 destToken, IUniswapFactory factory, uint256 amount, uint256 parts ) internal view returns (uint256[] memory rets) { rets = _linearInterpolation(amount, parts); rets = _calculate(fromToken, midToken, factory, rets); rets = _calculate(midToken, destToken, factory, rets); return rets; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/draft-IERC20Permit.sol"; import "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { 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)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ 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' 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) + value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } function safeDecreaseAllowance( IERC20 token, address spender, uint256 value ) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); uint256 newAllowance = oldAllowance - value; _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance)); } } function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed"); if (returndata.length > 0) { // Return data is optional require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "../interfaces/IUniswapFactory.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; abstract contract ISwitchView { struct ReturnArgs { IERC20 fromToken; IERC20 destToken; uint256 amount; uint256 parts; } struct CalculateArgs { IERC20 fromToken; IERC20 destToken; IUniswapFactory factory; uint256 amount; uint256 parts; } function getExpectedReturn( IERC20 fromToken, IERC20 destToken, uint256 amount, uint256 parts ) public virtual view returns ( uint256 returnAmount, uint256[] memory distribution ); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; abstract contract IWETH is IERC20 { function deposit() external virtual payable; function withdraw(uint256 amount) virtual external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "./ISwitchView.sol"; import "./IWETH.sol"; import "../lib/DisableFlags.sol"; import "../lib/UniversalERC20.sol"; import "../interfaces/IUniswapFactory.sol"; import "../lib/UniswapExchangeLib.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; abstract contract SwitchRoot is Ownable, ISwitchView { using DisableFlags for uint256; using UniversalERC20 for IERC20; using UniversalERC20 for IWETH; using UniswapExchangeLib for IUniswapExchange; address public ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); address public ZERO_ADDRESS = address(0); uint256 public dexCount; uint256 public pathCount; uint256 public pathSplit; IWETH public weth; // chain's native token IWETH public otherToken; //could be weth on a non-eth chain or other mid token(like busd) address[] public factories; int256 internal constant VERY_NEGATIVE_VALUE = -1e72; constructor(address _weth, address _otherToken, uint256 _pathCount, uint256 _pathSplit, address[] memory _factories) { weth = IWETH(_weth); otherToken = IWETH(_otherToken); pathCount = _pathCount; pathSplit = _pathSplit; dexCount = _factories.length; for (uint256 i = 0; i < _factories.length; i++) { factories.push(_factories[i]); } } event WETHSet(address _weth); event OtherTokenSet(address _otherToken); event PathCountSet(uint256 _pathCount); event PathSplitSet(uint256 _pathSplit); event FactoriesSet(address[] _factories); function setWETH(address _weth) external onlyOwner { weth = IWETH(_weth); emit WETHSet(_weth); } function setOtherToken(address _otherToken) external onlyOwner { otherToken = IWETH(_otherToken); emit OtherTokenSet(_otherToken); } function setPathCount(uint256 _pathCount) external onlyOwner { pathCount = _pathCount; emit PathCountSet(_pathCount); } function setPathSplit(uint256 _pathSplit) external onlyOwner { pathSplit = _pathSplit; emit PathSplitSet(_pathSplit); } function setFactories(address[] memory _factories) external onlyOwner { dexCount = _factories.length; for (uint256 i = 0; i < _factories.length; i++) { factories.push(_factories[i]); } emit FactoriesSet(_factories); } function _findBestDistribution( uint256 s, // parts int256[][] memory amounts // exchangesReturns ) internal view returns ( int256 returnAmount, uint256[] memory distribution ) { uint256 n = amounts.length; int256[][] memory answer = new int256[][](n); // int[n][s+1] uint256[][] memory parent = new uint256[][](n); // int[n][s+1] for (uint i = 0; i < n; i++) { answer[i] = new int256[](s + 1); parent[i] = new uint256[](s + 1); } for (uint j = 0; j <= s; j++) { answer[0][j] = amounts[0][j]; for (uint i = 1; i < n; i++) { answer[i][j] = -1e72; } parent[0][j] = 0; } for (uint i = 1; i < n; i++) { for (uint j = 0; j <= s; j++) { answer[i][j] = answer[i - 1][j]; parent[i][j] = j; for (uint k = 1; k <= j; k++) { if (answer[i - 1][j - k] + amounts[i][k] > answer[i][j]) { answer[i][j] = answer[i - 1][j - k] + amounts[i][k]; parent[i][j] = j - k; } } } } distribution = new uint256[](dexCount*pathCount*pathSplit); uint256 partsLeft = s; unchecked { for (uint curExchange = n - 1; partsLeft > 0; curExchange--) { distribution[curExchange] = partsLeft - parent[curExchange][partsLeft]; partsLeft = parent[curExchange][partsLeft]; } } returnAmount = (answer[n - 1][s] == VERY_NEGATIVE_VALUE) ? int256(0) : answer[n - 1][s]; } function _linearInterpolation( uint256 value, uint256 parts ) internal pure returns (uint256[] memory rets) { rets = new uint256[](parts); for (uint i = 0; i < parts; i++) { rets[i] = value * (i + 1) / parts; } } function _tokensEqual( IERC20 tokenA, IERC20 tokenB ) internal pure returns (bool) { return ((tokenA.isETH() && tokenB.isETH()) || tokenA == tokenB); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; interface IUniswapExchange { function getReserves() external view returns(uint112 _reserve0, uint112 _reserve1, uint32 _blockTimestampLast); function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data) external; function skim(address to) external; function sync() external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "./IUniswapExchange.sol"; interface IUniswapFactory { function getPair(IERC20 tokenA, IERC20 tokenB) external view returns (IUniswapExchange pair); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; library DisableFlags { function check( uint256 flags, uint256 flag ) internal pure returns (bool) { return (flags & flag) != 0; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; library Math { /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a >= b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow, so we distribute return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "../interfaces/IUniswapExchange.sol"; import "./Math.sol"; import "./UniversalERC20.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; library UniswapExchangeLib { using Math for uint256; using UniversalERC20 for IERC20; function getReturn( IUniswapExchange exchange, IERC20 fromToken, IERC20 destToken, uint amountIn ) internal view returns (uint256 result, bool needSync, bool needSkim) { uint256 reserveIn = fromToken.universalBalanceOf(address(exchange)); uint256 reserveOut = destToken.universalBalanceOf(address(exchange)); (uint112 reserve0, uint112 reserve1,) = exchange.getReserves(); if (fromToken > destToken) { (reserve0, reserve1) = (reserve1, reserve0); } needSync = (reserveIn < reserve0 || reserveOut < reserve1); needSkim = !needSync && (reserveIn > reserve0 || reserveOut > reserve1); uint256 amountInWithFee = amountIn * 997; uint256 numerator = amountInWithFee * Math.min(reserveOut, reserve1); uint256 denominator = Math.min(reserveIn, reserve0) * 1000 + amountInWithFee; result = (denominator == 0) ? 0 : numerator / denominator; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.9; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; library UniversalERC20 { using SafeERC20 for IERC20; address private constant ZERO_ADDRESS = address(0x0000000000000000000000000000000000000000); address private constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE); function universalTransfer( IERC20 token, address to, uint256 amount ) internal returns (bool) { if (amount == 0) { return true; } if (isETH(token)) { payable(to).transfer(amount); return true; } 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)) { payable(to).transfer(amount); } // commented following lines for passing celer fee properly. // if (msg.value > amount) { // payable(msg.sender).transfer(msg.value - 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 payable(msg.sender).transfer(msg.value - 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.safeApprove(to, 0); return; } uint256 approvedAmount = token.allowance(address(this), to); if (approvedAmount > 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 isETH(IERC20 token) internal pure returns(bool) { return (address(token) == address(ZERO_ADDRESS) || address(token) == address(ETH_ADDRESS)); } // function notExist(IERC20 token) internal pure returns(bool) { // return (address(token) == address(-1)); // } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"_weth","type":"address"},{"internalType":"address","name":"_otherToken","type":"address"},{"internalType":"uint256","name":"_pathCount","type":"uint256"},{"internalType":"uint256","name":"_pathSplit","type":"uint256"},{"internalType":"address[]","name":"_factories","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_factories","type":"address[]"}],"name":"FactoriesSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_otherToken","type":"address"}],"name":"OtherTokenSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_pathCount","type":"uint256"}],"name":"PathCountSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_pathSplit","type":"uint256"}],"name":"PathSplitSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"_weth","type":"address"}],"name":"WETHSet","type":"event"},{"inputs":[],"name":"ETH_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZERO_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"contract IUniswapFactory","name":"factory","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"}],"internalType":"struct ISwitchView.CalculateArgs","name":"args","type":"tuple"}],"name":"calculate","outputs":[{"internalType":"uint256[]","name":"rets","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dexCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"factories","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"fromToken","type":"address"},{"internalType":"contract IERC20","name":"destToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"parts","type":"uint256"}],"name":"getExpectedReturn","outputs":[{"internalType":"uint256","name":"returnAmount","type":"uint256"},{"internalType":"uint256[]","name":"distribution","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"otherToken","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pathCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pathSplit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_factories","type":"address[]"}],"name":"setFactories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_otherToken","type":"address"}],"name":"setOtherToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pathCount","type":"uint256"}],"name":"setPathCount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_pathSplit","type":"uint256"}],"name":"setPathSplit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_weth","type":"address"}],"name":"setWETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IWETH","name":"","type":"address"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052600180546001600160a01b031990811673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee179091556002805490911690553480156200004357600080fd5b5060405162002966380380620029668339810160408190526200006691620009d7565b848484848462000076336200030f565b600680546001600160a01b038088166001600160a01b031992831617909255600780549287169290911691909117905560048390556005829055805160035560005b815181101562000129576008828281518110620000d957620000d962000aec565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b0390921691909117905580620001208162000b18565b915050620000b8565b5050505050508260021415620001d45760098054600180820183556000839052600080516020620029468339815191526004808404820180546003958616600890810261010090810a6001600160401b03818102199094166200035f602090811b620004ef1786169290920217909455885496870190985592850490930180549490951690910290940a808202199092166200039a90941b6200059e17160291909117905562000304565b8260031415620002ac5760098054600180820183556000839052600080516020620029468339815191526004808404820180546003958616600890810261010090810a6001600160401b03818102199094166200035f602090811b620004ef178616929092021790945588548088018a5585810487018054918a168402830a808602199092166200039a871b6200059e17861692909202919091179055885496870190985592850490930180549490951690910290940a80820219909216620004aa90941b6200068a17160291909117905562000304565b60405162461bcd60e51b8152602060048201526024808201527f7061746820636f756e74206e6565647320746f206265206569746865722032206044820152636f72203360e01b606482015260840160405180910390fd5b505050505062000bd0565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060620003948260000151836020015184604001516200038e866060015187608001516200053560201b60201c565b620005e6565b92915050565b6060620003bf82600001516001600160a01b03166200081b60201b6200070e1760201c565b80620003da575060065482516001600160a01b039081169116145b806200040457506200040482602001516001600160a01b03166200081b60201b6200070e1760201c565b8062000422575060065460208301516001600160a01b039081169116145b15620004785781608001516001600160401b03811115620004475762000447620009c1565b60405190808252806020026020018201604052801562000471578160200160208202803683370190505b5092915050565b815160065460208401516040850151606086015160808701516200039495946001600160a01b03169392919062000855565b60075481516060916001600160a01b0391821691161480620004de575060075460208301516001600160a01b039081169116145b15620005035781608001516001600160401b03811115620004475762000447620009c1565b815160075460208401516040850151606086015160808701516200039495946001600160a01b03169392919062000855565b6060816001600160401b03811115620005525762000552620009c1565b6040519080825280602002602001820160405280156200057c578160200160208202803683370190505b50905060005b828110156200047157826200059982600162000b36565b620005a5908662000b51565b620005b1919062000b73565b828281518110620005c657620005c662000aec565b602090810291909101015280620005dd8162000b18565b91505062000582565b606081516001600160401b03811115620006045762000604620009c1565b6040519080825280602002602001820160405280156200062e578160200160208202803683370190505b509050600062000652866001600160a01b03166200081b60201b6200070e1760201c565b6200065e57856200066b565b6006546001600160a01b03165b905060006200068e866001600160a01b03166200081b60201b6200070e1760201c565b6200069a5785620006a7565b6006546001600160a01b03165b60405163e6a4390560e01b81526001600160a01b038481166004830152808316602483015291925060009187169063e6a439059060440160206040518083038186803b158015620006f757600080fd5b505afa1580156200070c573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000732919062000b96565b90506001600160a01b038116156200080f5760006200076982856001600160a01b03166200088e60201b620007471790919060201c565b905060006200079083856001600160a01b03166200088e60201b620007471790919060201c565b905060005b87518110156200080357620007ce83838a8481518110620007ba57620007ba62000aec565b60200260200101516200093760201b60201c565b878281518110620007e357620007e362000aec565b602090810291909101015280620007fa8162000b18565b91505062000795565b50505050505062000813565b5050505b949350505050565b60006001600160a01b03821615806200039457506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b606062000863838362000535565b90506200087387878684620005e6565b90506200088386868684620005e6565b979650505050505050565b60006200089b836200081b565b15620008b357506001600160a01b0381163162000394565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a082319060240160206040518083038186803b158015620008f557600080fd5b505afa1580156200090a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000930919062000bb6565b9392505050565b600081620009485750600062000930565b62000956826103e562000b51565b62000964856103e862000b51565b62000970919062000b36565b6200097c848462000b51565b6200098a906103e562000b51565b62000813919062000b73565b6001600160a01b0381168114620009ac57600080fd5b50565b8051620009bc8162000996565b919050565b634e487b7160e01b600052604160045260246000fd5b600080600080600060a08688031215620009f057600080fd5b8551620009fd8162000996565b8095505060208087015162000a128162000996565b6040880151606089015160808a015192975090955093506001600160401b038082111562000a3f57600080fd5b818901915089601f83011262000a5457600080fd5b81518181111562000a695762000a69620009c1565b8060051b604051601f19603f8301168101818110858211171562000a915762000a91620009c1565b60405291825284820192508381018501918c83111562000ab057600080fd5b938501935b8285101562000ad95762000ac985620009af565b8452938501939285019262000ab5565b8096505050505050509295509295909350565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060001982141562000b2f5762000b2f62000b02565b5060010190565b6000821982111562000b4c5762000b4c62000b02565b500190565b600081600019048311821515161562000b6e5762000b6e62000b02565b500290565b60008262000b9157634e487b7160e01b600052601260045260246000fd5b500490565b60006020828403121562000ba957600080fd5b8151620009308162000996565b60006020828403121562000bc957600080fd5b5051919050565b611d668062000be06000396000f3fe608060405234801561001057600080fd5b50600436106101165760003560e01c80638da5cb5b116100a2578063ab30469511610071578063ab3046951461022c578063b4c76fe014610235578063ea15afc314610248578063eb1def7d1461025b578063f2fde38b1461027b57600080fd5b80638da5cb5b146101ec57806390f3f208146101fd578063a734f06e14610206578063a85f32981461021957600080fd5b80635b769f3c116100e95780635b769f3c146101865780636076a0b414610199578063672383c4146101ba578063715018a6146101cd5780638c821e90146101d557600080fd5b806323a9495e1461011b5780633fc8cef314610130578063433b3c0514610160578063538ba4f914610173575b600080fd5b61012e610129366004611909565b61028e565b005b600654610143906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600754610143906001600160a01b031681565b600254610143906001600160a01b031681565b61012e610194366004611937565b6102d2565b6101ac6101a7366004611954565b610328565b6040516101579291906119d5565b6101436101c8366004611909565b610374565b61012e61039e565b6101de60045481565b604051908152602001610157565b6000546001600160a01b0316610143565b6101de60055481565b600154610143906001600160a01b031681565b61012e610227366004611909565b6103b2565b6101de60035481565b61012e610243366004611937565b6103ef565b61012e610256366004611a34565b610445565b61026e610269366004611ae5565b6104ef565b6040516101579190611b6c565b61012e610289366004611937565b610520565b6102966107e8565b60058190556040518181527f11e8ee12d79dc7314b845f4e82465af5bd3d2214081526061af36de8364eaa2e906020015b60405180910390a150565b6102da6107e8565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f41408be49f75701fe4bb8484ce88d68f1d82e03cb4eb44263b6682ce2dbd32f0906020016102c7565b600060606103676040518060800160405280886001600160a01b03168152602001876001600160a01b0316815260200186815260200185815250610842565b9097909650945050505050565b6008818154811061038457600080fd5b6000918252602090912001546001600160a01b0316905081565b6103a66107e8565b6103b06000610dc1565b565b6103ba6107e8565b60048190556040518181527f70f24e12a9db25e0d80cbcde19ffef47d6a7c52c1089db4c71e53ce1856577fc906020016102c7565b6103f76107e8565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527f17780f3919f73af11f29e4157534858a06c91294d64b679fe4e49340122cd322906020016102c7565b61044d6107e8565b805160035560005b81518110156104bf57600882828151811061047257610472611b7f565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b03909216919091179055806104b781611bab565b915050610455565b507fbbc63a7f378af7e269ef19f3fe0d08f044c91ee72930c0d045a58be58580f3d3816040516102c79190611bc6565b606061051a82600001518360200151846040015161051586606001518760800151610e11565b610eb1565b92915050565b6105286107e8565b6001600160a01b0381166105925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61059b81610dc1565b50565b60606105b682600001516001600160a01b031661070e565b806105d0575060065482516001600160a01b039081169116145b806105ec57506105ec82602001516001600160a01b031661070e565b80610609575060065460208301516001600160a01b039081169116145b1561065a5781608001516001600160401b0381111561062a5761062a6119ee565b604051908082528060200260200182016040528015610653578160200160208202803683370190505b5092915050565b8151600654602084015160408501516060860151608087015161051a95946001600160a01b03169392919061108c565b60075481516060916001600160a01b03918216911614806106bd575060075460208301516001600160a01b039081169116145b156106de5781608001516001600160401b0381111561062a5761062a6119ee565b8151600754602084015160408501516060860151608087015161051a95946001600160a01b03169392919061108c565b60006001600160a01b038216158061051a57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b60006107528361070e565b1561076857506001600160a01b0381163161051a565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a082319060240160206040518083038186803b1580156107a957600080fd5b505afa1580156107bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e19190611c13565b9392505050565b6000546001600160a01b031633146103b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610589565b60006060600060055460045460035461085b9190611c2c565b6108659190611c2c565b6001600160401b0381111561087c5761087c6119ee565b6040519080825280602002602001820160405280156108a5578160200160208202803683370190505b5090506004546003546108b89190611c2c565b6001600160401b038111156108cf576108cf6119ee565b6040519080825280602002602001820160405280156108f8578160200160208202803683370190505b50915083602001516001600160a01b031684600001516001600160a01b031614156109295760409093015193915050565b600060055460045460035461093e9190611c2c565b6109489190611c2c565b6001600160401b0381111561095f5761095f6119ee565b60405190808252806020026020018201604052801561099257816020015b606081526020019060019003908161097d5790505b5090506000805b600354811015610c3557606060005b600454811015610c2057610a726040518060a001604052808b600001516001600160a01b031681526020018b602001516001600160a01b03168152602001600886815481106109f9576109f9611b7f565b600091825260209182902001546001600160a01b031682526040808e01519183019190915260608d01519101526009805484908110610a3a57610a3a611b7f565b90600052602060002090600491828204019190066008029054906101000a9004801561190102176001600160401b031663ffffffff16565b915060005b600554811015610c0d5760008160055484610a929190611c2c565b600554600454610aa29089611c2c565b610aac9190611c2c565b610ab69190611c4b565b610ac09190611c4b565b90508a606001516001610ad39190611c4b565b6001600160401b03811115610aea57610aea6119ee565b604051908082528060200260200182016040528015610b13578160200160208202803683370190505b50878281518110610b2657610b26611b7f565b602002602001018190525060005b8451811015610bf857848181518110610b4f57610b4f611b7f565b6020026020010151888381518110610b6957610b69611b7f565b6020026020010151826001610b7e9190611c4b565b81518110610b8e57610b8e611b7f565b6020026020010181815250508680610be457506000888381518110610bb557610bb5611b7f565b6020026020010151826001610bca9190611c4b565b81518110610bda57610bda611b7f565b6020026020010151135b965080610bf081611bab565b915050610b34565b50508080610c0590611bab565b915050610a77565b5080610c1881611bab565b9150506109a8565b50508080610c2d90611bab565b915050610999565b5080610d1b5760005b600554600454600354610c519190611c2c565b610c5b9190611c2c565b811015610d195760015b6060880151610c75906001611c4b565b811015610d1057838281518110610c8e57610c8e611b7f565b60200260200101518181518110610ca757610ca7611b7f565b602002602001015160001415610cfe57600080516020611d11833981519152848381518110610cd857610cd8611b7f565b60200260200101518281518110610cf157610cf1611b7f565b6020026020010181815250505b80610d0881611bab565b915050610c65565b50600101610c3e565b505b610d298660600151836110bf565b9350610d37905082846117e2565b945060005b600554600454600354610d4f9190611c2c565b610d599190611c2c565b811015610db857838181518110610d7257610d72611b7f565b60200260200101518560055483610d899190611c63565b81518110610d9957610d99611b7f565b60200260200101818151610dad9190611c4b565b905250600101610d3c565b50505050915091565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816001600160401b03811115610e2b57610e2b6119ee565b604051908082528060200260200182016040528015610e54578160200160208202803683370190505b50905060005b828110156106535782610e6e826001611c4b565b610e789086611c2c565b610e829190611c63565b828281518110610e9457610e94611b7f565b602090810291909101015280610ea981611bab565b915050610e5a565b606081516001600160401b03811115610ecc57610ecc6119ee565b604051908082528060200260200182016040528015610ef5578160200160208202803683370190505b5090506000610f0c866001600160a01b031661070e565b610f165785610f23565b6006546001600160a01b03165b90506000610f39866001600160a01b031661070e565b610f435785610f50565b6006546001600160a01b03165b60405163e6a4390560e01b81526001600160a01b038481166004830152808316602483015291925060009187169063e6a439059060440160206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd79190611c85565b90506001600160a01b03811615611080576000610ffd6001600160a01b03851683610747565b905060006110146001600160a01b03851684610747565b905060005b87518110156110755761104683838a848151811061103957611039611b7f565b60200260200101516118b0565b87828151811061105857611058611b7f565b60209081029190910101528061106d81611bab565b915050611019565b505050505050611084565b5050505b949350505050565b60606110988383610e11565b90506110a687878684610eb1565b90506110b486868684610eb1565b979650505050505050565b805160009060609082816001600160401b038111156110e0576110e06119ee565b60405190808252806020026020018201604052801561111357816020015b60608152602001906001900390816110fe5790505b5090506000826001600160401b03811115611130576111306119ee565b60405190808252806020026020018201604052801561116357816020015b606081526020019060019003908161114e5790505b50905060005b838110156112565761117c886001611c4b565b6001600160401b03811115611193576111936119ee565b6040519080825280602002602001820160405280156111bc578160200160208202803683370190505b508382815181106111cf576111cf611b7f565b60209081029190910101526111e5886001611c4b565b6001600160401b038111156111fc576111fc6119ee565b604051908082528060200260200182016040528015611225578160200160208202803683370190505b5082828151811061123857611238611b7f565b6020026020010181905250808061124e90611bab565b915050611169565b5060005b87811161137a578660008151811061127457611274611b7f565b6020026020010151818151811061128d5761128d611b7f565b6020026020010151836000815181106112a8576112a8611b7f565b602002602001015182815181106112c1576112c1611b7f565b602090810291909101015260015b8481101561132e57600080516020611d118339815191528482815181106112f8576112f8611b7f565b6020026020010151838151811061131157611311611b7f565b60209081029190910101528061132681611bab565b9150506112cf565b5060008260008151811061134457611344611b7f565b6020026020010151828151811061135d5761135d611b7f565b60209081029190910101528061137281611bab565b91505061125a565b5060015b8381101561163c5760005b888111611629578361139c600184611ca2565b815181106113ac576113ac611b7f565b602002602001015181815181106113c5576113c5611b7f565b60200260200101518483815181106113df576113df611b7f565b602002602001015182815181106113f8576113f8611b7f565b6020026020010181815250508083838151811061141757611417611b7f565b6020026020010151828151811061143057611430611b7f565b602090810291909101015260015b8181116116165784838151811061145757611457611b7f565b6020026020010151828151811061147057611470611b7f565b602002602001015189848151811061148a5761148a611b7f565b602002602001015182815181106114a3576114a3611b7f565b6020026020010151866001866114b99190611ca2565b815181106114c9576114c9611b7f565b602002602001015183856114dd9190611ca2565b815181106114ed576114ed611b7f565b60200260200101516114ff9190611cb9565b13156116045788838151811061151757611517611b7f565b6020026020010151818151811061153057611530611b7f565b6020026020010151856001856115469190611ca2565b8151811061155657611556611b7f565b6020026020010151828461156a9190611ca2565b8151811061157a5761157a611b7f565b602002602001015161158c9190611cb9565b85848151811061159e5761159e611b7f565b602002602001015183815181106115b7576115b7611b7f565b60209081029190910101526115cc8183611ca2565b8484815181106115de576115de611b7f565b602002602001015183815181106115f7576115f7611b7f565b6020026020010181815250505b8061160e81611bab565b91505061143e565b508061162181611bab565b915050611389565b508061163481611bab565b91505061137e565b506005546004546003546116509190611c2c565b61165a9190611c2c565b6001600160401b03811115611671576116716119ee565b60405190808252806020026020018201604052801561169a578160200160208202803683370190505b5093508660001984015b811561173e578281815181106116bc576116bc611b7f565b602002602001015182815181106116d5576116d5611b7f565b602002602001015182038682815181106116f1576116f1611b7f565b60200260200101818152505082818151811061170f5761170f611b7f565b6020026020010151828151811061172857611728611b7f565b60209081029190910101519150600019016116a4565b50600080516020611d118339815191528361175a600187611ca2565b8151811061176a5761176a611b7f565b6020026020010151898151811061178357611783611b7f565b6020026020010151146117d2578261179c600186611ca2565b815181106117ac576117ac611b7f565b602002602001015188815181106117c5576117c5611b7f565b60200260200101516117d5565b60005b9550505050509250929050565b6000805b6005546004546003546117f99190611c2c565b6118039190611c2c565b81101561065357600083828151811061181e5761181e611b7f565b602002602001015111156118a857600084828151811061184057611840611b7f565b602002602001015184838151811061185a5761185a611b7f565b60200260200101518151811061187257611872611b7f565b60200260200101519050600080516020611d118339815191528114611897578061189a565b60005b6118a49084611c4b565b9250505b6001016117e6565b6000816118bf575060006107e1565b6118cb826103e5611c2c565b6118d7856103e8611c2c565b6118e19190611c4b565b6118eb8484611c2c565b6118f7906103e5611c2c565b6110849190611c63565b6103b0611cfa565b60006020828403121561191b57600080fd5b5035919050565b6001600160a01b038116811461059b57600080fd5b60006020828403121561194957600080fd5b81356107e181611922565b6000806000806080858703121561196a57600080fd5b843561197581611922565b9350602085013561198581611922565b93969395505050506040820135916060013590565b600081518084526020808501945080840160005b838110156119ca578151875295820195908201906001016119ae565b509495945050505050565b828152604060208201526000611084604083018461199a565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611a2c57611a2c6119ee565b604052919050565b60006020808385031215611a4757600080fd5b82356001600160401b0380821115611a5e57600080fd5b818501915085601f830112611a7257600080fd5b813581811115611a8457611a846119ee565b8060051b9150611a95848301611a04565b8181529183018401918481019088841115611aaf57600080fd5b938501935b83851015611ad95784359250611ac983611922565b8282529385019390850190611ab4565b98975050505050505050565b600060a08284031215611af757600080fd5b60405160a081018181106001600160401b0382111715611b1957611b196119ee565b6040528235611b2781611922565b81526020830135611b3781611922565b60208201526040830135611b4a81611922565b6040820152606083810135908201526080928301359281019290925250919050565b6020815260006107e1602083018461199a565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415611bbf57611bbf611b95565b5060010190565b6020808252825182820181905260009190848201906040850190845b81811015611c075783516001600160a01b031683529284019291840191600101611be2565b50909695505050505050565b600060208284031215611c2557600080fd5b5051919050565b6000816000190483118215151615611c4657611c46611b95565b500290565b60008219821115611c5e57611c5e611b95565b500190565b600082611c8057634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215611c9757600080fd5b81516107e181611922565b600082821015611cb457611cb4611b95565b500390565b600080821280156001600160ff1b0384900385131615611cdb57611cdb611b95565b600160ff1b8390038412811615611cf457611cf4611b95565b50500190565b634e487b7160e01b600052605160045260246000fdfeffff6f1bf04115e2c5b54376aa16b901ce32309909cb1f000000000000000000a2646970667358221220eb24b5a8d9f9451f78667d38f0d74f12ec9aac924b1aab840c4c8d4cb81d2a6f64736f6c634300080900336e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f000000000000000000000000c0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac000000000000000000000000115934131916c8b277dd010ee02de363c09d037c
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106101165760003560e01c80638da5cb5b116100a2578063ab30469511610071578063ab3046951461022c578063b4c76fe014610235578063ea15afc314610248578063eb1def7d1461025b578063f2fde38b1461027b57600080fd5b80638da5cb5b146101ec57806390f3f208146101fd578063a734f06e14610206578063a85f32981461021957600080fd5b80635b769f3c116100e95780635b769f3c146101865780636076a0b414610199578063672383c4146101ba578063715018a6146101cd5780638c821e90146101d557600080fd5b806323a9495e1461011b5780633fc8cef314610130578063433b3c0514610160578063538ba4f914610173575b600080fd5b61012e610129366004611909565b61028e565b005b600654610143906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b600754610143906001600160a01b031681565b600254610143906001600160a01b031681565b61012e610194366004611937565b6102d2565b6101ac6101a7366004611954565b610328565b6040516101579291906119d5565b6101436101c8366004611909565b610374565b61012e61039e565b6101de60045481565b604051908152602001610157565b6000546001600160a01b0316610143565b6101de60055481565b600154610143906001600160a01b031681565b61012e610227366004611909565b6103b2565b6101de60035481565b61012e610243366004611937565b6103ef565b61012e610256366004611a34565b610445565b61026e610269366004611ae5565b6104ef565b6040516101579190611b6c565b61012e610289366004611937565b610520565b6102966107e8565b60058190556040518181527f11e8ee12d79dc7314b845f4e82465af5bd3d2214081526061af36de8364eaa2e906020015b60405180910390a150565b6102da6107e8565b600680546001600160a01b0319166001600160a01b0383169081179091556040519081527f41408be49f75701fe4bb8484ce88d68f1d82e03cb4eb44263b6682ce2dbd32f0906020016102c7565b600060606103676040518060800160405280886001600160a01b03168152602001876001600160a01b0316815260200186815260200185815250610842565b9097909650945050505050565b6008818154811061038457600080fd5b6000918252602090912001546001600160a01b0316905081565b6103a66107e8565b6103b06000610dc1565b565b6103ba6107e8565b60048190556040518181527f70f24e12a9db25e0d80cbcde19ffef47d6a7c52c1089db4c71e53ce1856577fc906020016102c7565b6103f76107e8565b600780546001600160a01b0319166001600160a01b0383169081179091556040519081527f17780f3919f73af11f29e4157534858a06c91294d64b679fe4e49340122cd322906020016102c7565b61044d6107e8565b805160035560005b81518110156104bf57600882828151811061047257610472611b7f565b60209081029190910181015182546001810184556000938452919092200180546001600160a01b0319166001600160a01b03909216919091179055806104b781611bab565b915050610455565b507fbbc63a7f378af7e269ef19f3fe0d08f044c91ee72930c0d045a58be58580f3d3816040516102c79190611bc6565b606061051a82600001518360200151846040015161051586606001518760800151610e11565b610eb1565b92915050565b6105286107e8565b6001600160a01b0381166105925760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b61059b81610dc1565b50565b60606105b682600001516001600160a01b031661070e565b806105d0575060065482516001600160a01b039081169116145b806105ec57506105ec82602001516001600160a01b031661070e565b80610609575060065460208301516001600160a01b039081169116145b1561065a5781608001516001600160401b0381111561062a5761062a6119ee565b604051908082528060200260200182016040528015610653578160200160208202803683370190505b5092915050565b8151600654602084015160408501516060860151608087015161051a95946001600160a01b03169392919061108c565b60075481516060916001600160a01b03918216911614806106bd575060075460208301516001600160a01b039081169116145b156106de5781608001516001600160401b0381111561062a5761062a6119ee565b8151600754602084015160408501516060860151608087015161051a95946001600160a01b03169392919061108c565b60006001600160a01b038216158061051a57506001600160a01b03821673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee1492915050565b60006107528361070e565b1561076857506001600160a01b0381163161051a565b6040516370a0823160e01b81526001600160a01b0383811660048301528416906370a082319060240160206040518083038186803b1580156107a957600080fd5b505afa1580156107bd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e19190611c13565b9392505050565b6000546001600160a01b031633146103b05760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610589565b60006060600060055460045460035461085b9190611c2c565b6108659190611c2c565b6001600160401b0381111561087c5761087c6119ee565b6040519080825280602002602001820160405280156108a5578160200160208202803683370190505b5090506004546003546108b89190611c2c565b6001600160401b038111156108cf576108cf6119ee565b6040519080825280602002602001820160405280156108f8578160200160208202803683370190505b50915083602001516001600160a01b031684600001516001600160a01b031614156109295760409093015193915050565b600060055460045460035461093e9190611c2c565b6109489190611c2c565b6001600160401b0381111561095f5761095f6119ee565b60405190808252806020026020018201604052801561099257816020015b606081526020019060019003908161097d5790505b5090506000805b600354811015610c3557606060005b600454811015610c2057610a726040518060a001604052808b600001516001600160a01b031681526020018b602001516001600160a01b03168152602001600886815481106109f9576109f9611b7f565b600091825260209182902001546001600160a01b031682526040808e01519183019190915260608d01519101526009805484908110610a3a57610a3a611b7f565b90600052602060002090600491828204019190066008029054906101000a9004801561190102176001600160401b031663ffffffff16565b915060005b600554811015610c0d5760008160055484610a929190611c2c565b600554600454610aa29089611c2c565b610aac9190611c2c565b610ab69190611c4b565b610ac09190611c4b565b90508a606001516001610ad39190611c4b565b6001600160401b03811115610aea57610aea6119ee565b604051908082528060200260200182016040528015610b13578160200160208202803683370190505b50878281518110610b2657610b26611b7f565b602002602001018190525060005b8451811015610bf857848181518110610b4f57610b4f611b7f565b6020026020010151888381518110610b6957610b69611b7f565b6020026020010151826001610b7e9190611c4b565b81518110610b8e57610b8e611b7f565b6020026020010181815250508680610be457506000888381518110610bb557610bb5611b7f565b6020026020010151826001610bca9190611c4b565b81518110610bda57610bda611b7f565b6020026020010151135b965080610bf081611bab565b915050610b34565b50508080610c0590611bab565b915050610a77565b5080610c1881611bab565b9150506109a8565b50508080610c2d90611bab565b915050610999565b5080610d1b5760005b600554600454600354610c519190611c2c565b610c5b9190611c2c565b811015610d195760015b6060880151610c75906001611c4b565b811015610d1057838281518110610c8e57610c8e611b7f565b60200260200101518181518110610ca757610ca7611b7f565b602002602001015160001415610cfe57600080516020611d11833981519152848381518110610cd857610cd8611b7f565b60200260200101518281518110610cf157610cf1611b7f565b6020026020010181815250505b80610d0881611bab565b915050610c65565b50600101610c3e565b505b610d298660600151836110bf565b9350610d37905082846117e2565b945060005b600554600454600354610d4f9190611c2c565b610d599190611c2c565b811015610db857838181518110610d7257610d72611b7f565b60200260200101518560055483610d899190611c63565b81518110610d9957610d99611b7f565b60200260200101818151610dad9190611c4b565b905250600101610d3c565b50505050915091565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6060816001600160401b03811115610e2b57610e2b6119ee565b604051908082528060200260200182016040528015610e54578160200160208202803683370190505b50905060005b828110156106535782610e6e826001611c4b565b610e789086611c2c565b610e829190611c63565b828281518110610e9457610e94611b7f565b602090810291909101015280610ea981611bab565b915050610e5a565b606081516001600160401b03811115610ecc57610ecc6119ee565b604051908082528060200260200182016040528015610ef5578160200160208202803683370190505b5090506000610f0c866001600160a01b031661070e565b610f165785610f23565b6006546001600160a01b03165b90506000610f39866001600160a01b031661070e565b610f435785610f50565b6006546001600160a01b03165b60405163e6a4390560e01b81526001600160a01b038481166004830152808316602483015291925060009187169063e6a439059060440160206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd79190611c85565b90506001600160a01b03811615611080576000610ffd6001600160a01b03851683610747565b905060006110146001600160a01b03851684610747565b905060005b87518110156110755761104683838a848151811061103957611039611b7f565b60200260200101516118b0565b87828151811061105857611058611b7f565b60209081029190910101528061106d81611bab565b915050611019565b505050505050611084565b5050505b949350505050565b60606110988383610e11565b90506110a687878684610eb1565b90506110b486868684610eb1565b979650505050505050565b805160009060609082816001600160401b038111156110e0576110e06119ee565b60405190808252806020026020018201604052801561111357816020015b60608152602001906001900390816110fe5790505b5090506000826001600160401b03811115611130576111306119ee565b60405190808252806020026020018201604052801561116357816020015b606081526020019060019003908161114e5790505b50905060005b838110156112565761117c886001611c4b565b6001600160401b03811115611193576111936119ee565b6040519080825280602002602001820160405280156111bc578160200160208202803683370190505b508382815181106111cf576111cf611b7f565b60209081029190910101526111e5886001611c4b565b6001600160401b038111156111fc576111fc6119ee565b604051908082528060200260200182016040528015611225578160200160208202803683370190505b5082828151811061123857611238611b7f565b6020026020010181905250808061124e90611bab565b915050611169565b5060005b87811161137a578660008151811061127457611274611b7f565b6020026020010151818151811061128d5761128d611b7f565b6020026020010151836000815181106112a8576112a8611b7f565b602002602001015182815181106112c1576112c1611b7f565b602090810291909101015260015b8481101561132e57600080516020611d118339815191528482815181106112f8576112f8611b7f565b6020026020010151838151811061131157611311611b7f565b60209081029190910101528061132681611bab565b9150506112cf565b5060008260008151811061134457611344611b7f565b6020026020010151828151811061135d5761135d611b7f565b60209081029190910101528061137281611bab565b91505061125a565b5060015b8381101561163c5760005b888111611629578361139c600184611ca2565b815181106113ac576113ac611b7f565b602002602001015181815181106113c5576113c5611b7f565b60200260200101518483815181106113df576113df611b7f565b602002602001015182815181106113f8576113f8611b7f565b6020026020010181815250508083838151811061141757611417611b7f565b6020026020010151828151811061143057611430611b7f565b602090810291909101015260015b8181116116165784838151811061145757611457611b7f565b6020026020010151828151811061147057611470611b7f565b602002602001015189848151811061148a5761148a611b7f565b602002602001015182815181106114a3576114a3611b7f565b6020026020010151866001866114b99190611ca2565b815181106114c9576114c9611b7f565b602002602001015183856114dd9190611ca2565b815181106114ed576114ed611b7f565b60200260200101516114ff9190611cb9565b13156116045788838151811061151757611517611b7f565b6020026020010151818151811061153057611530611b7f565b6020026020010151856001856115469190611ca2565b8151811061155657611556611b7f565b6020026020010151828461156a9190611ca2565b8151811061157a5761157a611b7f565b602002602001015161158c9190611cb9565b85848151811061159e5761159e611b7f565b602002602001015183815181106115b7576115b7611b7f565b60209081029190910101526115cc8183611ca2565b8484815181106115de576115de611b7f565b602002602001015183815181106115f7576115f7611b7f565b6020026020010181815250505b8061160e81611bab565b91505061143e565b508061162181611bab565b915050611389565b508061163481611bab565b91505061137e565b506005546004546003546116509190611c2c565b61165a9190611c2c565b6001600160401b03811115611671576116716119ee565b60405190808252806020026020018201604052801561169a578160200160208202803683370190505b5093508660001984015b811561173e578281815181106116bc576116bc611b7f565b602002602001015182815181106116d5576116d5611b7f565b602002602001015182038682815181106116f1576116f1611b7f565b60200260200101818152505082818151811061170f5761170f611b7f565b6020026020010151828151811061172857611728611b7f565b60209081029190910101519150600019016116a4565b50600080516020611d118339815191528361175a600187611ca2565b8151811061176a5761176a611b7f565b6020026020010151898151811061178357611783611b7f565b6020026020010151146117d2578261179c600186611ca2565b815181106117ac576117ac611b7f565b602002602001015188815181106117c5576117c5611b7f565b60200260200101516117d5565b60005b9550505050509250929050565b6000805b6005546004546003546117f99190611c2c565b6118039190611c2c565b81101561065357600083828151811061181e5761181e611b7f565b602002602001015111156118a857600084828151811061184057611840611b7f565b602002602001015184838151811061185a5761185a611b7f565b60200260200101518151811061187257611872611b7f565b60200260200101519050600080516020611d118339815191528114611897578061189a565b60005b6118a49084611c4b565b9250505b6001016117e6565b6000816118bf575060006107e1565b6118cb826103e5611c2c565b6118d7856103e8611c2c565b6118e19190611c4b565b6118eb8484611c2c565b6118f7906103e5611c2c565b6110849190611c63565b6103b0611cfa565b60006020828403121561191b57600080fd5b5035919050565b6001600160a01b038116811461059b57600080fd5b60006020828403121561194957600080fd5b81356107e181611922565b6000806000806080858703121561196a57600080fd5b843561197581611922565b9350602085013561198581611922565b93969395505050506040820135916060013590565b600081518084526020808501945080840160005b838110156119ca578151875295820195908201906001016119ae565b509495945050505050565b828152604060208201526000611084604083018461199a565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715611a2c57611a2c6119ee565b604052919050565b60006020808385031215611a4757600080fd5b82356001600160401b0380821115611a5e57600080fd5b818501915085601f830112611a7257600080fd5b813581811115611a8457611a846119ee565b8060051b9150611a95848301611a04565b8181529183018401918481019088841115611aaf57600080fd5b938501935b83851015611ad95784359250611ac983611922565b8282529385019390850190611ab4565b98975050505050505050565b600060a08284031215611af757600080fd5b60405160a081018181106001600160401b0382111715611b1957611b196119ee565b6040528235611b2781611922565b81526020830135611b3781611922565b60208201526040830135611b4a81611922565b6040820152606083810135908201526080928301359281019290925250919050565b6020815260006107e1602083018461199a565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415611bbf57611bbf611b95565b5060010190565b6020808252825182820181905260009190848201906040850190845b81811015611c075783516001600160a01b031683529284019291840191600101611be2565b50909695505050505050565b600060208284031215611c2557600080fd5b5051919050565b6000816000190483118215151615611c4657611c46611b95565b500290565b60008219821115611c5e57611c5e611b95565b500190565b600082611c8057634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215611c9757600080fd5b81516107e181611922565b600082821015611cb457611cb4611b95565b500390565b600080821280156001600160ff1b0384900385131615611cdb57611cdb611b95565b600160ff1b8390038412811615611cf457611cf4611b95565b50500190565b634e487b7160e01b600052605160045260246000fdfeffff6f1bf04115e2c5b54376aa16b901ce32309909cb1f000000000000000000a2646970667358221220eb24b5a8d9f9451f78667d38f0d74f12ec9aac924b1aab840c4c8d4cb81d2a6f64736f6c63430008090033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc20000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000030000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f000000000000000000000000c0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac000000000000000000000000115934131916c8b277dd010ee02de363c09d037c
-----Decoded View---------------
Arg [0] : _weth (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : _otherToken (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [2] : _pathCount (uint256): 2
Arg [3] : _pathSplit (uint256): 2
Arg [4] : _factories (address[]): 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f,0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac,0x115934131916C8b277DD010Ee02de363c09d037c
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [4] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000003
Arg [6] : 0000000000000000000000005c69bee701ef814a2b6a3edd4b1652cb9cc5aa6f
Arg [7] : 000000000000000000000000c0aee478e3658e2610c5f7a4a2e1777ce9e4f2ac
Arg [8] : 000000000000000000000000115934131916c8b277dd010ee02de363c09d037c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
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.