MON Price: $0.018742 (-1.86%)

Contract

0x486D7C009B78310528AcA11574eC816d2FdEf71B

Overview

MON Balance

Monad Chain LogoMonad Chain LogoMonad Chain Logo0 MON

MON Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Swap Smart452216402025-12-29 13:58:1926 days ago1767016699IN
0x486D7C00...d2FdEf71B
0 MON0.05416989101.94
Swap Smart450040232025-12-28 13:41:3227 days ago1766929292IN
0x486D7C00...d2FdEf71B
0 MON0.1334225101.97557886
Swap Smart449939462025-12-28 12:33:2527 days ago1766925205IN
0x486D7C00...d2FdEf71B
6 MON0.06130393102
Swap Smart449935382025-12-28 12:30:3927 days ago1766925039IN
0x486D7C00...d2FdEf71B
1 MON0.05057374102
Swap Smart449933222025-12-28 12:29:1127 days ago1766924951IN
0x486D7C00...d2FdEf71B
1 MON0.05424625102
Swap Smart449929852025-12-28 12:26:5527 days ago1766924815IN
0x486D7C00...d2FdEf71B
10 MON0.0541978102
Swap Smart449507482025-12-28 7:41:0627 days ago1766907666IN
0x486D7C00...d2FdEf71B
0 MON0.12482678102
Swap Smart449502792025-12-28 7:37:5327 days ago1766907473IN
0x486D7C00...d2FdEf71B
0 MON0.14217433102
Swap Smart449502012025-12-28 7:37:2127 days ago1766907441IN
0x486D7C00...d2FdEf71B
0 MON0.08238417102
Swap Smart449501312025-12-28 7:36:5327 days ago1766907413IN
0x486D7C00...d2FdEf71B
0 MON0.05568261102
Swap Smart449014572025-12-28 2:07:2528 days ago1766887645IN
0x486D7C00...d2FdEf71B
0 MON0.05807297102.10004247
Swap Smart449013532025-12-28 2:06:4328 days ago1766887603IN
0x486D7C00...d2FdEf71B
0 MON0.09028104102.10004247
Swap Smart449012422025-12-28 2:05:5828 days ago1766887558IN
0x486D7C00...d2FdEf71B
0 MON0.07453037102.10004247
Swap Smart449011852025-12-28 2:05:3528 days ago1766887535IN
0x486D7C00...d2FdEf71B
0 MON0.06651685102.10004247
Swap Smart449010942025-12-28 2:04:5628 days ago1766887496IN
0x486D7C00...d2FdEf71B
0 MON0.06650847102.10004247
Swap Smart449010382025-12-28 2:04:3328 days ago1766887473IN
0x486D7C00...d2FdEf71B
0 MON0.06846614102.10004247
Swap Smart448757202025-12-27 23:13:0628 days ago1766877186IN
0x486D7C00...d2FdEf71B
0 MON0.10362312102
Swap Smart447947732025-12-27 14:05:0228 days ago1766844302IN
0x486D7C00...d2FdEf71B
80 MON0.06171926101.94
Swap Smart447604922025-12-27 10:14:2328 days ago1766830463IN
0x486D7C00...d2FdEf71B
13 MON0.46082765294
Swap Smart445405652025-12-26 9:42:5629 days ago1766742176IN
0x486D7C00...d2FdEf71B
0 MON0.28970583101.94
Swap Smart445396062025-12-26 9:36:3229 days ago1766741792IN
0x486D7C00...d2FdEf71B
0 MON0.25257225101.94
Swap Smart443666552025-12-25 14:21:2430 days ago1766672484IN
0x486D7C00...d2FdEf71B
0 MON0.1732834100.97
Swap Smart443026712025-12-25 7:14:0830 days ago1766646848IN
0x486D7C00...d2FdEf71B
5 MON0.07472703102
Swap Smart442909652025-12-25 5:55:5130 days ago1766642151IN
0x486D7C00...d2FdEf71B
5,500 MON0.07634354120.71346464
Swap Smart442688902025-12-25 3:28:1631 days ago1766633296IN
0x486D7C00...d2FdEf71B
0 MON0.10077671102
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
449939462025-12-28 12:33:2527 days ago1766925205
0x486D7C00...d2FdEf71B
6 MON
449935382025-12-28 12:30:3927 days ago1766925039
0x486D7C00...d2FdEf71B
1 MON
449933222025-12-28 12:29:1127 days ago1766924951
0x486D7C00...d2FdEf71B
1 MON
449929852025-12-28 12:26:5527 days ago1766924815
0x486D7C00...d2FdEf71B
10 MON
447947732025-12-27 14:05:0228 days ago1766844302
0x486D7C00...d2FdEf71B
80 MON
447604922025-12-27 10:14:2328 days ago1766830463
0x486D7C00...d2FdEf71B
13 MON
443026712025-12-25 7:14:0830 days ago1766646848
0x486D7C00...d2FdEf71B
5 MON
442909652025-12-25 5:55:5130 days ago1766642151
0x486D7C00...d2FdEf71B
5,500 MON
441492112025-12-24 14:08:3131 days ago1766585311
0x486D7C00...d2FdEf71B
200 MON
439318482025-12-23 13:54:3532 days ago1766498075
0x486D7C00...d2FdEf71B
200 MON
439307522025-12-23 13:47:1132 days ago1766497631
0x486D7C00...d2FdEf71B
200 MON
438485142025-12-23 4:36:4933 days ago1766464609
0x486D7C00...d2FdEf71B
2 MON
438236912025-12-23 1:51:0633 days ago1766454666
0x486D7C00...d2FdEf71B
500 MON
437268952025-12-22 15:04:1633 days ago1766415856
0x486D7C00...d2FdEf71B
500 MON
437246412025-12-22 14:49:1433 days ago1766414954
0x486D7C00...d2FdEf71B
200 MON
436338452025-12-22 4:41:1733 days ago1766378477
0x486D7C00...d2FdEf71B
100 MON
436089702025-12-22 1:54:5634 days ago1766368496
0x486D7C00...d2FdEf71B
7.00580185 MON
436054792025-12-22 1:31:2734 days ago1766367087
0x486D7C00...d2FdEf71B
7.499875 MON
435861302025-12-21 23:22:1634 days ago1766359336
0x486D7C00...d2FdEf71B
500 MON
435859632025-12-21 23:21:0934 days ago1766359269
0x486D7C00...d2FdEf71B
100 MON
435428842025-12-21 18:33:0334 days ago1766341983
0x486D7C00...d2FdEf71B
20 MON
435427952025-12-21 18:32:2834 days ago1766341948
0x486D7C00...d2FdEf71B
5 MON
435420052025-12-21 18:27:1034 days ago1766341630
0x486D7C00...d2FdEf71B
20 MON
434395322025-12-21 7:02:4634 days ago1766300566
0x486D7C00...d2FdEf71B
500 MON
432934132025-12-20 14:46:5035 days ago1766242010
0x486D7C00...d2FdEf71B
1 MON
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
AggregatorSmart

