Contract Overview
My Name Tag:
Not Available, login to update
[ Download CSV Export ]
Latest 25 internal transaction
[ Download CSV Export ]
Contract Name:
WooCrossChainRouterV4
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 20000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.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. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling 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 (last updated v4.7.0) (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { _requireNotPaused(); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { _requirePaused(); _; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Throws if the contract is paused. */ function _requireNotPaused() internal view virtual { require(!paused(), "Pausable: paused"); } /** * @dev Throws if the contract is not paused. */ function _requirePaused() internal view virtual { require(paused(), "Pausable: not paused"); } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// 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 // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol) // This file was procedurally generated from scripts/generate/templates/EnumerableSet.js. pragma solidity ^0.8.0; /** * @dev Library for managing * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive * types. * * Sets have the following properties: * * - Elements are added, removed, and checked for existence in constant time * (O(1)). * - Elements are enumerated in O(n). No guarantees are made on the ordering. * * ```solidity * contract Example { * // Add the library methods * using EnumerableSet for EnumerableSet.AddressSet; * * // Declare a set state variable * EnumerableSet.AddressSet private mySet; * } * ``` * * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`) * and `uint256` (`UintSet`) are supported. * * [WARNING] * ==== * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure * unusable. * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info. * * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an * array of EnumerableSet. * ==== */ library EnumerableSet { // To implement this library for multiple types with as little code // repetition as possible, we write it in terms of a generic Set type with // bytes32 values. // The Set implementation uses private functions, and user-facing // implementations (such as AddressSet) are just wrappers around the // underlying Set. // This means that we can only create new EnumerableSets for types that fit // in bytes32. struct Set { // Storage of set values bytes32[] _values; // Position of the value in the `values` array, plus 1 because index 0 // means a value is not in the set. mapping(bytes32 => uint256) _indexes; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function _add(Set storage set, bytes32 value) private returns (bool) { if (!_contains(set, value)) { set._values.push(value); // The value is stored at length-1, but we add 1 to all indexes // and use 0 as a sentinel value set._indexes[value] = set._values.length; return true; } else { return false; } } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value]; if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}. uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; if (lastIndex != toDeleteIndex) { bytes32 lastValue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastValue; // Update the index for the moved value set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex } // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true; } else { return false; } } /** * @dev Returns true if the value is in the set. O(1). */ function _contains(Set storage set, bytes32 value) private view returns (bool) { return set._indexes[value] != 0; } /** * @dev Returns the number of values on the set. O(1). */ function _length(Set storage set) private view returns (uint256) { return set._values.length; } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function _at(Set storage set, uint256 index) private view returns (bytes32) { return set._values[index]; } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function _values(Set storage set) private view returns (bytes32[] memory) { return set._values; } // Bytes32Set struct Bytes32Set { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _add(set._inner, value); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) { return _remove(set._inner, value); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) { return _contains(set._inner, value); } /** * @dev Returns the number of values in the set. O(1). */ function length(Bytes32Set storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) { return _at(set._inner, index); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(Bytes32Set storage set) internal view returns (bytes32[] memory) { bytes32[] memory store = _values(set._inner); bytes32[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // AddressSet struct AddressSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(AddressSet storage set, address value) internal returns (bool) { return _add(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(AddressSet storage set, address value) internal returns (bool) { return _remove(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(AddressSet storage set, address value) internal view returns (bool) { return _contains(set._inner, bytes32(uint256(uint160(value)))); } /** * @dev Returns the number of values in the set. O(1). */ function length(AddressSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(AddressSet storage set, uint256 index) internal view returns (address) { return address(uint160(uint256(_at(set._inner, index)))); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(AddressSet storage set) internal view returns (address[] memory) { bytes32[] memory store = _values(set._inner); address[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } // UintSet struct UintSet { Set _inner; } /** * @dev Add a value to a set. O(1). * * Returns true if the value was added to the set, that is if it was not * already present. */ function add(UintSet storage set, uint256 value) internal returns (bool) { return _add(set._inner, bytes32(value)); } /** * @dev Removes a value from a set. O(1). * * Returns true if the value was removed from the set, that is if it was * present. */ function remove(UintSet storage set, uint256 value) internal returns (bool) { return _remove(set._inner, bytes32(value)); } /** * @dev Returns true if the value is in the set. O(1). */ function contains(UintSet storage set, uint256 value) internal view returns (bool) { return _contains(set._inner, bytes32(value)); } /** * @dev Returns the number of values in the set. O(1). */ function length(UintSet storage set) internal view returns (uint256) { return _length(set._inner); } /** * @dev Returns the value stored at position `index` in the set. O(1). * * Note that there are no guarantees on the ordering of values inside the * array, and it may change when more values are added or removed. * * Requirements: * * - `index` must be strictly less than {length}. */ function at(UintSet storage set, uint256 index) internal view returns (uint256) { return uint256(_at(set._inner, index)); } /** * @dev Return the entire set in an array * * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that * this function has an unbounded cost, and using it as part of a state-changing function may render the function * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block. */ function values(UintSet storage set) internal view returns (uint256[] memory) { bytes32[] memory store = _values(set._inner); uint256[] memory result; /// @solidity memory-safe-assembly assembly { result := store } return result; } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.14; // OpenZeppelin Contracts import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Pausable} from "@openzeppelin/contracts/security/Pausable.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; // Local Contracts import {IWETH} from "../interfaces/IWETH.sol"; import {IWooCrossChainRouterV3} from "../interfaces/CrossChain/IWooCrossChainRouterV3.sol"; import {IWooRouterV2} from "../interfaces/IWooRouterV2.sol"; import {IStargateEthVault} from "../interfaces/Stargate/IStargateEthVault.sol"; import {IStargateRouter} from "../interfaces/Stargate/IStargateRouter.sol"; import {ILzApp} from "../interfaces/LayerZero/ILzApp.sol"; import {ISgInfo} from "../interfaces/CrossChain/ISgInfo.sol"; import {TransferHelper} from "../libraries/TransferHelper.sol"; /// @title cross chain router implementation, version 3. /// @notice Router for stateless execution of cross chain swap against WOOFi or 1inch swap. /// @custom:stargate-contracts https://stargateprotocol.gitbook.io/stargate/developers/contract-addresses/mainnet contract WooCrossChainRouterV4 is IWooCrossChainRouterV3, Ownable, Pausable, ReentrancyGuard { using EnumerableSet for EnumerableSet.AddressSet; /* ----- Constants ----- */ address public constant ETH_PLACEHOLDER_ADDR = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; /* ----- Variables ----- */ IWooRouterV2 public wooRouter; ISgInfo public sgInfo; address public immutable weth; address public feeAddr; uint256 public bridgeSlippage; // 1 in 10000th: default 1% uint16 public srcExternalFeeRate; // unit: 0.1 bps (1e6 = 100%, 25 = 2.5 bps) uint16 public dstExternalFeeRate; // unit: 0.1 bps (1e6 = 100%, 25 = 2.5 bps) uint256 public constant FEE_BASE = 1e5; mapping(uint16 => address) public wooCrossRouters; // chainId => WooCrossChainRouterV3 address receive() external payable {} constructor( address _weth, address _wooRouter, address _sgInfo ) { weth = _weth; wooRouter = IWooRouterV2(_wooRouter); sgInfo = ISgInfo(_sgInfo); bridgeSlippage = 100; srcExternalFeeRate = 25; dstExternalFeeRate = 25; } /* ----- Functions ----- */ function crossSwap( uint256 refId, address payable to, SrcInfos memory srcInfos, DstInfos calldata dstInfos, Src1inch calldata src1inch, Dst1inch calldata dst1inch ) external payable whenNotPaused nonReentrant { require(srcInfos.fromToken != address(0), "WooCrossChainRouterV3: !srcInfos.fromToken"); require( dstInfos.toToken != address(0) && dstInfos.toToken != sgInfo.sgETHs(dstInfos.chainId), "WooCrossChainRouterV3: !dstInfos.toToken" ); require(to != address(0), "WooCrossChainRouterV3: !to"); uint256 msgValue = msg.value; uint256 bridgeAmount; uint256 fee = 0; { // Step 1: transfer if (srcInfos.fromToken == ETH_PLACEHOLDER_ADDR) { require(srcInfos.fromAmount <= msgValue, "WooCrossChainRouterV3: !srcInfos.fromAmount"); srcInfos.fromToken = weth; IWETH(weth).deposit{value: srcInfos.fromAmount}(); msgValue -= srcInfos.fromAmount; } else { TransferHelper.safeTransferFrom(srcInfos.fromToken, msg.sender, address(this), srcInfos.fromAmount); } // Step 2: local swap by 1inch router if (srcInfos.fromToken != srcInfos.bridgeToken) { TransferHelper.safeApprove(srcInfos.fromToken, address(wooRouter), srcInfos.fromAmount); if (src1inch.swapRouter != address(0)) { // external swap via 1inch bridgeAmount = wooRouter.externalSwap( src1inch.swapRouter, src1inch.swapRouter, srcInfos.fromToken, srcInfos.bridgeToken, srcInfos.fromAmount, srcInfos.minBridgeAmount, payable(address(this)), src1inch.data ); fee = (bridgeAmount * srcExternalFeeRate) / FEE_BASE; } else { // swap via WOOFi bridgeAmount = wooRouter.swap( srcInfos.fromToken, srcInfos.bridgeToken, srcInfos.fromAmount, srcInfos.minBridgeAmount, payable(address(this)), to ); } } else { require( srcInfos.fromAmount == srcInfos.minBridgeAmount, "WooCrossChainRouterV3: !srcInfos.minBridgeAmount" ); bridgeAmount = srcInfos.fromAmount; } require( bridgeAmount <= IERC20(srcInfos.bridgeToken).balanceOf(address(this)), "WooCrossChainRouterV3: !bridgeAmount" ); } // Step 3: deduct the swap fee bridgeAmount -= fee; // Step 4: cross chain swap by StargateRouter _bridgeByStargate(refId, to, msgValue, bridgeAmount, srcInfos, dstInfos, dst1inch); emit WooCrossSwapOnSrcChain( refId, _msgSender(), to, srcInfos.fromToken, srcInfos.fromAmount, srcInfos.bridgeToken, srcInfos.minBridgeAmount, bridgeAmount, src1inch.swapRouter == address(0) ? 0 : 1, fee ); } function sgReceive( uint16, // srcChainId bytes memory, // srcAddress uint256, // nonce address bridgedToken, uint256 amountLD, bytes memory payload ) external { require(msg.sender == sgInfo.sgRouter(), "WooCrossChainRouterV3: INVALID_CALLER"); // make sure the same order to abi.encode when decode payload (uint256 refId, address to, address toToken, uint256 minToAmount, Dst1inch memory dst1inch) = abi.decode( payload, (uint256, address, address, uint256, Dst1inch) ); // toToken won't be SGETH, and bridgedToken won't be ETH_PLACEHOLDER_ADDR if (bridgedToken == sgInfo.sgETHs(sgInfo.sgChainIdLocal())) { // bridgedToken is SGETH, received native token _handleNativeReceived(refId, to, toToken, amountLD, minToAmount, dst1inch); } else { // bridgedToken is not SGETH, received ERC20 token _handleERC20Received(refId, to, toToken, bridgedToken, amountLD, minToAmount, dst1inch); } } function quoteLayerZeroFee( uint256 refId, address to, DstInfos calldata dstInfos, Dst1inch calldata dst1inch ) external view returns (uint256, uint256) { bytes memory payload = abi.encode(refId, to, dstInfos.toToken, dstInfos.minToAmount, dst1inch); IStargateRouter.lzTxObj memory obj = IStargateRouter.lzTxObj( dstInfos.dstGasForCall, dstInfos.airdropNativeAmount, abi.encodePacked(to) ); IStargateRouter stargateRouter = IStargateRouter(sgInfo.sgRouter()); return stargateRouter.quoteLayerZeroFee( dstInfos.chainId, 1, // https://stargateprotocol.gitbook.io/stargate/developers/function-types obj.dstNativeAddr, payload, obj ); } /// @dev OKAY to be public method function claimFee(address token) external nonReentrant { require(feeAddr != address(0), "WooCrossChainRouterV3: !feeAddr"); uint256 amount = _generalBalanceOf(token, address(this)); if (amount > 0) { if (token == ETH_PLACEHOLDER_ADDR) { TransferHelper.safeTransferETH(feeAddr, amount); } else { TransferHelper.safeTransfer(token, feeAddr, amount); } } } function _bridgeByStargate( uint256 refId, address payable to, uint256 msgValue, uint256 bridgeAmount, SrcInfos memory srcInfos, DstInfos calldata dstInfos, Dst1inch calldata dst1inch ) internal { require( sgInfo.sgPoolIds(sgInfo.sgChainIdLocal(), srcInfos.bridgeToken) > 0, "WooCrossChainRouterV3: !srcInfos.bridgeToken" ); require( sgInfo.sgPoolIds(dstInfos.chainId, dstInfos.bridgeToken) > 0, "WooCrossChainRouterV3: !dstInfos.bridgeToken" ); bytes memory payload = abi.encode(refId, to, dstInfos.toToken, dstInfos.minToAmount, dst1inch); uint256 dstMinBridgeAmount = (bridgeAmount * (10000 - bridgeSlippage)) / 10000; bytes memory dstWooCrossChainRouter = abi.encodePacked(wooCrossRouters[dstInfos.chainId]); IStargateRouter.lzTxObj memory obj = IStargateRouter.lzTxObj( dstInfos.dstGasForCall, dstInfos.airdropNativeAmount, abi.encodePacked(to) ); IStargateRouter stargateRouter = IStargateRouter(sgInfo.sgRouter()); if (srcInfos.bridgeToken == weth) { IWETH(weth).withdraw(bridgeAmount); msgValue += bridgeAmount; } else { TransferHelper.safeApprove(srcInfos.bridgeToken, sgInfo.sgRouter(), bridgeAmount); } stargateRouter.swap{value: msgValue}( dstInfos.chainId, // dst chain id sgInfo.sgPoolIds(sgInfo.sgChainIdLocal(), srcInfos.bridgeToken), // bridge token's pool id on src chain sgInfo.sgPoolIds(dstInfos.chainId, dstInfos.bridgeToken), // bridge token's pool id on dst chain payable(_msgSender()), // rebate address bridgeAmount, // swap amount on src chain dstMinBridgeAmount, // min received amount on dst chain obj, // config: dstGasForCall, dstAirdropNativeAmount, dstReceiveAirdropNativeTokenAddr dstWooCrossChainRouter, // smart contract to call on dst chain payload // payload to piggyback ); } function _handleNativeReceived( uint256 refId, address to, address toToken, uint256 bridgedAmount, uint256 minToAmount, Dst1inch memory dst1inch ) internal { address msgSender = _msgSender(); if (toToken == ETH_PLACEHOLDER_ADDR) { // Directly transfer ETH TransferHelper.safeTransferETH(to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, weth, bridgedAmount, toToken, ETH_PLACEHOLDER_ADDR, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); return; } // Swap required! IWETH(weth).deposit{value: bridgedAmount}(); if (dst1inch.swapRouter != address(0)) { uint256 fee = (bridgedAmount * dstExternalFeeRate) / FEE_BASE; uint256 swapAmount = bridgedAmount - fee; TransferHelper.safeApprove(weth, address(wooRouter), swapAmount); try wooRouter.externalSwap( dst1inch.swapRouter, dst1inch.swapRouter, weth, toToken, swapAmount, minToAmount, payable(to), dst1inch.data ) returns (uint256 realToAmount) { emit WooCrossSwapOnDstChain( refId, msgSender, to, weth, swapAmount, toToken, toToken, minToAmount, realToAmount, dst1inch.swapRouter == address(0) ? 0 : 1, fee ); } catch { TransferHelper.safeApprove(weth, address(wooRouter), 0); TransferHelper.safeTransfer(weth, to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, weth, bridgedAmount, toToken, weth, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } } else { TransferHelper.safeApprove(weth, address(wooRouter), bridgedAmount); try wooRouter.swap(weth, toToken, bridgedAmount, minToAmount, payable(to), to) returns ( uint256 realToAmount ) { emit WooCrossSwapOnDstChain( refId, msgSender, to, weth, bridgedAmount, toToken, toToken, minToAmount, realToAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } catch { TransferHelper.safeApprove(weth, address(wooRouter), 0); TransferHelper.safeTransfer(weth, to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, weth, bridgedAmount, toToken, weth, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } } } function _handleERC20Received( uint256 refId, address to, address toToken, address bridgedToken, uint256 bridgedAmount, uint256 minToAmount, Dst1inch memory dst1inch ) internal { address msgSender = _msgSender(); if (toToken == bridgedToken) { TransferHelper.safeTransfer(bridgedToken, to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, bridgedToken, bridgedAmount, toToken, toToken, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } else { // Deduct the external swap fee uint256 fee = (bridgedAmount * dstExternalFeeRate) / FEE_BASE; bridgedAmount -= fee; TransferHelper.safeApprove(bridgedToken, address(wooRouter), bridgedAmount); if (dst1inch.swapRouter != address(0)) { try wooRouter.externalSwap( dst1inch.swapRouter, dst1inch.swapRouter, bridgedToken, toToken, bridgedAmount, minToAmount, payable(to), dst1inch.data ) returns (uint256 realToAmount) { emit WooCrossSwapOnDstChain( refId, msgSender, to, bridgedToken, bridgedAmount, toToken, toToken, minToAmount, realToAmount, dst1inch.swapRouter == address(0) ? 0 : 1, fee ); } catch { bridgedAmount += fee; TransferHelper.safeTransfer(bridgedToken, to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, bridgedToken, bridgedAmount, toToken, bridgedToken, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } } else { try wooRouter.swap(bridgedToken, toToken, bridgedAmount, minToAmount, payable(to), to) returns ( uint256 realToAmount ) { emit WooCrossSwapOnDstChain( refId, msgSender, to, bridgedToken, bridgedAmount, toToken, toToken, minToAmount, realToAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } catch { TransferHelper.safeTransfer(bridgedToken, to, bridgedAmount); emit WooCrossSwapOnDstChain( refId, msgSender, to, bridgedToken, bridgedAmount, toToken, bridgedToken, minToAmount, bridgedAmount, dst1inch.swapRouter == address(0) ? 0 : 1, 0 ); } } } } function _generalBalanceOf(address token, address who) internal view returns (uint256) { return token == ETH_PLACEHOLDER_ADDR ? who.balance : IERC20(token).balanceOf(who); } /* ----- Owner & Admin Functions ----- */ function setFeeAddr(address _feeAddr) external onlyOwner { feeAddr = _feeAddr; } function setWooRouter(address _wooRouter) external onlyOwner { require(_wooRouter != address(0), "WooCrossChainRouterV3: !_wooRouter"); wooRouter = IWooRouterV2(_wooRouter); } function setBridgeSlippage(uint256 _bridgeSlippage) external onlyOwner { require(_bridgeSlippage <= 10000, "WooCrossChainRouterV3: !_bridgeSlippage"); bridgeSlippage = _bridgeSlippage; } function setWooCrossRouter(uint16 _chainId, address _crossRouter) external onlyOwner { require(_crossRouter != address(0), "WooCrossChainRouterV3: !_crossRouter"); wooCrossRouters[_chainId] = _crossRouter; } function pause() external onlyOwner { _pause(); } function unpause() external onlyOwner { _unpause(); } function inCaseTokenGotStuck(address stuckToken) external onlyOwner { if (stuckToken == ETH_PLACEHOLDER_ADDR) { TransferHelper.safeTransferETH(msg.sender, address(this).balance); } else { uint256 amount = IERC20(stuckToken).balanceOf(address(this)); TransferHelper.safeTransfer(stuckToken, msg.sender, amount); } } }
// SPDX-License-Identifier: MIT pragma solidity =0.8.14; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title WOOFi cross fee. interface ISgInfo { /* ----- State Variables ----- */ function sgRouter() external view returns (address sgRouter); function sgChainIdLocal() external view returns (uint16 sgChainIdLocal); function sgPoolIds(uint16 _chainId, address _addr) external view returns (uint256 sgPoolId); function sgETHs(uint16 _chainId) external view returns (address sgETH); }
// SPDX-License-Identifier: MIT pragma solidity =0.8.14; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title WOOFi cross chain router interface (version 3, supporting WOOFi and 1inch). /// @notice functions to interface with WOOFi cross chain swap, and 1inch for local swap interface IWooCrossChainRouterV3 { /* ----- Structs ----- */ struct SrcInfos { address fromToken; address bridgeToken; uint256 fromAmount; uint256 minBridgeAmount; } struct Src1inch { address swapRouter; bytes data; } struct DstInfos { uint16 chainId; address toToken; address bridgeToken; uint256 minToAmount; uint256 airdropNativeAmount; uint256 dstGasForCall; } struct Dst1inch { address swapRouter; bytes data; } /* ----- Events ----- */ event WooCrossSwapOnSrcChain( uint256 indexed refId, address indexed sender, address indexed to, address fromToken, uint256 fromAmount, address bridgeToken, uint256 minBridgeAmount, uint256 realBridgeAmount, uint8 swapType, uint256 fee ); event WooCrossSwapOnDstChain( uint256 indexed refId, address indexed sender, address indexed to, address bridgedToken, uint256 bridgedAmount, address toToken, address realToToken, uint256 minToAmount, uint256 realToAmount, uint8 swapType, uint256 fee ); /* ----- State Variables ----- */ function bridgeSlippage() external view returns (uint256); function wooCrossRouters(uint16 chainId) external view returns (address wooCrossRouter); /* ----- Functions ----- */ function crossSwap( uint256 refId, address payable to, SrcInfos memory srcInfos, DstInfos calldata dstInfos, Src1inch calldata src1inch, Dst1inch calldata dst1inch ) external payable; function sgReceive( uint16 srcChainId, bytes memory srcAddress, uint256 nonce, address bridgedToken, uint256 amountLD, bytes memory payload ) external; function quoteLayerZeroFee( uint256 refId, address to, DstInfos calldata dstInfos, Dst1inch calldata dst1inch ) external view returns (uint256 nativeAmount, uint256 zroAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /// @title Wrapped ETH. interface IWETH { /// @dev Deposit ETH into WETH function deposit() external payable; /// @dev Transfer WETH to receiver /// @param to address of WETH receiver /// @param value amount of WETH to transfer /// @return get true when succeed, else false function transfer(address to, uint256 value) external returns (bool); /// @dev Withdraw WETH to ETH function withdraw(uint256) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.14; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /// @title Woo private pool for swap. /// @notice Use this contract to directly interfact with woo's synthetic proactive /// marketing making pool. /// @author woo.network interface IWooPPV2 { /* ----- Events ----- */ event Deposit(address indexed token, address indexed sender, uint256 amount); event Withdraw(address indexed token, address indexed receiver, uint256 amount); event Migrate(address indexed token, address indexed receiver, uint256 amount); event AdminUpdated(address indexed addr, bool flag); event FeeAddrUpdated(address indexed newFeeAddr); event WooracleUpdated(address indexed newWooracle); event WooSwap( address indexed fromToken, address indexed toToken, uint256 fromAmount, uint256 toAmount, address from, address indexed to, address rebateTo, uint256 swapVol, uint256 swapFee ); /* ----- External Functions ----- */ /// @notice The quote token address (immutable). /// @return address of quote token function quoteToken() external view returns (address); /// @notice Gets the pool size of the specified token (swap liquidity). /// @param token the token address /// @return the pool size function poolSize(address token) external view returns (uint256); /// @notice Query the amount to swap `fromToken` to `toToken`, without checking the pool reserve balance. /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of `fromToken` to swap /// @return toAmount the swapped amount of `toToken` function tryQuery( address fromToken, address toToken, uint256 fromAmount ) external view returns (uint256 toAmount); /// @notice Query the amount to swap `fromToken` to `toToken`, with checking the pool reserve balance. /// @dev tx reverts when 'toToken' balance is insufficient. /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of `fromToken` to swap /// @return toAmount the swapped amount of `toToken` function query( address fromToken, address toToken, uint256 fromAmount ) external view returns (uint256 toAmount); /// @notice Swap `fromToken` to `toToken`. /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of `fromToken` to swap /// @param minToAmount the minimum amount of `toToken` to receive /// @param to the destination address /// @param rebateTo the rebate address (optional, can be address ZERO) /// @return realToAmount the amount of toToken to receive function swap( address fromToken, address toToken, uint256 fromAmount, uint256 minToAmount, address to, address rebateTo ) external returns (uint256 realToAmount); /// @notice Deposit the specified token into the liquidity pool of WooPPV2. /// @param token the token to deposit /// @param amount the deposit amount function deposit(address token, uint256 amount) external; }
// SPDX-License-Identifier: MIT pragma solidity =0.8.14; /* ░██╗░░░░░░░██╗░█████╗░░█████╗░░░░░░░███████╗██╗ ░██║░░██╗░░██║██╔══██╗██╔══██╗░░░░░░██╔════╝██║ ░╚██╗████╗██╔╝██║░░██║██║░░██║█████╗█████╗░░██║ ░░████╔═████║░██║░░██║██║░░██║╚════╝██╔══╝░░██║ ░░╚██╔╝░╚██╔╝░╚█████╔╝╚█████╔╝░░░░░░██║░░░░░██║ ░░░╚═╝░░░╚═╝░░░╚════╝░░╚════╝░░░░░░░╚═╝░░░░░╚═╝ * * MIT License * =========== * * Copyright (c) 2020 WooTrade * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import "../interfaces/IWooPPV2.sol"; /// @title Woo router interface (version 2) /// @notice functions to interface with WooFi swap interface IWooRouterV2 { /* ----- Type declarations ----- */ enum SwapType { WooSwap, DodoSwap } /* ----- Events ----- */ event WooRouterSwap( SwapType swapType, address indexed fromToken, address indexed toToken, uint256 fromAmount, uint256 toAmount, address from, address indexed to, address rebateTo ); event WooPoolChanged(address newPool); /* ----- Router properties ----- */ function WETH() external view returns (address); function wooPool() external view returns (IWooPPV2); /* ----- Main query & swap APIs ----- */ /// @notice query the amount to swap fromToken -> toToken /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of fromToken to swap /// @return toAmount the predicted amount to receive function querySwap( address fromToken, address toToken, uint256 fromAmount ) external view returns (uint256 toAmount); /// @notice query the amount to swap fromToken -> toToken, /// WITHOUT checking the reserve balance; so it /// always returns the quoted amount (for reference). /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of fromToken to swap /// @return toAmount the predicted amount to receive function tryQuerySwap( address fromToken, address toToken, uint256 fromAmount ) external view returns (uint256 toAmount); /// @notice Swap `fromToken` to `toToken`. /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of `fromToken` to swap /// @param minToAmount the minimum amount of `toToken` to receive /// @param to the destination address /// @param rebateTo the rebate address (optional, can be 0) /// @return realToAmount the amount of toToken to receive function swap( address fromToken, address toToken, uint256 fromAmount, uint256 minToAmount, address payable to, address rebateTo ) external payable returns (uint256 realToAmount); /* ----- 3rd party DEX swap ----- */ /// @notice swap fromToken -> toToken via an external 3rd swap /// @param approveTarget the contract address for token transfer approval /// @param swapTarget the contract address for swap /// @param fromToken the from token /// @param toToken the to token /// @param fromAmount the amount of fromToken to swap /// @param minToAmount the min amount of swapped toToken /// @param to the destination address /// @param data call data for external call function externalSwap( address approveTarget, address swapTarget, address fromToken, address toToken, uint256 fromAmount, uint256 minToAmount, address payable to, bytes calldata data ) external payable returns (uint256 realToAmount); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; /** * @dev Interface of the LzApp that functions not exist in the @layerzerolabs package */ interface ILzApp { function minDstGasLookup(uint16 _dstChainId, uint16 _type) external view returns (uint256 _minGasLimit); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IStargateEthVault { function deposit() external payable; function transfer(address to, uint256 value) external returns (bool); function withdraw(uint256) external; function approve(address guy, uint256 wad) external returns (bool); function transferFrom( address src, address dst, uint256 wad ) external returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IStargateRouter { struct lzTxObj { uint256 dstGasForCall; uint256 dstNativeAmount; bytes dstNativeAddr; } function addLiquidity( uint256 _poolId, uint256 _amountLD, address _to ) external; function swap( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLD, uint256 _minAmountLD, lzTxObj memory _lzTxParams, bytes calldata _to, bytes calldata _payload ) external payable; function redeemRemote( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, uint256 _minAmountLD, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function instantRedeemLocal( uint16 _srcPoolId, uint256 _amountLP, address _to ) external returns (uint256); function redeemLocal( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress, uint256 _amountLP, bytes calldata _to, lzTxObj memory _lzTxParams ) external payable; function sendCredits( uint16 _dstChainId, uint256 _srcPoolId, uint256 _dstPoolId, address payable _refundAddress ) external payable; function quoteLayerZeroFee( uint16 _dstChainId, uint8 _functionType, bytes calldata _toAddress, bytes calldata _transferAndCallPayload, lzTxObj memory _lzTxParams ) external view returns (uint256, uint256); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.0; // helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false library TransferHelper { function safeApprove( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('approve(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed" ); } function safeTransfer( address token, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transfer(address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed" ); } function safeTransferFrom( address token, address from, address to, uint256 value ) internal { // bytes4(keccak256(bytes('transferFrom(address,address,uint256)'))); (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value)); require( success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::transferFrom: transferFrom failed" ); } function safeTransferETH(address to, uint256 value) internal { (bool success, ) = to.call{value: value}(new bytes(0)); require(success, "TransferHelper::safeTransferETH: ETH transfer failed"); } }
{ "optimizer": { "enabled": true, "runs": 20000 }, "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":"_wooRouter","type":"address"},{"internalType":"address","name":"_sgInfo","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"bridgedToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"bridgedAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"toToken","type":"address"},{"indexed":false,"internalType":"address","name":"realToToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"minToAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"realToAmount","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"swapType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"WooCrossSwapOnDstChain","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"refId","type":"uint256"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"fromToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"fromAmount","type":"uint256"},{"indexed":false,"internalType":"address","name":"bridgeToken","type":"address"},{"indexed":false,"internalType":"uint256","name":"minBridgeAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"realBridgeAmount","type":"uint256"},{"indexed":false,"internalType":"uint8","name":"swapType","type":"uint8"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"WooCrossSwapOnSrcChain","type":"event"},{"inputs":[],"name":"ETH_PLACEHOLDER_ADDR","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FEE_BASE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"bridgeSlippage","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"claimFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"refId","type":"uint256"},{"internalType":"address payable","name":"to","type":"address"},{"components":[{"internalType":"address","name":"fromToken","type":"address"},{"internalType":"address","name":"bridgeToken","type":"address"},{"internalType":"uint256","name":"fromAmount","type":"uint256"},{"internalType":"uint256","name":"minBridgeAmount","type":"uint256"}],"internalType":"struct IWooCrossChainRouterV3.SrcInfos","name":"srcInfos","type":"tuple"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"address","name":"bridgeToken","type":"address"},{"internalType":"uint256","name":"minToAmount","type":"uint256"},{"internalType":"uint256","name":"airdropNativeAmount","type":"uint256"},{"internalType":"uint256","name":"dstGasForCall","type":"uint256"}],"internalType":"struct IWooCrossChainRouterV3.DstInfos","name":"dstInfos","type":"tuple"},{"components":[{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IWooCrossChainRouterV3.Src1inch","name":"src1inch","type":"tuple"},{"components":[{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IWooCrossChainRouterV3.Dst1inch","name":"dst1inch","type":"tuple"}],"name":"crossSwap","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"dstExternalFeeRate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"feeAddr","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stuckToken","type":"address"}],"name":"inCaseTokenGotStuck","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"refId","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"address","name":"toToken","type":"address"},{"internalType":"address","name":"bridgeToken","type":"address"},{"internalType":"uint256","name":"minToAmount","type":"uint256"},{"internalType":"uint256","name":"airdropNativeAmount","type":"uint256"},{"internalType":"uint256","name":"dstGasForCall","type":"uint256"}],"internalType":"struct IWooCrossChainRouterV3.DstInfos","name":"dstInfos","type":"tuple"},{"components":[{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct IWooCrossChainRouterV3.Dst1inch","name":"dst1inch","type":"tuple"}],"name":"quoteLayerZeroFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_bridgeSlippage","type":"uint256"}],"name":"setBridgeSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_feeAddr","type":"address"}],"name":"setFeeAddr","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_chainId","type":"uint16"},{"internalType":"address","name":"_crossRouter","type":"address"}],"name":"setWooCrossRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_wooRouter","type":"address"}],"name":"setWooRouter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sgInfo","outputs":[{"internalType":"contract ISgInfo","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"},{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"bridgedToken","type":"address"},{"internalType":"uint256","name":"amountLD","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"sgReceive","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"srcExternalFeeRate","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"wooCrossRouters","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"wooRouter","outputs":[{"internalType":"contract IWooRouterV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523480156200001157600080fd5b50604051620044283803806200442883398101604081905262000034916200010d565b6200003f33620000a0565b6000805460ff60a01b19169055600180556001600160a01b03928316608052600280549284166001600160a01b0319938416179055600380549190931691161790556064600555600680546219001963ffffffff1990911617905562000157565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b03811681146200010857600080fd5b919050565b6000806000606084860312156200012357600080fd5b6200012e84620000f0565b92506200013e60208501620000f0565b91506200014e60408501620000f0565b90509250925092565b608051614230620001f86000396000818161020c0152818161122501528181611d7801528181611e3301528181611efa01528181611f590152818161200a0152818161203f0152818161209d015281816120c0015281816121990152818161224a015281816122ac0152818161236a0152818161239f015281816123fd01528181612420015281816124f901528181613316015261338001526142306000f3fe60806040526004361061019a5760003560e01c80638da5cb5b116100e1578063e56f85401161008a578063f2fde38b11610064578063f2fde38b14610498578063f6af6957146104b8578063fd594a08146104ee578063fdeba4e51461050157600080fd5b8063e56f854014610431578063ecb911de14610466578063ecefc7051461048157600080fd5b8063b2855b4f116100bb578063b2855b4f146103bd578063b9292141146103dd578063e1a4e72a1461041157600080fd5b80638da5cb5b1461035f57806397ebb4521461037d578063ab8236f31461039d57600080fd5b80635c975abb1161014357806383af55501161011d57806383af5550146102fe5780638456cb591461032257806388c4cb361461033757600080fd5b80635c975abb1461028e5780636ebc51e1146102c9578063715018a6146102e957600080fd5b8063403a01e511610174578063403a01e51461022e5780634dba39a21461024e57806358800adf1461026e57600080fd5b806339e7fddc146101a65780633f4ba83a146101e35780633fc8cef3146101fa57600080fd5b366101a157005b600080fd5b3480156101b257600080fd5b506004546101c6906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101ef57600080fd5b506101f8610521565b005b34801561020657600080fd5b506101c67f000000000000000000000000000000000000000000000000000000000000000081565b34801561023a57600080fd5b506101f861024936600461376b565b610533565b34801561025a57600080fd5b506101f8610269366004613799565b6105d7565b34801561027a57600080fd5b506003546101c6906001600160a01b031681565b34801561029a57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1660405190151581526020016101da565b3480156102d557600080fd5b506101f86102e4366004613799565b6106af565b3480156102f557600080fd5b506101f86107ad565b34801561030a57600080fd5b5061031460055481565b6040519081526020016101da565b34801561032e57600080fd5b506101f86107bf565b34801561034357600080fd5b506101c673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561036b57600080fd5b506000546001600160a01b03166101c6565b34801561038957600080fd5b506101f86103983660046137c6565b6107cf565b3480156103a957600080fd5b506101f86103b8366004613965565b6108b8565b3480156103c957600080fd5b506101f86103d8366004613799565b610b48565b3480156103e957600080fd5b506006546103fe9062010000900461ffff1681565b60405161ffff90911681526020016101da565b34801561041d57600080fd5b506101f861042c366004613799565b610b8a565b34801561043d57600080fd5b5061045161044c366004613a2c565b610c61565b604080519283526020830191909152016101da565b34801561047257600080fd5b506006546103fe9061ffff1681565b34801561048d57600080fd5b50610314620186a081565b3480156104a457600080fd5b506101f86104b3366004613799565b610e23565b3480156104c457600080fd5b506101c66104d3366004613a99565b6007602052600090815260409020546001600160a01b031681565b6101f86104fc366004613ab6565b610eca565b34801561050d57600080fd5b506002546101c6906001600160a01b031681565b61052961178b565b6105316117ff565b565b61053b61178b565b6127108111156105d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f576f6f43726f7373436861696e526f7574657256333a20215f6272696467655360448201527f6c6970706167650000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600555565b6105df61178b565b6001600160a01b038116610675576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f576f6f43726f7373436861696e526f7574657256333a20215f776f6f526f757460448201527f657200000000000000000000000000000000000000000000000000000000000060648201526084016105c9565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106b761186f565b6004546001600160a01b0316610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f576f6f43726f7373436861696e526f7574657256333a2021666565416464720060448201526064016105c9565b600061073582306118e2565b905080156107a0577fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0383160161078857600454610783906001600160a01b0316826119a3565b6107a0565b6004546107a09083906001600160a01b031683611aa5565b506107aa60018055565b50565b6107b561178b565b6105316000611c2e565b6107c761178b565b610531611c96565b6107d761178b565b6001600160a01b03811661086c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f576f6f43726f7373436861696e526f7574657256333a20215f63726f7373526f60448201527f757465720000000000000000000000000000000000000000000000000000000060648201526084016105c9565b61ffff91909116600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa15801561090b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092f9190613bb2565b6001600160a01b0316336001600160a01b0316146109cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f576f6f43726f7373436861696e526f7574657256333a20494e56414c49445f4360448201527f414c4c455200000000000000000000000000000000000000000000000000000060648201526084016105c9565b6000806000806000858060200190518101906109eb9190613bff565b600354604080517fb88dafcb0000000000000000000000000000000000000000000000000000000081529051969b5094995092975090955093506001600160a01b03169163a4cd49ba91839163b88dafcb916004808201926020929091908290030181865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190613cf9565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815261ffff9091166004820152602401602060405180830381865afa158015610add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b019190613bb2565b6001600160a01b0316886001600160a01b031603610b2c57610b278585858a8686611d05565b610b3b565b610b3b8585858b8b87876125a3565b5050505050505050505050565b610b5061178b565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610b9261178b565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601610bcc576107aa33476119a3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190613d16565b9050610c5d823383611aa5565b5050565b600080808686610c776040880160208901613799565b876060013587604051602001610c91959493929190613e10565b6040516020818303038152906040529050600060405180606001604052808760a0013581526020018760800135815260200188604051602001610cff919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405281525090506000600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190613bb2565b90506001600160a01b038116630a512369610daa60208a018a613a99565b6001856040015187876040518663ffffffff1660e01b8152600401610dd3959493929190613ece565b6040805180830381865afa158015610def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e139190613f26565b9450945050505094509492505050565b610e2b61178b565b6001600160a01b038116610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105c9565b6107aa81611c2e565b610ed2612abe565b610eda61186f565b83516001600160a01b0316610f71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e66726f6d546f6b656e0000000000000000000000000000000000000000000060648201526084016105c9565b6000610f836040850160208601613799565b6001600160a01b03161415801561105357506003546001600160a01b031663a4cd49ba610fb36020860186613a99565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815261ffff9091166004820152602401602060405180830381865afa15801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e9190613bb2565b6001600160a01b03166110476040850160208601613799565b6001600160a01b031614155b6110df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f576f6f43726f7373436861696e526f7574657256333a2021647374496e666f7360448201527f2e746f546f6b656e00000000000000000000000000000000000000000000000060648201526084016105c9565b6001600160a01b03851661114f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f576f6f43726f7373436861696e526f7574657256333a2021746f00000000000060448201526064016105c9565b8351349060009081906001600160a01b03167fffffffffffffffffffffffff1111111111111111111111111111111111111112016112cc57828760400151111561121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e66726f6d416d6f756e7400000000000000000000000000000000000000000060648201526084016105c9565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001680885260408089015181517fd0e30db0000000000000000000000000000000000000000000000000000000008152915163d0e30db09260048082019260009290919082900301818588803b15801561129c57600080fd5b505af11580156112b0573d6000803e3d6000fd5b50505050508660400151836112c59190613f79565b92506112e0565b6112e0876000015133308a60400151612b43565b86602001516001600160a01b031687600001516001600160a01b0316146114dd578651600254604089015161131f92916001600160a01b031690612ccd565b600061132e6020870187613799565b6001600160a01b03161461141d576002546001600160a01b031663199b83fa61135a6020880188613799565b6113676020890189613799565b8a600001518b602001518c604001518d60600151308d806020019061138c9190613f90565b6040518a63ffffffff1660e01b81526004016113b099989796959493929190613ffc565b6020604051808303816000875af11580156113cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f39190613d16565b600654909250620186a09061140c9061ffff168461405e565b611416919061409b565b905061157c565b600254875160208901516040808b015160608c015191517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201529284166024840152604483015260648201523060848201528a821660a4820152911690637dc203829060c4016020604051808303816000875af11580156114b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d69190613d16565b915061157c565b8660600151876040015114611574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e6d696e427269646765416d6f756e740000000000000000000000000000000060648201526084016105c9565b866040015191505b60208701516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116039190613d16565b821115611691576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f576f6f43726f7373436861696e526f7574657256333a2021627269646765416d60448201527f6f756e740000000000000000000000000000000000000000000000000000000060648201526084016105c9565b61169b8183613f79565b91506116ac898985858b8b8a612e4f565b6001600160a01b038816336001600160a01b03168a7f546dc08c5438b68796e5047ad2ac863ab74300bdf49457917d47021f090c45c48a600001518b604001518c602001518d606001518960006001600160a01b03168e60000160208101906117159190613799565b6001600160a01b03161461172a57600161172d565b60005b604080516001600160a01b039788168152602081019690965293909516928401929092526060830152608082015260ff90911660a082015260c0810186905260e00160405180910390a450505061178360018055565b505050505050565b6000546001600160a01b03163314610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105c9565b6118076136e7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6002600154036118db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105c9565b6002600155565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611990576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190613d16565b61199c565b816001600160a01b0316315b9392505050565b604080516000808252602082019092526001600160a01b0384169083906040516119cd91906140d6565b60006040518083038185875af1925050503d8060008114611a0a576040519150601f19603f3d011682016040523d82523d6000602084013e611a0f565b606091505b5050905080611aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c656400000000000000000000000060648201526084016105c9565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691611b2f91906140d6565b6000604051808303816000865af19150503d8060008114611b6c576040519150601f19603f3d011682016040523d82523d6000602084013e611b71565b606091505b5091509150818015611b9b575080511580611b9b575080806020019051810190611b9b91906140f2565b611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c65640000000000000000000000000000000000000060648201526084016105c9565b5050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611c9e612abe565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118523390565b336001600160a01b0385167fffffffffffffffffffffffff111111111111111111111111111111111111111201611e3157611d4086856119a3565b856001600160a01b0316816001600160a01b0316887fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000000000000000000000000000000000000000000000888a73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8a8c60006001600160a01b03168c600001516001600160a01b031614611dd5576001611dd8565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a450611783565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e8c57600080fd5b505af1158015611ea0573d6000803e3d6000fd5b505084516001600160a01b031615925061224191505057600654600090620186a090611ed69062010000900461ffff168761405e565b611ee0919061409b565b90506000611eee8287613f79565b600254909150611f29907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031683612ccd565b600260009054906101000a90046001600160a01b03166001600160a01b031663199b83fa856000015186600001517f00000000000000000000000000000000000000000000000000000000000000008b868b8f8c602001516040518963ffffffff1660e01b8152600401611fa4989796959493929190614114565b6020604051808303816000875af1925050508015611ffd575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611ffa91810190613d16565b60015b6121615760025461203a907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166000612ccd565b6120657f00000000000000000000000000000000000000000000000000000000000000008988611aa5565b876001600160a01b0316836001600160a01b03168a7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f00000000000000000000000000000000000000000000000000000000000000008a8c7f00000000000000000000000000000000000000000000000000000000000000008c8e60006001600160a01b03168e600001516001600160a01b031614612106576001612109565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a461223a565b886001600160a01b0316846001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000000000000000000000000000000000000000000000868d8e8d8960006001600160a01b03168f600001516001600160a01b0316146121e25760016121e5565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c082015260e081018990529051908190036101000190a4505b505061259a565b600254612279907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b031686612ccd565b6002546040517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000081166004830152878116602483015260448201879052606482018690528881166084830181905260a483015290911690637dc203829060c4016020604051808303816000875af192505050801561235d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261235a91810190613d16565b60015b6124c15760025461239a907f0000000000000000000000000000000000000000000000000000000000000000906001600160a01b03166000612ccd565b6123c57f00000000000000000000000000000000000000000000000000000000000000008786611aa5565b856001600160a01b0316816001600160a01b0316887fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000000000000000000000000000000000000000000000888a7f00000000000000000000000000000000000000000000000000000000000000008a8c60006001600160a01b03168c600001516001600160a01b031614612466576001612469565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a461259a565b866001600160a01b0316826001600160a01b0316897fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000000000000000000000000000000000000000000000898b8c8b8960006001600160a01b03168d600001516001600160a01b031614612542576001612545565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4505b50505050505050565b336001600160a01b038086169087160361267e576125c2858886611aa5565b866001600160a01b0316816001600160a01b0316897fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c88888b8c8a8c60006001600160a01b03168c600001516001600160a01b031614612623576001612626565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4612ab4565b600654600090620186a09061269d9062010000900461ffff168761405e565b6126a7919061409b565b90506126b38186613f79565b6002549095506126ce9087906001600160a01b031687612ccd565b82516001600160a01b03161561292657600260009054906101000a90046001600160a01b03166001600160a01b031663199b83fa84600001518560000151898b8a8a8f8b602001516040518963ffffffff1660e01b8152600401612739989796959493929190614114565b6020604051808303816000875af1925050508015612792575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261278f91810190613d16565b60015b612869576127a08186614174565b94506127ad868987611aa5565b876001600160a01b0316826001600160a01b03168a7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c89898c8c8b8d60006001600160a01b03168d600001516001600160a01b03161461280e576001612811565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4612ab2565b886001600160a01b0316836001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c8a8a8d8e8c8960006001600160a01b03168e600001516001600160a01b0316146128ca5760016128cd565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c082015260e081018890529051908190036101000190a450612ab2565b6002546040517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152898116602483015260448201889052606482018790528a81166084830181905260a483015290911690637dc203829060c4016020604051808303816000875af19250505080156129ea575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526129e791810190613d16565b60015b6129f9576127ad868987611aa5565b886001600160a01b0316836001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c8a8a8d8e8c8960006001600160a01b03168e600001516001600160a01b031614612a5a576001612a5d565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4505b505b5050505050505050565b60005474010000000000000000000000000000000000000000900460ff1615610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016105c9565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612bd591906140d6565b6000604051808303816000865af19150503d8060008114612c12576040519150601f19603f3d011682016040523d82523d6000602084013e612c17565b606091505b5091509150818015612c41575080511580612c41575080806020019051810190612c4191906140f2565b611783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c656400000000000000000000000000000060648201526084016105c9565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839290871691612d5791906140d6565b6000604051808303816000865af19150503d8060008114612d94576040519150601f19603f3d011682016040523d82523d6000602084013e612d99565b606091505b5091509150818015612dc3575080511580612dc3575080806020019051810190612dc391906140f2565b611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c656400000000000000000000000000000000000000000060648201526084016105c9565b600354604080517fb88dafcb00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163498f309791839163b88dafcb9160048083019260209291908290030181865afa158015612eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ede9190613cf9565b60208701516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa158015612f48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6c9190613d16565b11612ff9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e627269646765546f6b656e000000000000000000000000000000000000000060648201526084016105c9565b6003546000906001600160a01b031663498f309761301a6020860186613a99565b61302a6060870160408801613799565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa15801561308f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b39190613d16565b11613140576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f576f6f43726f7373436861696e526f7574657256333a2021647374496e666f7360448201527f2e627269646765546f6b656e000000000000000000000000000000000000000060648201526084016105c9565b600087876131546040860160208701613799565b85606001358560405160200161316e959493929190613e10565b604051602081830303815290604052905060006127106005546127106131949190613f79565b61319e908861405e565b6131a8919061409b565b905060006007816131bc6020880188613a99565b61ffff1681526020808201929092526040908101600020549051613217926001600160a01b03909216910160609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040529050600060405180606001604052808760a001358152602001876080013581526020018b604051602001613285919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405281525090506000600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190613bb2565b90507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031688602001516001600160a01b0316036133f7576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156133cc57600080fd5b505af11580156133e0573d6000803e3d6000fd5b50505050888a6133f09190614174565b9950613489565b602080890151600354604080517f0517cb760000000000000000000000000000000000000000000000000000000081529051613489946001600160a01b0390931692630517cb7692600480820193918290030181865afa15801561345f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134839190613bb2565b8b612ccd565b6001600160a01b038116639fbf10fc8b6134a660208b018b613a99565b600354604080517fb88dafcb00000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163498f309791839163b88dafcb916004808201926020929091908290030181865afa158015613511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135359190613cf9565b60208f01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa15801561359f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c39190613d16565b6003546001600160a01b031663498f30976135e160208f018f613a99565b8e60400160208101906135f49190613799565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190613d16565b338f8b8a8c8f6040518b63ffffffff1660e01b81526004016136a79998979695949392919061418c565b6000604051808303818588803b1580156136c057600080fd5b505af11580156136d4573d6000803e3d6000fd5b5050505050505050505050505050505050565b60005474010000000000000000000000000000000000000000900460ff16610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016105c9565b60006020828403121561377d57600080fd5b5035919050565b6001600160a01b03811681146107aa57600080fd5b6000602082840312156137ab57600080fd5b813561199c81613784565b61ffff811681146107aa57600080fd5b600080604083850312156137d957600080fd5b82356137e4816137b6565b915060208301356137f481613784565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613851576138516137ff565b60405290565b6040805190810167ffffffffffffffff81118282101715613851576138516137ff565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c16137ff565b604052919050565b600067ffffffffffffffff8211156138e3576138e36137ff565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261392057600080fd5b813561393361392e826138c9565b61387a565b81815284602083860101111561394857600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561397e57600080fd5b8635613989816137b6565b9550602087013567ffffffffffffffff808211156139a657600080fd5b6139b28a838b0161390f565b965060408901359550606089013591506139cb82613784565b9093506080880135925060a088013590808211156139e857600080fd5b506139f589828a0161390f565b9150509295509295509295565b600060c08284031215613a1457600080fd5b50919050565b600060408284031215613a1457600080fd5b6000806000806101208587031215613a4357600080fd5b843593506020850135613a5581613784565b9250613a648660408701613a02565b915061010085013567ffffffffffffffff811115613a8157600080fd5b613a8d87828801613a1a565b91505092959194509250565b600060208284031215613aab57600080fd5b813561199c816137b6565b6000806000806000808688036101c0811215613ad157600080fd5b873596506020880135613ae381613784565b955060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b1557600080fd5b50613b1e61382e565b6040880135613b2c81613784565b81526060880135613b3c81613784565b60208201526080880135604082015260a088013560608201529350613b648860c08901613a02565b925061018087013567ffffffffffffffff80821115613b8257600080fd5b613b8e8a838b01613a1a565b93506101a0890135915080821115613ba557600080fd5b506139f589828a01613a1a565b600060208284031215613bc457600080fd5b815161199c81613784565b60005b83811015613bea578181015183820152602001613bd2565b83811115613bf9576000848401525b50505050565b600080600080600060a08688031215613c1757600080fd5b85519450602080870151613c2a81613784565b6040880151909550613c3b81613784565b60608801516080890151919550935067ffffffffffffffff80821115613c6057600080fd5b908801906040828b031215613c7457600080fd5b613c7c613857565b8251613c8781613784565b81528284015182811115613c9a57600080fd5b8084019350508a601f840112613caf57600080fd5b82519150613cbf61392e836138c9565b8281528b85848601011115613cd357600080fd5b613ce283868301878701613bcf565b808583015250809450505050509295509295909350565b600060208284031215613d0b57600080fd5b815161199c816137b6565b600060208284031215613d2857600080fd5b5051919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60008135613d8581613784565b6001600160a01b031683526020820135368390037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112613dc657600080fd5b820160208101903567ffffffffffffffff811115613de357600080fd5b803603821315613df257600080fd5b60406020860152613e07604086018284613d2f565b95945050505050565b85815260006001600160a01b03808716602084015280861660408401525083606083015260a06080830152613e4860a0830184613d78565b979650505050505050565b60008151808452613e6b816020860160208601613bcf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b80518252602081015160208301526000604082015160606040850152613ec66060850182613e53565b949350505050565b61ffff8616815260ff8516602082015260a060408201526000613ef460a0830186613e53565b8281036060840152613f068186613e53565b90508281036080840152613f1a8185613e9d565b98975050505050505050565b60008060408385031215613f3957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613f8b57613f8b613f4a565b500390565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fc557600080fd5b83018035915067ffffffffffffffff821115613fe057600080fd5b602001915036819003821315613ff557600080fd5b9250929050565b60006101006001600160a01b03808d168452808c166020850152808b166040850152808a1660608501528860808501528760a085015280871660c0850152508060e084015261404e8184018587613d2f565b9c9b505050505050505050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561409657614096613f4a565b500290565b6000826140d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082516140e8818460208701613bcf565b9190910192915050565b60006020828403121561410457600080fd5b8151801515811461199c57600080fd5b60006101006001600160a01b03808c168452808b166020850152808a16604085015280891660608501528760808501528660a085015280861660c0850152508060e084015261416581840185613e53565b9b9a5050505050505050505050565b6000821982111561418757614187613f4a565b500190565b600061012061ffff8c1683528a60208401528960408401526001600160a01b03891660608401528760808401528660a08401528060c08401526141d181840187613e9d565b905082810360e08401526141e58186613e53565b905082810361010084015261404e8185613e5356fea2646970667358221220d1ec554da5158dca6e209c9c8564ae6967834e93ac85c98bb014ee9a0ed4f74364736f6c634300080e0033000000000000000000000000420000000000000000000000000000000000000600000000000000000000000027425e9fb6a9a625e8484cfd9620851d1fa322e5000000000000000000000000be07e5eb5e4b6ca700586b41e4ecab614ad3a05b
Deployed Bytecode
0x60806040526004361061019a5760003560e01c80638da5cb5b116100e1578063e56f85401161008a578063f2fde38b11610064578063f2fde38b14610498578063f6af6957146104b8578063fd594a08146104ee578063fdeba4e51461050157600080fd5b8063e56f854014610431578063ecb911de14610466578063ecefc7051461048157600080fd5b8063b2855b4f116100bb578063b2855b4f146103bd578063b9292141146103dd578063e1a4e72a1461041157600080fd5b80638da5cb5b1461035f57806397ebb4521461037d578063ab8236f31461039d57600080fd5b80635c975abb1161014357806383af55501161011d57806383af5550146102fe5780638456cb591461032257806388c4cb361461033757600080fd5b80635c975abb1461028e5780636ebc51e1146102c9578063715018a6146102e957600080fd5b8063403a01e511610174578063403a01e51461022e5780634dba39a21461024e57806358800adf1461026e57600080fd5b806339e7fddc146101a65780633f4ba83a146101e35780633fc8cef3146101fa57600080fd5b366101a157005b600080fd5b3480156101b257600080fd5b506004546101c6906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b3480156101ef57600080fd5b506101f8610521565b005b34801561020657600080fd5b506101c67f000000000000000000000000420000000000000000000000000000000000000681565b34801561023a57600080fd5b506101f861024936600461376b565b610533565b34801561025a57600080fd5b506101f8610269366004613799565b6105d7565b34801561027a57600080fd5b506003546101c6906001600160a01b031681565b34801561029a57600080fd5b5060005474010000000000000000000000000000000000000000900460ff1660405190151581526020016101da565b3480156102d557600080fd5b506101f86102e4366004613799565b6106af565b3480156102f557600080fd5b506101f86107ad565b34801561030a57600080fd5b5061031460055481565b6040519081526020016101da565b34801561032e57600080fd5b506101f86107bf565b34801561034357600080fd5b506101c673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b34801561036b57600080fd5b506000546001600160a01b03166101c6565b34801561038957600080fd5b506101f86103983660046137c6565b6107cf565b3480156103a957600080fd5b506101f86103b8366004613965565b6108b8565b3480156103c957600080fd5b506101f86103d8366004613799565b610b48565b3480156103e957600080fd5b506006546103fe9062010000900461ffff1681565b60405161ffff90911681526020016101da565b34801561041d57600080fd5b506101f861042c366004613799565b610b8a565b34801561043d57600080fd5b5061045161044c366004613a2c565b610c61565b604080519283526020830191909152016101da565b34801561047257600080fd5b506006546103fe9061ffff1681565b34801561048d57600080fd5b50610314620186a081565b3480156104a457600080fd5b506101f86104b3366004613799565b610e23565b3480156104c457600080fd5b506101c66104d3366004613a99565b6007602052600090815260409020546001600160a01b031681565b6101f86104fc366004613ab6565b610eca565b34801561050d57600080fd5b506002546101c6906001600160a01b031681565b61052961178b565b6105316117ff565b565b61053b61178b565b6127108111156105d2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f576f6f43726f7373436861696e526f7574657256333a20215f6272696467655360448201527f6c6970706167650000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b600555565b6105df61178b565b6001600160a01b038116610675576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f576f6f43726f7373436861696e526f7574657256333a20215f776f6f526f757460448201527f657200000000000000000000000000000000000000000000000000000000000060648201526084016105c9565b600280547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6106b761186f565b6004546001600160a01b0316610729576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f576f6f43726f7373436861696e526f7574657256333a2021666565416464720060448201526064016105c9565b600061073582306118e2565b905080156107a0577fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b0383160161078857600454610783906001600160a01b0316826119a3565b6107a0565b6004546107a09083906001600160a01b031683611aa5565b506107aa60018055565b50565b6107b561178b565b6105316000611c2e565b6107c761178b565b610531611c96565b6107d761178b565b6001600160a01b03811661086c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f576f6f43726f7373436861696e526f7574657256333a20215f63726f7373526f60448201527f757465720000000000000000000000000000000000000000000000000000000060648201526084016105c9565b61ffff91909116600090815260076020526040902080547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b03909216919091179055565b600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa15801561090b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092f9190613bb2565b6001600160a01b0316336001600160a01b0316146109cf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f576f6f43726f7373436861696e526f7574657256333a20494e56414c49445f4360448201527f414c4c455200000000000000000000000000000000000000000000000000000060648201526084016105c9565b6000806000806000858060200190518101906109eb9190613bff565b600354604080517fb88dafcb0000000000000000000000000000000000000000000000000000000081529051969b5094995092975090955093506001600160a01b03169163a4cd49ba91839163b88dafcb916004808201926020929091908290030181865afa158015610a62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a869190613cf9565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815261ffff9091166004820152602401602060405180830381865afa158015610add573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b019190613bb2565b6001600160a01b0316886001600160a01b031603610b2c57610b278585858a8686611d05565b610b3b565b610b3b8585858b8b87876125a3565b5050505050505050505050565b610b5061178b565b600480547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b610b9261178b565b7fffffffffffffffffffffffff11111111111111111111111111111111111111126001600160a01b03821601610bcc576107aa33476119a3565b6040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526000906001600160a01b038316906370a0823190602401602060405180830381865afa158015610c2c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c509190613d16565b9050610c5d823383611aa5565b5050565b600080808686610c776040880160208901613799565b876060013587604051602001610c91959493929190613e10565b6040516020818303038152906040529050600060405180606001604052808760a0013581526020018760800135815260200188604051602001610cff919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405281525090506000600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d68573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d8c9190613bb2565b90506001600160a01b038116630a512369610daa60208a018a613a99565b6001856040015187876040518663ffffffff1660e01b8152600401610dd3959493929190613ece565b6040805180830381865afa158015610def573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e139190613f26565b9450945050505094509492505050565b610e2b61178b565b6001600160a01b038116610ec1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f646472657373000000000000000000000000000000000000000000000000000060648201526084016105c9565b6107aa81611c2e565b610ed2612abe565b610eda61186f565b83516001600160a01b0316610f71576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e66726f6d546f6b656e0000000000000000000000000000000000000000000060648201526084016105c9565b6000610f836040850160208601613799565b6001600160a01b03161415801561105357506003546001600160a01b031663a4cd49ba610fb36020860186613a99565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e084901b16815261ffff9091166004820152602401602060405180830381865afa15801561100a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102e9190613bb2565b6001600160a01b03166110476040850160208601613799565b6001600160a01b031614155b6110df576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602860248201527f576f6f43726f7373436861696e526f7574657256333a2021647374496e666f7360448201527f2e746f546f6b656e00000000000000000000000000000000000000000000000060648201526084016105c9565b6001600160a01b03851661114f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601a60248201527f576f6f43726f7373436861696e526f7574657256333a2021746f00000000000060448201526064016105c9565b8351349060009081906001600160a01b03167fffffffffffffffffffffffff1111111111111111111111111111111111111112016112cc57828760400151111561121b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e66726f6d416d6f756e7400000000000000000000000000000000000000000060648201526084016105c9565b6001600160a01b037f00000000000000000000000042000000000000000000000000000000000000061680885260408089015181517fd0e30db0000000000000000000000000000000000000000000000000000000008152915163d0e30db09260048082019260009290919082900301818588803b15801561129c57600080fd5b505af11580156112b0573d6000803e3d6000fd5b50505050508660400151836112c59190613f79565b92506112e0565b6112e0876000015133308a60400151612b43565b86602001516001600160a01b031687600001516001600160a01b0316146114dd578651600254604089015161131f92916001600160a01b031690612ccd565b600061132e6020870187613799565b6001600160a01b03161461141d576002546001600160a01b031663199b83fa61135a6020880188613799565b6113676020890189613799565b8a600001518b602001518c604001518d60600151308d806020019061138c9190613f90565b6040518a63ffffffff1660e01b81526004016113b099989796959493929190613ffc565b6020604051808303816000875af11580156113cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113f39190613d16565b600654909250620186a09061140c9061ffff168461405e565b611416919061409b565b905061157c565b600254875160208901516040808b015160608c015191517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b0394851660048201529284166024840152604483015260648201523060848201528a821660a4820152911690637dc203829060c4016020604051808303816000875af11580156114b2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114d69190613d16565b915061157c565b8660600151876040015114611574576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603060248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e6d696e427269646765416d6f756e740000000000000000000000000000000060648201526084016105c9565b866040015191505b60208701516040517f70a082310000000000000000000000000000000000000000000000000000000081523060048201526001600160a01b03909116906370a0823190602401602060405180830381865afa1580156115df573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116039190613d16565b821115611691576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f576f6f43726f7373436861696e526f7574657256333a2021627269646765416d60448201527f6f756e740000000000000000000000000000000000000000000000000000000060648201526084016105c9565b61169b8183613f79565b91506116ac898985858b8b8a612e4f565b6001600160a01b038816336001600160a01b03168a7f546dc08c5438b68796e5047ad2ac863ab74300bdf49457917d47021f090c45c48a600001518b604001518c602001518d606001518960006001600160a01b03168e60000160208101906117159190613799565b6001600160a01b03161461172a57600161172d565b60005b604080516001600160a01b039788168152602081019690965293909516928401929092526060830152608082015260ff90911660a082015260c0810186905260e00160405180910390a450505061178360018055565b505050505050565b6000546001600160a01b03163314610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016105c9565b6118076136e7565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b03909116815260200160405180910390a1565b6002600154036118db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016105c9565b6002600155565b60006001600160a01b03831673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611990576040517f70a082310000000000000000000000000000000000000000000000000000000081526001600160a01b0383811660048301528416906370a0823190602401602060405180830381865afa158015611967573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061198b9190613d16565b61199c565b816001600160a01b0316315b9392505050565b604080516000808252602082019092526001600160a01b0384169083906040516119cd91906140d6565b60006040518083038185875af1925050503d8060008114611a0a576040519150601f19603f3d011682016040523d82523d6000602084013e611a0f565b606091505b5050905080611aa0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603460248201527f5472616e7366657248656c7065723a3a736166655472616e736665724554483a60448201527f20455448207472616e73666572206661696c656400000000000000000000000060648201526084016105c9565b505050565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb000000000000000000000000000000000000000000000000000000001790529151600092839290871691611b2f91906140d6565b6000604051808303816000865af19150503d8060008114611b6c576040519150601f19603f3d011682016040523d82523d6000602084013e611b71565b606091505b5091509150818015611b9b575080511580611b9b575080806020019051810190611b9b91906140f2565b611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f5472616e7366657248656c7065723a3a736166655472616e736665723a20747260448201527f616e73666572206661696c65640000000000000000000000000000000000000060648201526084016105c9565b5050505050565b600080546001600160a01b038381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611c9e612abe565b600080547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586118523390565b336001600160a01b0385167fffffffffffffffffffffffff111111111111111111111111111111111111111201611e3157611d4086856119a3565b856001600160a01b0316816001600160a01b0316887fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000004200000000000000000000000000000000000006888a73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee8a8c60006001600160a01b03168c600001516001600160a01b031614611dd5576001611dd8565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a450611783565b7f00000000000000000000000042000000000000000000000000000000000000066001600160a01b031663d0e30db0856040518263ffffffff1660e01b81526004016000604051808303818588803b158015611e8c57600080fd5b505af1158015611ea0573d6000803e3d6000fd5b505084516001600160a01b031615925061224191505057600654600090620186a090611ed69062010000900461ffff168761405e565b611ee0919061409b565b90506000611eee8287613f79565b600254909150611f29907f0000000000000000000000004200000000000000000000000000000000000006906001600160a01b031683612ccd565b600260009054906101000a90046001600160a01b03166001600160a01b031663199b83fa856000015186600001517f00000000000000000000000042000000000000000000000000000000000000068b868b8f8c602001516040518963ffffffff1660e01b8152600401611fa4989796959493929190614114565b6020604051808303816000875af1925050508015611ffd575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611ffa91810190613d16565b60015b6121615760025461203a907f0000000000000000000000004200000000000000000000000000000000000006906001600160a01b03166000612ccd565b6120657f00000000000000000000000042000000000000000000000000000000000000068988611aa5565b876001600160a01b0316836001600160a01b03168a7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f00000000000000000000000042000000000000000000000000000000000000068a8c7f00000000000000000000000042000000000000000000000000000000000000068c8e60006001600160a01b03168e600001516001600160a01b031614612106576001612109565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a461223a565b886001600160a01b0316846001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000004200000000000000000000000000000000000006868d8e8d8960006001600160a01b03168f600001516001600160a01b0316146121e25760016121e5565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c082015260e081018990529051908190036101000190a4505b505061259a565b600254612279907f0000000000000000000000004200000000000000000000000000000000000006906001600160a01b031686612ccd565b6002546040517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b037f000000000000000000000000420000000000000000000000000000000000000681166004830152878116602483015260448201879052606482018690528881166084830181905260a483015290911690637dc203829060c4016020604051808303816000875af192505050801561235d575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261235a91810190613d16565b60015b6124c15760025461239a907f0000000000000000000000004200000000000000000000000000000000000006906001600160a01b03166000612ccd565b6123c57f00000000000000000000000042000000000000000000000000000000000000068786611aa5565b856001600160a01b0316816001600160a01b0316887fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000004200000000000000000000000000000000000006888a7f00000000000000000000000042000000000000000000000000000000000000068a8c60006001600160a01b03168c600001516001600160a01b031614612466576001612469565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a461259a565b866001600160a01b0316826001600160a01b0316897fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c7f0000000000000000000000004200000000000000000000000000000000000006898b8c8b8960006001600160a01b03168d600001516001600160a01b031614612542576001612545565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4505b50505050505050565b336001600160a01b038086169087160361267e576125c2858886611aa5565b866001600160a01b0316816001600160a01b0316897fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c88888b8c8a8c60006001600160a01b03168c600001516001600160a01b031614612623576001612626565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4612ab4565b600654600090620186a09061269d9062010000900461ffff168761405e565b6126a7919061409b565b90506126b38186613f79565b6002549095506126ce9087906001600160a01b031687612ccd565b82516001600160a01b03161561292657600260009054906101000a90046001600160a01b03166001600160a01b031663199b83fa84600001518560000151898b8a8a8f8b602001516040518963ffffffff1660e01b8152600401612739989796959493929190614114565b6020604051808303816000875af1925050508015612792575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016820190925261278f91810190613d16565b60015b612869576127a08186614174565b94506127ad868987611aa5565b876001600160a01b0316826001600160a01b03168a7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c89898c8c8b8d60006001600160a01b03168d600001516001600160a01b03161461280e576001612811565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4612ab2565b886001600160a01b0316836001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c8a8a8d8e8c8960006001600160a01b03168e600001516001600160a01b0316146128ca5760016128cd565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c082015260e081018890529051908190036101000190a450612ab2565b6002546040517f7dc203820000000000000000000000000000000000000000000000000000000081526001600160a01b038881166004830152898116602483015260448201889052606482018790528a81166084830181905260a483015290911690637dc203829060c4016020604051808303816000875af19250505080156129ea575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526129e791810190613d16565b60015b6129f9576127ad868987611aa5565b886001600160a01b0316836001600160a01b03168b7fe025e234368c681f94aa603de304cf6708c5638fe7454d6ed22a55430776a71c8a8a8d8e8c8960006001600160a01b03168e600001516001600160a01b031614612a5a576001612a5d565b60005b604080516001600160a01b039889168152602081019790975294871686860152929095166060850152608084015260a083019390935260ff90921660c0820152600060e08201529051908190036101000190a4505b505b5050505050505050565b60005474010000000000000000000000000000000000000000900460ff1615610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a207061757365640000000000000000000000000000000060448201526064016105c9565b604080516001600160a01b0385811660248301528481166044830152606480830185905283518084039091018152608490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f23b872dd000000000000000000000000000000000000000000000000000000001790529151600092839290881691612bd591906140d6565b6000604051808303816000865af19150503d8060008114612c12576040519150601f19603f3d011682016040523d82523d6000602084013e612c17565b606091505b5091509150818015612c41575080511580612c41575080806020019051810190612c4191906140f2565b611783576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a20747260448201527f616e7366657246726f6d206661696c656400000000000000000000000000000060648201526084016105c9565b604080516001600160a01b038481166024830152604480830185905283518084039091018152606490920183526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f095ea7b3000000000000000000000000000000000000000000000000000000001790529151600092839290871691612d5791906140d6565b6000604051808303816000865af19150503d8060008114612d94576040519150601f19603f3d011682016040523d82523d6000602084013e612d99565b606091505b5091509150818015612dc3575080511580612dc3575080806020019051810190612dc391906140f2565b611c27576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f5472616e7366657248656c7065723a3a73616665417070726f76653a2061707060448201527f726f7665206661696c656400000000000000000000000000000000000000000060648201526084016105c9565b600354604080517fb88dafcb00000000000000000000000000000000000000000000000000000000815290516000926001600160a01b03169163498f309791839163b88dafcb9160048083019260209291908290030181865afa158015612eba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ede9190613cf9565b60208701516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa158015612f48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612f6c9190613d16565b11612ff9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f576f6f43726f7373436861696e526f7574657256333a2021737263496e666f7360448201527f2e627269646765546f6b656e000000000000000000000000000000000000000060648201526084016105c9565b6003546000906001600160a01b031663498f309761301a6020860186613a99565b61302a6060870160408801613799565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa15801561308f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130b39190613d16565b11613140576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f576f6f43726f7373436861696e526f7574657256333a2021647374496e666f7360448201527f2e627269646765546f6b656e000000000000000000000000000000000000000060648201526084016105c9565b600087876131546040860160208701613799565b85606001358560405160200161316e959493929190613e10565b604051602081830303815290604052905060006127106005546127106131949190613f79565b61319e908861405e565b6131a8919061409b565b905060006007816131bc6020880188613a99565b61ffff1681526020808201929092526040908101600020549051613217926001600160a01b03909216910160609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b6040516020818303038152906040529050600060405180606001604052808760a001358152602001876080013581526020018b604051602001613285919060609190911b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016815260140190565b60405160208183030381529060405281525090506000600360009054906101000a90046001600160a01b03166001600160a01b0316630517cb766040518163ffffffff1660e01b8152600401602060405180830381865afa1580156132ee573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133129190613bb2565b90507f00000000000000000000000042000000000000000000000000000000000000066001600160a01b031688602001516001600160a01b0316036133f7576040517f2e1a7d4d000000000000000000000000000000000000000000000000000000008152600481018a90527f00000000000000000000000042000000000000000000000000000000000000066001600160a01b031690632e1a7d4d90602401600060405180830381600087803b1580156133cc57600080fd5b505af11580156133e0573d6000803e3d6000fd5b50505050888a6133f09190614174565b9950613489565b602080890151600354604080517f0517cb760000000000000000000000000000000000000000000000000000000081529051613489946001600160a01b0390931692630517cb7692600480820193918290030181865afa15801561345f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134839190613bb2565b8b612ccd565b6001600160a01b038116639fbf10fc8b6134a660208b018b613a99565b600354604080517fb88dafcb00000000000000000000000000000000000000000000000000000000815290516001600160a01b039092169163498f309791839163b88dafcb916004808201926020929091908290030181865afa158015613511573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135359190613cf9565b60208f01516040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa15801561359f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135c39190613d16565b6003546001600160a01b031663498f30976135e160208f018f613a99565b8e60400160208101906135f49190613799565b6040517fffffffff0000000000000000000000000000000000000000000000000000000060e085901b16815261ffff90921660048301526001600160a01b03166024820152604401602060405180830381865afa158015613659573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061367d9190613d16565b338f8b8a8c8f6040518b63ffffffff1660e01b81526004016136a79998979695949392919061418c565b6000604051808303818588803b1580156136c057600080fd5b505af11580156136d4573d6000803e3d6000fd5b5050505050505050505050505050505050565b60005474010000000000000000000000000000000000000000900460ff16610531576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f742070617573656400000000000000000000000060448201526064016105c9565b60006020828403121561377d57600080fd5b5035919050565b6001600160a01b03811681146107aa57600080fd5b6000602082840312156137ab57600080fd5b813561199c81613784565b61ffff811681146107aa57600080fd5b600080604083850312156137d957600080fd5b82356137e4816137b6565b915060208301356137f481613784565b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040516080810167ffffffffffffffff81118282101715613851576138516137ff565b60405290565b6040805190810167ffffffffffffffff81118282101715613851576138516137ff565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156138c1576138c16137ff565b604052919050565b600067ffffffffffffffff8211156138e3576138e36137ff565b50601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600082601f83011261392057600080fd5b813561393361392e826138c9565b61387a565b81815284602083860101111561394857600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060c0878903121561397e57600080fd5b8635613989816137b6565b9550602087013567ffffffffffffffff808211156139a657600080fd5b6139b28a838b0161390f565b965060408901359550606089013591506139cb82613784565b9093506080880135925060a088013590808211156139e857600080fd5b506139f589828a0161390f565b9150509295509295509295565b600060c08284031215613a1457600080fd5b50919050565b600060408284031215613a1457600080fd5b6000806000806101208587031215613a4357600080fd5b843593506020850135613a5581613784565b9250613a648660408701613a02565b915061010085013567ffffffffffffffff811115613a8157600080fd5b613a8d87828801613a1a565b91505092959194509250565b600060208284031215613aab57600080fd5b813561199c816137b6565b6000806000806000808688036101c0811215613ad157600080fd5b873596506020880135613ae381613784565b955060807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082011215613b1557600080fd5b50613b1e61382e565b6040880135613b2c81613784565b81526060880135613b3c81613784565b60208201526080880135604082015260a088013560608201529350613b648860c08901613a02565b925061018087013567ffffffffffffffff80821115613b8257600080fd5b613b8e8a838b01613a1a565b93506101a0890135915080821115613ba557600080fd5b506139f589828a01613a1a565b600060208284031215613bc457600080fd5b815161199c81613784565b60005b83811015613bea578181015183820152602001613bd2565b83811115613bf9576000848401525b50505050565b600080600080600060a08688031215613c1757600080fd5b85519450602080870151613c2a81613784565b6040880151909550613c3b81613784565b60608801516080890151919550935067ffffffffffffffff80821115613c6057600080fd5b908801906040828b031215613c7457600080fd5b613c7c613857565b8251613c8781613784565b81528284015182811115613c9a57600080fd5b8084019350508a601f840112613caf57600080fd5b82519150613cbf61392e836138c9565b8281528b85848601011115613cd357600080fd5b613ce283868301878701613bcf565b808583015250809450505050509295509295909350565b600060208284031215613d0b57600080fd5b815161199c816137b6565b600060208284031215613d2857600080fd5b5051919050565b8183528181602085013750600060208284010152600060207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f840116840101905092915050565b60008135613d8581613784565b6001600160a01b031683526020820135368390037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1018112613dc657600080fd5b820160208101903567ffffffffffffffff811115613de357600080fd5b803603821315613df257600080fd5b60406020860152613e07604086018284613d2f565b95945050505050565b85815260006001600160a01b03808716602084015280861660408401525083606083015260a06080830152613e4860a0830184613d78565b979650505050505050565b60008151808452613e6b816020860160208601613bcf565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b80518252602081015160208301526000604082015160606040850152613ec66060850182613e53565b949350505050565b61ffff8616815260ff8516602082015260a060408201526000613ef460a0830186613e53565b8281036060840152613f068186613e53565b90508281036080840152613f1a8185613e9d565b98975050505050505050565b60008060408385031215613f3957600080fd5b505080516020909101519092909150565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015613f8b57613f8b613f4a565b500390565b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112613fc557600080fd5b83018035915067ffffffffffffffff821115613fe057600080fd5b602001915036819003821315613ff557600080fd5b9250929050565b60006101006001600160a01b03808d168452808c166020850152808b166040850152808a1660608501528860808501528760a085015280871660c0850152508060e084015261404e8184018587613d2f565b9c9b505050505050505050505050565b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff048311821515161561409657614096613f4a565b500290565b6000826140d1577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b600082516140e8818460208701613bcf565b9190910192915050565b60006020828403121561410457600080fd5b8151801515811461199c57600080fd5b60006101006001600160a01b03808c168452808b166020850152808a16604085015280891660608501528760808501528660a085015280861660c0850152508060e084015261416581840185613e53565b9b9a5050505050505050505050565b6000821982111561418757614187613f4a565b500190565b600061012061ffff8c1683528a60208401528960408401526001600160a01b03891660608401528760808401528660a08401528060c08401526141d181840187613e9d565b905082810360e08401526141e58186613e53565b905082810361010084015261404e8185613e5356fea2646970667358221220d1ec554da5158dca6e209c9c8564ae6967834e93ac85c98bb014ee9a0ed4f74364736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000420000000000000000000000000000000000000600000000000000000000000027425e9fb6a9a625e8484cfd9620851d1fa322e5000000000000000000000000be07e5eb5e4b6ca700586b41e4ecab614ad3a05b
-----Decoded View---------------
Arg [0] : _weth (address): 0x4200000000000000000000000000000000000006
Arg [1] : _wooRouter (address): 0x27425e9FB6A9A625E8484CFD9620851D1Fa322E5
Arg [2] : _sgInfo (address): 0xbe07E5EB5e4B6ca700586b41e4eCAB614Ad3a05b
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000004200000000000000000000000000000000000006
Arg [1] : 00000000000000000000000027425e9fb6a9a625e8484cfd9620851d1fa322e5
Arg [2] : 000000000000000000000000be07e5eb5e4b6ca700586b41e4ecab614ad3a05b
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.