Source Code
Overview
ETH Balance
0.001 ETH
Eth Value
$4.20 (@ $4,201.60/ETH)Latest 25 from a total of 766 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap Exact In | 23638054 | 3 days ago | IN | 0 ETH | 0.00003367 | ||||
| Swap Exact In | 23615388 | 7 days ago | IN | 0 ETH | 0.00049152 | ||||
| Swap Exact In | 23589241 | 10 days ago | IN | 0 ETH | 0.00003945 | ||||
| Swap Exact In | 23580242 | 11 days ago | IN | 0 ETH | 0.00003932 | ||||
| Swap Exact In | 23579961 | 12 days ago | IN | 0 ETH | 0.00005316 | ||||
| Swap Exact In | 23571607 | 13 days ago | IN | 0 ETH | 0.00129618 | ||||
| Swap Exact In | 23562353 | 14 days ago | IN | 0 ETH | 0.00067801 | ||||
| Swap Exact In | 23562348 | 14 days ago | IN | 0 ETH | 0.00049178 | ||||
| Swap Exact In | 23549121 | 16 days ago | IN | 0 ETH | 0.00096389 | ||||
| Swap Exact In | 23519778 | 20 days ago | IN | 0.02 ETH | 0.00060346 | ||||
| Swap Exact In | 23512513 | 21 days ago | IN | 0 ETH | 0.00029748 | ||||
| Swap Exact In | 23512173 | 21 days ago | IN | 0 ETH | 0.00034831 | ||||
| Swap Exact In | 23508430 | 22 days ago | IN | 0 ETH | 0.00030953 | ||||
| Swap Exact In | 23500579 | 23 days ago | IN | 0.1 ETH | 0.00003788 | ||||
| Swap Exact In | 23500575 | 23 days ago | IN | 0 ETH | 0.00007624 | ||||
| Swap Exact In | 23500388 | 23 days ago | IN | 0.02 ETH | 0.00006626 | ||||
| Swap Exact In | 23485230 | 25 days ago | IN | 0 ETH | 0.00035152 | ||||
| Swap Exact In | 23482764 | 25 days ago | IN | 0 ETH | 0.00034937 | ||||
| Swap Exact In | 23480171 | 25 days ago | IN | 0 ETH | 0.0003131 | ||||
| Swap Exact In | 23479560 | 26 days ago | IN | 0 ETH | 0.00032628 | ||||
| Swap Exact In | 23477966 | 26 days ago | IN | 0 ETH | 0.00037184 | ||||
| Swap Exact In | 23476443 | 26 days ago | IN | 0 ETH | 0.00045416 | ||||
| Swap Exact In | 23476212 | 26 days ago | IN | 0.002 ETH | 0.00071161 | ||||
| Swap Exact In | 23476206 | 26 days ago | IN | 0.07 ETH | 0.00054629 | ||||
| Swap Exact In | 23476201 | 26 days ago | IN | 0.05 ETH | 0.00056863 |
Latest 25 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
To
|
|||
|---|---|---|---|---|---|---|---|
| Deposit | 23519778 | 20 days ago | 0.02 ETH | ||||
| Transfer | 23512513 | 21 days ago | 0.06694486 ETH | ||||
| Transfer | 23512513 | 21 days ago | 0.06694486 ETH | ||||
| Transfer | 23512173 | 21 days ago | 0.06387273 ETH | ||||
| Transfer | 23512173 | 21 days ago | 0.06387273 ETH | ||||
| Transfer | 23508430 | 22 days ago | 0.06925374 ETH | ||||
| Transfer | 23508430 | 22 days ago | 0.06925374 ETH | ||||
| Deposit | 23500579 | 23 days ago | 0.1 ETH | ||||
| Transfer | 23500575 | 23 days ago | 0.11673133 ETH | ||||
| Transfer | 23500575 | 23 days ago | 0.11673133 ETH | ||||
| Deposit | 23500388 | 23 days ago | 0.02 ETH | ||||
| Transfer | 23485230 | 25 days ago | 0.06897309 ETH | ||||
| Transfer | 23485230 | 25 days ago | 0.06897309 ETH | ||||
| Transfer | 23482764 | 25 days ago | 0.09264218 ETH | ||||
| Transfer | 23482764 | 25 days ago | 0.09264218 ETH | ||||
| Transfer | 23480171 | 25 days ago | 0.08043382 ETH | ||||
| Transfer | 23480171 | 25 days ago | 0.08043382 ETH | ||||
| Transfer | 23479560 | 26 days ago | 0.07368262 ETH | ||||
| Transfer | 23479560 | 26 days ago | 0.07368262 ETH | ||||
| Transfer | 23477966 | 26 days ago | 0.08392933 ETH | ||||
| Transfer | 23477966 | 26 days ago | 0.08392933 ETH | ||||
| Transfer | 23476443 | 26 days ago | 0.07960975 ETH | ||||
| Transfer | 23476443 | 26 days ago | 0.07960975 ETH | ||||
| Deposit | 23476212 | 26 days ago | 0.002 ETH | ||||
| Deposit | 23476206 | 26 days ago | 0.07 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Router
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 100000 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Ownable, Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {IRouter} from "./interfaces/IRouter.sol";
import {RouterLib} from "./libraries/RouterLib.sol";
import {TokenLib} from "./libraries/TokenLib.sol";
/**
* @title Router
* @dev Router contract for swapping tokens using a predefined route.
* The route must follow the PackedRoute format.
*/
contract Router is Ownable2Step, ReentrancyGuard, IRouter {
using EnumerableSet for EnumerableSet.AddressSet;
address public immutable WNATIVE;
EnumerableSet.AddressSet private _trustedLogics;
/**
* @dev The allowances represent the maximum amount of tokens that the logic contract can spend on behalf of the sender.
* It is always reseted at the end of the swap.
* The key is calculated as keccak256(abi.encodePacked(token, sender, user)).
*/
mapping(bytes32 key => uint256 allowance) private _allowances;
/**
* @dev Constructor for the Router contract.
*
* Requirements:
* - The wnative address must be a contract with code.
*/
constructor(address wnative, address initialOwner) Ownable(initialOwner) {
if (address(wnative).code.length == 0) revert Router__InvalidWnative();
WNATIVE = wnative;
}
/**
* @dev Only allows native token to be received from unwrapping wnative.
*/
receive() external payable {
if (msg.sender != WNATIVE) revert Router__OnlyWnative();
}
/**
* @dev Fallback function to validate and transfer tokens.
*/
fallback() external {
RouterLib.validateAndTransfer(_allowances);
}
/**
* @dev Returns the logic contract address at the specified index.
*/
function getTrustedLogicAt(uint256 index) external view override returns (address) {
return _trustedLogics.at(index);
}
/**
* @dev Returns the number of trusted logic contracts.
*/
function getTrustedLogicLength() external view override returns (uint256) {
return _trustedLogics.length();
}
/**
* @dev Swaps tokens from the sender to the recipient using the exact input amount. It will use the specified logic contract.
*
* Emits a {SwapExactIn} event.
*
* Requirements:
* - The logic contract must be a trusted logic contract.
* - The recipient address must not be zero or the router address.
* - The deadline must not have passed.
* - The input token and output token must not be the same.
* - If the amountIn is zero, the entire balance of the input token will be used and it must not be zero.
* - The entire amountIn of the input token must be spent.
* - The actual amount of tokenOut received must be greater than or equal to the amountOutMin.
*/
function swapExactIn(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOutMin,
address to,
uint256 deadline,
bytes calldata route
) external payable override nonReentrant returns (uint256 totalIn, uint256 totalOut) {
if (amountIn == 0) amountIn = tokenIn == address(0) ? msg.value : TokenLib.balanceOf(tokenIn, msg.sender);
_verifyParameters(amountIn, amountOutMin, to, deadline);
(totalIn, totalOut) = _swap(logic, tokenIn, tokenOut, amountIn, amountOutMin, msg.sender, to, route, true);
emit SwapExactIn(msg.sender, to, tokenIn, tokenOut, totalIn, totalOut);
}
/**
* @dev Swaps tokens from the sender to the recipient using the exact output amount. It will use the specified logic contract.
*
* Emits a {SwapExactOut} event.
*
* Requirements:
* - The logic contract must be a trusted logic contract.
* - The recipient address must not be zero or the router address.
* - The deadline must not have passed.
* - The input token and output token must not be the same.
* - If the amountInMax is zero, the entire balance of the input token will be used and it must not be zero.
* - The actual amount of tokenIn spent must be less than or equal to the amountInMax.
* - The actual amount of tokenOut received must be greater than or equal to the amountOut.
*/
function swapExactOut(
address logic,
address tokenIn,
address tokenOut,
uint256 amountOut,
uint256 amountInMax,
address to,
uint256 deadline,
bytes calldata route
) external payable override nonReentrant returns (uint256 totalIn, uint256 totalOut) {
_verifyParameters(amountInMax, amountOut, to, deadline);
(totalIn, totalOut) = _swap(logic, tokenIn, tokenOut, amountInMax, amountOut, msg.sender, to, route, false);
emit SwapExactOut(msg.sender, to, tokenIn, tokenOut, totalIn, totalOut);
}
/**
* @dev Simulates the swap of tokens using multiple routes and the specified logic contract.
* The simulation will revert with an array of amounts if the swap is valid.
*/
function simulate(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address to,
bool exactIn,
bytes[] calldata multiRoutes
) external payable override {
uint256 length = multiRoutes.length;
uint256[] memory amounts = new uint256[](length);
for (uint256 i; i < length;) {
(, bytes memory data) = address(this).delegatecall(
abi.encodeWithSelector(
IRouter.simulateSingle.selector,
logic,
tokenIn,
tokenOut,
amountIn,
amountOut,
to,
exactIn,
multiRoutes[i++]
)
);
if (bytes4(data) == IRouter.Router__SimulateSingle.selector) {
assembly ("memory-safe") {
mstore(add(amounts, mul(i, 32)), mload(add(data, 36)))
}
} else {
amounts[i - 1] = exactIn ? 0 : type(uint256).max;
}
}
revert Router__Simulations(amounts);
}
/**
* @dev Simulates the swap of tokens using a single route and the specified logic contract.
* The simulation will revert with the total amount of tokenIn or tokenOut if the swap is valid.
*/
function simulateSingle(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address to,
bool exactIn,
bytes calldata route
) external payable override {
_verifyParameters(amountIn, amountOut, to, block.timestamp);
(uint256 totalIn, uint256 totalOut) =
_swap(logic, tokenIn, tokenOut, amountIn, amountOut, msg.sender, to, route, exactIn);
revert Router__SimulateSingle(exactIn ? totalOut : totalIn);
}
/**
* @dev Updates the logic contract address.
*
* Emits a {RouterLogicUpdated} event.
*
* Requirements:
* - The caller must be the owner.
*/
function updateRouterLogic(address logic, bool add) external override onlyOwner {
if (add) {
if (!_trustedLogics.add(logic)) revert Router__LogicAlreadyAdded(logic);
} else {
if (!_trustedLogics.remove(logic)) revert Router__LogicNotFound(logic);
}
emit RouterLogicUpdated(logic, add);
}
/**
* @dev Helper function to verify the input parameters of a swap.
*
* Requirements:
* - The recipient address must not be zero or the router address.
* - The deadline must not have passed.
* - The amounts must not be zero.
*/
function _verifyParameters(uint256 amountIn, uint256 amountOut, address to, uint256 deadline) internal view {
if (to == address(0) || to == address(this)) revert Router__InvalidTo();
if (block.timestamp > deadline) revert Router__DeadlineExceeded();
if (amountIn == 0 || amountOut == 0) revert Router__ZeroAmount();
}
/**
* @dev Helper function to verify the output of a swap.
*
* Requirements:
* - The actual amount of tokenOut returned by the logic contract must be greater than the amountOutMin.
* - The actual balance increase of the recipient must be greater than the amountOutMin.
*/
function _verifySwap(address tokenOut, address to, uint256 balance, uint256 amountOutMin, uint256 amountOut)
internal
view
returns (uint256)
{
if (amountOut < amountOutMin) revert Router__InsufficientOutputAmount(amountOut, amountOutMin);
uint256 balanceAfter = TokenLib.universalBalanceOf(tokenOut, to);
if (balanceAfter < balance + amountOutMin) {
revert Router__InsufficientAmountReceived(balance, balanceAfter, amountOutMin);
}
unchecked {
return balanceAfter - balance;
}
}
/**
* @dev Helper function to call the logic contract to swap tokens.
* It will use the specified logic contract to swap the input token to the output token.
* This function will wrap the input token if it is native and unwrap the output token if it is native.
* It will also refund the sender if there is any excess amount of native token.
* It will allow the logic contract to spend at most amountIn of the input token from the sender, and reset
* the allowance after the swap, see {RouterLib.swap}.
*
* Requirements:
* - The logic contract must be a trusted logic contract.
* - If the swap is exactIn, the totalIn must be equal to the amountIn.
* - If the swap is exactOut, the totalIn must be less than or equal to the amountIn.
*/
function _swap(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address from,
address to,
bytes calldata route,
bool exactIn
) internal returns (uint256 totalIn, uint256 totalOut) {
if (!_trustedLogics.contains(logic)) revert Router__UntrustedLogic(logic);
address recipient;
(recipient, tokenOut) = tokenOut == address(0) ? (address(this), WNATIVE) : (to, tokenOut);
if (tokenIn == address(0)) {
tokenIn = WNATIVE;
from = address(this);
TokenLib.wrap(WNATIVE, amountIn);
}
if (tokenIn == tokenOut) revert Router__IdenticalTokens();
uint256 balance = TokenLib.universalBalanceOf(tokenOut, recipient);
(totalIn, totalOut) =
RouterLib.swap(_allowances, tokenIn, tokenOut, amountIn, amountOut, from, recipient, route, exactIn, logic);
if (recipient == address(this)) {
totalOut = _verifySwap(tokenOut, recipient, balance, amountOut, totalOut);
TokenLib.unwrap(WNATIVE, totalOut);
TokenLib.transferNative(to, totalOut);
} else {
totalOut = _verifySwap(tokenOut, to, balance, amountOut, totalOut);
}
unchecked {
uint256 refund;
if (from == address(this)) {
uint256 unwrap = amountIn - totalIn;
if (unwrap > 0) TokenLib.unwrap(WNATIVE, unwrap);
refund = msg.value + unwrap - amountIn;
} else {
refund = msg.value;
}
if (refund > 0) TokenLib.transferNative(msg.sender, refund);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)
pragma solidity ^0.8.20;
import {Ownable} from "./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/
abstract contract Ownable2Step is Ownable {
address private _pendingOwner;
event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/
function pendingOwner() public view virtual returns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual override onlyOwner {
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual override {
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/
function acceptOwnership() public virtual {
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @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;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
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
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// 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 v5.0.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
/**
* @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 is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @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._positions[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 cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 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 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[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._positions[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.20;
interface IRouter {
error Router__DeadlineExceeded();
error Router__InsufficientOutputAmount(uint256 outputAmount, uint256 minOutputAmount);
error Router__InsufficientAmountReceived(uint256 balanceBefore, uint256 balanceAfter, uint256 amountOutMin);
error Router__InvalidTo();
error Router__ZeroAmount();
error Router__OnlyWnative();
error Router__InvalidWnative();
error Router__IdenticalTokens();
error Router__LogicAlreadyAdded(address routerLogic);
error Router__LogicNotFound(address routerLogic);
error Router__UntrustedLogic(address routerLogic);
error Router__Simulations(uint256[] amounts);
error Router__SimulateSingle(uint256 amount);
event SwapExactIn(
address indexed sender, address to, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut
);
event SwapExactOut(
address indexed sender, address to, address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut
);
event RouterLogicUpdated(address indexed routerLogic, bool added);
function WNATIVE() external view returns (address);
function getTrustedLogicAt(uint256 index) external view returns (address);
function getTrustedLogicLength() external view returns (uint256);
function updateRouterLogic(address routerLogic, bool added) external;
function swapExactIn(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOutMin,
address to,
uint256 deadline,
bytes memory route
) external payable returns (uint256, uint256);
function swapExactOut(
address logic,
address tokenIn,
address tokenOut,
uint256 amountOut,
uint256 amountInMax,
address to,
uint256 deadline,
bytes memory route
) external payable returns (uint256, uint256);
function simulate(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address to,
bool exactIn,
bytes[] calldata route
) external payable;
function simulateSingle(
address logic,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address to,
bool exactIn,
bytes calldata route
) external payable;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./TokenLib.sol";
/**
* @title RouterLib
* @dev Helper library for router operations, such as validateAndTransfer, transfer, and swap.
* The router must implement a fallback function that uses `validateAndTransfer` to validate the allowance
* and transfer the tokens and functions that uses `swap` to call the router logic to swap tokens.
* The router logic must implement the `swapExactIn` and `swapExactOut` functions to swap tokens and
* use the `transfer` function to transfer tokens from the router according to the route selected.
*/
library RouterLib {
error RouterLib__ZeroAmount();
error RouterLib__InsufficientAllowance(uint256 allowance, uint256 amount);
/**
* @dev Returns the slot for the allowance of a token for a sender from an address.
*/
function getAllowanceSlot(
mapping(bytes32 key => uint256) storage allowances,
address token,
address sender,
address from
) internal pure returns (bytes32 s) {
assembly ("memory-safe") {
mstore(0, shl(96, token))
mstore(20, shl(96, sender))
// Overwrite the last 8 bytes of the free memory pointer with zero,
//which should always be zeros
mstore(40, shl(96, from))
let key := keccak256(0, 60)
mstore(0, key)
mstore(32, allowances.slot)
s := keccak256(0, 64)
}
}
/**
* @dev Validates the allowance of a token for a sender from an address, and transfers the token.
*
* Requirements:
* - The allowance must be greater than or equal to the amount.
* - The amount must be greater than zero.
* - If from is not the router, the token must have been approved for the router.
*/
function validateAndTransfer(mapping(bytes32 key => uint256) storage allowances) internal {
address token;
address from;
address to;
uint256 amount;
uint256 allowance;
uint256 success;
assembly ("memory-safe") {
token := shr(96, calldataload(4))
from := shr(96, calldataload(24))
to := shr(96, calldataload(44))
amount := calldataload(64)
}
bytes32 allowanceSlot = getAllowanceSlot(allowances, token, msg.sender, from);
assembly ("memory-safe") {
allowance := sload(allowanceSlot)
if iszero(lt(allowance, amount)) {
success := 1
sstore(allowanceSlot, sub(allowance, amount))
}
}
if (amount == 0) revert RouterLib__ZeroAmount(); // Also prevent calldata <= 64
if (success == 0) revert RouterLib__InsufficientAllowance(allowance, amount);
from == address(this) ? TokenLib.transfer(token, to, amount) : TokenLib.transferFrom(token, from, to, amount);
}
/**
* @dev Calls the router to transfer tokens from an account to another account.
*
* Requirements:
* - The call must succeed.
* - The target contract must use `validateAndTransfer` inside its fallback function to validate the allowance
* and transfer the tokens accordingly.
*/
function transfer(address router, address token, address from, address to, uint256 amount) internal {
assembly ("memory-safe") {
let m0x40 := mload(0x40)
mstore(0, shr(32, shl(96, token)))
mstore(24, shl(96, from))
mstore(44, shl(96, to))
mstore(64, amount)
if iszero(call(gas(), router, 0, 0, 96, 0, 0)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
mstore(0x40, m0x40)
}
}
/**
* @dev Swaps tokens using the router logic.
* It will also set the allowance for the logic contract to spend the token from the sender and reset it
* after the swap is done.
*
* Requirements:
* - The logic contract must not be the zero address.
* - The call must succeed.
* - The logic contract must call this contract's fallback function to validate the allowance and transfer the tokens.
*/
function swap(
mapping(bytes32 key => uint256) storage allowances,
address tokenIn,
address tokenOut,
uint256 amountIn,
uint256 amountOut,
address from,
address to,
bytes calldata route,
bool exactIn,
address logic
) internal returns (uint256 totalIn, uint256 totalOut) {
bytes32 allowanceSlot = getAllowanceSlot(allowances, tokenIn, logic, from);
uint256 length = 256 + route.length; // 32 * 6 + 32 + 32 + route.length
bytes memory data = new bytes(length);
assembly ("memory-safe") {
sstore(allowanceSlot, amountIn)
switch exactIn
// swapExactIn(tokenIn, tokenOut, amountIn, amountOut, from, to, route)
// swapExactOut(tokenIn, tokenOut, amountOut, amountIn, from, to, route)
case 1 { mstore(data, 0xbd084435) }
default { mstore(data, 0xcb7e0007) }
mstore(add(data, 32), tokenIn)
mstore(add(data, 64), tokenOut)
mstore(add(data, 96), amountIn)
mstore(add(data, 128), amountOut)
mstore(add(data, 160), from)
mstore(add(data, 192), to)
mstore(add(data, 224), 224) // 32 * 6 + 32
mstore(add(data, 256), route.length)
calldatacopy(add(data, 288), route.offset, route.length)
if iszero(call(gas(), logic, 0, add(data, 28), add(length, 4), 0, 64)) {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
totalIn := mload(0)
totalOut := mload(32)
sstore(allowanceSlot, 0)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title TokenLib
* @dev Helper library for token operations, such as balanceOf, transfer, transferFrom, wrap, and unwrap.
*/
library TokenLib {
error TokenLib__BalanceOfFailed();
error TokenLib__WrapFailed();
error TokenLib__UnwrapFailed();
error TokenLib__NativeTransferFailed();
error TokenLib__TransferFromFailed();
error TokenLib__TransferFailed();
/**
* @dev Returns the balance of a token for an account.
*
* Requirements:
* - The call must succeed.
* - The target contract must return at least 32 bytes.
*/
function balanceOf(address token, address account) internal view returns (uint256 amount) {
uint256 success;
uint256 returnDataSize;
assembly ("memory-safe") {
mstore(0, 0x70a08231) // balanceOf(address)
mstore(32, account)
success := staticcall(gas(), token, 28, 36, 0, 32)
returnDataSize := returndatasize()
amount := mload(0)
}
if (success == 0) _tryRevertWithReason();
// If call failed, and it didn't already bubble up the revert reason, then the return data size must be 0,
// which will revert here with a generic error message
if (returnDataSize < 32) revert TokenLib__BalanceOfFailed();
}
/**
* @dev Returns the balance of a token for an account, or the native balance of the account if the token is the native token.
*
* Requirements:
* - The call must succeed (if the token is not the native token).
* - The target contract must return at least 32 bytes (if the token is not the native token).
*/
function universalBalanceOf(address token, address account) internal view returns (uint256 amount) {
return token == address(0) ? account.balance : balanceOf(token, account);
}
/**
* @dev Transfers native tokens to an account.
*
* Requirements:
* - The call must succeed.
*/
function transferNative(address to, uint256 amount) internal {
uint256 success;
assembly ("memory-safe") {
success := call(gas(), to, amount, 0, 0, 0, 0)
}
if (success == 0) {
_tryRevertWithReason();
revert TokenLib__NativeTransferFailed();
}
}
/**
* @dev Transfers tokens from an account to another account.
* This function does not check if the target contract has code, this should be done before calling this function
*
* Requirements:
* - The call must succeed.
*/
function wrap(address wnative, uint256 amount) internal {
uint256 success;
assembly ("memory-safe") {
mstore(0, 0xd0e30db0) // deposit()
success := call(gas(), wnative, amount, 28, 4, 0, 0)
}
if (success == 0) {
_tryRevertWithReason();
revert TokenLib__WrapFailed();
}
}
/**
* @dev Transfers tokens from an account to another account.
* This function does not check if the target contract has code, this should be done before calling this function
*
* Requirements:
* - The call must succeed.
*/
function unwrap(address wnative, uint256 amount) internal {
uint256 success;
assembly ("memory-safe") {
mstore(0, 0x2e1a7d4d) // withdraw(uint256)
mstore(32, amount)
success := call(gas(), wnative, 0, 28, 36, 0, 0)
}
if (success == 0) {
_tryRevertWithReason();
revert TokenLib__UnwrapFailed();
}
}
/**
* @dev Transfers tokens from an account to another account.
*
* Requirements:
* - The call must succeed
* - The target contract must either return true or no value.
* - The target contract must have code.
*/
function transfer(address token, address to, uint256 amount) internal {
uint256 success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let m0x40 := mload(0x40)
mstore(0, 0xa9059cbb) // transfer(address,uint256)
mstore(32, to)
mstore(64, amount)
success := call(gas(), token, 0, 28, 68, 0, 32)
returnSize := returndatasize()
returnValue := mload(0)
mstore(0x40, m0x40)
}
if (success == 0) {
_tryRevertWithReason();
revert TokenLib__TransferFailed();
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) revert TokenLib__TransferFailed();
}
/**
* @dev Transfers tokens from an account to another account.
*
* Requirements:
* - The call must succeed.
* - The target contract must either return true or no value.
* - The target contract must have code.
*/
function transferFrom(address token, address from, address to, uint256 amount) internal {
uint256 success;
uint256 returnSize;
uint256 returnValue;
assembly ("memory-safe") {
let m0x40 := mload(0x40)
let m0x60 := mload(0x60)
mstore(0, 0x23b872dd) // transferFrom(address,address,uint256)
mstore(32, from)
mstore(64, to)
mstore(96, amount)
success := call(gas(), token, 0, 28, 100, 0, 32)
returnSize := returndatasize()
returnValue := mload(0)
mstore(0x40, m0x40)
mstore(0x60, m0x60)
}
if (success == 0) {
_tryRevertWithReason();
revert TokenLib__TransferFromFailed();
}
if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) revert TokenLib__TransferFromFailed();
}
/**
* @dev Tries to bubble up the revert reason.
* This function needs to be called only if the call has failed, and will revert if there is a revert reason.
* This function might no revert if there is no revert reason, always use it in conjunction with a revert.
*/
function _tryRevertWithReason() private pure {
assembly ("memory-safe") {
if returndatasize() {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../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.
*
* The initial owner is set to the address provided by the deployer. 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;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @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 {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @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 {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_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 v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}{
"remappings": [
"@forge-std/contracts/=lib/forge-std/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"ds-test/=lib/openzeppelin-contracts-upgradeable/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/"
],
"optimizer": {
"enabled": true,
"runs": 100000
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "paris",
"viaIR": true,
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"wnative","type":"address"},{"internalType":"address","name":"initialOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"RouterLib__InsufficientAllowance","type":"error"},{"inputs":[],"name":"RouterLib__ZeroAmount","type":"error"},{"inputs":[],"name":"Router__DeadlineExceeded","type":"error"},{"inputs":[],"name":"Router__IdenticalTokens","type":"error"},{"inputs":[{"internalType":"uint256","name":"balanceBefore","type":"uint256"},{"internalType":"uint256","name":"balanceAfter","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"}],"name":"Router__InsufficientAmountReceived","type":"error"},{"inputs":[{"internalType":"uint256","name":"outputAmount","type":"uint256"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"}],"name":"Router__InsufficientOutputAmount","type":"error"},{"inputs":[],"name":"Router__InvalidTo","type":"error"},{"inputs":[],"name":"Router__InvalidWnative","type":"error"},{"inputs":[{"internalType":"address","name":"routerLogic","type":"address"}],"name":"Router__LogicAlreadyAdded","type":"error"},{"inputs":[{"internalType":"address","name":"routerLogic","type":"address"}],"name":"Router__LogicNotFound","type":"error"},{"inputs":[],"name":"Router__OnlyWnative","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Router__SimulateSingle","type":"error"},{"inputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"Router__Simulations","type":"error"},{"inputs":[{"internalType":"address","name":"routerLogic","type":"address"}],"name":"Router__UntrustedLogic","type":"error"},{"inputs":[],"name":"Router__ZeroAmount","type":"error"},{"inputs":[],"name":"TokenLib__BalanceOfFailed","type":"error"},{"inputs":[],"name":"TokenLib__NativeTransferFailed","type":"error"},{"inputs":[],"name":"TokenLib__TransferFailed","type":"error"},{"inputs":[],"name":"TokenLib__TransferFromFailed","type":"error"},{"inputs":[],"name":"TokenLib__UnwrapFailed","type":"error"},{"inputs":[],"name":"TokenLib__WrapFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"routerLogic","type":"address"},{"indexed":false,"internalType":"bool","name":"added","type":"bool"}],"name":"RouterLogicUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SwapExactIn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"address","name":"tokenOut","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SwapExactOut","type":"event"},{"stateMutability":"nonpayable","type":"fallback"},{"inputs":[],"name":"WNATIVE","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getTrustedLogicAt","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTrustedLogicLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"logic","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"exactIn","type":"bool"},{"internalType":"bytes[]","name":"multiRoutes","type":"bytes[]"}],"name":"simulate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"logic","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"bool","name":"exactIn","type":"bool"},{"internalType":"bytes","name":"route","type":"bytes"}],"name":"simulateSingle","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"logic","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"route","type":"bytes"}],"name":"swapExactIn","outputs":[{"internalType":"uint256","name":"totalIn","type":"uint256"},{"internalType":"uint256","name":"totalOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"logic","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"address","name":"tokenOut","type":"address"},{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"route","type":"bytes"}],"name":"swapExactOut","outputs":[{"internalType":"uint256","name":"totalIn","type":"uint256"},{"internalType":"uint256","name":"totalOut","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"logic","type":"address"},{"internalType":"bool","name":"add","type":"bool"}],"name":"updateRouterLogic","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
60a0346200015357601f6200220138819003918201601f19168301916001600160401b0383118484101762000158578084926040948552833981010312620001535760206200004e826200016e565b916001600160a01b039182916200006691016200016e565b1680156200013a5760018060a01b0319918260015416600155816000549384161760005560405192167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a36001600255813b156200012b575060805260405161207d908162000184823960805181818161025f0152818161047e015281816106480152818161070c015281816107ad01528181610b5701528181610d0201528181610db401528181610e0b01528181610f0e015281816110d601526111910152f35b632cac3e4f60e21b8152600490fd5b604051631e4fbdf760e01b815260006004820152602490fd5b600080fd5b634e487b7160e01b600052604160045260246000fd5b51906001600160a01b0382168203620001535756fe60808060405260043610156102b1575b50361561024857346102435760006060600435811c91601835821c91602c35811c926040359261006282338860601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9081549185831015610235575b50841561020b57156101d4575030810361012d5750506040519163a9059cbb600052602052604052602060006044601c82865af13d9060005192604052156100f4576100e957503b155b6100bf57005b60046040517f87c6ec7c000000000000000000000000000000000000000000000000000000008152fd5b6001915014156100b9565b3d6101235760046040517f87c6ec7c000000000000000000000000000000000000000000000000000000008152fd5b3d6000803e3d6000fd5b9091604051938351926323b872dd6000526020526040528252602060006064601c82885af1903d926000519460405252156101a55761019a57503b155b61017057005b60046040517f7695ba3a000000000000000000000000000000000000000000000000000000008152fd5b60019150141561016a565b3d6101235760046040517f7695ba3a000000000000000000000000000000000000000000000000000000008152fd5b60449084604051917fc67b4be300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f2af6418c000000000000000000000000000000000000000000000000000000008152fd5b85830390555060013861006f565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016330361028757005b60046040517f589a15c3000000000000000000000000000000000000000000000000000000008152fd5b60003560e01c908163470a2fd0146118665750806354f461a11461182a578063715018a61461178557806379ba5097146116a85780638da5cb5b14611656578063a4b77eb9146111b5578063b381cf4014611146578063c7a3e3ce14610e93578063cfc6cb6914610a60578063de55a527146108dc578063e30c39781461088a578063f1910f70146103fa5763f2fde38b1461034d573861000f565b346102435760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576103846118e8565b61038c611a56565b73ffffffffffffffffffffffffffffffffffffffff80911690817fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b610403366119b1565b939796916104149693959196611aae565b811561084e575b61042790868a84611db4565b8196339673ffffffffffffffffffffffffffffffffffffffff8216610459816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff85166108145730987f0000000000000000000000000000000000000000000000000000000000000000925b73ffffffffffffffffffffffffffffffffffffffff8616156107a8575b73ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff83161461077e576104f98b85611f89565b976105278b838560601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9381610100016101001161074f5781908e6105456101008401611b6f565b95604051966105549088611ae7565b610100840180885261056590611b6f565b60208801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013682378a895563bd08443588525287604087015288606087015260808601528c60a08601528d60c086015260e0850160e09052816101008601526101208501376101040191601c01915a9260008093604095f115610123576040997fd9a8cfa901e597f6bbb7ea94478cf9ad6f38d0dc3fd24d493e99cb40692e39f1966000519a60006020519455838a3073ffffffffffffffffffffffffffffffffffffffff84161460001461073c57505061064194611e84565b9561066c877f0000000000000000000000000000000000000000000000000000000000000000611ff7565b6106768787611fb6565b73ffffffffffffffffffffffffffffffffffffffff1630036107355786810380610706575b3401035b806106f6575b50865173ffffffffffffffffffffffffffffffffffffffff94851681529084166020820152921660408301526060820184905260808201839052339160a090a2600160025582519182526020820152f35b6107009033611fb6565b876106a5565b610730817f0000000000000000000000000000000000000000000000000000000000000000611ff7565b61069b565b503461069f565b9150935061074994611e84565b95610676565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517fe454f9b7000000000000000000000000000000000000000000000000000000008152fd5b9850507f0000000000000000000000000000000000000000000000000000000000000000309863d0e30db06000526000806004601c88865af16104bc573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b8698859261049f565b602490604051907f94fad8f10000000000000000000000000000000000000000000000000000000082526004820152fd5b905073ffffffffffffffffffffffffffffffffffffffff821661087857610427345b91905061041b565b6104276108853384611f22565b610870565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346102435760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576109136118e8565b60243590811515918281036102435761092a611a56565b156109cb5773ffffffffffffffffffffffffffffffffffffffff811661094f81611ba9565b1561099a5750602073ffffffffffffffffffffffffffffffffffffffff7f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f6925b6040519485521692a2005b602490604051907f386374180000000000000000000000000000000000000000000000000000000082526004820152fd5b73ffffffffffffffffffffffffffffffffffffffff81166109eb81611c62565b15610a2f5750602073ffffffffffffffffffffffffffffffffffffffff7f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f69261098f565b602490604051907fc10f95900000000000000000000000000000000000000000000000000000000082526004820152fd5b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357610a936118e8565b610a9b61190b565b90610aa461192e565b90610aad611951565b91610ab6611974565b9060e43567ffffffffffffffff811161024357610ad7903690600401611983565b939095610aea4287608435606435611db4565b8094339373ffffffffffffffffffffffffffffffffffffffff8416610b1c816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff8116610e755750309573ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000935b1615610e06575b73ffffffffffffffffffffffffffffffffffffffff831673ffffffffffffffffffffffffffffffffffffffff82161461077e57610bbc8784611f89565b98610bea86868460601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9483610100016101001161074f576000601c6101048680610c26968e86998f8e90610c1a60409e61010001611b6f565b918e519c8d9384611ae7565b866101000183527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020610c5d8961010001611b6f565b940193013684376064359055600114610dfa5763cb7e00078b525b528b8b8a015260643560608a015260843560808a01528d60a08a015260c089015260e08089015281610100890152610120880137019301915af115610123576024966000519560006020519455833073ffffffffffffffffffffffffffffffffffffffff831614600014610de3575091610d2b9391610cfa9360843592611e84565b8095610d26827f0000000000000000000000000000000000000000000000000000000000000000611ff7565b611fb6565b73ffffffffffffffffffffffffffffffffffffffff163003610ddd5760643582900380610dae575b606435903401035b80610d9e575b5015610d9757505b604051907f4e37d9e50000000000000000000000000000000000000000000000000000000082526004820152fd5b9050610d69565b610da89033611fb6565b84610d61565b610dd8817f0000000000000000000000000000000000000000000000000000000000000000611ff7565b610d53565b34610d5b565b935050610df4939660843592611e84565b92610d2b565b63bd0844358b52610c78565b5092507f000000000000000000000000000000000000000000000000000000000000000092309363d0e30db06000526000806004601c606435855af1610b7f573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b9573ffffffffffffffffffffffffffffffffffffffff889793610b78565b610eb7610e9f366119b1565b9498909692959391610eaf611aae565b868a84611db4565b8196339673ffffffffffffffffffffffffffffffffffffffff8216610ee9816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff851661113d5730987f0000000000000000000000000000000000000000000000000000000000000000925b73ffffffffffffffffffffffffffffffffffffffff8616156110d1575b73ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff83161461077e57610f898b85611f89565b97610fb78b838560601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9381610100016101001161074f5781908e610fd56101008401611b6f565b9560405196610fe49088611ae7565b6101008401808852610ff590611b6f565b60208801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013682378a895563cb7e000788525287604087015288606087015260808601528c60a08601528d60c086015260e0850160e09052816101008601526101208501376101040191601c01915a9260008093604095f115610123576040997fbdf9df8586c933e26c968397ba74608d4b9accd48f470ef60ec2d8b98067e5b2966000519a60006020519455838a3073ffffffffffffffffffffffffffffffffffffffff84161460001461073c57505061064194611e84565b9850507f0000000000000000000000000000000000000000000000000000000000000000309863d0e30db06000526000806004601c88865af1610f4c573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b86988592610f2f565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576111e86118e8565b6111f061190b565b6111f861192e565b611200611951565b611208611974565b9267ffffffffffffffff60e435116102435736602360e4350112156102435767ffffffffffffffff60e43560040135116102435736602460e4356004013560051b60e4350101116102435761126260e43560040135611b57565b946112706040519687611ae7565b600460e43501358087527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0906112a590611b57565b0136602088013760009373ffffffffffffffffffffffffffffffffffffffff5b60e43560040135861061133e578760405180917fbec3e3fa0000000000000000000000000000000000000000000000000000000082526024820160206004840152815180915260206044840192019060005b818110611325575050500390fd5b8251845285945060209384019390920191600101611317565b857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461074f57600101809660e435600401358110156115e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd60e43536030160248260051b60e43501013512156102435760249060051b60e43501013560e4350167ffffffffffffffff6024820135116102435760248101353603604482011361024357600080916114b4604051917fcfc6cb690000000000000000000000000000000000000000000000000000000060208401528689166024840152868a1660448401528688166064840152606435608484015260843560a4840152868b1660c48401528c151560e4840152610100610104840152610124602482013581850152837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60246101449581810135604482018887013701358381018601899052011681010390810184520182611ae7565b602081519101305af4503d1561164f573d6114ce81611b6f565b906114dc6040519283611ae7565b81523d6000602083013e5b7f4e37d9e5000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082516020840151828116916004811061163a575b5050160361155557602401519060051b8901526112c5565b508715611613576000905b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161074f5789517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820110156115e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0160051b8901602001526112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90611560565b839250829060040360031b1b16168d8061153d565b60606114e7565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102435760015473ffffffffffffffffffffffffffffffffffffffff3381831603611755577fffffffffffffffffffffffff00000000000000000000000000000000000000008092166001556000549133908316176000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576117bc611a56565b600073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffff0000000000000000000000000000000000000000806001541660015582549081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576020600354604051908152f35b346102435760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357600435906003548210156115e45773ffffffffffffffffffffffffffffffffffffffff60209260036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0154168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b60a4359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b60c43590811515820361024357565b9181601f840112156102435782359167ffffffffffffffff8311610243576020838186019501011161024357565b906101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126102435773ffffffffffffffffffffffffffffffffffffffff90600435828116810361024357926024358381168103610243579260443581811681036102435792606435926084359260a4359081168103610243579160c4359160e4359067ffffffffffffffff821161024357611a5291600401611983565b9091565b73ffffffffffffffffffffffffffffffffffffffff60005416330361175557565b6003548110156115e45760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b6002805414611abd5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611b2857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff8111611b285760051b60200190565b67ffffffffffffffff8111611b2857601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600081815260046020526040812054611c5d5760035468010000000000000000811015611c30579082611c1c611be784600160409601600355611a77565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560035492815260046020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b600090808252600490816020526040832054801515600014611dae577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90818101818111611d825760035490838201918211611d5657818103611d23575b5050506003548015611cf757810190611cd882611a77565b909182549160031b1b1916905560035582526020526040812055600190565b6024856031867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b611d41611d32611be793611a77565b90549060031b1c928392611a77565b90558552836020526040852055388080611cc0565b6024876011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024866011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b50505090565b9092909173ffffffffffffffffffffffffffffffffffffffff168015908115611e7a575b50611e50574211611e265715908115611e1d575b50611df357565b60046040517f98bbadf5000000000000000000000000000000000000000000000000000000008152fd5b90501538611dec565b60046040517fb9f421fc000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc9d3e5fb000000000000000000000000000000000000000000000000000000008152fd5b9050301438611dd8565b909193838110611eeb575090611e9991611f89565b9080830180841161074f578210611eaf57500390565b60649291604051927fdae5794a000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b60449084604051917f8de8583f00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b91906020906024601c60009586936370a08231855285525afa8251923d9115611f7a575b50602011611f5057565b60046040517f07e05a0c000000000000000000000000000000000000000000000000000000008152fd5b3d15611f46575b3d81803e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff8116611fa957503190565b90611fb391611f22565b90565b60008080809481945af115611fc85750565b3d611f815760046040517fa01b4606000000000000000000000000000000000000000000000000000000008152fd5b601c9160246000938480948194632e1a7d4d83526020525af1156120185750565b3d611f815760046040517fa39163c0000000000000000000000000000000000000000000000000000000008152fdfea2646970667358221220e2666f02eeb34e529aff4a74fe6e630019c163be373f2860feb04f2ea3360ff364736f6c63430008140033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
Deployed Bytecode
0x60808060405260043610156102b1575b50361561024857346102435760006060600435811c91601835821c91602c35811c926040359261006282338860601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9081549185831015610235575b50841561020b57156101d4575030810361012d5750506040519163a9059cbb600052602052604052602060006044601c82865af13d9060005192604052156100f4576100e957503b155b6100bf57005b60046040517f87c6ec7c000000000000000000000000000000000000000000000000000000008152fd5b6001915014156100b9565b3d6101235760046040517f87c6ec7c000000000000000000000000000000000000000000000000000000008152fd5b3d6000803e3d6000fd5b9091604051938351926323b872dd6000526020526040528252602060006064601c82885af1903d926000519460405252156101a55761019a57503b155b61017057005b60046040517f7695ba3a000000000000000000000000000000000000000000000000000000008152fd5b60019150141561016a565b3d6101235760046040517f7695ba3a000000000000000000000000000000000000000000000000000000008152fd5b60449084604051917fc67b4be300000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60046040517f2af6418c000000000000000000000000000000000000000000000000000000008152fd5b85830390555060013861006f565b600080fd5b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc216330361028757005b60046040517f589a15c3000000000000000000000000000000000000000000000000000000008152fd5b60003560e01c908163470a2fd0146118665750806354f461a11461182a578063715018a61461178557806379ba5097146116a85780638da5cb5b14611656578063a4b77eb9146111b5578063b381cf4014611146578063c7a3e3ce14610e93578063cfc6cb6914610a60578063de55a527146108dc578063e30c39781461088a578063f1910f70146103fa5763f2fde38b1461034d573861000f565b346102435760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576103846118e8565b61038c611a56565b73ffffffffffffffffffffffffffffffffffffffff80911690817fffffffffffffffffffffffff00000000000000000000000000000000000000006001541617600155600054167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700600080a3005b610403366119b1565b939796916104149693959196611aae565b811561084e575b61042790868a84611db4565b8196339673ffffffffffffffffffffffffffffffffffffffff8216610459816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff85166108145730987f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2925b73ffffffffffffffffffffffffffffffffffffffff8616156107a8575b73ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff83161461077e576104f98b85611f89565b976105278b838560601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9381610100016101001161074f5781908e6105456101008401611b6f565b95604051966105549088611ae7565b610100840180885261056590611b6f565b60208801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013682378a895563bd08443588525287604087015288606087015260808601528c60a08601528d60c086015260e0850160e09052816101008601526101208501376101040191601c01915a9260008093604095f115610123576040997fd9a8cfa901e597f6bbb7ea94478cf9ad6f38d0dc3fd24d493e99cb40692e39f1966000519a60006020519455838a3073ffffffffffffffffffffffffffffffffffffffff84161460001461073c57505061064194611e84565b9561066c877f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611ff7565b6106768787611fb6565b73ffffffffffffffffffffffffffffffffffffffff1630036107355786810380610706575b3401035b806106f6575b50865173ffffffffffffffffffffffffffffffffffffffff94851681529084166020820152921660408301526060820184905260808201839052339160a090a2600160025582519182526020820152f35b6107009033611fb6565b876106a5565b610730817f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611ff7565b61069b565b503461069f565b9150935061074994611e84565b95610676565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60046040517fe454f9b7000000000000000000000000000000000000000000000000000000008152fd5b9850507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2309863d0e30db06000526000806004601c88865af16104bc573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b8698859261049f565b602490604051907f94fad8f10000000000000000000000000000000000000000000000000000000082526004820152fd5b905073ffffffffffffffffffffffffffffffffffffffff821661087857610427345b91905061041b565b6104276108853384611f22565b610870565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b346102435760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576109136118e8565b60243590811515918281036102435761092a611a56565b156109cb5773ffffffffffffffffffffffffffffffffffffffff811661094f81611ba9565b1561099a5750602073ffffffffffffffffffffffffffffffffffffffff7f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f6925b6040519485521692a2005b602490604051907f386374180000000000000000000000000000000000000000000000000000000082526004820152fd5b73ffffffffffffffffffffffffffffffffffffffff81166109eb81611c62565b15610a2f5750602073ffffffffffffffffffffffffffffffffffffffff7f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f69261098f565b602490604051907fc10f95900000000000000000000000000000000000000000000000000000000082526004820152fd5b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357610a936118e8565b610a9b61190b565b90610aa461192e565b90610aad611951565b91610ab6611974565b9060e43567ffffffffffffffff811161024357610ad7903690600401611983565b939095610aea4287608435606435611db4565b8094339373ffffffffffffffffffffffffffffffffffffffff8416610b1c816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff8116610e755750309573ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2935b1615610e06575b73ffffffffffffffffffffffffffffffffffffffff831673ffffffffffffffffffffffffffffffffffffffff82161461077e57610bbc8784611f89565b98610bea86868460601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9483610100016101001161074f576000601c6101048680610c26968e86998f8e90610c1a60409e61010001611b6f565b918e519c8d9384611ae7565b866101000183527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06020610c5d8961010001611b6f565b940193013684376064359055600114610dfa5763cb7e00078b525b528b8b8a015260643560608a015260843560808a01528d60a08a015260c089015260e08089015281610100890152610120880137019301915af115610123576024966000519560006020519455833073ffffffffffffffffffffffffffffffffffffffff831614600014610de3575091610d2b9391610cfa9360843592611e84565b8095610d26827f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611ff7565b611fb6565b73ffffffffffffffffffffffffffffffffffffffff163003610ddd5760643582900380610dae575b606435903401035b80610d9e575b5015610d9757505b604051907f4e37d9e50000000000000000000000000000000000000000000000000000000082526004820152fd5b9050610d69565b610da89033611fb6565b84610d61565b610dd8817f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2611ff7565b610d53565b34610d5b565b935050610df4939660843592611e84565b92610d2b565b63bd0844358b52610c78565b5092507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc292309363d0e30db06000526000806004601c606435855af1610b7f573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b9573ffffffffffffffffffffffffffffffffffffffff889793610b78565b610eb7610e9f366119b1565b9498909692959391610eaf611aae565b868a84611db4565b8196339673ffffffffffffffffffffffffffffffffffffffff8216610ee9816000526004602052604060002054151590565b1561081d575073ffffffffffffffffffffffffffffffffffffffff851661113d5730987f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2925b73ffffffffffffffffffffffffffffffffffffffff8616156110d1575b73ffffffffffffffffffffffffffffffffffffffff841673ffffffffffffffffffffffffffffffffffffffff83161461077e57610f898b85611f89565b97610fb78b838560601b60005260601b60145260601b602852603c6000206000526005602052604060002090565b9381610100016101001161074f5781908e610fd56101008401611b6f565b9560405196610fe49088611ae7565b6101008401808852610ff590611b6f565b60208801907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0013682378a895563cb7e000788525287604087015288606087015260808601528c60a08601528d60c086015260e0850160e09052816101008601526101208501376101040191601c01915a9260008093604095f115610123576040997fbdf9df8586c933e26c968397ba74608d4b9accd48f470ef60ec2d8b98067e5b2966000519a60006020519455838a3073ffffffffffffffffffffffffffffffffffffffff84161460001461073c57505061064194611e84565b9850507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2309863d0e30db06000526000806004601c88865af1610f4c573d6101235760046040517fdc0c8cd1000000000000000000000000000000000000000000000000000000008152fd5b86988592610f2f565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2168152f35b6101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576111e86118e8565b6111f061190b565b6111f861192e565b611200611951565b611208611974565b9267ffffffffffffffff60e435116102435736602360e4350112156102435767ffffffffffffffff60e43560040135116102435736602460e4356004013560051b60e4350101116102435761126260e43560040135611b57565b946112706040519687611ae7565b600460e43501358087527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0906112a590611b57565b0136602088013760009373ffffffffffffffffffffffffffffffffffffffff5b60e43560040135861061133e578760405180917fbec3e3fa0000000000000000000000000000000000000000000000000000000082526024820160206004840152815180915260206044840192019060005b818110611325575050500390fd5b8251845285945060209384019390920191600101611317565b857fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff811461074f57600101809660e435600401358110156115e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbd60e43536030160248260051b60e43501013512156102435760249060051b60e43501013560e4350167ffffffffffffffff6024820135116102435760248101353603604482011361024357600080916114b4604051917fcfc6cb690000000000000000000000000000000000000000000000000000000060208401528689166024840152868a1660448401528688166064840152606435608484015260843560a4840152868b1660c48401528c151560e4840152610100610104840152610124602482013581850152837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60246101449581810135604482018887013701358381018601899052011681010390810184520182611ae7565b602081519101305af4503d1561164f573d6114ce81611b6f565b906114dc6040519283611ae7565b81523d6000602083013e5b7f4e37d9e5000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000082516020840151828116916004811061163a575b5050160361155557602401519060051b8901526112c5565b508715611613576000905b807fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81011161074f5789517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820110156115e4577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0160051b8901602001526112c5565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90611560565b839250829060040360031b1b16168d8061153d565b60606114e7565b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126102435760015473ffffffffffffffffffffffffffffffffffffffff3381831603611755577fffffffffffffffffffffffff00000000000000000000000000000000000000008092166001556000549133908316176000553391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3005b60246040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152fd5b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576117bc611a56565b600073ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffff0000000000000000000000000000000000000000806001541660015582549081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a3005b346102435760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610243576020600354604051908152f35b346102435760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261024357600435906003548210156115e45773ffffffffffffffffffffffffffffffffffffffff60209260036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0154168152f35b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b6044359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b60a4359073ffffffffffffffffffffffffffffffffffffffff8216820361024357565b60c43590811515820361024357565b9181601f840112156102435782359167ffffffffffffffff8311610243576020838186019501011161024357565b906101007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126102435773ffffffffffffffffffffffffffffffffffffffff90600435828116810361024357926024358381168103610243579260443581811681036102435792606435926084359260a4359081168103610243579160c4359160e4359067ffffffffffffffff821161024357611a5291600401611983565b9091565b73ffffffffffffffffffffffffffffffffffffffff60005416330361175557565b6003548110156115e45760036000527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b0190600090565b6002805414611abd5760028055565b60046040517f3ee5aeb5000000000000000000000000000000000000000000000000000000008152fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117611b2857604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff8111611b285760051b60200190565b67ffffffffffffffff8111611b2857601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b600081815260046020526040812054611c5d5760035468010000000000000000811015611c30579082611c1c611be784600160409601600355611a77565b81939154907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9060031b92831b921b19161790565b905560035492815260046020522055600190565b6024827f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b905090565b600090808252600490816020526040832054801515600014611dae577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90818101818111611d825760035490838201918211611d5657818103611d23575b5050506003548015611cf757810190611cd882611a77565b909182549160031b1b1916905560035582526020526040812055600190565b6024856031867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b611d41611d32611be793611a77565b90549060031b1c928392611a77565b90558552836020526040852055388080611cc0565b6024876011887f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b6024866011877f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b50505090565b9092909173ffffffffffffffffffffffffffffffffffffffff168015908115611e7a575b50611e50574211611e265715908115611e1d575b50611df357565b60046040517f98bbadf5000000000000000000000000000000000000000000000000000000008152fd5b90501538611dec565b60046040517fb9f421fc000000000000000000000000000000000000000000000000000000008152fd5b60046040517fc9d3e5fb000000000000000000000000000000000000000000000000000000008152fd5b9050301438611dd8565b909193838110611eeb575090611e9991611f89565b9080830180841161074f578210611eaf57500390565b60649291604051927fdae5794a000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b60449084604051917f8de8583f00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b91906020906024601c60009586936370a08231855285525afa8251923d9115611f7a575b50602011611f5057565b60046040517f07e05a0c000000000000000000000000000000000000000000000000000000008152fd5b3d15611f46575b3d81803e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff8116611fa957503190565b90611fb391611f22565b90565b60008080809481945af115611fc85750565b3d611f815760046040517fa01b4606000000000000000000000000000000000000000000000000000000008152fd5b601c9160246000938480948194632e1a7d4d83526020525af1156120185750565b3d611f815760046040517fa39163c0000000000000000000000000000000000000000000000000000000008152fdfea2646970667358221220e2666f02eeb34e529aff4a74fe6e630019c163be373f2860feb04f2ea3360ff364736f6c63430008140033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
-----Decoded View---------------
Arg [0] : wnative (address): 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2
Arg [1] : initialOwner (address): 0xF961ee51015b1EfB4461D40D1f6b58a7832E931D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.