Latest 25 from a total of 18,559 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Swap Exact In | 50848225 | 19 mins ago | IN | 0 MON | 0.10142002 | ||||
| Swap Exact In | 50844549 | 43 mins ago | IN | 0 MON | 0.24882946 | ||||
| Swap Exact In | 50841227 | 1 hr ago | IN | 4,160 MON | 0.06202798 | ||||
| Swap Exact In | 50838147 | 1 hr ago | IN | 0 MON | 0.04453983 | ||||
| Swap Exact In | 50837920 | 1 hr ago | IN | 0 MON | 0.04455947 | ||||
| Swap Exact In | 50837682 | 1 hr ago | IN | 0 MON | 0.04497649 | ||||
| Swap Exact In | 50837413 | 1 hr ago | IN | 0 MON | 0.04457336 | ||||
| Swap Exact In | 50837260 | 1 hr ago | IN | 0 MON | 0.12061877 | ||||
| Swap Exact In | 50837152 | 1 hr ago | IN | 0 MON | 0.09008884 | ||||
| Swap Exact In | 50834409 | 1 hr ago | IN | 0.001 MON | 0.08754048 | ||||
| Swap Exact In | 50834043 | 1 hr ago | IN | 133,345 MON | 0.20655397 | ||||
| Swap Exact In | 50832118 | 2 hrs ago | IN | 0 MON | 0.1754605 | ||||
| Swap Exact In | 50831412 | 2 hrs ago | IN | 0 MON | 0.55052665 | ||||
| Swap Exact In | 50830686 | 2 hrs ago | IN | 13,217.98037505 MON | 0.1041599 | ||||
| Swap Exact In | 50830579 | 2 hrs ago | IN | 0 MON | 0.20774332 | ||||
| Swap Exact In | 50826334 | 2 hrs ago | IN | 0 MON | 0.25726689 | ||||
| Swap Exact In | 50825650 | 2 hrs ago | IN | 0 MON | 0.40873975 | ||||
| Swap Exact In | 50823809 | 3 hrs ago | IN | 0 MON | 0.16644844 | ||||
| Swap Exact In | 50817497 | 3 hrs ago | IN | 0 MON | 0.194934 | ||||
| Swap Exact In | 50814930 | 4 hrs ago | IN | 0 MON | 0.3404642 | ||||
| Swap Exact In | 50812892 | 4 hrs ago | IN | 100 MON | 0.13664455 | ||||
| Swap Exact In | 50812006 | 4 hrs ago | IN | 990 MON | 0.23077141 | ||||
| Swap Exact In | 50809707 | 4 hrs ago | IN | 2,600 MON | 0.28361145 | ||||
| Swap Exact In | 50809432 | 4 hrs ago | IN | 3,000 MON | 0.08706199 | ||||
| Swap Exact In | 50809393 | 4 hrs ago | IN | 3,000 MON | 0.09014526 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 50848225 | 19 mins ago | 6,037.79539787 MON | ||||
| 50848225 | 19 mins ago | 6,037.79539787 MON | ||||
| 50844549 | 43 mins ago | 133,687.00942374 MON | ||||
| 50844549 | 43 mins ago | 133,687.00942374 MON | ||||
| 50841227 | 1 hr ago | 4,160 MON | ||||
| 50838147 | 1 hr ago | 3.0502385 MON | ||||
| 50838147 | 1 hr ago | 3.0502385 MON | ||||
| 50837920 | 1 hr ago | 3.0502578 MON | ||||
| 50837920 | 1 hr ago | 3.0502578 MON | ||||
| 50837682 | 1 hr ago | 3.05027711 MON | ||||
| 50837682 | 1 hr ago | 3.05027711 MON | ||||
| 50837413 | 1 hr ago | 3.05029641 MON | ||||
| 50837413 | 1 hr ago | 3.05029641 MON | ||||
| 50837260 | 1 hr ago | 50.63902282 MON | ||||
| 50837260 | 1 hr ago | 50.63902282 MON | ||||
| 50837152 | 1 hr ago | 3.06820579 MON | ||||
| 50837152 | 1 hr ago | 3.06820579 MON | ||||
| 50834409 | 1 hr ago | 0.001 MON | ||||
| 50834043 | 1 hr ago | 133,345 MON | ||||
| 50832118 | 2 hrs ago | 1,327.51472662 MON | ||||
| 50832118 | 2 hrs ago | 1,327.51472662 MON | ||||
| 50830686 | 2 hrs ago | 13,217.98037505 MON | ||||
| 50830579 | 2 hrs ago | 12,259.11351984 MON | ||||
| 50830579 | 2 hrs ago | 12,259.11351984 MON | ||||
| 50826334 | 2 hrs ago | 168,491.68558954 MON |
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.26+commit.8a97fa7a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {Ownable2Step, Ownable} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {TokenLib} from "./libraries/TokenLib.sol";
import {RouterLib} from "./libraries/RouterLib.sol";
import {IRouter} from "./interfaces/IRouter.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);
address logic_ = logic; // avoid stack too deep error
(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) (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/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) (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;
}
}// 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;
}
}{
"optimizer": {
"enabled": true,
"runs": 100000
},
"evmVersion": "paris",
"remappings": [
"@forge-std/contracts/=lib/forge-std/src/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/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/"
],
"metadata": {
"bytecodeHash": "ipfs"
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}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
60a060405234801561001057600080fd5b50604051611f83380380611f8383398101604081905261002f91610132565b806001600160a01b03811661005e57604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b610067816100aa565b5060016002556001600160a01b0382163b60000361009857604051632cac3e4f60e21b815260040160405180910390fd5b506001600160a01b0316608052610165565b600180546001600160a01b03191690556100c3816100c6565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b80516001600160a01b038116811461012d57600080fd5b919050565b6000806040838503121561014557600080fd5b61014e83610116565b915061015c60208401610116565b90509250929050565b608051611dda6101a96000396000818160f30152818161024a01528181610f5b01528181610f9c01528181610fc5015281816110a8015261111a0152611dda6000f3fe6080604052600436106100d65760003560e01c8063b381cf401161007f578063de55a52711610059578063de55a527146102a7578063e30c3978146102c7578063f1910f70146102f2578063f2fde38b146103055761014c565b8063b381cf4014610238578063c7a3e3ce1461026c578063cfc6cb69146102945761014c565b806379ba5097116100b057806379ba5097146101e55780638da5cb5b146101fa578063a4b77eb9146102255761014c565b8063470a2fd01461016357806354f461a1146101ad578063715018a6146101d05761014c565b3661014c573373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000161461014a576040517f589a15c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b34801561015857600080fd5b5061014a6005610325565b34801561016f57600080fd5b5061018361017e366004611773565b61044d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b506101c2610460565b6040519081526020016101a4565b3480156101dc57600080fd5b5061014a610471565b3480156101f157600080fd5b5061014a610485565b34801561020657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610183565b61014a6102333660046117c5565b6104fc565b34801561024457600080fd5b506101837f000000000000000000000000000000000000000000000000000000000000000081565b61027f61027a3660046118ed565b610783565b604080519283526020830191909152016101a4565b61014a6102a2366004611993565b610837565b3480156102b357600080fd5b5061014a6102c2366004611a1d565b61089e565b3480156102d357600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610183565b61027f6103003660046118ed565b6109b9565b34801561031157600080fd5b5061014a610320366004611a50565b610a89565b600435606090811c90601835811c90602c35901c6040356000808061037088883389606092831b600090815291831b60145290911b602852603c812081526020919091526040902090565b905080549250838310610387576001915083830381555b836000036103c1576040517f2af6418c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160000361040a576040517fc67b4be300000000000000000000000000000000000000000000000000000000815260048101849052602481018590526044015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146104385761043387878787610b39565b610443565b610443878686610c25565b5050505050505050565b600061045a600383610d04565b92915050565b600061046c6003610d17565b905090565b610479610d21565b6104836000610d74565b565b600154339073ffffffffffffffffffffffffffffffffffffffff1681146104f0576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610401565b6104f981610d74565b50565b8060008167ffffffffffffffff81111561051857610518611a6b565b604051908082528060200260200182016040528015610541578160200160208202803683370190505b50905060005b8281101561074e576000307fcfc6cb69000000000000000000000000000000000000000000000000000000008e8e8e8e8e8e8e8e8e8c61058681611ac9565b9d5081811061059757610597611b01565b90506020028101906105a99190611b30565b6040516024016105c199989796959493929190611b95565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161064a9190611c71565b600060405180830381855af49150503d8060008114610685576040519150601f19603f3d011682016040523d82523d6000602084013e61068a565b606091505b5091507f4e37d9e50000000000000000000000000000000000000000000000000000000090506106b982611ca0565b7fffffffff0000000000000000000000000000000000000000000000000000000016036106f157602481015160208302840152610748565b8661071c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61071f565b60005b8361072b600185611d0c565b8151811061073b5761073b611b01565b6020026020010181815250505b50610547565b50806040517fbec3e3fa0000000000000000000000000000000000000000000000000000000081526004016104019190611d1f565b60008061078e610da5565b61079a87898888610de6565b6107ad8b8b8b8a8c338c8b8b6000610ed7565b6040805173ffffffffffffffffffffffffffffffffffffffff808b168252808f1660208301528d16918101919091526060810183905260808101829052919350915033907fbdf9df8586c933e26c968397ba74608d4b9accd48f470ef60ec2d8b98067e5b29060a0015b60405180910390a26108296001600255565b995099975050505050505050565b61084386868642610de6565b6000806108588b8b8b8b8b338c8b8b8e610ed7565b91509150846108675781610869565b805b6040517f4e37d9e500000000000000000000000000000000000000000000000000000000815260040161040191815260200190565b6108a6610d21565b801561090a576108b7600383611171565b610905576040517f3863741800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610401565b610963565b610915600383611193565b610963576040517fc10f959000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610401565b8173ffffffffffffffffffffffffffffffffffffffff167f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f6826040516109ad911515815260200190565b60405180910390a25050565b6000806109c4610da5565b876000036109fc5773ffffffffffffffffffffffffffffffffffffffff8a16156109f7576109f28a336111b5565b6109f9565b345b97505b610a0888888888610de6565b610a1b8b8b8b8b8b338c8b8b6001610ed7565b6040805173ffffffffffffffffffffffffffffffffffffffff808b168252808f1660208301528d16918101919091526060810183905260808101829052919350915033907fd9a8cfa901e597f6bbb7ea94478cf9ad6f38d0dc3fd24d493e99cb40692e39f19060a001610817565b610a91610d21565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610af460005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60008060006040516060516323b872dd600052876020528660405285606052602060006064601c60008d5af194503d935060005192508160405280606052505082600003610bbb57610b8961122e565b6040517f7695ba3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115610bcb578060011415610be5565b73ffffffffffffffffffffffffffffffffffffffff87163b155b15610c1c576040517f7695ba3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600080600060405163a9059cbb6000528560205284604052602060006044601c60008b5af193503d92506000519150806040525082600003610c9b57610c6961122e565b6040517f87c6ec7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115610cab578060011415610cc5565b73ffffffffffffffffffffffffffffffffffffffff86163b155b15610cfc576040517f87c6ec7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000610d10838361123e565b9392505050565b600061045a825490565b60005473ffffffffffffffffffffffffffffffffffffffff163314610483576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610401565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104f981611268565b6002805403610de0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028055565b73ffffffffffffffffffffffffffffffffffffffff82161580610e1e575073ffffffffffffffffffffffffffffffffffffffff821630145b15610e55576040517fc9d3e5fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115610e8f576040517fb9f421fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580610e9a575082155b15610ed1576040517f98bbadf500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080610ee560038d6112dd565b610f33576040517f94fad8f100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d166004820152602401610401565b600073ffffffffffffffffffffffffffffffffffffffff8b1615610f5857868b610f7b565b307f00000000000000000000000000000000000000000000000000000000000000005b9b50905073ffffffffffffffffffffffffffffffffffffffff8c16610fea577f00000000000000000000000000000000000000000000000000000000000000009b50309750610fea7f00000000000000000000000000000000000000000000000000000000000000008b61130c565b8a73ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361104f576040517fe454f9b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061105b8c8361136a565b90508d61107260058f8f8f8f8f898f8f8f8b6113b4565b90955093503073ffffffffffffffffffffffffffffffffffffffff8416036110dc576110a18d84848e886114ce565b93506110cd7f000000000000000000000000000000000000000000000000000000000000000085611583565b6110d789856115e1565b6110ec565b6110e98d8a848e886114ce565b93505b60003073ffffffffffffffffffffffffffffffffffffffff8c160361114b57858d038d871461113f5761113f7f000000000000000000000000000000000000000000000000000000000000000082611583565b34018d9003905061114e565b50345b801561115e5761115e33826115e1565b505050509a509a98505050505050505050565b6000610d108373ffffffffffffffffffffffffffffffffffffffff8416611631565b6000610d108373ffffffffffffffffffffffffffffffffffffffff8416611680565b60008060006370a0823160005283602052602060006024601c885afa91503d90506000519250816000036111eb576111eb61122e565b6020811015611226576040517f07e05a0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505092915050565b3d15610483573d6000803e3d6000fd5b600082600001828154811061125557611255611b01565b9060005260206000200154905092915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610d10565b600063d0e30db06000526000806004601c85875af19050806000036113655761133361122e565b6040517fdc0c8cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff8316156113975761139283836111b5565b610d10565b5073ffffffffffffffffffffffffffffffffffffffff1631919050565b60608a811b600090815282821b6014529087901b602852603c8120815260208c905260408120819060006113ea87610100611d62565b905060008167ffffffffffffffff81111561140757611407611a6b565b6040519080825280601f01601f191660200182016040528015611431576020820181803683370190505b5090508c8355866001811461144c5763cb7e00078252611454565b63bd08443582525b508e60208201528d60408201528c60608201528b60808201528a60a08201528960c082015260e0808201528761010082015287896101208301376040600060048401601c840160008a5af16114ad573d6000803e3d6000fd5b60005194506020519350600083555050509b509b9950505050505050505050565b600082821015611514576040517f8de8583f0000000000000000000000000000000000000000000000000000000081526004810183905260248101849052604401610401565b6000611520878761136a565b905061152c8486611d62565b811015611576576040517fdae5794a000000000000000000000000000000000000000000000000000000008152600481018690526024810182905260448101859052606401610401565b9390930395945050505050565b6000632e1a7d4d600052816020526000806024601c6000875af1905080600003611365576115af61122e565b6040517fa39163c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080600085875af1905080600003611365576115ff61122e565b6040517fa01b460600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001830160205260408120546116785750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561045a565b50600061045a565b600081815260018301602052604081205480156117695760006116a4600183611d0c565b85549091506000906116b890600190611d0c565b905080821461171d5760008660000182815481106116d8576116d8611b01565b90600052602060002001549050808760000184815481106116fb576116fb611b01565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061172e5761172e611d75565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061045a565b600091505061045a565b60006020828403121561178557600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b057600080fd5b919050565b803580151581146117b057600080fd5b60008060008060008060008060006101008a8c0312156117e457600080fd5b6117ed8a61178c565b98506117fb60208b0161178c565b975061180960408b0161178c565b965060608a0135955060808a0135945061182560a08b0161178c565b935061183360c08b016117b5565b925060e08a013567ffffffffffffffff81111561184f57600080fd5b8a01601f81018c1361186057600080fd5b803567ffffffffffffffff81111561187757600080fd5b8c60208260051b840101111561188c57600080fd5b60208201935080925050509295985092959850929598565b60008083601f8401126118b657600080fd5b50813567ffffffffffffffff8111156118ce57600080fd5b6020830191508360208285010111156118e657600080fd5b9250929050565b60008060008060008060008060006101008a8c03121561190c57600080fd5b6119158a61178c565b985061192360208b0161178c565b975061193160408b0161178c565b965060608a0135955060808a0135945061194d60a08b0161178c565b935060c08a0135925060e08a013567ffffffffffffffff81111561197057600080fd5b61197c8c828d016118a4565b915080935050809150509295985092959850929598565b60008060008060008060008060006101008a8c0312156119b257600080fd5b6119bb8a61178c565b98506119c960208b0161178c565b97506119d760408b0161178c565b965060608a0135955060808a013594506119f360a08b0161178c565b9350611a0160c08b016117b5565b925060e08a013567ffffffffffffffff81111561197057600080fd5b60008060408385031215611a3057600080fd5b611a398361178c565b9150611a47602084016117b5565b90509250929050565b600060208284031215611a6257600080fd5b610d108261178c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611afa57611afa611a9a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611b6557600080fd5b83018035915067ffffffffffffffff821115611b8057600080fd5b6020019150368190038213156118e657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8a16815273ffffffffffffffffffffffffffffffffffffffff8916602082015273ffffffffffffffffffffffffffffffffffffffff8816604082015286606082015285608082015273ffffffffffffffffffffffffffffffffffffffff851660a082015283151560c082015261010060e0820152816101008201528183610120830137600081830161012090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010198975050505050505050565b6000825160005b81811015611c925760208186018101518583015201611c78565b506000920191825250919050565b805160208201517fffffffff00000000000000000000000000000000000000000000000000000000811691906004821015611d05577fffffffff00000000000000000000000000000000000000000000000000000000808360040360031b1b82161692505b5050919050565b8181038181111561045a5761045a611a9a565b602080825282518282018190526000918401906040840190835b81811015611d57578351835260209384019390920191600101611d39565b509095945050505050565b8082018082111561045a5761045a611a9a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122060b0325ca60d123f026d7a745d139c8fb10f56b1de58404c4d2dd03e55d0cf2964736f6c634300081a00330000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
Deployed Bytecode
0x6080604052600436106100d65760003560e01c8063b381cf401161007f578063de55a52711610059578063de55a527146102a7578063e30c3978146102c7578063f1910f70146102f2578063f2fde38b146103055761014c565b8063b381cf4014610238578063c7a3e3ce1461026c578063cfc6cb69146102945761014c565b806379ba5097116100b057806379ba5097146101e55780638da5cb5b146101fa578063a4b77eb9146102255761014c565b8063470a2fd01461016357806354f461a1146101ad578063715018a6146101d05761014c565b3661014c573373ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a161461014a576040517f589a15c300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b005b34801561015857600080fd5b5061014a6005610325565b34801561016f57600080fd5b5061018361017e366004611773565b61044d565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b3480156101b957600080fd5b506101c2610460565b6040519081526020016101a4565b3480156101dc57600080fd5b5061014a610471565b3480156101f157600080fd5b5061014a610485565b34801561020657600080fd5b5060005473ffffffffffffffffffffffffffffffffffffffff16610183565b61014a6102333660046117c5565b6104fc565b34801561024457600080fd5b506101837f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a81565b61027f61027a3660046118ed565b610783565b604080519283526020830191909152016101a4565b61014a6102a2366004611993565b610837565b3480156102b357600080fd5b5061014a6102c2366004611a1d565b61089e565b3480156102d357600080fd5b5060015473ffffffffffffffffffffffffffffffffffffffff16610183565b61027f6103003660046118ed565b6109b9565b34801561031157600080fd5b5061014a610320366004611a50565b610a89565b600435606090811c90601835811c90602c35901c6040356000808061037088883389606092831b600090815291831b60145290911b602852603c812081526020919091526040902090565b905080549250838310610387576001915083830381555b836000036103c1576040517f2af6418c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160000361040a576040517fc67b4be300000000000000000000000000000000000000000000000000000000815260048101849052602481018590526044015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff861630146104385761043387878787610b39565b610443565b610443878686610c25565b5050505050505050565b600061045a600383610d04565b92915050565b600061046c6003610d17565b905090565b610479610d21565b6104836000610d74565b565b600154339073ffffffffffffffffffffffffffffffffffffffff1681146104f0576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff82166004820152602401610401565b6104f981610d74565b50565b8060008167ffffffffffffffff81111561051857610518611a6b565b604051908082528060200260200182016040528015610541578160200160208202803683370190505b50905060005b8281101561074e576000307fcfc6cb69000000000000000000000000000000000000000000000000000000008e8e8e8e8e8e8e8e8e8c61058681611ac9565b9d5081811061059757610597611b01565b90506020028101906105a99190611b30565b6040516024016105c199989796959493929190611b95565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090941693909317909252905161064a9190611c71565b600060405180830381855af49150503d8060008114610685576040519150601f19603f3d011682016040523d82523d6000602084013e61068a565b606091505b5091507f4e37d9e50000000000000000000000000000000000000000000000000000000090506106b982611ca0565b7fffffffff0000000000000000000000000000000000000000000000000000000016036106f157602481015160208302840152610748565b8661071c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff61071f565b60005b8361072b600185611d0c565b8151811061073b5761073b611b01565b6020026020010181815250505b50610547565b50806040517fbec3e3fa0000000000000000000000000000000000000000000000000000000081526004016104019190611d1f565b60008061078e610da5565b61079a87898888610de6565b6107ad8b8b8b8a8c338c8b8b6000610ed7565b6040805173ffffffffffffffffffffffffffffffffffffffff808b168252808f1660208301528d16918101919091526060810183905260808101829052919350915033907fbdf9df8586c933e26c968397ba74608d4b9accd48f470ef60ec2d8b98067e5b29060a0015b60405180910390a26108296001600255565b995099975050505050505050565b61084386868642610de6565b6000806108588b8b8b8b8b338c8b8b8e610ed7565b91509150846108675781610869565b805b6040517f4e37d9e500000000000000000000000000000000000000000000000000000000815260040161040191815260200190565b6108a6610d21565b801561090a576108b7600383611171565b610905576040517f3863741800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610401565b610963565b610915600383611193565b610963576040517fc10f959000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83166004820152602401610401565b8173ffffffffffffffffffffffffffffffffffffffff167f25e48677e09b350ea4357542e7ea3d9b4a6665edbc68a909f93ed335dce512f6826040516109ad911515815260200190565b60405180910390a25050565b6000806109c4610da5565b876000036109fc5773ffffffffffffffffffffffffffffffffffffffff8a16156109f7576109f28a336111b5565b6109f9565b345b97505b610a0888888888610de6565b610a1b8b8b8b8b8b338c8b8b6001610ed7565b6040805173ffffffffffffffffffffffffffffffffffffffff808b168252808f1660208301528d16918101919091526060810183905260808101829052919350915033907fd9a8cfa901e597f6bbb7ea94478cf9ad6f38d0dc3fd24d493e99cb40692e39f19060a001610817565b610a91610d21565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610af460005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60008060006040516060516323b872dd600052876020528660405285606052602060006064601c60008d5af194503d935060005192508160405280606052505082600003610bbb57610b8961122e565b6040517f7695ba3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115610bcb578060011415610be5565b73ffffffffffffffffffffffffffffffffffffffff87163b155b15610c1c576040517f7695ba3a00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050505050565b600080600060405163a9059cbb6000528560205284604052602060006044601c60008b5af193503d92506000519150806040525082600003610c9b57610c6961122e565b6040517f87c6ec7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8115610cab578060011415610cc5565b73ffffffffffffffffffffffffffffffffffffffff86163b155b15610cfc576040517f87c6ec7c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050505050565b6000610d10838361123e565b9392505050565b600061045a825490565b60005473ffffffffffffffffffffffffffffffffffffffff163314610483576040517f118cdaa7000000000000000000000000000000000000000000000000000000008152336004820152602401610401565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556104f981611268565b6002805403610de0576040517f3ee5aeb500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60028055565b73ffffffffffffffffffffffffffffffffffffffff82161580610e1e575073ffffffffffffffffffffffffffffffffffffffff821630145b15610e55576040517fc9d3e5fb00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80421115610e8f576040517fb9f421fc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b831580610e9a575082155b15610ed1576040517f98bbadf500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b600080610ee560038d6112dd565b610f33576040517f94fad8f100000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8d166004820152602401610401565b600073ffffffffffffffffffffffffffffffffffffffff8b1615610f5857868b610f7b565b307f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a5b9b50905073ffffffffffffffffffffffffffffffffffffffff8c16610fea577f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a9b50309750610fea7f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a8b61130c565b8a73ffffffffffffffffffffffffffffffffffffffff168c73ffffffffffffffffffffffffffffffffffffffff160361104f576040517fe454f9b700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061105b8c8361136a565b90508d61107260058f8f8f8f8f898f8f8f8b6113b4565b90955093503073ffffffffffffffffffffffffffffffffffffffff8416036110dc576110a18d84848e886114ce565b93506110cd7f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a85611583565b6110d789856115e1565b6110ec565b6110e98d8a848e886114ce565b93505b60003073ffffffffffffffffffffffffffffffffffffffff8c160361114b57858d038d871461113f5761113f7f0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a82611583565b34018d9003905061114e565b50345b801561115e5761115e33826115e1565b505050509a509a98505050505050505050565b6000610d108373ffffffffffffffffffffffffffffffffffffffff8416611631565b6000610d108373ffffffffffffffffffffffffffffffffffffffff8416611680565b60008060006370a0823160005283602052602060006024601c885afa91503d90506000519250816000036111eb576111eb61122e565b6020811015611226576040517f07e05a0c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505092915050565b3d15610483573d6000803e3d6000fd5b600082600001828154811061125557611255611b01565b9060005260206000200154905092915050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001830160205260408120541515610d10565b600063d0e30db06000526000806004601c85875af19050806000036113655761133361122e565b6040517fdc0c8cd100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b505050565b600073ffffffffffffffffffffffffffffffffffffffff8316156113975761139283836111b5565b610d10565b5073ffffffffffffffffffffffffffffffffffffffff1631919050565b60608a811b600090815282821b6014529087901b602852603c8120815260208c905260408120819060006113ea87610100611d62565b905060008167ffffffffffffffff81111561140757611407611a6b565b6040519080825280601f01601f191660200182016040528015611431576020820181803683370190505b5090508c8355866001811461144c5763cb7e00078252611454565b63bd08443582525b508e60208201528d60408201528c60608201528b60808201528a60a08201528960c082015260e0808201528761010082015287896101208301376040600060048401601c840160008a5af16114ad573d6000803e3d6000fd5b60005194506020519350600083555050509b509b9950505050505050505050565b600082821015611514576040517f8de8583f0000000000000000000000000000000000000000000000000000000081526004810183905260248101849052604401610401565b6000611520878761136a565b905061152c8486611d62565b811015611576576040517fdae5794a000000000000000000000000000000000000000000000000000000008152600481018690526024810182905260448101859052606401610401565b9390930395945050505050565b6000632e1a7d4d600052816020526000806024601c6000875af1905080600003611365576115af61122e565b6040517fa39163c000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080600080600085875af1905080600003611365576115ff61122e565b6040517fa01b460600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008181526001830160205260408120546116785750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915561045a565b50600061045a565b600081815260018301602052604081205480156117695760006116a4600183611d0c565b85549091506000906116b890600190611d0c565b905080821461171d5760008660000182815481106116d8576116d8611b01565b90600052602060002001549050808760000184815481106116fb576116fb611b01565b6000918252602080832090910192909255918252600188019052604090208390555b855486908061172e5761172e611d75565b60019003818190600052602060002001600090559055856001016000868152602001908152602001600020600090556001935050505061045a565b600091505061045a565b60006020828403121561178557600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff811681146117b057600080fd5b919050565b803580151581146117b057600080fd5b60008060008060008060008060006101008a8c0312156117e457600080fd5b6117ed8a61178c565b98506117fb60208b0161178c565b975061180960408b0161178c565b965060608a0135955060808a0135945061182560a08b0161178c565b935061183360c08b016117b5565b925060e08a013567ffffffffffffffff81111561184f57600080fd5b8a01601f81018c1361186057600080fd5b803567ffffffffffffffff81111561187757600080fd5b8c60208260051b840101111561188c57600080fd5b60208201935080925050509295985092959850929598565b60008083601f8401126118b657600080fd5b50813567ffffffffffffffff8111156118ce57600080fd5b6020830191508360208285010111156118e657600080fd5b9250929050565b60008060008060008060008060006101008a8c03121561190c57600080fd5b6119158a61178c565b985061192360208b0161178c565b975061193160408b0161178c565b965060608a0135955060808a0135945061194d60a08b0161178c565b935060c08a0135925060e08a013567ffffffffffffffff81111561197057600080fd5b61197c8c828d016118a4565b915080935050809150509295985092959850929598565b60008060008060008060008060006101008a8c0312156119b257600080fd5b6119bb8a61178c565b98506119c960208b0161178c565b97506119d760408b0161178c565b965060608a0135955060808a013594506119f360a08b0161178c565b9350611a0160c08b016117b5565b925060e08a013567ffffffffffffffff81111561197057600080fd5b60008060408385031215611a3057600080fd5b611a398361178c565b9150611a47602084016117b5565b90509250929050565b600060208284031215611a6257600080fd5b610d108261178c565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611afa57611afa611a9a565b5060010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60008083357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1843603018112611b6557600080fd5b83018035915067ffffffffffffffff821115611b8057600080fd5b6020019150368190038213156118e657600080fd5b73ffffffffffffffffffffffffffffffffffffffff8a16815273ffffffffffffffffffffffffffffffffffffffff8916602082015273ffffffffffffffffffffffffffffffffffffffff8816604082015286606082015285608082015273ffffffffffffffffffffffffffffffffffffffff851660a082015283151560c082015261010060e0820152816101008201528183610120830137600081830161012090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010198975050505050505050565b6000825160005b81811015611c925760208186018101518583015201611c78565b506000920191825250919050565b805160208201517fffffffff00000000000000000000000000000000000000000000000000000000811691906004821015611d05577fffffffff00000000000000000000000000000000000000000000000000000000808360040360031b1b82161692505b5050919050565b8181038181111561045a5761045a611a9a565b602080825282518282018190526000918401906040840190835b81811015611d57578351835260209384019390920191600101611d39565b509095945050505050565b8082018082111561045a5761045a611a9a565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfea264697066735822122060b0325ca60d123f026d7a745d139c8fb10f56b1de58404c4d2dd03e55d0cf2964736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
-----Decoded View---------------
Arg [0] : wnative (address): 0x3bd359C1119dA7Da1D913D1C4D2B7c461115433A
Arg [1] : initialOwner (address): 0xF961ee51015b1EfB4461D40D1f6b58a7832E931D
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000003bd359c1119da7da1d913d1c4d2b7c461115433a
Arg [1] : 000000000000000000000000f961ee51015b1efb4461d40d1f6b58a7832e931d
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$40.94
Net Worth in MON
Token Allocations
ETH
79.46%
USDC
20.48%
POL
0.06%
Others
0.00%
Multichain Portfolio | 35 Chains
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.