Compiler Version
v0.8.27+commit.40a35a09

Optimization Enabled:
Yes with 200 runs

Other Settings:
prague EvmVersion
// SPDX-License-Identifier: GPL-2.0-or-later
// website: https://www.zkswap.finance

pragma solidity 0.8.27;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/security/ReentrancyGuard.sol";

/// @notice Interface for Permit2, a token approval system
interface IPermit2 {
    function approve(address token, address spender, uint160 amount, uint48 expiration) external;

    function allowance(address owner, address token, address spender)
        external
        view
        returns (uint160 amount, uint48 expiration, uint48 nonce);
}

/// @title AggregatorSmart
/// @notice A smart contract that allows users to interact with whitelisted swap aggregators
/// @dev This contract serves as a trusted intermediary for executing swaps through various aggregators
contract AggregatorSmart is ReentrancyGuard {
    using SafeERC20 for IERC20;
    /// @notice The address representing ETH, used for native ETH transactions

    address constant ETH_ADDRESS = address(1);

    /// @notice The owner of this contract who can whitelist/remove aggregators
    address public owner;

    /// @notice Mapping to track whitelisted aggregator contracts
    mapping(address => bool) public whitelistedAggregators;

    /// @notice Address of the Permit2 contract for token approvals
    mapping(address => address) public aggregatorWithPermit2;

    /// @notice Emitted when an aggregator is added to the whitelist
    /// @param aggregator The address of the aggregator contract
    event AggregatorWhitelisted(address indexed aggregator);

    /// @notice Emitted when an aggregator is set with a Permit2 contract
    /// @param aggregator The address of the aggregator contract
    /// @param permit2 The address of the Permit2 contract associated with the aggregator
    event AggregatorWithPermit2(address indexed aggregator, address indexed permit2);

    /// @notice Emitted when an aggregator is removed from the whitelist
    /// @param aggregator The address of the aggregator contract
    event AggregatorRemoved(address indexed aggregator);

    /// @notice Emitted when a swap is executed
    /// @param user The address of the user initiating the swap
    /// @param aggregator The aggregator contract used for the swap
    /// @param tokenIn The input token address
    /// @param amountIn The amount of input tokens
    event SwapSmart(address indexed user, address indexed aggregator, address indexed tokenIn, uint256 amountIn);

    /// @notice Emitted when tokens are approved for an aggregator
    /// @param token The token address that was approved
    /// @param aggregator The aggregator that was approved to spend tokens
    /// @param amount The approved amount
    event TokenApproved(address indexed token, address indexed aggregator, uint256 amount);

    /// @notice Emitted when tokens are recovered in an emergency
    /// @param token The address of the token that was recovered
    /// @param to The address to which the tokens were sent
    /// @param amount The amount of tokens that were recovered
    event EmergencyRecover(address indexed token, address indexed to, uint256 amount);

    /// @notice Emitted when ETH is recovered in an emergency
    /// @param to The address to which the ETH was sent
    /// @param amount The amount of ETH that was recovered
    event EmergencyRecoverETH(address indexed to, uint256 amount);

    /// @notice Emitted when ownership is transferred
    /// @param previousOwner The previous owner address
    /// @param newOwner The new owner address
    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /// @notice Modifier to restrict access to only the owner
    modifier onlyOwner() {
        require(msg.sender == owner, "AggregatorSmart: caller is not the owner");
        _;
    }

    /// @notice Constructor sets the deployer as the initial owner
    constructor() {
        owner = msg.sender;
        emit OwnershipTransferred(address(0), msg.sender);
    }

    /// @notice Executes a swap through a whitelisted aggregator
    /// @param aggregator The address of the whitelisted aggregator to use
    /// @param tokenIn The address of the input token
    /// @param amountIn The amount of input tokens to swap
    /// @param callData The calldata to execute on the aggregator
    /// @return success Whether the aggregator call was successful
    /// @return returnData The return data from the aggregator call
    function swapSmart(address aggregator, address tokenIn, uint256 amountIn, bytes calldata callData)
        external
        payable
        nonReentrant
        returns (bool success, bytes memory returnData)
    {
        // Verify aggregator is whitelisted
        require(whitelistedAggregators[aggregator], "AggregatorSmart: aggregator not whitelisted");
        require(amountIn > 0, "AggregatorSmart: amount must be greater than 0");
        require(callData.length > 0, "AggregatorSmart: empty calldata");

        // Emit the swap executed event
        emit SwapSmart(msg.sender, aggregator, tokenIn, amountIn);

        if (tokenIn == ETH_ADDRESS) {
            // Handle native ETH swap
            require(msg.value == amountIn, "AggregatorSmart: ETH amount mismatch");

            // Execute the swap through the aggregator with ETH value
            (success, returnData) = aggregator.call{value: amountIn}(callData);
            require(success, "AggregatorSmart: aggregator call failed");
        } else {
            // Handle ERC20 token swap
            require(tokenIn != address(0), "AggregatorSmart: invalid token address");
            require(msg.value == 0, "AggregatorSmart: unexpected ETH sent for ERC20 swap");

            // Transfer tokens from user to this contract
            IERC20(tokenIn).safeTransferFrom(msg.sender, address(this), amountIn);

            address permit2Address = aggregatorWithPermit2[aggregator];
            if (permit2Address != address(0)) {
                // Approve the Permit2 contract to spend the tokens if needed
                approveIfNeeded(tokenIn, permit2Address, amountIn);
                // Approve the aggregator to spend the tokens through Permit2
                approveAggregatorThroughPermit2(tokenIn, aggregator, permit2Address, amountIn);
            } else {
                // Approve the aggregator to spend the tokens if needed
                approveIfNeeded(tokenIn, aggregator, amountIn);
            }

            // Execute the swap through the aggregator
            (success, returnData) = aggregator.call(callData);
            require(success, "AggregatorSmart: aggregator call failed");
        }
    }

    /// @notice Safely approves tokens for spending, handling non-standard tokens
    /// @param token The token contract address
    /// @param spender The address to approve for spending
    /// @param amount The amount to approve
    function approveIfNeeded(address token, address spender, uint256 amount) internal {
        IERC20 tokenContract = IERC20(token);
        uint256 currentAllowance = tokenContract.allowance(address(this), spender);

        if (currentAllowance < amount) {
            // First set allowance to 0 to handle non-standard tokens like USDT
            if (currentAllowance > 0) {
                _removeAllowance(token, spender);
            }

            // Then set the required allowance
            (bool success,) =
                token.call(abi.encodeWithSelector(tokenContract.approve.selector, spender, type(uint256).max));
            require(success, "AggregatorSmart: approve failed");

            emit TokenApproved(token, spender, type(uint256).max);
        }
    }

    /// @notice Give Universal Router permission through Permit2's allowance system
    function approveAggregatorThroughPermit2(address token, address aggregator, address permit2, uint256 amount)
        internal
    {
        IPermit2 permit2Contract = IPermit2(permit2);

        // Check current Permit2 allowance
        (uint160 currentAmount, uint48 expiration,) = permit2Contract.allowance(address(this), token, aggregator);

        // If allowance is insufficient or expired, set new allowance
        if (currentAmount < amount || expiration < block.timestamp + 3600) {
            permit2Contract.approve(token, aggregator, type(uint160).max, uint48(block.timestamp + 365 days));
        }
    }

    /// @notice Adds an aggregator to the whitelist
    /// @param aggregator The address of the aggregator contract to whitelist
    function setWhitelistAggregator(address aggregator) external onlyOwner {
        require(aggregator != address(0), "AggregatorSmart: invalid aggregator address");
        require(!whitelistedAggregators[aggregator], "AggregatorSmart: aggregator already whitelisted");

        whitelistedAggregators[aggregator] = true;
        emit AggregatorWhitelisted(aggregator);
    }

    function setAggregatorWithPermit2(address aggregator, address permit2) external onlyOwner {
        require(aggregator != address(0), "AggregatorSmart: invalid aggregator address");
        require(permit2 != address(0), "AggregatorSmart: invalid permit2 address");
        aggregatorWithPermit2[aggregator] = permit2;

        emit AggregatorWithPermit2(aggregator, permit2);
    }

    /// @notice Removes an aggregator from the whitelist
    /// @param aggregator The address of the aggregator contract to remove
    function removeAggregator(address aggregator) external onlyOwner {
        require(whitelistedAggregators[aggregator], "AggregatorSmart: aggregator not whitelisted");

        whitelistedAggregators[aggregator] = false;
        emit AggregatorRemoved(aggregator);
    }

    /// @notice Check if an aggregator is whitelisted
    /// @param aggregator The aggregator address to check
    /// @return Whether the aggregator is whitelisted
    function isWhitelisted(address aggregator) external view returns (bool) {
        return whitelistedAggregators[aggregator];
    }

    /// @notice Emergency function to recover any tokens stuck in the contract
    /// @param token The address of the token to recover
    /// @param to The address to send the recovered tokens to
    /// @param amount The amount of tokens to recover
    function emergencyRecover(address token, address to, uint256 amount) external onlyOwner {
        require(to != address(0), "AggregatorSmart: invalid recipient address");
        IERC20(token).safeTransfer(to, amount);

        emit EmergencyRecover(token, to, amount);
    }

    /// @notice Emergency function to recover ETH stuck in the contract
    /// @param to The address to send the ETH to
    /// @param amount The amount of ETH to recover
    function emergencyRecoverETH(address payable to, uint256 amount) external onlyOwner {
        require(to != address(0), "AggregatorSmart: invalid recipient address");
        require(address(this).balance >= amount, "AggregatorSmart: insufficient balance");
        (bool success,) = to.call{value: amount}("");
        require(success, "AggregatorSmart: ETH transfer failed");

        emit EmergencyRecoverETH(to, amount);
    }

    /// @notice Removes allowance for a spender on a specific token
    /// @param token The address of the token to remove allowance for
    /// @param spender The address of the spender to remove allowance for
    function removeAllowance(address token, address spender) external onlyOwner {
        require(token != address(0), "AggregatorSmart: invalid token address");
        require(spender != address(0), "AggregatorSmart: invalid spender address");

        _removeAllowance(token, spender);
    }

    /// @notice Internal function to remove allowance for a spender on a specific token
    /// @param token The address of the token to remove allowance for
    /// @param spender The address of the spender to remove allowance for
    function _removeAllowance(address token, address spender) internal {
        IERC20 tokenContract = IERC20(token);
        // Use low-level call to handle tokens that don't return bool
        (bool success,) = token.call(abi.encodeWithSelector(tokenContract.approve.selector, spender, 0));
        require(success, "AggregatorSmart: approve to 0 failed");
    }

    /// @notice Transfers ownership of the contract to a new account
    /// @param newOwner The address of the new owner
    function transferOwnership(address newOwner) external onlyOwner {
        require(newOwner != address(0), "AggregatorSmart: new owner is the zero address");
        emit OwnershipTransferred(owner, newOwner);
        owner = newOwner;
    }

    /// @notice Fallback function to receive ETH (needed for some aggregator interactions)
    receive() external payable {}
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";
import "../extensions/IERC20Permit.sol";
import "../../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using Address for address;

    /**
     * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    /**
     * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
     * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
     */
    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        require(
            (value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value));
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        unchecked {
            uint256 oldAllowance = token.allowance(address(this), spender);
            require(oldAllowance >= value, "SafeERC20: decreased allowance below zero");
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value));
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeWithSelector(token.approve.selector, spender, value);

        if (!_callOptionalReturnBool(token, approvalCall)) {
            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0));
            _callOptionalReturn(token, approvalCall);
        }
    }

    /**
     * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`.
     * Revert on invalid signature.
     */
    function safePermit(
        IERC20Permit token,
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        uint256 nonceBefore = token.nonces(owner);
        token.permit(owner, spender, value, deadline, v, r, s);
        uint256 nonceAfter = token.nonces(owner);
        require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

        (bool success, bytes memory returndata) = address(token).call(data);
        return
            success && (returndata.length == 0 || abi.decode(returndata, (bool))) && Address.isContract(address(token));
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol)

