ETH Price: $4,483.66 (-1.23%)

Contract

0x3B1f4ABA1667EeB992B623E7c6d119728cEd3b15

Overview

ETH Balance

0 ETH

ETH Value

$0.00

More Info

Private Name Tags

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Connect Socket113941172025-09-17 19:22:0816 days ago1758136928IN
0x3B1f4ABA...28cEd3b15
0 ETH0.000001450.00105027
Grant Role113923802025-09-17 18:53:1116 days ago1758135191IN
0x3B1f4ABA...28cEd3b15
0 ETH0.00000140.00105027

Latest 1 internal transaction

Advanced mode:
Parent Transaction Hash Block From To
113941172025-09-17 19:22:0816 days ago1758136928
0x3B1f4ABA...28cEd3b15
0 ETH

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
FeesPlug

Compiler Version
v0.8.22+commit.4fc1097e

Optimization Enabled:
Yes with 1 runs

Other Settings:
paris EvmVersion
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import "lib/solady/src/utils/SafeTransferLib.sol";
import "../../protocol/base/PlugBase.sol";
import "../../utils/AccessControl.sol";
import {RESCUE_ROLE} from "../../utils/common/AccessRoles.sol";
import {IFeesPlug} from "../interfaces/IFeesPlug.sol";
import "../../utils/RescueFundsLib.sol";
import {InvalidTokenAddress} from "../../utils/common/Errors.sol";
import "../interfaces/IERC20.sol";