pragma solidity ^0.8.1;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     *
     * Furthermore, `isContract` will also return true if the target contract within
     * the same transaction is already scheduled for destruction by `SELFDESTRUCT`,
     * which only has an effect at the end of a transaction.
     * ====
     *
     * [IMPORTANT]
     * ====
     * You shouldn't rely on `isContract` to protect against flash loan attacks!
     *
     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
     * constructor.
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize/address.code.length, which returns 0
        // for contracts in construction, since the code is only stored at the end
        // of the constructor execution.

        return account.code.length > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        (bool success, ) = recipient.call{value: amount}("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(
        address target,
        bytes memory data,
        uint256 value,
        string memory errorMessage
    ) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(
        address target,
        bytes memory data,
        string memory errorMessage
    ) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata, errorMessage);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
     *
     * _Available since v4.8._
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal view returns (bytes memory) {
        if (success) {
            if (returndata.length == 0) {
                // only check isContract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                require(isContract(target), "Address: call to non-contract");
            }
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
     * revert reason or using the provided one.
     *
     * _Available since v4.3._
     */
    function verifyCallResult(
        bool success,
        bytes memory returndata,
        string memory errorMessage
    ) internal pure returns (bytes memory) {
        if (success) {
            return returndata;
        } else {
            _revert(returndata, errorMessage);
        }
    }

    function _revert(bytes memory returndata, string memory errorMessage) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert(errorMessage);
        }
    }
}

Settings
{
  "remappings": [
    "forge-std/=vendor/forge-std/src/",
    "@openzeppelin/contracts/=vendor/openzeppelin-contracts-v4.9.3/contracts/",
    "solmate/src/=vendor/solmate/src/",
    "solidity-bytes-utils/contracts/=vendor/solidity-bytes-utils/contracts/",
    "@uniswap/lib/contracts/=vendor/solidity-lib/contracts/",
    "@zf/=vendor/@zf/",
    "base64-sol/=vendor/base64-sol/",
    "@uniswap/v2-core/contracts/=vendor/uniswap-v2-core/contracts/",
    "devtools/=vendor/devtools/",
    "ds-test/=vendor/ds-test/src/",
    "layerzero-v2/=vendor/layerzero-v2/",
    "openzeppelin-contracts-upgradeable-v5.2.0/=vendor/openzeppelin-contracts-upgradeable-v5.2.0/contracts/",
    "openzeppelin-contracts-v3.4.2-solc-0.7/=vendor/openzeppelin-contracts-v3.4.2-solc-0.7/contracts/",
    "openzeppelin-contracts-v4.9.3/=vendor/openzeppelin-contracts-v4.9.3/contracts/",
    "openzeppelin-contracts-v5.2.0/=vendor/openzeppelin-contracts-v5.2.0/contracts/",
    "solidity-lib/=vendor/solidity-lib/contracts/",
    "uniswap-v2-core/=vendor/uniswap-v2-core/contracts/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "prague",
  "viaIR": false
}

Contract Security Audit

Contract ABI

API
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"AggregatorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"}],"name":"AggregatorWhitelisted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"aggregator","type":"address"},{"indexed":true,"internalType":"address","name":"permit2","type":"address"}],"name":"AggregatorWithPermit2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyRecover","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EmergencyRecoverETH","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":"user","type":"address"},{"indexed":true,"internalType":"address","name":"aggregator","type":"address"},{"indexed":true,"internalType":"address","name":"tokenIn","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"}],"name":"SwapSmart","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"aggregator","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenApproved","type":"event"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"aggregatorWithPermit2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyRecover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"emergencyRecoverETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"isWhitelisted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"removeAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"removeAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"address","name":"permit2","type":"address"}],"name":"setAggregatorWithPermit2","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"}],"name":"setWhitelistAggregator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"aggregator","type":"address"},{"internalType":"address","name":"tokenIn","type":"address"},{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"bytes","name":"callData","type":"bytes"}],"name":"swapSmart","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"returnData","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedAggregators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