/// @title FeesPlug
/// @notice Contract for managing fees on a network
/// @dev The amount deposited here is locked and updated in the EVMx for an app gateway
/// @dev The fees are redeemed by the transmitters executing request or can be withdrawn by the owner
contract FeesPlug is IFeesPlug, PlugBase, AccessControl {
    using SafeTransferLib for address;

    /// @notice Mapping to store if a token is whitelisted
    mapping(address => bool) public whitelistedTokens;

    /// @notice Error thrown when balance is not enough to cover fees
    error InsufficientTokenBalance(address token_, uint256 balance_, uint256 fee_);
    /// @notice Error thrown when deposit amount does not match msg.value
    error InvalidDepositAmount();
    /// @notice Error thrown when token is not whitelisted
    error TokenNotWhitelisted(address token_);

    /// @notice Constructor for the FeesPlug contract
    /// @param socket_ The socket address
    /// @param owner_ The owner address
    constructor(address socket_, address owner_) {
        _setSocket(socket_);
        _initializeOwner(owner_);

        isSocketInitialized = 1;
    }

    /////////////////////// DEPOSIT AND WITHDRAWAL ///////////////////////
    function depositCredit(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external override {
        _deposit(token_, receiver_, amount_, 0, data_);
    }

    function depositCreditAndNative(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external override {
        uint256 nativeAmount_ = amount_ / 10;
        _deposit(token_, receiver_, amount_ - nativeAmount_, nativeAmount_, data_);
    }

    function depositToNative(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external override {
        _deposit(token_, receiver_, 0, amount_, data_);
    }

    /// @notice Deposits funds
    /// @param token_ The token address
    /// @param creditAmount_ The amount of fees
    /// @param nativeAmount_ The amount of native tokens
    /// @param receiver_ The receiver address
    function _deposit(
        address token_,
        address receiver_,
        uint256 creditAmount_,
        uint256 nativeAmount_,
        bytes memory data_
    ) internal {
        if (!whitelistedTokens[token_]) revert TokenNotWhitelisted(token_);
        token_.safeTransferFrom(msg.sender, address(this), creditAmount_ + nativeAmount_);
        emit FeesDeposited(token_, receiver_, creditAmount_, nativeAmount_, data_);
    }

    /// @notice Withdraws fees
    /// @param token_ The token address
    /// @param amount_ The amount
    /// @param receiver_ The receiver address
    function withdrawFees(
        address token_,
        address receiver_,
        uint256 amount_
    ) external override onlySocket {
        uint256 balance = IERC20(token_).balanceOf(address(this));
        uint8 decimals = IERC20(token_).decimals();

        if (decimals < 18) {
            amount_ = amount_ / 10 ** (18 - decimals);
        } else if (decimals > 18) {
            amount_ = amount_ * 10 ** (decimals - 18);
        }
        if (balance < amount_) revert InsufficientTokenBalance(token_, balance, amount_);

        token_.safeTransfer(receiver_, amount_);
        emit FeesWithdrawn(token_, receiver_, amount_);
    }

    /////////////////////// ADMIN FUNCTIONS ///////////////////////

    /// @notice Adds a token to the whitelist
    /// @param token_ The token address to whitelist
    function whitelistToken(address token_) external onlyOwner {
        if (token_.code.length == 0) revert InvalidTokenAddress();
        whitelistedTokens[token_] = true;
        emit TokenWhitelisted(token_);
    }

    /// @notice Removes a token from the whitelist
    /// @param token_ The token address to remove
    function removeTokenFromWhitelist(address token_) external onlyOwner {
        whitelistedTokens[token_] = false;
        emit TokenRemovedFromWhitelist(token_);
    }

    function connectSocket(
        bytes32 appGatewayId_,
        address socket_,
        uint64 switchboardId_
    ) external onlyOwner {
        _connectSocket(appGatewayId_, socket_, switchboardId_);
    }

    function disconnectSocket() external onlyOwner {
        socket__.disconnect();
    }

    /**
     * @notice Rescues funds from the contract if they are locked by mistake. This contract does not
     * theoretically need this function but it is added for safety.
     * @param token_ The address of the token contract.
     * @param rescueTo_ The address where rescued tokens need to be sent.
     * @param amount_ The amount of tokens to be rescued.
     */
    function rescueFunds(
        address token_,
        address rescueTo_,
        uint256 amount_
    ) external onlyRole(RESCUE_ROLE) {
        RescueFundsLib._rescueFunds(token_, rescueTo_, amount_);
    }
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

interface IERC20 {
    function totalSupply() external view returns (uint256);

    function balanceOf(address account) external view returns (uint256);

    function transfer(address to, uint256 amount) external returns (bool);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 amount) external returns (bool);

    function transferFrom(address from, address to, uint256 amount) external returns (bool);

    function decimals() external view returns (uint8);

    event Transfer(address indexed from, address indexed to, uint256 value);

    event Approval(address indexed owner, address indexed spender, uint256 value);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

interface IFeesPlug {
    /// @notice Event emitted when fees are deposited
    event FeesDeposited(
        address token,
        address receiver,
        uint256 creditAmount,
        uint256 nativeAmount,
        bytes data
    );
    /// @notice Event emitted when fees are withdrawn
    event FeesWithdrawn(address token, address receiver, uint256 amount);
    /// @notice Event emitted when a token is whitelisted
    event TokenWhitelisted(address token);
    /// @notice Event emitted when a token is removed from whitelist
    event TokenRemovedFromWhitelist(address token);

    function depositCredit(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external;

    function depositCreditAndNative(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external;

    function depositToNative(
        address token_,
        address receiver_,
        uint256 amount_,
        bytes memory data_
    ) external;

    function withdrawFees(address token_, address receiver_, uint256 amount_) external;
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import {ISocket} from "../interfaces/ISocket.sol";
import {IPlug} from "../interfaces/IPlug.sol";
import {NotSocket, SocketAlreadyInitialized} from "../../utils/common/Errors.sol";

/// @title PlugBase
/// @notice Abstract contract for plugs
/// @dev This contract contains helpers for socket connection, disconnection, and overrides
abstract contract PlugBase is IPlug {
    // socket instance
    ISocket public socket__;

    // app gateway id connected to this plug
    bytes32 public appGatewayId;

    // tracks if socket is initialized
    uint256 public isSocketInitialized;

    // overrides encoded in bytes
    bytes public overrides;

    // event emitted when plug is disconnected
    event ConnectorPlugDisconnected();

    /// @notice Modifier to ensure only the socket can call the function
    /// @dev only the socket can call the function
    modifier onlySocket() {
        if (msg.sender != address(socket__)) revert NotSocket();
        _;
    }

    /// @notice Modifier to ensure the socket is initialized and if not already initialized, it will be initialized
    modifier socketInitializer() {
        if (isSocketInitialized == 1) revert SocketAlreadyInitialized();
        isSocketInitialized = 1;
        _;
    }

    /// @notice Connects the plug to the app gateway and switchboard
    /// @param appGatewayId_ The app gateway id
    /// @param socket_ The socket address
    /// @param switchboardId_ The switchboard id
    function _connectSocket(
        bytes32 appGatewayId_,
        address socket_,
        uint64 switchboardId_
    ) internal {
        _setSocket(socket_);
        appGatewayId = appGatewayId_;

        // connect to the app gateway and switchboard
        socket__.connect(appGatewayId_, switchboardId_);
    }

    /// @notice Disconnects the plug from the socket
    function _disconnectSocket() internal {
        socket__.disconnect();
        emit ConnectorPlugDisconnected();
    }

    /// @notice Sets the socket
    /// @param socket_ The socket address
    function _setSocket(address socket_) internal {
        socket__ = ISocket(socket_);
    }

    /// @notice Sets the overrides needed for the trigger
    /// @dev encoding format depends on the watcher system
    /// @param overrides_ The overrides
    function _setOverrides(bytes memory overrides_) internal {
        overrides = overrides_;
    }

    /// @notice Initializes the socket
    /// @dev this function should be called even if deployed independently
    /// to avoid ownership and permission exploit
    /// @param appGatewayId_ The app gateway id
    /// @param socket_ The socket address
    /// @param switchboardId_ The switchboard id
    function initSocket(
        bytes32 appGatewayId_,
        address socket_,
        uint64 switchboardId_
    ) external virtual socketInitializer {
        _connectSocket(appGatewayId_, socket_, switchboardId_);
    }
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

/**
 * @title IPlug
 * @notice Interface for a plug contract that executes the payload received from a source chain.
 */
interface IPlug {
    /// @notice Initializes the socket
    /// @param appGatewayId_ The app gateway id
    /// @param socket_ The socket address
    /// @param switchboardId_ The switchboard id
    function initSocket(bytes32 appGatewayId_, address socket_, uint64 switchboardId_) external;

    /// @notice Gets the overrides
    /// @dev encoding format depends on the watcher system
    /// @return overrides_ The overrides
    function overrides() external view returns (bytes memory overrides_);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import {ExecuteParams, TransmissionParams, ExecutionStatus} from "../../utils/common/Structs.sol";

/**
 * @title ISocket
 * @notice An interface for a Chain Abstraction contract
 * @dev This interface provides methods for transmitting and executing payloads,
 * connecting a plug to a remote chain and setting up switchboards for the payload transmission
 * This interface also emits events for important operations such as payload transmission, execution status,
 * and plug connection
 */
interface ISocket {
    /**
     * @notice emits the status of payload after external call
     * @param payloadId payload id which is executed
     */
    event ExecutionSuccess(bytes32 payloadId, bool exceededMaxCopy, bytes returnData);

    /**
     * @notice emits the status of payload after external call
     * @param payloadId payload id which is executed
     */
    event ExecutionFailed(bytes32 payloadId, bool exceededMaxCopy, bytes returnData);

    /**
     * @notice emits the config set by a plug for a remoteChainSlug
     * @param plug The address of plug on current chain
     * @param appGatewayId The address of plug on sibling chain
     * @param switchboardId The outbound switchboard (select from registered options)
     */
    event PlugConnected(address plug, bytes32 appGatewayId, uint64 switchboardId);

    /**
     * @notice emits the config set by a plug for a remoteChainSlug
     * @param plug The address of plug on current chain
     */
    event PlugDisconnected(address plug);

    /**
     * @notice emits the payload details when a new payload arrives at outbound
     * @param triggerId trigger id
     * @param switchboardId switchboard id
     * @param plug local plug address
     * @param overrides params, for specifying details like fee pool chain, fee pool token and max fees if required
     * @param payload the data which will be used by contracts on chain
     */
    event AppGatewayCallRequested(
        bytes32 triggerId,
        bytes32 appGatewayId,
        uint64 switchboardId,
        bytes32 plug,
        bytes overrides,
        bytes payload
    );

    /**
     * @notice Executes a payload
     * @param executeParams_ The execution parameters
     * @param transmissionParams_ The transmission parameters
     * @return success True if the payload was executed successfully
     * @return returnData The return data from the execution
     */
    function execute(
        ExecuteParams calldata executeParams_,
        TransmissionParams calldata transmissionParams_
    ) external payable returns (bool, bytes memory);

    /**
     * @notice sets the config specific to the plug
     * @param appGatewayId_ The address of plug present at sibling chain
     * @param switchboardId_ The id of switchboard to use for executing payloads
     */
    function connect(bytes32 appGatewayId_, uint64 switchboardId_) external;

    /**
     * @notice Disconnects Plug from Socket
     */
    function disconnect() external;

    /**
     * @notice Registers a switchboard for the socket
     * @return switchboardId The id of the switchboard
     */
    function registerSwitchboard() external returns (uint64);

    /**
     * @notice Returns the config for given `plugAddress_` and `siblingChainSlug_`
     * @param plugAddress_ The address of plug present at current chain
     * @return appGatewayId The address of plug on sibling chain
     * @return switchboardId The id of the switchboard
     */
    function getPlugConfig(
        address plugAddress_
    ) external view returns (bytes32 appGatewayId, uint64 switchboardId);

    /**
     * @notice Returns the execution status of a payload
     * @param payloadId_ The payload id
     * @return executionStatus The execution status
     */
    function payloadExecuted(bytes32 payloadId_) external view returns (ExecutionStatus);

    /**
     * @notice Returns the chain slug
     * @return chainSlug The chain slug
     */
    function chainSlug() external view returns (uint32);

    /**
     * @notice Returns the digest of a payload
     * @param payloadId_ The payload id
     * @return digest The digest
     */
    function payloadIdToDigest(bytes32 payloadId_) external view returns (bytes32);

    /**
     * @notice Returns the current trigger counter
     * @return triggerCounter The trigger counter
     */
    function triggerCounter() external view returns (uint64);

    /**
     * @notice Returns the switchboard address for a given switchboard id
     * @param switchboardId_ The switchboard id
     * @return switchboardAddress The switchboard address
     */
    function switchboardAddresses(uint64 switchboardId_) external view returns (address);
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import "lib/solady/src/auth/Ownable.sol";

/**
 * @title AccessControl
 * @dev This abstract contract implements access control mechanism based on roles.
 * Each role can have one or more addresses associated with it, which are granted
 * permission to execute functions with the onlyRole modifier.
 */
abstract contract AccessControl is Ownable {
    /**
     * @dev A mapping of roles to a mapping of addresses to boolean values indicating whether or not they have the role.
     * @dev slot 0
     */
    mapping(bytes32 => mapping(address => bool)) private _permits;

    // slots 1-50: gap for future storage variables
    uint256[49] _gap_access_control;

    /**
     * @dev Emitted when a role is granted to an address.
     */
    event RoleGranted(bytes32 indexed role, address indexed grantee);

    /**
     * @dev Emitted when a role is revoked from an address.
     */
    event RoleRevoked(bytes32 indexed role, address indexed revokee);

    /**
     * @dev Error message thrown when an address does not have permission to execute a function with onlyRole modifier.
     */
    error NoPermit(bytes32 role);

    /**
     * @dev Modifier that restricts access to addresses having roles
     * Throws an error if the caller do not have permit
     */
    modifier onlyRole(bytes32 role) {
        if (!_permits[role][msg.sender]) revert NoPermit(role);
        _;
    }

    /**
     * @dev Checks and reverts if an address do not have a specific role.
     * @param role_ The role to check.
     * @param address_ The address to check.
     */
    function _checkRole(bytes32 role_, address address_) internal virtual {
        if (!_hasRole(role_, address_)) revert NoPermit(role_);
    }

    /**
     * @dev Grants a role to a given address.
     * @param role_ The role to grant.
     * @param grantee_ The address to grant the role to.
     * Emits a RoleGranted event.
     * Can only be called by the owner of the contract.
     */
    function grantRole(bytes32 role_, address grantee_) external virtual onlyOwner {
        _grantRole(role_, grantee_);
    }

    /**
     * @dev Revokes a role from a given address.
     * @param role_ The role to revoke.
     * @param revokee_ The address to revoke the role from.
     * Emits a RoleRevoked event.
     * Can only be called by the owner of the contract.
     */
    function revokeRole(bytes32 role_, address revokee_) external virtual onlyOwner {
        _revokeRole(role_, revokee_);
    }

    /**
     * @dev Internal function to grant a role to a given address.
     * @param role_ The role to grant.
     * @param grantee_ The address to grant the role to.
     * Emits a RoleGranted event.
     */
    function _grantRole(bytes32 role_, address grantee_) internal {
        _permits[role_][grantee_] = true;
        emit RoleGranted(role_, grantee_);
    }

    /**
     * @dev Internal function to revoke a role from a given address.
     * @param role_ The role to revoke.
     * @param revokee_ The address to revoke the role from.
     * Emits a RoleRevoked event.
     */
    function _revokeRole(bytes32 role_, address revokee_) internal {
        _permits[role_][revokee_] = false;
        emit RoleRevoked(role_, revokee_);
    }

    /**
     * @dev Checks whether an address has a specific role.
     * @param role_ The role to check.
     * @param address_ The address to check.
     * @return A boolean value indicating whether or not the address has the role.
     */
    function hasRole(bytes32 role_, address address_) external view returns (bool) {
        return _hasRole(role_, address_);
    }

    function _hasRole(bytes32 role_, address address_) internal view returns (bool) {
        return _permits[role_][address_];
    }
}

File 8 of 14 : AccessRoles.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

// contains role hashes used in socket for various different operation
// used to rescue funds
bytes32 constant RESCUE_ROLE = keccak256("RESCUE_ROLE");
// used by governance
bytes32 constant GOVERNANCE_ROLE = keccak256("GOVERNANCE_ROLE");
// used by transmitters who execute payloads in socket
bytes32 constant TRANSMITTER_ROLE = keccak256("TRANSMITTER_ROLE");
// used by switchboard watchers who work against transmitters
bytes32 constant WATCHER_ROLE = keccak256("WATCHER_ROLE");
// used to disable switchboard
bytes32 constant SWITCHBOARD_DISABLER_ROLE = keccak256("SWITCHBOARD_DISABLER_ROLE");
// used by fees manager to withdraw native tokens
bytes32 constant FEE_MANAGER_ROLE = keccak256("FEE_MANAGER_ROLE");

File 9 of 14 : Constants.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

address constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

bytes32 constant FORWARD_CALL = keccak256("FORWARD_CALL");
bytes32 constant DISTRIBUTE_FEE = keccak256("DISTRIBUTE_FEE");
bytes32 constant DEPLOY = keccak256("DEPLOY");

bytes4 constant READ = bytes4(keccak256("READ"));
bytes4 constant WRITE = bytes4(keccak256("WRITE"));
bytes4 constant SCHEDULE = bytes4(keccak256("SCHEDULE"));

bytes32 constant CALLBACK = keccak256("CALLBACK");
bytes32 constant FAST = keccak256("FAST");
bytes32 constant CCTP = keccak256("CCTP");

uint256 constant PAYLOAD_SIZE_LIMIT = 24_500;
uint16 constant MAX_COPY_BYTES = 2048; // 2KB

uint32 constant CHAIN_SLUG_SOLANA_MAINNET = 10000001;
uint32 constant CHAIN_SLUG_SOLANA_DEVNET = 10000002;

// Constant appGatewayId used on all chains
bytes32 constant APP_GATEWAY_ID = 0xdeadbeefcafebabe1234567890abcdef1234567890abcdef1234567890abcdef;

File 10 of 14 : Errors.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

error ZeroAddress();
error InvalidTransmitter();
error InvalidTokenAddress();
error InvalidSwitchboard();
error SocketAlreadyInitialized();

// Socket
error NotSocket();
error PlugNotFound();

// EVMx
error ResolvingScheduleTooEarly();
error CallFailed();
error InvalidAppGateway();
error AppGatewayAlreadyCalled();
error InvalidCallerTriggered();
error InvalidPromise();
error InvalidWatcherSignature();
error NonceUsed();
error AsyncModifierNotSet();
error WatcherNotSet();
error InvalidTarget();
error InvalidIndex();
error InvalidChainSlug();
error InvalidPayloadSize();
error InvalidOnChainAddress();
error InvalidScheduleDelay();
/// @notice Error thrown when trying to start or bid a closed auction
error AuctionClosed();
/// @notice Error thrown when trying to start or bid an auction that is not open
error AuctionNotOpen();
/// @notice Error thrown if fees exceed the maximum set fees
error BidExceedsMaxFees();
/// @notice Error thrown if a lower bid already exists
error LowerBidAlreadyExists();
/// @notice Error thrown when request count mismatch
error RequestCountMismatch();

error InvalidAmount();
error InsufficientCreditsAvailable();
error InsufficientBalance();
/// @notice Error thrown when a caller is invalid
error InvalidCaller();

/// @notice Error thrown when a gateway is invalid
error InvalidGateway();
/// @notice Error thrown when a request is already cancelled
error RequestAlreadyCancelled();
error DeadlineNotPassedForOnChainRevert();

error InvalidBid();
error MaxReAuctionCountReached();
error MaxMsgValueLimitExceeded();
/// @notice Error thrown when an invalid address attempts to call the Watcher only function
error OnlyWatcherAllowed();
error InvalidPrecompileData();
error InvalidCallType();
error NotRequestHandler();
error NotInvoker();
error NotPromiseResolver();
error RequestPayloadCountLimitExceeded();
error InsufficientFees();
error RequestAlreadySettled();
error NoWriteRequest();
error AlreadyAssigned();

error OnlyAppGateway();
error NewMaxFeesLowerThanCurrent(uint256 currentMaxFees, uint256 newMaxFees);
error InvalidContract();
error InvalidData();
error InvalidSignature();

error DeadlinePassed();
// Only Watcher can call functions
error OnlyRequestHandlerAllowed();
error OnlyPromiseResolverAllowed();
error InvalidReceiver();

File 11 of 14 : Structs.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

//// ENUMS ////
enum IsPlug {
    YES,
    NO
}

enum Parallel {
    OFF,
    ON
}

enum Read {
    OFF,
    ON
}

enum WriteFinality {
    LOW,
    MEDIUM,
    HIGH
}

enum SwitchboardStatus {
    NOT_REGISTERED,
    REGISTERED,
    DISABLED
}

/// @notice The state of the async promise
enum AsyncPromiseState {
    WAITING_FOR_CALLBACK_SELECTOR,
    WAITING_FOR_CALLBACK_EXECUTION,
    CALLBACK_REVERTING,
    ONCHAIN_REVERTING,
    RESOLVED
}

enum ExecutionStatus {
    NotExecuted,
    Executed,
    Reverted
}

struct AppGatewayApprovals {
    address appGateway;
    bool approval;
}

//// STRUCTS ////
struct AppGatewayConfig {
    PlugConfigGeneric plugConfig;
    bytes32 plug;
    uint32 chainSlug;
}
// Plug config:
struct PlugConfigGeneric {
    bytes32 appGatewayId;
    uint64 switchboardId;
}

// Plug config:
struct PlugConfigEvm {
    bytes32 appGatewayId;
    uint64 switchboardId;
}

//trigger:
struct TriggerParams {
    bytes32 triggerId;
    bytes32 plug;
    bytes32 appGatewayId;
    uint32 chainSlug;
    bytes overrides;
    bytes payload;
}

struct PromiseReturnData {
    bool exceededMaxCopy;
    bytes32 payloadId;
    bytes returnData;
}
// AM
struct ExecuteParams {
    bytes4 callType;
    uint160 payloadPointer;
    uint256 deadline;
    uint256 gasLimit;
    uint256 value;
    bytes32 prevBatchDigestHash;
    address target;
    bytes payload;
    bytes extraData;
}

struct TransmissionParams {
    uint256 socketFees;
    address refundAddress;
    bytes extraData;
    bytes transmitterProof;
}

struct WatcherMultiCallParams {
    address contractAddress;
    bytes data;
    uint256 nonce;
    bytes signature;
}

struct CreateRequestResult {
    uint256 totalEstimatedWatcherFees;
    uint256 writeCount;
    address[] promiseList;
    PayloadParams[] payloadParams;
}

struct Bid {
    uint256 fee;
    address transmitter;
    bytes extraData;
}

struct UserCredits {
    uint256 totalCredits;
    uint256 blockedCredits;
}

// digest:
struct DigestParams {
    bytes32 socket;
    bytes32 transmitter;
    bytes32 payloadId;
    uint256 deadline;
    bytes4 callType;
    uint256 gasLimit;
    uint256 value;
    bytes payload;
    bytes32 target;
    bytes32 appGatewayId;
    bytes32 prevBatchDigestHash;
    bytes extraData;
}

// App gateway base:
struct OverrideParams {
    bytes4 callType;
    Parallel isParallelCall;
    WriteFinality writeFinality;
    uint256 gasLimit;
    uint256 value;
    uint256 readAtBlockNumber;
    uint256 delayInSeconds;
}

struct Transaction {
    uint32 chainSlug;
    bytes32 target;
    bytes payload;
}

struct QueueParams {
    OverrideParams overrideParams;
    Transaction transaction;
    address asyncPromise;
    bytes32 switchboardType;
}

struct PayloadParams {
    bytes4 callType;
    uint160 payloadPointer;
    address asyncPromise;
    address appGateway;
    bytes32 payloadId;
    uint256 resolvedAt;
    uint256 deadline;
    bytes precompileData;
}

// request
struct RequestTrackingParams {
    bool isRequestCancelled;
    bool isRequestExecuted;
    uint40 currentBatch;
    uint256 currentBatchPayloadsLeft;
    uint256 payloadsRemaining;
}

struct RequestFeesDetails {
    uint256 maxFees;
    address consumeFrom;
    Bid winningBid;
}

struct RequestParams {
    RequestTrackingParams requestTrackingParams;
    RequestFeesDetails requestFeesDetails;
    address appGateway;
    address auctionManager;
    uint256 writeCount;
    bytes onCompleteData;
}

struct CCTPExecutionParams {
    ExecuteParams executeParams;
    bytes32 digest;
    bytes proof;
    bytes transmitterSignature;
    address refundAddress;
}

struct CCTPBatchParams {
    bytes32[] previousPayloadIds;
    uint32[] nextBatchRemoteChainSlugs;
    bytes[] messages;
    bytes[] attestations;
}

struct SolanaInstruction {
    SolanaInstructionData data;
    SolanaInstructionDataDescription description;
}

struct SolanaInstructionData {
    bytes32 programId;
    bytes32[] accounts;
    bytes8 instructionDiscriminator;
    // for now we assume the all functionArguments are simple types (uint256, address, bool, etc.) not complex types (struct, array, etc.)
    bytes[] functionArguments;
}

struct SolanaInstructionDataDescription {
    // flags for accounts, we only need isWritable for now
    // 0 bit - isWritable (0|1)
    bytes1[] accountFlags;
    // names for function argument types used later in data decoding in watcher and transmitter
    string[] functionArgumentTypeNames;
}

// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import "lib/solady/src/utils/SafeTransferLib.sol";
import {ZeroAddress, InvalidTokenAddress} from "./common/Errors.sol";
import {ETH_ADDRESS} from "./common/Constants.sol";

interface IERC721 {
    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes calldata data
    ) external;
}

interface IERC165 {
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

/**
 * @title RescueFundsLib
 * @dev A library that provides a function to rescue funds from a contract.
 */
library RescueFundsLib {
    /**
     * @dev Rescues funds from a contract.
     * @param token_ The address of the token contract.
     * @param rescueTo_ The address of the user.
     * @param amount_ The amount of tokens to be rescued.
     */
    function _rescueFunds(address token_, address rescueTo_, uint256 amount_) internal {
        if (rescueTo_ == address(0)) revert ZeroAddress();

        if (token_ == ETH_ADDRESS) {
            SafeTransferLib.forceSafeTransferETH(rescueTo_, amount_);
        } else {
            if (token_.code.length == 0) revert InvalidTokenAddress();

            // Identify if a token is an NFT (ERC721) by checking if it supports the ERC721 interface
            try IERC165(token_).supportsInterface(0x80ac58cd) returns (bool isERC721) {
                if (isERC721)
                    IERC721(token_).safeTransferFrom(address(this), rescueTo_, amount_, "");
                else {
                    SafeTransferLib.safeTransfer(token_, rescueTo_, amount_);
                }
            } catch {
                SafeTransferLib.safeTransfer(token_, rescueTo_, amount_);
            }
        }
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The caller is not authorized to call the function.
    error Unauthorized();

    /// @dev The `newOwner` cannot be the zero address.
    error NewOwnerIsZeroAddress();

    /// @dev The `pendingOwner` does not have a valid handover request.
    error NoHandoverRequest();

    /// @dev Cannot double-initialize.
    error AlreadyInitialized();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                           EVENTS                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ownership is transferred from `oldOwner` to `newOwner`.
    /// This event is intentionally kept the same as OpenZeppelin's Ownable to be
    /// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
    /// despite it not being as lightweight as a single argument event.
    event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);

    /// @dev An ownership handover to `pendingOwner` has been requested.
    event OwnershipHandoverRequested(address indexed pendingOwner);

    /// @dev The ownership handover to `pendingOwner` has been canceled.
    event OwnershipHandoverCanceled(address indexed pendingOwner);

    /// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
    uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
        0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;

    /// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
        0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;

    /// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
    uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
        0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                          STORAGE                           */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The owner slot is given by:
    /// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
    /// It is intentionally chosen to be a high value
    /// to avoid collision with lower slots.
    /// The choice of manual storage layout is to enable compatibility
    /// with both regular and upgradeable contracts.
    bytes32 internal constant _OWNER_SLOT =
        0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;

    /// The ownership handover slot of `newOwner` is given by:
    /// ```
    ///     mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
    ///     let handoverSlot := keccak256(0x00, 0x20)
    /// ```
    /// It stores the expiry timestamp of the two-step ownership handover.
    uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                     INTERNAL FUNCTIONS                     */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
    function _guardInitializeOwner() internal pure virtual returns (bool guard) {}

    /// @dev Initializes the owner directly without authorization guard.
    /// This function must be called upon initialization,
    /// regardless of whether the contract is upgradeable or not.
    /// This is to enable generalization to both regular and upgradeable contracts,
    /// and to save gas in case the initial owner is not the caller.
    /// For performance reasons, this function will not check if there
    /// is an existing owner.
    function _initializeOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                if sload(ownerSlot) {
                    mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
                    revert(0x1c, 0x04)
                }
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Store the new value.
                sstore(_OWNER_SLOT, newOwner)
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
            }
        }
    }

    /// @dev Sets the owner directly without authorization guard.
    function _setOwner(address newOwner) internal virtual {
        if (_guardInitializeOwner()) {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
            }
        } else {
            /// @solidity memory-safe-assembly
            assembly {
                let ownerSlot := _OWNER_SLOT
                // Clean the upper 96 bits.
                newOwner := shr(96, shl(96, newOwner))
                // Emit the {OwnershipTransferred} event.
                log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
                // Store the new value.
                sstore(ownerSlot, newOwner)
            }
        }
    }

    /// @dev Throws if the sender is not the owner.
    function _checkOwner() internal view virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // If the caller is not the stored owner, revert.
            if iszero(eq(caller(), sload(_OWNER_SLOT))) {
                mstore(0x00, 0x82b42900) // `Unauthorized()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Returns how long a two-step ownership handover is valid for in seconds.
    /// Override to return a different value if needed.
    /// Made internal to conserve bytecode. Wrap it in a public function if needed.
    function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
        return 48 * 3600;
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                  PUBLIC UPDATE FUNCTIONS                   */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Allows the owner to transfer the ownership to `newOwner`.
    function transferOwnership(address newOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(shl(96, newOwner)) {
                mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
                revert(0x1c, 0x04)
            }
        }
        _setOwner(newOwner);
    }

    /// @dev Allows the owner to renounce their ownership.
    function renounceOwnership() public payable virtual onlyOwner {
        _setOwner(address(0));
    }

    /// @dev Request a two-step ownership handover to the caller.
    /// The request will automatically expire in 48 hours (172800 seconds) by default.
    function requestOwnershipHandover() public payable virtual {
        unchecked {
            uint256 expires = block.timestamp + _ownershipHandoverValidFor();
            /// @solidity memory-safe-assembly
            assembly {
                // Compute and set the handover slot to `expires`.
                mstore(0x0c, _HANDOVER_SLOT_SEED)
                mstore(0x00, caller())
                sstore(keccak256(0x0c, 0x20), expires)
                // Emit the {OwnershipHandoverRequested} event.
                log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
            }
        }
    }

    /// @dev Cancels the two-step ownership handover to the caller, if any.
    function cancelOwnershipHandover() public payable virtual {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, caller())
            sstore(keccak256(0x0c, 0x20), 0)
            // Emit the {OwnershipHandoverCanceled} event.
            log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
        }
    }

    /// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
    /// Reverts if there is no existing ownership handover requested by `pendingOwner`.
    function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute and set the handover slot to 0.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            let handoverSlot := keccak256(0x0c, 0x20)
            // If the handover does not exist, or has expired.
            if gt(timestamp(), sload(handoverSlot)) {
                mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
                revert(0x1c, 0x04)
            }
            // Set the handover slot to 0.
            sstore(handoverSlot, 0)
        }
        _setOwner(pendingOwner);
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                   PUBLIC READ FUNCTIONS                    */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Returns the owner of the contract.
    function owner() public view virtual returns (address result) {
        /// @solidity memory-safe-assembly
        assembly {
            result := sload(_OWNER_SLOT)
        }
    }

    /// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
    function ownershipHandoverExpiresAt(address pendingOwner)
        public
        view
        virtual
        returns (uint256 result)
    {
        /// @solidity memory-safe-assembly
        assembly {
            // Compute the handover slot.
            mstore(0x0c, _HANDOVER_SLOT_SEED)
            mstore(0x00, pendingOwner)
            // Load the handover slot.
            result := sload(keccak256(0x0c, 0x20))
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         MODIFIERS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Marks a function as only callable by the owner.
    modifier onlyOwner() virtual {
        _checkOwner();
        _;
    }
}

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Permit2 operations from (https://github.com/Uniswap/permit2/blob/main/src/libraries/Permit2Lib.sol)
///
/// @dev Note:
/// - For ETH transfers, please use `forceSafeTransferETH` for DoS protection.
library SafeTransferLib {
    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       CUSTOM ERRORS                        */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev The ETH transfer has failed.
    error ETHTransferFailed();

    /// @dev The ERC20 `transferFrom` has failed.
    error TransferFromFailed();

    /// @dev The ERC20 `transfer` has failed.
    error TransferFailed();

    /// @dev The ERC20 `approve` has failed.
    error ApproveFailed();

    /// @dev The ERC20 `totalSupply` query has failed.
    error TotalSupplyQueryFailed();

    /// @dev The Permit2 operation has failed.
    error Permit2Failed();

    /// @dev The Permit2 amount must be less than `2**160 - 1`.
    error Permit2AmountOverflow();

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                         CONSTANTS                          */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Suggested gas stipend for contract receiving ETH that disallows any storage writes.
    uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;

    /// @dev Suggested gas stipend for contract receiving ETH to perform a few
    /// storage reads and writes, but low enough to prevent griefing.
    uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;

    /// @dev The unique EIP-712 domain domain separator for the DAI token contract.
    bytes32 internal constant DAI_DOMAIN_SEPARATOR =
        0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7;

    /// @dev The address for the WETH9 contract on Ethereum mainnet.
    address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;

    /// @dev The canonical Permit2 address.
    /// [Github](https://github.com/Uniswap/permit2)
    /// [Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3)
    address internal constant PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                       ETH OPERATIONS                       */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    // If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants.
    //
    // The regular variants:
    // - Forwards all remaining gas to the target.
    // - Reverts if the target reverts.
    // - Reverts if the current contract has insufficient balance.
    //
    // The force variants:
    // - Forwards with an optional gas stipend
    //   (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases).
    // - If the target reverts, or if the gas stipend is exhausted,
    //   creates a temporary contract to force send the ETH via `SELFDESTRUCT`.
    //   Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758.
    // - Reverts if the current contract has insufficient balance.
    //
    // The try variants:
    // - Forwards with a mandatory gas stipend.
    // - Instead of reverting, returns whether the transfer succeeded.

    /// @dev Sends `amount` (in wei) ETH to `to`.
    function safeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gas(), to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`.
    function safeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // Transfer all the ETH and check if it succeeded or not.
            if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function forceSafeTransferETH(address to, uint256 amount, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function forceSafeTransferAllETH(address to, uint256 gasStipend) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if iszero(call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferETH(address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            if lt(selfbalance(), amount) {
                mstore(0x00, 0xb12d13eb) // `ETHTransferFailed()`.
                revert(0x1c, 0x04)
            }
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, amount, codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(amount, 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`.
    function forceSafeTransferAllETH(address to) internal {
        /// @solidity memory-safe-assembly
        assembly {
            // forgefmt: disable-next-item
            if iszero(call(GAS_STIPEND_NO_GRIEF, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
                mstore(0x00, to) // Store the address in scratch space.
                mstore8(0x0b, 0x73) // Opcode `PUSH20`.
                mstore8(0x20, 0xff) // Opcode `SELFDESTRUCT`.
                if iszero(create(selfbalance(), 0x0b, 0x16)) { revert(codesize(), codesize()) } // For gas estimation.
            }
        }
    }

    /// @dev Sends `amount` (in wei) ETH to `to`, with a `gasStipend`.
    function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, amount, codesize(), 0x00, codesize(), 0x00)
        }
    }

    /// @dev Sends all the ETH in the current contract to `to`, with a `gasStipend`.
    function trySafeTransferAllETH(address to, uint256 gasStipend)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            success := call(gasStipend, to, selfbalance(), codesize(), 0x00, codesize(), 0x00)
        }
    }

    /*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
    /*                      ERC20 OPERATIONS                      */
    /*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for
    /// the current contract to manage.
    function safeTransferFrom(address token, address from, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function trySafeTransferFrom(address token, address from, address to, uint256 amount)
        internal
        returns (bool success)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x60, amount) // Store the `amount` argument.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x23b872dd000000000000000000000000) // `transferFrom(address,address,uint256)`.
            success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                success := lt(or(iszero(extcodesize(token)), returndatasize()), success)
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends all of ERC20 `token` from `from` to `to`.
    /// Reverts upon failure.
    ///
    /// The `from` account must have their entire balance approved for the current contract to manage.
    function safeTransferAllFrom(address token, address from, address to)
        internal
        returns (uint256 amount)
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40) // Cache the free memory pointer.
            mstore(0x40, to) // Store the `to` argument.
            mstore(0x2c, shl(96, from)) // Store the `from` argument.
            mstore(0x0c, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x60, 0x20)
                )
            ) {
                mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x00, 0x23b872dd) // `transferFrom(address,address,uint256)`.
            amount := mload(0x60) // The `amount` is already at 0x60. We'll need to return it.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x1c, 0x64, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x7939f424) // `TransferFromFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x60, 0) // Restore the zero slot to zero.
            mstore(0x40, m) // Restore the free memory pointer.
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransfer(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sends all of ERC20 `token` from the current contract to `to`.
    /// Reverts upon failure.
    function safeTransferAll(address token, address to) internal returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x70a08231) // Store the function selector of `balanceOf(address)`.
            mstore(0x20, address()) // Store the address of the current contract.
            // Read the balance, reverting upon failure.
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                    staticcall(gas(), token, 0x1c, 0x24, 0x34, 0x20)
                )
            ) {
                mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                revert(0x1c, 0x04)
            }
            mstore(0x14, to) // Store the `to` argument.
            amount := mload(0x34) // The `amount` is already at 0x34. We'll need to return it.
            mstore(0x00, 0xa9059cbb000000000000000000000000) // `transfer(address,uint256)`.
            // Perform the transfer, reverting upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x90b8ec18) // `TransferFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// Reverts upon failure.
    function safeApprove(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                    revert(0x1c, 0x04)
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract.
    /// If the initial attempt to approve fails, attempts to reset the approved amount to zero,
    /// then retries the approval again (some tokens, e.g. USDT, requires this).
    /// Reverts upon failure.
    function safeApproveWithRetry(address token, address to, uint256 amount) internal {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, to) // Store the `to` argument.
            mstore(0x34, amount) // Store the `amount` argument.
            mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
            // Perform the approval, retrying upon failure.
            let success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
            if iszero(and(eq(mload(0x00), 1), success)) {
                if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                    mstore(0x34, 0) // Store 0 for the `amount`.
                    mstore(0x00, 0x095ea7b3000000000000000000000000) // `approve(address,uint256)`.
                    pop(call(gas(), token, 0, 0x10, 0x44, codesize(), 0x00)) // Reset the approval.
                    mstore(0x34, amount) // Store back the original `amount`.
                    // Retry the approval, reverting upon failure.
                    success := call(gas(), token, 0, 0x10, 0x44, 0x00, 0x20)
                    if iszero(and(eq(mload(0x00), 1), success)) {
                        // Check the `extcodesize` again just in case the token selfdestructs lol.
                        if iszero(lt(or(iszero(extcodesize(token)), returndatasize()), success)) {
                            mstore(0x00, 0x3e3f8f73) // `ApproveFailed()`.
                            revert(0x1c, 0x04)
                        }
                    }
                }
            }
            mstore(0x34, 0) // Restore the part of the free memory pointer that was overwritten.
        }
    }

    /// @dev Returns the amount of ERC20 `token` owned by `account`.
    /// Returns zero if the `token` does not exist.
    function balanceOf(address token, address account) internal view returns (uint256 amount) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x14, account) // Store the `account` argument.
            mstore(0x00, 0x70a08231000000000000000000000000) // `balanceOf(address)`.
            amount :=
                mul( // The arguments of `mul` are evaluated from right to left.
                    mload(0x20),
                    and( // The arguments of `and` are evaluated from right to left.
                        gt(returndatasize(), 0x1f), // At least 32 bytes returned.
                        staticcall(gas(), token, 0x10, 0x24, 0x20, 0x20)
                    )
                )
        }
    }

    /// @dev Returns the total supply of the `token`.
    /// Reverts if the token does not exist or does not implement `totalSupply()`.
    function totalSupply(address token) internal view returns (uint256 result) {
        /// @solidity memory-safe-assembly
        assembly {
            mstore(0x00, 0x18160ddd) // `totalSupply()`.
            if iszero(
                and(gt(returndatasize(), 0x1f), staticcall(gas(), token, 0x1c, 0x04, 0x00, 0x20))
            ) {
                mstore(0x00, 0x54cd9435) // `TotalSupplyQueryFailed()`.
                revert(0x1c, 0x04)
            }
            result := mload(0x00)
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to`.
    /// If the initial attempt fails, try to use Permit2 to transfer the token.
    /// Reverts upon failure.
    ///
    /// The `from` account must have at least `amount` approved for the current contract to manage.
    function safeTransferFrom2(address token, address from, address to, uint256 amount) internal {
        if (!trySafeTransferFrom(token, from, to, amount)) {
            permit2TransferFrom(token, from, to, amount);
        }
    }

    /// @dev Sends `amount` of ERC20 `token` from `from` to `to` via Permit2.
    /// Reverts upon failure.
    function permit2TransferFrom(address token, address from, address to, uint256 amount)
        internal
    {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(add(m, 0x74), shr(96, shl(96, token)))
            mstore(add(m, 0x54), amount)
            mstore(add(m, 0x34), to)
            mstore(add(m, 0x20), shl(96, from))
            // `transferFrom(address,address,uint160,address)`.
            mstore(m, 0x36c78516000000000000000000000000)
            let p := PERMIT2
            let exists := eq(chainid(), 1)
            if iszero(exists) { exists := iszero(iszero(extcodesize(p))) }
            if iszero(
                and(
                    call(gas(), p, 0, add(m, 0x10), 0x84, codesize(), 0x00),
                    lt(iszero(extcodesize(token)), exists) // Token has code and Permit2 exists.
                )
            ) {
                mstore(0x00, 0x7939f4248757f0fd) // `TransferFromFailed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(iszero(shr(160, amount))))), 0x04)
            }
        }
    }

    /// @dev Permit a user to spend a given amount of
    /// another user's tokens via native EIP-2612 permit if possible, falling
    /// back to Permit2 if native permit fails or is not implemented on the token.
    function permit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        bool success;
        /// @solidity memory-safe-assembly
        assembly {
            for {} shl(96, xor(token, WETH9)) {} {
                mstore(0x00, 0x3644e515) // `DOMAIN_SEPARATOR()`.
                if iszero(
                    and( // The arguments of `and` are evaluated from right to left.
                        lt(iszero(mload(0x00)), eq(returndatasize(), 0x20)), // Returns 1 non-zero word.
                        // Gas stipend to limit gas burn for tokens that don't refund gas when
                        // an non-existing function is called. 5K should be enough for a SLOAD.
                        staticcall(5000, token, 0x1c, 0x04, 0x00, 0x20)
                    )
                ) { break }
                // After here, we can be sure that token is a contract.
                let m := mload(0x40)
                mstore(add(m, 0x34), spender)
                mstore(add(m, 0x20), shl(96, owner))
                mstore(add(m, 0x74), deadline)
                if eq(mload(0x00), DAI_DOMAIN_SEPARATOR) {
                    mstore(0x14, owner)
                    mstore(0x00, 0x7ecebe00000000000000000000000000) // `nonces(address)`.
                    mstore(add(m, 0x94), staticcall(gas(), token, 0x10, 0x24, add(m, 0x54), 0x20))
                    mstore(m, 0x8fcbaf0c000000000000000000000000) // `IDAIPermit.permit`.
                    // `nonces` is already at `add(m, 0x54)`.
                    // `1` is already stored at `add(m, 0x94)`.
                    mstore(add(m, 0xb4), and(0xff, v))
                    mstore(add(m, 0xd4), r)
                    mstore(add(m, 0xf4), s)
                    success := call(gas(), token, 0, add(m, 0x10), 0x104, codesize(), 0x00)
                    break
                }
                mstore(m, 0xd505accf000000000000000000000000) // `IERC20Permit.permit`.
                mstore(add(m, 0x54), amount)
                mstore(add(m, 0x94), and(0xff, v))
                mstore(add(m, 0xb4), r)
                mstore(add(m, 0xd4), s)
                success := call(gas(), token, 0, add(m, 0x10), 0xe4, codesize(), 0x00)
                break
            }
        }
        if (!success) simplePermit2(token, owner, spender, amount, deadline, v, r, s);
    }

    /// @dev Simple permit on the Permit2 contract.
    function simplePermit2(
        address token,
        address owner,
        address spender,
        uint256 amount,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal {
        /// @solidity memory-safe-assembly
        assembly {
            let m := mload(0x40)
            mstore(m, 0x927da105) // `allowance(address,address,address)`.
            {
                let addressMask := shr(96, not(0))
                mstore(add(m, 0x20), and(addressMask, owner))
                mstore(add(m, 0x40), and(addressMask, token))
                mstore(add(m, 0x60), and(addressMask, spender))
                mstore(add(m, 0xc0), and(addressMask, spender))
            }
            let p := mul(PERMIT2, iszero(shr(160, amount)))
            if iszero(
                and( // The arguments of `and` are evaluated from right to left.
                    gt(returndatasize(), 0x5f), // Returns 3 words: `amount`, `expiration`, `nonce`.
                    staticcall(gas(), p, add(m, 0x1c), 0x64, add(m, 0x60), 0x60)
                )
            ) {
                mstore(0x00, 0x6b836e6b8757f0fd) // `Permit2Failed()` or `Permit2AmountOverflow()`.
                revert(add(0x18, shl(2, iszero(p))), 0x04)
            }
            mstore(m, 0x2b67b570) // `Permit2.permit` (PermitSingle variant).
            // `owner` is already `add(m, 0x20)`.
            // `token` is already at `add(m, 0x40)`.
            mstore(add(m, 0x60), amount)
            mstore(add(m, 0x80), 0xffffffffffff) // `expiration = type(uint48).max`.
            // `nonce` is already at `add(m, 0xa0)`.
            // `spender` is already at `add(m, 0xc0)`.
            mstore(add(m, 0xe0), deadline)
            mstore(add(m, 0x100), 0x100) // `signature` offset.
            mstore(add(m, 0x120), 0x41) // `signature` length.
            mstore(add(m, 0x140), r)
            mstore(add(m, 0x160), s)
            mstore(add(m, 0x180), shl(248, v))
            if iszero( // Revert if token does not have code, or if the call fails.
            mul(extcodesize(token), call(gas(), p, 0, add(m, 0x1c), 0x184, codesize(), 0x00))) {
                mstore(0x00, 0x6b836e6b) // `Permit2Failed()`.
                revert(0x1c, 0x04)
            }
        }
    }
}

Settings
{
  "evmVersion": "paris",
  "optimizer": {
    "enabled": true,
    "runs": 1,
    "details": {
      "yul": true,
      "yulDetails": {
        "stackAllocation": true
      }
    }
  },
  "viaIR": false,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  }
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"socket_","type":"address"},{"internalType":"address","name":"owner_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"uint256","name":"balance_","type":"uint256"},{"internalType":"uint256","name":"fee_","type":"uint256"}],"name":"InsufficientTokenBalance","type":"error"},{"inputs":[],"name":"InvalidDepositAmount","type":"error"},{"inputs":[],"name":"InvalidTokenAddress","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"NoPermit","type":"error"},{"inputs":[],"name":"NotSocket","type":"error"},{"inputs":[],"name":"SocketAlreadyInitialized","type":"error"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"TokenNotWhitelisted","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[],"name":"ConnectorPlugDisconnected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"creditAmount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nativeAmount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"FeesDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FeesWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"grantee","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"revokee","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"TokenRemovedFromWhitelist","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"TokenWhitelisted","type":"event"},{"inputs":[],"name":"appGatewayId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"appGatewayId_","type":"bytes32"},{"internalType":"address","name":"socket_","type":"address"},{"internalType":"uint64","name":"switchboardId_","type":"uint64"}],"name":"connectSocket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"depositCredit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"depositCreditAndNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"depositToNative","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"disconnectSocket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"grantee_","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"address_","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"appGatewayId_","type":"bytes32"},{"internalType":"address","name":"socket_","type":"address"},{"internalType":"uint64","name":"switchboardId_","type":"uint64"}],"name":"initSocket","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isSocketInitialized","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"overrides","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"removeTokenFromWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"rescueTo_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role_","type":"bytes32"},{"internalType":"address","name":"revokee_","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"socket__","outputs":[{"internalType":"contract ISocket","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"}],"name":"whitelistToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"whitelistedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token_","type":"address"},{"internalType":"address","name":"receiver_","type":"address"},{"internalType":"uint256","name":"amount_","type":"uint256"}],"name":"withdrawFees","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60806040523480156200001157600080fd5b50604051620014fa380380620014fa8339810160408190526200003491620000c0565b600080546001600160a01b0319166001600160a01b0384161790556200005a8162000067565b50506001600255620000f8565b6001600160a01b0316638b78c6d8198190558060007f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b80516001600160a01b0381168114620000bb57600080fd5b919050565b60008060408385031215620000d457600080fd5b620000df83620000a3565b9150620000ef60208401620000a3565b90509250929050565b6113f280620001086000396000f3fe6080604052600436106101255760003560e01c80622306dc1461012a57806318b7ff721461014c5780631c335f491461016c57806325692962146101955780632f2ff15d1461019d578063306275be146101bd5780634a85f041146101dd578063528bd235146101ff57806354d1f13d1461021f5780636247f6f2146102275780636ccae05414610247578063715018a6146102675780638da5cb5b1461026f57806391d1485414610291578063943103c3146102c15780639a7d9a9b146102e1578063ab395191146102f7578063c6a261d214610317578063d547741f14610337578063daf9c21014610357578063e55dc4e614610387578063e90e5cc1146103a7578063f04e283e146103bc578063f2fde38b146103cf578063fee81cf4146103e2575b600080fd5b34801561013657600080fd5b5061014a610145366004610f40565b610415565b005b34801561015857600080fd5b5061014a61016736600461101b565b610441565b34801561017857600080fd5b5061018260015481565b6040519081526020015b60405180910390f35b61014a610478565b3480156101a957600080fd5b5061014a6101b8366004611067565b6104c7565b3480156101c957600080fd5b5061014a6101d8366004611093565b6104dd565b3480156101e957600080fd5b506101f2610540565b60405161018c91906110f4565b34801561020b57600080fd5b5061014a61021a366004610f40565b6105ce565b61014a6105e2565b34801561023357600080fd5b5061014a610242366004611093565b61061e565b34801561025357600080fd5b5061014a610262366004611107565b6106a4565b61014a610728565b34801561027b57600080fd5b50638b78c6d819545b60405161018c9190611143565b34801561029d57600080fd5b506102b16102ac366004611067565b61073c565b604051901515815260200161018c565b3480156102cd57600080fd5b5061014a6102dc36600461101b565b61076c565b3480156102ed57600080fd5b5061018260025481565b34801561030357600080fd5b5061014a610312366004610f40565b61077f565b34801561032357600080fd5b50600054610284906001600160a01b031681565b34801561034357600080fd5b5061014a610352366004611067565b61078d565b34801561036357600080fd5b506102b1610372366004611093565b60366020526000908152604090205460ff1681565b34801561039357600080fd5b5061014a6103a2366004611107565b61079f565b3480156103b357600080fd5b5061014a6109a5565b61014a6103ca366004611093565b610a02565b61014a6103dd366004611093565b610a42565b3480156103ee57600080fd5b506101826103fd366004611093565b63389a75e1600c908152600091909152602090205490565b6000610422600a8461116d565b905061043a8585610433848761118f565b8486610a69565b5050505050565b6002546001036104635760405162c9500b60e81b815260040160405180910390fd5b6001600255610473838383610afc565b505050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b6104cf610b8e565b6104d98282610ba9565b5050565b6104e5610b8e565b6001600160a01b03811660009081526036602052604090819020805460ff19169055517fdd2e6d9f52cbe8f695939d018b7d4a216dc613a669876163ac548b916489d91790610535908390611143565b60405180910390a150565b6003805461054d906111a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610579906111a2565b80156105c65780601f1061059b576101008083540402835291602001916105c6565b820191906000526020600020905b8154815290600101906020018083116105a957829003601f168201915b505050505081565b6105dc848484600085610a69565b50505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610626610b8e565b806001600160a01b03163b60000361065157604051630f58058360e11b815260040160405180910390fd5b6001600160a01b03811660009081526036602052604090819020805460ff19166001179055517f6a65f90b1a644d2faac467a21e07e50e3f8fa5846e26231d30ae79a417d3d26290610535908390611143565b3360009081527f80dde0063ab259f132ebe19ca7c3f445dd67076b1475ae6c8b166d937934592960205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661071d5760405163962f633360e01b8152600481018290526024015b60405180910390fd5b6105dc848484610c04565b610730610b8e565b61073a6000610d87565b565b60008281526004602090815260408083206001600160a01b038516845290915281205460ff165b90505b92915050565b610774610b8e565b610473838383610afc565b6105dc848460008585610a69565b610795610b8e565b6104d98282610dc5565b6000546001600160a01b031633146107ca57604051633167e3df60e21b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906107f9903090600401611143565b602060405180830381865afa158015610816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083a91906111dc565b90506000846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561087c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a091906111f5565b905060128160ff1610156108d5576108b981601261121f565b6108c490600a61131c565b6108ce908461116d565b9250610904565b60128160ff161115610904576108ec60128261121f565b6108f790600a61131c565b610901908461132b565b92505b8282101561093e5760405163ebd6ced960e01b81526001600160a01b03861660048201526024810183905260448101849052606401610714565b6109526001600160a01b0386168585610e1d565b604080516001600160a01b038088168252861660208201529081018490527f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa8906060015b60405180910390a15050505050565b6109ad610b8e565b600080546040805163d9374bff60e01b815290516001600160a01b039092169263d9374bff9260048084019382900301818387803b1580156109ee57600080fd5b505af11580156105dc573d6000803e3d6000fd5b610a0a610b8e565b63389a75e1600c52806000526020600c208054421115610a3257636f5e88186000526004601cfd5b60009055610a3f81610d87565b50565b610a4a610b8e565b8060601b610a6057637448fbae6000526004601cfd5b610a3f81610d87565b6001600160a01b03851660009081526036602052604090205460ff16610aa4578460405163751dff9760e11b81526004016107149190611143565b610ac53330610ab38587611342565b6001600160a01b038916929190610e6d565b7f91f985f17a8632ae2e0a009d65ae250f373d82359d2389b58ea50ada6436682a8585858585604051610996959493929190611355565b600080546001600160a01b0319166001600160a01b038416179055600183905560005460405163f3aebe4d60e01b8152600481018590526001600160401b03831660248201526001600160a01b039091169063f3aebe4d90604401600060405180830381600087803b158015610b7157600080fd5b505af1158015610b85573d6000803e3d6000fd5b50505050505050565b638b78c6d81954331461073a576382b429006000526004601cfd5b60008281526004602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6001600160a01b038216610c2b5760405163d92e233d60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610c5a576104738282610ecb565b826001600160a01b03163b600003610c8557604051630f58058360e11b815260040160405180910390fd5b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015610cec575060408051601f3d908101601f19168201909252610ce99181019061139a565b60015b610cfb57610473838383610e1d565b8015610d7c57604051635c46a7ef60e11b81523060048201526001600160a01b03848116602483015260448201849052608060648301526000608483015285169063b88d4fde9060a401600060405180830381600087803b158015610d5f57600080fd5b505af1158015610d73573d6000803e3d6000fd5b505050506105dc565b6105dc848484610e1d565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b60008281526004602090815260408083206001600160a01b0385168085529252808320805460ff1916905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b816014528060345263a9059cbb60601b60005260206000604460106000875af18060016000511416610e6257803d853b151710610e62576390b8ec186000526004601cfd5b506000603452505050565b60405181606052826040528360601b602c526323b872dd60601b600c52602060006064601c6000895af18060016000511416610ebc57803d873b151710610ebc57637939f4246000526004601cfd5b50600060605260405250505050565b80471015610ee15763b12d13eb6000526004601cfd5b6000386000388486620186a0f16104d957816000526073600b5360ff6020536016600b82f06104d9573838fd5b80356001600160a01b0381168114610f2557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215610f5657600080fd5b610f5f85610f0e565b9350610f6d60208601610f0e565b92506040850135915060608501356001600160401b0380821115610f9057600080fd5b818701915087601f830112610fa457600080fd5b813581811115610fb657610fb6610f2a565b604051601f8201601f19908116603f01168101908382118183101715610fde57610fde610f2a565b816040528281528a6020848701011115610ff757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060006060848603121561103057600080fd5b8335925061104060208501610f0e565b915060408401356001600160401b038116811461105c57600080fd5b809150509250925092565b6000806040838503121561107a57600080fd5b8235915061108a60208401610f0e565b90509250929050565b6000602082840312156110a557600080fd5b61076382610f0e565b6000815180845260005b818110156110d4576020818501810151868301820152016110b8565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061076360208301846110ae565b60008060006060848603121561111c57600080fd5b61112584610f0e565b925061113360208501610f0e565b9150604084013590509250925092565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b60008261118a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561076657610766611157565b600181811c908216806111b657607f821691505b6020821081036111d657634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156111ee57600080fd5b5051919050565b60006020828403121561120757600080fd5b815160ff8116811461121857600080fd5b9392505050565b60ff828116828216039081111561076657610766611157565b600181815b8085111561127357816000190482111561125957611259611157565b8085161561126657918102915b93841c939080029061123d565b509250929050565b60008261128a57506001610766565b8161129757506000610766565b81600181146112ad57600281146112b7576112d3565b6001915050610766565b60ff8411156112c8576112c8611157565b50506001821b610766565b5060208310610133831016604e8410600b84101617156112f6575081810a610766565b6113008383611238565b806000190482111561131457611314611157565b029392505050565b600061076360ff84168361127b565b808202811582820484141761076657610766611157565b8082018082111561076657610766611157565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061138f908301846110ae565b979650505050505050565b6000602082840312156113ac57600080fd5b8151801515811461121857600080fdfea2646970667358221220c3b3d1f8951aff3bbbe49498e3a46c2eab155ddcdcd4fcb21f57ea9734a80bee64736f6c63430008160033000000000000000000000000b94742b094f89a8d53e15a45cdbf9810a5b090eb0000000000000000000000007bd61c667f869fb21b77626f0ac0acee51e4be7c

Deployed Bytecode

0x6080604052600436106101255760003560e01c80622306dc1461012a57806318b7ff721461014c5780631c335f491461016c57806325692962146101955780632f2ff15d1461019d578063306275be146101bd5780634a85f041146101dd578063528bd235146101ff57806354d1f13d1461021f5780636247f6f2146102275780636ccae05414610247578063715018a6146102675780638da5cb5b1461026f57806391d1485414610291578063943103c3146102c15780639a7d9a9b146102e1578063ab395191146102f7578063c6a261d214610317578063d547741f14610337578063daf9c21014610357578063e55dc4e614610387578063e90e5cc1146103a7578063f04e283e146103bc578063f2fde38b146103cf578063fee81cf4146103e2575b600080fd5b34801561013657600080fd5b5061014a610145366004610f40565b610415565b005b34801561015857600080fd5b5061014a61016736600461101b565b610441565b34801561017857600080fd5b5061018260015481565b6040519081526020015b60405180910390f35b61014a610478565b3480156101a957600080fd5b5061014a6101b8366004611067565b6104c7565b3480156101c957600080fd5b5061014a6101d8366004611093565b6104dd565b3480156101e957600080fd5b506101f2610540565b60405161018c91906110f4565b34801561020b57600080fd5b5061014a61021a366004610f40565b6105ce565b61014a6105e2565b34801561023357600080fd5b5061014a610242366004611093565b61061e565b34801561025357600080fd5b5061014a610262366004611107565b6106a4565b61014a610728565b34801561027b57600080fd5b50638b78c6d819545b60405161018c9190611143565b34801561029d57600080fd5b506102b16102ac366004611067565b61073c565b604051901515815260200161018c565b3480156102cd57600080fd5b5061014a6102dc36600461101b565b61076c565b3480156102ed57600080fd5b5061018260025481565b34801561030357600080fd5b5061014a610312366004610f40565b61077f565b34801561032357600080fd5b50600054610284906001600160a01b031681565b34801561034357600080fd5b5061014a610352366004611067565b61078d565b34801561036357600080fd5b506102b1610372366004611093565b60366020526000908152604090205460ff1681565b34801561039357600080fd5b5061014a6103a2366004611107565b61079f565b3480156103b357600080fd5b5061014a6109a5565b61014a6103ca366004611093565b610a02565b61014a6103dd366004611093565b610a42565b3480156103ee57600080fd5b506101826103fd366004611093565b63389a75e1600c908152600091909152602090205490565b6000610422600a8461116d565b905061043a8585610433848761118f565b8486610a69565b5050505050565b6002546001036104635760405162c9500b60e81b815260040160405180910390fd5b6001600255610473838383610afc565b505050565b60006202a3006001600160401b03164201905063389a75e1600c5233600052806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d600080a250565b6104cf610b8e565b6104d98282610ba9565b5050565b6104e5610b8e565b6001600160a01b03811660009081526036602052604090819020805460ff19169055517fdd2e6d9f52cbe8f695939d018b7d4a216dc613a669876163ac548b916489d91790610535908390611143565b60405180910390a150565b6003805461054d906111a2565b80601f0160208091040260200160405190810160405280929190818152602001828054610579906111a2565b80156105c65780601f1061059b576101008083540402835291602001916105c6565b820191906000526020600020905b8154815290600101906020018083116105a957829003601f168201915b505050505081565b6105dc848484600085610a69565b50505050565b63389a75e1600c523360005260006020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92600080a2565b610626610b8e565b806001600160a01b03163b60000361065157604051630f58058360e11b815260040160405180910390fd5b6001600160a01b03811660009081526036602052604090819020805460ff19166001179055517f6a65f90b1a644d2faac467a21e07e50e3f8fa5846e26231d30ae79a417d3d26290610535908390611143565b3360009081527f80dde0063ab259f132ebe19ca7c3f445dd67076b1475ae6c8b166d937934592960205260409020547fc4c453d647953c0fd35db5a34ee76e60fb4abc3a8fb891a25936b70b38f292539060ff1661071d5760405163962f633360e01b8152600481018290526024015b60405180910390fd5b6105dc848484610c04565b610730610b8e565b61073a6000610d87565b565b60008281526004602090815260408083206001600160a01b038516845290915281205460ff165b90505b92915050565b610774610b8e565b610473838383610afc565b6105dc848460008585610a69565b610795610b8e565b6104d98282610dc5565b6000546001600160a01b031633146107ca57604051633167e3df60e21b815260040160405180910390fd5b6040516370a0823160e01b81526000906001600160a01b038516906370a08231906107f9903090600401611143565b602060405180830381865afa158015610816573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061083a91906111dc565b90506000846001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa15801561087c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a091906111f5565b905060128160ff1610156108d5576108b981601261121f565b6108c490600a61131c565b6108ce908461116d565b9250610904565b60128160ff161115610904576108ec60128261121f565b6108f790600a61131c565b610901908461132b565b92505b8282101561093e5760405163ebd6ced960e01b81526001600160a01b03861660048201526024810183905260448101849052606401610714565b6109526001600160a01b0386168585610e1d565b604080516001600160a01b038088168252861660208201529081018490527f5e110f8bc8a20b65dcc87f224bdf1cc039346e267118bae2739847f07321ffa8906060015b60405180910390a15050505050565b6109ad610b8e565b600080546040805163d9374bff60e01b815290516001600160a01b039092169263d9374bff9260048084019382900301818387803b1580156109ee57600080fd5b505af11580156105dc573d6000803e3d6000fd5b610a0a610b8e565b63389a75e1600c52806000526020600c208054421115610a3257636f5e88186000526004601cfd5b60009055610a3f81610d87565b50565b610a4a610b8e565b8060601b610a6057637448fbae6000526004601cfd5b610a3f81610d87565b6001600160a01b03851660009081526036602052604090205460ff16610aa4578460405163751dff9760e11b81526004016107149190611143565b610ac53330610ab38587611342565b6001600160a01b038916929190610e6d565b7f91f985f17a8632ae2e0a009d65ae250f373d82359d2389b58ea50ada6436682a8585858585604051610996959493929190611355565b600080546001600160a01b0319166001600160a01b038416179055600183905560005460405163f3aebe4d60e01b8152600481018590526001600160401b03831660248201526001600160a01b039091169063f3aebe4d90604401600060405180830381600087803b158015610b7157600080fd5b505af1158015610b85573d6000803e3d6000fd5b50505050505050565b638b78c6d81954331461073a576382b429006000526004601cfd5b60008281526004602090815260408083206001600160a01b0385168085529252808320805460ff1916600117905551909184917f2ae6a113c0ed5b78a53413ffbb7679881f11145ccfba4fb92e863dfcd5a1d2f39190a35050565b6001600160a01b038216610c2b5760405163d92e233d60e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03841601610c5a576104738282610ecb565b826001600160a01b03163b600003610c8557604051630f58058360e11b815260040160405180910390fd5b6040516301ffc9a760e01b81526380ac58cd60e01b60048201526001600160a01b038416906301ffc9a790602401602060405180830381865afa925050508015610cec575060408051601f3d908101601f19168201909252610ce99181019061139a565b60015b610cfb57610473838383610e1d565b8015610d7c57604051635c46a7ef60e11b81523060048201526001600160a01b03848116602483015260448201849052608060648301526000608483015285169063b88d4fde9060a401600060405180830381600087803b158015610d5f57600080fd5b505af1158015610d73573d6000803e3d6000fd5b505050506105dc565b6105dc848484610e1d565b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a355565b60008281526004602090815260408083206001600160a01b0385168085529252808320805460ff1916905551909184917f155aaafb6329a2098580462df33ec4b7441b19729b9601c5fc17ae1cf99a8a529190a35050565b816014528060345263a9059cbb60601b60005260206000604460106000875af18060016000511416610e6257803d853b151710610e62576390b8ec186000526004601cfd5b506000603452505050565b60405181606052826040528360601b602c526323b872dd60601b600c52602060006064601c6000895af18060016000511416610ebc57803d873b151710610ebc57637939f4246000526004601cfd5b50600060605260405250505050565b80471015610ee15763b12d13eb6000526004601cfd5b6000386000388486620186a0f16104d957816000526073600b5360ff6020536016600b82f06104d9573838fd5b80356001600160a01b0381168114610f2557600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60008060008060808587031215610f5657600080fd5b610f5f85610f0e565b9350610f6d60208601610f0e565b92506040850135915060608501356001600160401b0380821115610f9057600080fd5b818701915087601f830112610fa457600080fd5b813581811115610fb657610fb6610f2a565b604051601f8201601f19908116603f01168101908382118183101715610fde57610fde610f2a565b816040528281528a6020848701011115610ff757600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060006060848603121561103057600080fd5b8335925061104060208501610f0e565b915060408401356001600160401b038116811461105c57600080fd5b809150509250925092565b6000806040838503121561107a57600080fd5b8235915061108a60208401610f0e565b90509250929050565b6000602082840312156110a557600080fd5b61076382610f0e565b6000815180845260005b818110156110d4576020818501810151868301820152016110b8565b506000602082860101526020601f19601f83011685010191505092915050565b60208152600061076360208301846110ae565b60008060006060848603121561111c57600080fd5b61112584610f0e565b925061113360208501610f0e565b9150604084013590509250925092565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052601160045260246000fd5b60008261118a57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561076657610766611157565b600181811c908216806111b657607f821691505b6020821081036111d657634e487b7160e01b600052602260045260246000fd5b50919050565b6000602082840312156111ee57600080fd5b5051919050565b60006020828403121561120757600080fd5b815160ff8116811461121857600080fd5b9392505050565b60ff828116828216039081111561076657610766611157565b600181815b8085111561127357816000190482111561125957611259611157565b8085161561126657918102915b93841c939080029061123d565b509250929050565b60008261128a57506001610766565b8161129757506000610766565b81600181146112ad57600281146112b7576112d3565b6001915050610766565b60ff8411156112c8576112c8611157565b50506001821b610766565b5060208310610133831016604e8410600b84101617156112f6575081810a610766565b6113008383611238565b806000190482111561131457611314611157565b029392505050565b600061076360ff84168361127b565b808202811582820484141761076657610766611157565b8082018082111561076657610766611157565b6001600160a01b03868116825285166020820152604081018490526060810183905260a06080820181905260009061138f908301846110ae565b979650505050505050565b6000602082840312156113ac57600080fd5b8151801515811461121857600080fdfea2646970667358221220c3b3d1f8951aff3bbbe49498e3a46c2eab155ddcdcd4fcb21f57ea9734a80bee64736f6c63430008160033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000b94742b094f89a8d53e15a45cdbf9810a5b090eb0000000000000000000000007bd61c667f869fb21b77626f0ac0acee51e4be7c

-----Decoded View---------------
Arg [0] : socket_ (address): 0xB94742B094f89A8D53e15A45CdBf9810a5B090Eb
Arg [1] : owner_ (address): 0x7BD61c667f869FB21b77626f0Ac0ACEE51e4BE7C

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000b94742b094f89a8d53e15a45cdbf9810a5b090eb
Arg [1] : 0000000000000000000000007bd61c667f869fb21b77626f0ac0acee51e4be7c


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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