6080604052348015600e575f5ffd5b5060015f81815581546001600160a01b031916339081179092556040517f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0908290a36119348061005d5f395ff3fe6080604052600436106100a8575f3560e01c8063a3aa8e8711610062578063a3aa8e87146101b6578063ad1329d1146101d5578063b24c7d2f146101f4578063b85a41d414610222578063dc856a5e14610241578063f2fde38b14610275575f5ffd5b80633af32abf146100b357806371d277e7146100ff578063843ad9c5146101205780638c651f11146101415780638da5cb5b14610160578063a3529b3414610197575f5ffd5b366100af57005b5f5ffd5b3480156100be575f5ffd5b506100ea6100cd3660046114b9565b6001600160a01b03165f9081526002602052604090205460ff1690565b60405190151581526020015b60405180910390f35b34801561010a575f5ffd5b5061011e6101193660046114db565b610294565b005b61013361012e366004611505565b61043e565b6040516100f69291906115cc565b34801561014c575f5ffd5b5061011e61015b3660046114b9565b6107f4565b34801561016b575f5ffd5b5060015461017f906001600160a01b031681565b6040516001600160a01b0390911681526020016100f6565b3480156101a2575f5ffd5b5061011e6101b13660046114b9565b61089d565b3480156101c1575f5ffd5b5061011e6101d03660046115e6565b6109b8565b3480156101e0575f5ffd5b5061011e6101ef36600461161d565b610ac5565b3480156101ff575f5ffd5b506100ea61020e3660046114b9565b60026020525f908152604090205460ff1681565b34801561022d575f5ffd5b5061011e61023c3660046115e6565b610b7b565b34801561024c575f5ffd5b5061017f61025b3660046114b9565b60036020525f90815260409020546001600160a01b031681565b348015610280575f5ffd5b5061011e61028f3660046114b9565b610c40565b6001546001600160a01b031633146102c75760405162461bcd60e51b81526004016102be9061165b565b60405180910390fd5b6001600160a01b0382166102ed5760405162461bcd60e51b81526004016102be906116a3565b8047101561034b5760405162461bcd60e51b815260206004820152602560248201527f41676772656761746f72536d6172743a20696e73756666696369656e742062616044820152646c616e636560d81b60648201526084016102be565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610394576040519150601f19603f3d011682016040523d82523d5f602084013e610399565b606091505b50509050806103f65760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a20455448207472616e736665722066616044820152631a5b195960e21b60648201526084016102be565b826001600160a01b03167fe4afa7dbd362098b01cda2fb38d6390719a48039f6a7cd4b88b3319c92a1d4cc8360405161043191815260200190565b60405180910390a2505050565b5f6060610449610d32565b6001600160a01b0387165f9081526002602052604090205460ff166104805760405162461bcd60e51b81526004016102be906116ed565b5f85116104e65760405162461bcd60e51b815260206004820152602e60248201527f41676772656761746f72536d6172743a20616d6f756e74206d7573742062652060448201526d067726561746572207468616e20360941b60648201526084016102be565b826105335760405162461bcd60e51b815260206004820152601f60248201527f41676772656761746f72536d6172743a20656d7074792063616c6c646174610060448201526064016102be565b856001600160a01b0316876001600160a01b0316336001600160a01b03167f03240560cd0109ce6bfa487f49ea5e3fa7e72b1ad6c6d55c57f744d27bbb6b6e8860405161058291815260200190565b60405180910390a45f196001600160a01b03871601610678578434146105f65760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a2045544820616d6f756e74206d69736d6044820152630c2e8c6d60e31b60648201526084016102be565b866001600160a01b0316858585604051610611929190611738565b5f6040518083038185875af1925050503d805f811461064b576040519150601f19603f3d011682016040523d82523d5f602084013e610650565b606091505b509092509050816106735760405162461bcd60e51b81526004016102be90611747565b6107e1565b6001600160a01b03861661069e5760405162461bcd60e51b81526004016102be9061178e565b34156107085760405162461bcd60e51b815260206004820152603360248201527f41676772656761746f72536d6172743a20756e65787065637465642045544820604482015272073656e7420666f72204552433230207377617606c1b60648201526084016102be565b61071d6001600160a01b038716333088610d89565b6001600160a01b038088165f9081526003602052604090205416801561075957610748878288610dfa565b61075487898389610fc6565b610764565b610764878988610dfa565b876001600160a01b0316858560405161077e929190611738565b5f604051808303815f865af19150503d805f81146107b7576040519150601f19603f3d011682016040523d82523d5f602084013e6107bc565b606091505b509093509150826107df5760405162461bcd60e51b81526004016102be90611747565b505b6107ea60015f55565b9550959350505050565b6001546001600160a01b0316331461081e5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b0381165f9081526002602052604090205460ff166108555760405162461bcd60e51b81526004016102be906116ed565b6001600160a01b0381165f81815260026020526040808220805460ff19169055517fe57df70929b1c62badc06b12770e8aceca66ffc8c10367bbedb6b894445dbcd49190a250565b6001546001600160a01b031633146108c75760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b0381166108ed5760405162461bcd60e51b81526004016102be906117d4565b6001600160a01b0381165f9081526002602052604090205460ff161561096d5760405162461bcd60e51b815260206004820152602f60248201527f41676772656761746f72536d6172743a2061676772656761746f7220616c726560448201526e18591e481dda1a5d195b1a5cdd1959608a1b60648201526084016102be565b6001600160a01b0381165f81815260026020526040808220805460ff19166001179055517f5fb07c1d8e5a90425056b3176533efc88cd7c4da3abd0b8fb22b4fb59cab60ed9190a250565b6001546001600160a01b031633146109e25760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610a085760405162461bcd60e51b81526004016102be906117d4565b6001600160a01b038116610a6f5760405162461bcd60e51b815260206004820152602860248201527f41676772656761746f72536d6172743a20696e76616c6964207065726d697432604482015267206164647265737360c01b60648201526084016102be565b6001600160a01b038281165f8181526003602052604080822080546001600160a01b0319169486169485179055517f69c7bb365a8cf032a6e0f43168b7e1363cd0b4ccb562c4933cd491cbd7e8d5019190a35050565b6001546001600160a01b03163314610aef5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610b155760405162461bcd60e51b81526004016102be906116a3565b610b296001600160a01b038416838361111b565b816001600160a01b0316836001600160a01b03167f1fb552e352146cbf91ab18bef411c89c83078d9c853e55bef197d0b67312850083604051610b6e91815260200190565b60405180910390a3505050565b6001546001600160a01b03163314610ba55760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610bcb5760405162461bcd60e51b81526004016102be9061178e565b6001600160a01b038116610c325760405162461bcd60e51b815260206004820152602860248201527f41676772656761746f72536d6172743a20696e76616c6964207370656e646572604482015267206164647265737360c01b60648201526084016102be565b610c3c8282611150565b5050565b6001546001600160a01b03163314610c6a5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038116610cd75760405162461bcd60e51b815260206004820152602e60248201527f41676772656761746f72536d6172743a206e6577206f776e657220697320746860448201526d65207a65726f206164647265737360901b60648201526084016102be565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60025f5403610d835760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016102be565b60025f55565b6040516001600160a01b0380851660248301528316604482015260648101829052610df49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611245565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284915f9183169063dd62ed3e90604401602060405180830381865afa158015610e48573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6c919061181f565b905082811015610fbf578015610e8657610e868585611150565b604080516001600160a01b0386811660248301525f1960448084019190915283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291515f92881691610ee091611836565b5f604051808303815f865af19150503d805f8114610f19576040519150601f19603f3d011682016040523d82523d5f602084013e610f1e565b606091505b5050905080610f6f5760405162461bcd60e51b815260206004820152601f60248201527f41676772656761746f72536d6172743a20617070726f7665206661696c65640060448201526064016102be565b846001600160a01b0316866001600160a01b03167fc532e6b60637d86dd3fe55f7548ed169de9c79cfdef610593bea3569f079bc655f19604051610fb591815260200190565b60405180910390a3505b5050505050565b60405163927da10560e01b81523060048201526001600160a01b038581166024830152848116604483015283915f9182919084169063927da10590606401606060405180830381865afa15801561101f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110439190611866565b509150915083826001600160a01b03161080611071575061106642610e106118a8565b8165ffffffffffff16105b1561111257826001600160a01b03166387517c4588886001600160a01b03426301e1338061109f91906118a8565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b1580156110fb575f5ffd5b505af115801561110d573d5f5f3e3d5ffd5b505050505b50505050505050565b6040516001600160a01b03831660248201526044810182905261114b90849063a9059cbb60e01b90606401610dbd565b505050565b604080516001600160a01b0383811660248301525f604480840182905284518085039091018152606490930184526020830180516001600160e01b031663095ea7b360e01b1790529251859392918416916111aa91611836565b5f604051808303815f865af19150503d805f81146111e3576040519150601f19603f3d011682016040523d82523d5f602084013e6111e8565b606091505b5050905080610df45760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a20617070726f766520746f20302066616044820152631a5b195960e21b60648201526084016102be565b5f611299826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166113189092919063ffffffff16565b905080515f14806112b95750808060200190518101906112b991906118cd565b61114b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102be565b606061132684845f8561132e565b949350505050565b60608247101561138f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102be565b5f5f866001600160a01b031685876040516113aa9190611836565b5f6040518083038185875af1925050503d805f81146113e4576040519150601f19603f3d011682016040523d82523d5f602084013e6113e9565b606091505b50915091506113fa87838387611405565b979650505050505050565b606083156114735782515f0361146c576001600160a01b0385163b61146c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102be565b5081611326565b61132683838151156114885781518083602001fd5b8060405162461bcd60e51b81526004016102be91906118ec565b6001600160a01b03811681146114b6575f5ffd5b50565b5f602082840312156114c9575f5ffd5b81356114d4816114a2565b9392505050565b5f5f604083850312156114ec575f5ffd5b82356114f7816114a2565b946020939093013593505050565b5f5f5f5f5f60808688031215611519575f5ffd5b8535611524816114a2565b94506020860135611534816114a2565b935060408601359250606086013567ffffffffffffffff811115611556575f5ffd5b8601601f81018813611566575f5ffd5b803567ffffffffffffffff81111561157c575f5ffd5b88602082840101111561158d575f5ffd5b959894975092955050506020019190565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8215158152604060208201525f611326604083018461159e565b5f5f604083850312156115f7575f5ffd5b8235611602816114a2565b91506020830135611612816114a2565b809150509250929050565b5f5f5f6060848603121561162f575f5ffd5b833561163a816114a2565b9250602084013561164a816114a2565b929592945050506040919091013590565b60208082526028908201527f41676772656761746f72536d6172743a2063616c6c6572206973206e6f74207460408201526734329037bbb732b960c11b606082015260800190565b6020808252602a908201527f41676772656761746f72536d6172743a20696e76616c696420726563697069656040820152696e74206164647265737360b01b606082015260800190565b6020808252602b908201527f41676772656761746f72536d6172743a2061676772656761746f72206e6f742060408201526a1dda1a5d195b1a5cdd195960aa1b606082015260800190565b818382375f9101908152919050565b60208082526027908201527f41676772656761746f72536d6172743a2061676772656761746f722063616c6c6040820152660819985a5b195960ca1b606082015260800190565b60208082526026908201527f41676772656761746f72536d6172743a20696e76616c696420746f6b656e206160408201526564647265737360d01b606082015260800190565b6020808252602b908201527f41676772656761746f72536d6172743a20696e76616c6964206167677265676160408201526a746f72206164647265737360a81b606082015260800190565b5f6020828403121561182f575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b805165ffffffffffff81168114611861575f5ffd5b919050565b5f5f5f60608486031215611878575f5ffd5b8351611883816114a2565b92506118916020850161184c565b915061189f6040850161184c565b90509250925092565b808201808211156118c757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f602082840312156118dd575f5ffd5b815180151581146114d4575f5ffd5b602081525f6114d4602083018461159e56fea264697066735822122054cd77083704606be98563253a07a79feef563b1ba96390bdddef956b2f6482a64736f6c634300081b0033

Deployed Bytecode

0x6080604052600436106100a8575f3560e01c8063a3aa8e8711610062578063a3aa8e87146101b6578063ad1329d1146101d5578063b24c7d2f146101f4578063b85a41d414610222578063dc856a5e14610241578063f2fde38b14610275575f5ffd5b80633af32abf146100b357806371d277e7146100ff578063843ad9c5146101205780638c651f11146101415780638da5cb5b14610160578063a3529b3414610197575f5ffd5b366100af57005b5f5ffd5b3480156100be575f5ffd5b506100ea6100cd3660046114b9565b6001600160a01b03165f9081526002602052604090205460ff1690565b60405190151581526020015b60405180910390f35b34801561010a575f5ffd5b5061011e6101193660046114db565b610294565b005b61013361012e366004611505565b61043e565b6040516100f69291906115cc565b34801561014c575f5ffd5b5061011e61015b3660046114b9565b6107f4565b34801561016b575f5ffd5b5060015461017f906001600160a01b031681565b6040516001600160a01b0390911681526020016100f6565b3480156101a2575f5ffd5b5061011e6101b13660046114b9565b61089d565b3480156101c1575f5ffd5b5061011e6101d03660046115e6565b6109b8565b3480156101e0575f5ffd5b5061011e6101ef36600461161d565b610ac5565b3480156101ff575f5ffd5b506100ea61020e3660046114b9565b60026020525f908152604090205460ff1681565b34801561022d575f5ffd5b5061011e61023c3660046115e6565b610b7b565b34801561024c575f5ffd5b5061017f61025b3660046114b9565b60036020525f90815260409020546001600160a01b031681565b348015610280575f5ffd5b5061011e61028f3660046114b9565b610c40565b6001546001600160a01b031633146102c75760405162461bcd60e51b81526004016102be9061165b565b60405180910390fd5b6001600160a01b0382166102ed5760405162461bcd60e51b81526004016102be906116a3565b8047101561034b5760405162461bcd60e51b815260206004820152602560248201527f41676772656761746f72536d6172743a20696e73756666696369656e742062616044820152646c616e636560d81b60648201526084016102be565b5f826001600160a01b0316826040515f6040518083038185875af1925050503d805f8114610394576040519150601f19603f3d011682016040523d82523d5f602084013e610399565b606091505b50509050806103f65760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a20455448207472616e736665722066616044820152631a5b195960e21b60648201526084016102be565b826001600160a01b03167fe4afa7dbd362098b01cda2fb38d6390719a48039f6a7cd4b88b3319c92a1d4cc8360405161043191815260200190565b60405180910390a2505050565b5f6060610449610d32565b6001600160a01b0387165f9081526002602052604090205460ff166104805760405162461bcd60e51b81526004016102be906116ed565b5f85116104e65760405162461bcd60e51b815260206004820152602e60248201527f41676772656761746f72536d6172743a20616d6f756e74206d7573742062652060448201526d067726561746572207468616e20360941b60648201526084016102be565b826105335760405162461bcd60e51b815260206004820152601f60248201527f41676772656761746f72536d6172743a20656d7074792063616c6c646174610060448201526064016102be565b856001600160a01b0316876001600160a01b0316336001600160a01b03167f03240560cd0109ce6bfa487f49ea5e3fa7e72b1ad6c6d55c57f744d27bbb6b6e8860405161058291815260200190565b60405180910390a45f196001600160a01b03871601610678578434146105f65760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a2045544820616d6f756e74206d69736d6044820152630c2e8c6d60e31b60648201526084016102be565b866001600160a01b0316858585604051610611929190611738565b5f6040518083038185875af1925050503d805f811461064b576040519150601f19603f3d011682016040523d82523d5f602084013e610650565b606091505b509092509050816106735760405162461bcd60e51b81526004016102be90611747565b6107e1565b6001600160a01b03861661069e5760405162461bcd60e51b81526004016102be9061178e565b34156107085760405162461bcd60e51b815260206004820152603360248201527f41676772656761746f72536d6172743a20756e65787065637465642045544820604482015272073656e7420666f72204552433230207377617606c1b60648201526084016102be565b61071d6001600160a01b038716333088610d89565b6001600160a01b038088165f9081526003602052604090205416801561075957610748878288610dfa565b61075487898389610fc6565b610764565b610764878988610dfa565b876001600160a01b0316858560405161077e929190611738565b5f604051808303815f865af19150503d805f81146107b7576040519150601f19603f3d011682016040523d82523d5f602084013e6107bc565b606091505b509093509150826107df5760405162461bcd60e51b81526004016102be90611747565b505b6107ea60015f55565b9550959350505050565b6001546001600160a01b0316331461081e5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b0381165f9081526002602052604090205460ff166108555760405162461bcd60e51b81526004016102be906116ed565b6001600160a01b0381165f81815260026020526040808220805460ff19169055517fe57df70929b1c62badc06b12770e8aceca66ffc8c10367bbedb6b894445dbcd49190a250565b6001546001600160a01b031633146108c75760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b0381166108ed5760405162461bcd60e51b81526004016102be906117d4565b6001600160a01b0381165f9081526002602052604090205460ff161561096d5760405162461bcd60e51b815260206004820152602f60248201527f41676772656761746f72536d6172743a2061676772656761746f7220616c726560448201526e18591e481dda1a5d195b1a5cdd1959608a1b60648201526084016102be565b6001600160a01b0381165f81815260026020526040808220805460ff19166001179055517f5fb07c1d8e5a90425056b3176533efc88cd7c4da3abd0b8fb22b4fb59cab60ed9190a250565b6001546001600160a01b031633146109e25760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610a085760405162461bcd60e51b81526004016102be906117d4565b6001600160a01b038116610a6f5760405162461bcd60e51b815260206004820152602860248201527f41676772656761746f72536d6172743a20696e76616c6964207065726d697432604482015267206164647265737360c01b60648201526084016102be565b6001600160a01b038281165f8181526003602052604080822080546001600160a01b0319169486169485179055517f69c7bb365a8cf032a6e0f43168b7e1363cd0b4ccb562c4933cd491cbd7e8d5019190a35050565b6001546001600160a01b03163314610aef5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610b155760405162461bcd60e51b81526004016102be906116a3565b610b296001600160a01b038416838361111b565b816001600160a01b0316836001600160a01b03167f1fb552e352146cbf91ab18bef411c89c83078d9c853e55bef197d0b67312850083604051610b6e91815260200190565b60405180910390a3505050565b6001546001600160a01b03163314610ba55760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038216610bcb5760405162461bcd60e51b81526004016102be9061178e565b6001600160a01b038116610c325760405162461bcd60e51b815260206004820152602860248201527f41676772656761746f72536d6172743a20696e76616c6964207370656e646572604482015267206164647265737360c01b60648201526084016102be565b610c3c8282611150565b5050565b6001546001600160a01b03163314610c6a5760405162461bcd60e51b81526004016102be9061165b565b6001600160a01b038116610cd75760405162461bcd60e51b815260206004820152602e60248201527f41676772656761746f72536d6172743a206e6577206f776e657220697320746860448201526d65207a65726f206164647265737360901b60648201526084016102be565b6001546040516001600160a01b038084169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3600180546001600160a01b0319166001600160a01b0392909216919091179055565b60025f5403610d835760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016102be565b60025f55565b6040516001600160a01b0380851660248301528316604482015260648101829052610df49085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152611245565b50505050565b604051636eb1769f60e11b81523060048201526001600160a01b03838116602483015284915f9183169063dd62ed3e90604401602060405180830381865afa158015610e48573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6c919061181f565b905082811015610fbf578015610e8657610e868585611150565b604080516001600160a01b0386811660248301525f1960448084019190915283518084039091018152606490920183526020820180516001600160e01b031663095ea7b360e01b17905291515f92881691610ee091611836565b5f604051808303815f865af19150503d805f8114610f19576040519150601f19603f3d011682016040523d82523d5f602084013e610f1e565b606091505b5050905080610f6f5760405162461bcd60e51b815260206004820152601f60248201527f41676772656761746f72536d6172743a20617070726f7665206661696c65640060448201526064016102be565b846001600160a01b0316866001600160a01b03167fc532e6b60637d86dd3fe55f7548ed169de9c79cfdef610593bea3569f079bc655f19604051610fb591815260200190565b60405180910390a3505b5050505050565b60405163927da10560e01b81523060048201526001600160a01b038581166024830152848116604483015283915f9182919084169063927da10590606401606060405180830381865afa15801561101f573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110439190611866565b509150915083826001600160a01b03161080611071575061106642610e106118a8565b8165ffffffffffff16105b1561111257826001600160a01b03166387517c4588886001600160a01b03426301e1338061109f91906118a8565b6040516001600160e01b031960e087901b1681526001600160a01b03948516600482015292841660248401529216604482015265ffffffffffff90911660648201526084015f604051808303815f87803b1580156110fb575f5ffd5b505af115801561110d573d5f5f3e3d5ffd5b505050505b50505050505050565b6040516001600160a01b03831660248201526044810182905261114b90849063a9059cbb60e01b90606401610dbd565b505050565b604080516001600160a01b0383811660248301525f604480840182905284518085039091018152606490930184526020830180516001600160e01b031663095ea7b360e01b1790529251859392918416916111aa91611836565b5f604051808303815f865af19150503d805f81146111e3576040519150601f19603f3d011682016040523d82523d5f602084013e6111e8565b606091505b5050905080610df45760405162461bcd60e51b8152602060048201526024808201527f41676772656761746f72536d6172743a20617070726f766520746f20302066616044820152631a5b195960e21b60648201526084016102be565b5f611299826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166113189092919063ffffffff16565b905080515f14806112b95750808060200190518101906112b991906118cd565b61114b5760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b60648201526084016102be565b606061132684845f8561132e565b949350505050565b60608247101561138f5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b60648201526084016102be565b5f5f866001600160a01b031685876040516113aa9190611836565b5f6040518083038185875af1925050503d805f81146113e4576040519150601f19603f3d011682016040523d82523d5f602084013e6113e9565b606091505b50915091506113fa87838387611405565b979650505050505050565b606083156114735782515f0361146c576001600160a01b0385163b61146c5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016102be565b5081611326565b61132683838151156114885781518083602001fd5b8060405162461bcd60e51b81526004016102be91906118ec565b6001600160a01b03811681146114b6575f5ffd5b50565b5f602082840312156114c9575f5ffd5b81356114d4816114a2565b9392505050565b5f5f604083850312156114ec575f5ffd5b82356114f7816114a2565b946020939093013593505050565b5f5f5f5f5f60808688031215611519575f5ffd5b8535611524816114a2565b94506020860135611534816114a2565b935060408601359250606086013567ffffffffffffffff811115611556575f5ffd5b8601601f81018813611566575f5ffd5b803567ffffffffffffffff81111561157c575f5ffd5b88602082840101111561158d575f5ffd5b959894975092955050506020019190565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b8215158152604060208201525f611326604083018461159e565b5f5f604083850312156115f7575f5ffd5b8235611602816114a2565b91506020830135611612816114a2565b809150509250929050565b5f5f5f6060848603121561162f575f5ffd5b833561163a816114a2565b9250602084013561164a816114a2565b929592945050506040919091013590565b60208082526028908201527f41676772656761746f72536d6172743a2063616c6c6572206973206e6f74207460408201526734329037bbb732b960c11b606082015260800190565b6020808252602a908201527f41676772656761746f72536d6172743a20696e76616c696420726563697069656040820152696e74206164647265737360b01b606082015260800190565b6020808252602b908201527f41676772656761746f72536d6172743a2061676772656761746f72206e6f742060408201526a1dda1a5d195b1a5cdd195960aa1b606082015260800190565b818382375f9101908152919050565b60208082526027908201527f41676772656761746f72536d6172743a2061676772656761746f722063616c6c6040820152660819985a5b195960ca1b606082015260800190565b60208082526026908201527f41676772656761746f72536d6172743a20696e76616c696420746f6b656e206160408201526564647265737360d01b606082015260800190565b6020808252602b908201527f41676772656761746f72536d6172743a20696e76616c6964206167677265676160408201526a746f72206164647265737360a81b606082015260800190565b5f6020828403121561182f575f5ffd5b5051919050565b5f82518060208501845e5f920191825250919050565b805165ffffffffffff81168114611861575f5ffd5b919050565b5f5f5f60608486031215611878575f5ffd5b8351611883816114a2565b92506118916020850161184c565b915061189f6040850161184c565b90509250925092565b808201808211156118c757634e487b7160e01b5f52601160045260245ffd5b92915050565b5f602082840312156118dd575f5ffd5b815180151581146114d4575f5ffd5b602081525f6114d4602083018461159e56fea264697066735822122054cd77083704606be98563253a07a79feef563b1ba96390bdddef956b2f6482a64736f6c634300081b0033

Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ 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.