ETH Price: $2,861.02 (-2.79%)

Contract

0x5b83C5A915Ac06Dd0181756685F70F5C55FC7E61

Overview

ETH Balance

1 wei

ETH Value

Less Than $0.01 (@ $2,861.02/ETH)

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Block
From
To
Execute164890042025-05-14 15:42:43256 days ago1747237363IN
0x5b83C5A9...C55FC7E61
0 ETH0.000000010.00030011
Transfer164888412025-05-14 15:40:00256 days ago1747237200IN
0x5b83C5A9...C55FC7E61
0 ETH0.000000010.00030978
Transfer164887902025-05-14 15:39:09256 days ago1747237149IN
0x5b83C5A9...C55FC7E61
1 wei0.000000010.00030052

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
159641722025-05-08 13:55:31262 days ago1746712531
0x5b83C5A9...C55FC7E61
0.005052 ETH
159641692025-05-08 13:55:28262 days ago1746712528
0x5b83C5A9...C55FC7E61
0.005052 ETH
159625362025-05-08 13:28:15262 days ago1746710895
0x5b83C5A9...C55FC7E61
0.00253905 ETH
159625322025-05-08 13:28:11262 days ago1746710891
0x5b83C5A9...C55FC7E61
0.002535 ETH
154703522025-05-02 20:45:11268 days ago1746218711
0x5b83C5A9...C55FC7E61
0.00009349 ETH
154703522025-05-02 20:45:11268 days ago1746218711
0x5b83C5A9...C55FC7E61
0.00009755 ETH
154703482025-05-02 20:45:07268 days ago1746218707
0x5b83C5A9...C55FC7E61
0.000187 ETH
154677072025-05-02 20:01:06268 days ago1746216066
0x5b83C5A9...C55FC7E61
0.00027349 ETH
154677072025-05-02 20:01:06268 days ago1746216066
0x5b83C5A9...C55FC7E61
0.0002816 ETH
154677022025-05-02 20:01:01268 days ago1746216061
0x5b83C5A9...C55FC7E61
0.000547 ETH
154677022025-05-02 20:01:01268 days ago1746216061
0x5b83C5A9...C55FC7E61
0.00027349 ETH
154677022025-05-02 20:01:01268 days ago1746216061
0x5b83C5A9...C55FC7E61
0.0002897 ETH
154676952025-05-02 20:00:54268 days ago1746216054
0x5b83C5A9...C55FC7E61
0.000547 ETH
154665252025-05-02 19:41:24268 days ago1746214884
0x5b83C5A9...C55FC7E61
0.000053 ETH
154665252025-05-02 19:41:24268 days ago1746214884
0x5b83C5A9...C55FC7E61
0.0000162 ETH
154665252025-05-02 19:41:24268 days ago1746214884
0x5b83C5A9...C55FC7E61
0.000053 ETH
154665252025-05-02 19:41:24268 days ago1746214884
0x5b83C5A9...C55FC7E61
0.0000162 ETH
154663292025-05-02 19:38:08268 days ago1746214688
0x5b83C5A9...C55FC7E61
0.000053 ETH
154663292025-05-02 19:38:08268 days ago1746214688
0x5b83C5A9...C55FC7E61
0.0000162 ETH
154663282025-05-02 19:38:07268 days ago1746214687
0x5b83C5A9...C55FC7E61
0.000053 ETH
154663282025-05-02 19:38:07268 days ago1746214687
0x5b83C5A9...C55FC7E61
0.0000162 ETH
154663062025-05-02 19:37:45268 days ago1746214665
0x5b83C5A9...C55FC7E61
0.0000265 ETH
154663062025-05-02 19:37:45268 days ago1746214665
0x5b83C5A9...C55FC7E61
0.0000589 ETH
154663052025-05-02 19:37:44268 days ago1746214664
0x5b83C5A9...C55FC7E61
0.0000265 ETH
154663052025-05-02 19:37:44268 days ago1746214664
0x5b83C5A9...C55FC7E61
0.00014429 ETH
View All Internal Transactions

Cross-Chain Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StargateV2Receiver

Compiler Version
v0.8.28+commit.7893614a

Optimization Enabled:
Yes with 200 runs

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

import {ILayerZeroComposer} from "@layerzerolabs/lz-evm-protocol-v2/contracts/interfaces/ILayerZeroComposer.sol";
import {OFTComposeMsgCodec} from "@layerzerolabs/lz-evm-oapp-v2/contracts/oft/libs/OFTComposeMsgCodec.sol";
import {SafeERC20, IERC20} from "openzeppelin-contracts/token/ERC20/utils/SafeERC20.sol";
import {VM} from "enso-weiroll/VM.sol";

contract StargateV2Receiver is VM, ILayerZeroComposer {
    using OFTComposeMsgCodec for bytes;
    using SafeERC20 for IERC20;

    address private constant _NATIVE_ASSET = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    address public immutable endpoint;

    event ShortcutExecutionSuccessful(bytes32 guid, bytes32 requestId);
    event ShortcutExecutionFailed(bytes32 guid, bytes32 requestId);
    
    error NotEndpoint(address sender);
    error NotSelf();
    error TransferFailed(bytes32 guid, address receiver);

    constructor(address _endpoint) {
        endpoint = _endpoint;
    }

    function lzCompose(
        address,
        bytes32 _guid,
        bytes calldata _message,
        address,
        bytes calldata
    ) external payable {
        if (msg.sender != endpoint) revert NotEndpoint(msg.sender);

        bytes memory composeMsg = _message.composeMsg();
        (address token, address receiver, bytes32 requestId, bytes32[] memory commands, bytes[] memory state) = 
            abi.decode(composeMsg, (address, address, bytes32, bytes32[], bytes[]));

        // try to execute shortcut
        try this.execute(commands, state) {
            emit ShortcutExecutionSuccessful(_guid, requestId);
        } catch {
            // if shortcut fails send funds to receiver
            emit ShortcutExecutionFailed(_guid, requestId);
            uint256 amount = _message.amountLD();
            if (token == _NATIVE_ASSET) {
                (bool success, ) = receiver.call{value: amount}("");
                if (!success) revert TransferFailed(_guid, receiver);
            } else {
                IERC20(token).safeTransfer(receiver, amount);
            }
        }
    }

    function execute(bytes32[] calldata commands, bytes[] memory state) public {
        if (msg.sender != address(this)) revert NotSelf();
        _execute(commands, state);
    }

    receive() external payable {}
}

File 2 of 11 : ILayerZeroComposer.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.0;

/**
 * @title ILayerZeroComposer
 */
interface ILayerZeroComposer {
    /**
     * @notice Composes a LayerZero message from an OApp.
     * @param _from The address initiating the composition, typically the OApp where the lzReceive was called.
     * @param _guid The unique identifier for the corresponding LayerZero src/dst tx.
     * @param _message The composed message payload in bytes. NOT necessarily the same payload passed via lzReceive.
     * @param _executor The address of the executor for the composed message.
     * @param _extraData Additional arbitrary data in bytes passed by the entity who executes the lzCompose.
     */
    function lzCompose(
        address _from,
        bytes32 _guid,
        bytes calldata _message,
        address _executor,
        bytes calldata _extraData
    ) external payable;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

library OFTComposeMsgCodec {
    // Offset constants for decoding composed messages
    uint8 private constant NONCE_OFFSET = 8;
    uint8 private constant SRC_EID_OFFSET = 12;
    uint8 private constant AMOUNT_LD_OFFSET = 44;
    uint8 private constant COMPOSE_FROM_OFFSET = 76;

    /**
     * @dev Encodes a OFT composed message.
     * @param _nonce The nonce value.
     * @param _srcEid The source endpoint ID.
     * @param _amountLD The amount in local decimals.
     * @param _composeMsg The composed message.
     * @return _msg The encoded Composed message.
     */
    function encode(
        uint64 _nonce,
        uint32 _srcEid,
        uint256 _amountLD,
        bytes memory _composeMsg // 0x[composeFrom][composeMsg]
    ) internal pure returns (bytes memory _msg) {
        _msg = abi.encodePacked(_nonce, _srcEid, _amountLD, _composeMsg);
    }

    /**
     * @dev Retrieves the nonce from the composed message.
     * @param _msg The message.
     * @return The nonce value.
     */
    function nonce(bytes calldata _msg) internal pure returns (uint64) {
        return uint64(bytes8(_msg[:NONCE_OFFSET]));
    }

    /**
     * @dev Retrieves the source endpoint ID from the composed message.
     * @param _msg The message.
     * @return The source endpoint ID.
     */
    function srcEid(bytes calldata _msg) internal pure returns (uint32) {
        return uint32(bytes4(_msg[NONCE_OFFSET:SRC_EID_OFFSET]));
    }

    /**
     * @dev Retrieves the amount in local decimals from the composed message.
     * @param _msg The message.
     * @return The amount in local decimals.
     */
    function amountLD(bytes calldata _msg) internal pure returns (uint256) {
        return uint256(bytes32(_msg[SRC_EID_OFFSET:AMOUNT_LD_OFFSET]));
    }

    /**
     * @dev Retrieves the composeFrom value from the composed message.
     * @param _msg The message.
     * @return The composeFrom value.
     */
    function composeFrom(bytes calldata _msg) internal pure returns (bytes32) {
        return bytes32(_msg[AMOUNT_LD_OFFSET:COMPOSE_FROM_OFFSET]);
    }

    /**
     * @dev Retrieves the composed message.
     * @param _msg The message.
     * @return The composed message.
     */
    function composeMsg(bytes calldata _msg) internal pure returns (bytes memory) {
        return _msg[COMPOSE_FROM_OFFSET:];
    }

    /**
     * @dev Converts an address to bytes32.
     * @param _addr The address to convert.
     * @return The bytes32 representation of the address.
     */
    function addressToBytes32(address _addr) internal pure returns (bytes32) {
        return bytes32(uint256(uint160(_addr)));
    }

    /**
     * @dev Converts bytes32 to an address.
     * @param _b The bytes32 value to convert.
     * @return The address representation of bytes32.
     */
    function bytes32ToAddress(bytes32 _b) internal pure returns (address) {
        return address(uint160(uint256(_b)));
    }
}

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

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";

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

    /**
     * @dev Indicates a failed `decreaseAllowance` request.
     */
    error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);

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

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

    /**
     * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 oldAllowance = token.allowance(address(this), spender);
        forceApprove(token, spender, oldAllowance + value);
    }

    /**
     * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
     * value, non-reverting calls are assumed to be successful.
     *
     * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
     * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
     * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
     * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
     */
    function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
        unchecked {
            uint256 currentAllowance = token.allowance(address(this), spender);
            if (currentAllowance < requestedDecrease) {
                revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
            }
            forceApprove(token, spender, currentAllowance - requestedDecrease);
        }
    }

    /**
     * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
     * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
     * to be set to zero before setting it to a non-zero value, such as USDT.
     *
     * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
     * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
     * set here.
     */
    function forceApprove(IERC20 token, address spender, uint256 value) internal {
        bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value));

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

    /**
     * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            safeTransfer(token, to, value);
        } else if (!token.transferAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
     * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * Reverts if the returned value is other than `true`.
     */
    function transferFromAndCallRelaxed(
        IERC1363 token,
        address from,
        address to,
        uint256 value,
        bytes memory data
    ) internal {
        if (to.code.length == 0) {
            safeTransferFrom(token, from, to, value);
        } else if (!token.transferFromAndCall(from, to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
     * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
     * targeting contracts.
     *
     * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
     * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
     * once without retrying, and relies on the returned value to be true.
     *
     * Reverts if the returned value is other than `true`.
     */
    function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
        if (to.code.length == 0) {
            forceApprove(token, to, value);
        } else if (!token.approveAndCall(to, value, data)) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements.
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            // bubble errors
            if iszero(success) {
                let ptr := mload(0x40)
                returndatacopy(ptr, 0, returndatasize())
                revert(ptr, returndatasize())
            }
            returnSize := returndatasize()
            returnValue := mload(0)
        }

        if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) {
            revert SafeERC20FailedOperation(address(token));
        }
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     *
     * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        bool success;
        uint256 returnSize;
        uint256 returnValue;
        assembly ("memory-safe") {
            success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20)
            returnSize := returndatasize()
            returnValue := mload(0)
        }
        return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1);
    }
}

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.16;

import "./CommandBuilder.sol";

abstract contract VM {
    using CommandBuilder for bytes[];

    uint256 constant FLAG_CT_DELEGATECALL = 0x00; // Delegate call not currently supported
    uint256 constant FLAG_CT_CALL = 0x01;
    uint256 constant FLAG_CT_STATICCALL = 0x02;
    uint256 constant FLAG_CT_VALUECALL = 0x03;
    uint256 constant FLAG_CT_MASK = 0x03;
    uint256 constant FLAG_DATA = 0x20;
    uint256 constant FLAG_EXTENDED_COMMAND = 0x40;
    uint256 constant FLAG_TUPLE_RETURN = 0x80;

    uint256 constant SHORT_COMMAND_FILL =
        0x000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    error ExecutionFailed(
        uint256 command_index,
        address target,
        string message
    );

    function _execute(bytes32[] calldata commands, bytes[] memory state)
        internal
        returns (bytes[] memory)
    {
        bytes32 command;
        uint256 flags;
        bytes32 indices;

        bool success;
        bytes memory outData;

        uint256 commandsLength = commands.length;
        uint256 indicesLength;
        for (uint256 i; i < commandsLength; i = _uncheckedIncrement(i)) {
            command = commands[i];
            flags = uint256(uint8(bytes1(command << 32)));

            if (flags & FLAG_EXTENDED_COMMAND != 0) {
                i = _uncheckedIncrement(i);
                indices = commands[i];
                indicesLength = 32;
            } else {
                indices = bytes32(uint256(command << 40) | SHORT_COMMAND_FILL);
                indicesLength = 6;
            }

            if (flags & FLAG_CT_MASK == FLAG_CT_CALL) {
                (success, outData) = address(uint160(uint256(command))).call( // target
                    // inputs
                    flags & FLAG_DATA == 0
                        ? state.buildInputs(
                            bytes4(command), // selector
                            indices,
                            indicesLength
                        )
                        : state[
                            uint8(bytes1(indices)) &
                            CommandBuilder.IDX_VALUE_MASK
                        ]
                );
            } else if (flags & FLAG_CT_MASK == FLAG_CT_STATICCALL) {
                (success, outData) = address(uint160(uint256(command))) // target
                    .staticcall(
                        // inputs
                        flags & FLAG_DATA == 0
                            ? state.buildInputs(
                                bytes4(command), // selector
                                indices,
                                indicesLength
                            )
                            : state[
                                uint8(bytes1(indices)) &
                                CommandBuilder.IDX_VALUE_MASK
                            ]
                    );
            } else if (flags & FLAG_CT_MASK == FLAG_CT_VALUECALL) {
                bytes memory v = state[
                    uint8(bytes1(indices)) &
                    CommandBuilder.IDX_VALUE_MASK
                ];
                require(v.length == 32, "Value must be 32 bytes");
                uint256 callEth = uint256(bytes32(v));
                (success, outData) = address(uint160(uint256(command))).call{ // target
                    value: callEth
                }(
                    // inputs
                    flags & FLAG_DATA == 0
                        ? state.buildInputs(
                            bytes4(command), // selector
                            indices << 8, // skip value input
                            indicesLength - 1 // max indices length reduced by value input
                        )
                        : state[
                            uint8(bytes1(indices << 8)) & // first byte after value input
                            CommandBuilder.IDX_VALUE_MASK
                        ]
                );
            } else {
                revert("Invalid calltype");
            }

            if (!success) {
                string memory message = "Unknown";
                if (outData.length > 68) {
                    // This might be an error message, parse the outData
                    // Estimate the bytes length of the possible error message
                    uint256 estimatedLength = _estimateBytesLength(outData, 68);
                    // Remove selector. First 32 bytes should be a pointer that indicates the start of data in memory
                    assembly {
                        outData := add(outData, 4)
                    }
                    uint256 pointer = uint256(bytes32(outData));
                    if (pointer == 32) {
                        // Remove pointer. If it is a string, the next 32 bytes will hold the size
                        assembly {
                            outData := add(outData, 32)
                        }
                        uint256 size = uint256(bytes32(outData));
                        // If the size variable is the same as the estimated bytes length, we can be fairly certain
                        // this is a dynamic string, so convert the bytes to a string and emit the message. While an
                        // error function with 3 static parameters is capable of producing a similar output, there is
                        // low risk of a contract unintentionally emitting a message.
                        if (size == estimatedLength) {
                            // Remove size. The remaining data should be the string content
                            assembly {
                                outData := add(outData, 32)
                            }
                            message = string(outData);
                        }
                    }
                }
                revert ExecutionFailed({
                    command_index: flags & FLAG_EXTENDED_COMMAND == 0
                        ? i
                        : i - 1,
                    target: address(uint160(uint256(command))),
                    message: message
                });
            }

            if (flags & FLAG_TUPLE_RETURN != 0) {
                state.writeTuple(bytes1(command << 88), outData);
            } else {
                state = state.writeOutputs(bytes1(command << 88), outData);
            }
        }
        return state;
    }

    function _estimateBytesLength(bytes memory data, uint256 pos) internal pure returns (uint256 estimate) {
        uint256 length = data.length;
        estimate = length - pos; // Assume length equals alloted space
        for (uint256 i = pos; i < length; ) {
            if (data[i] == 0) {
                // Zero bytes found, adjust estimated length
                estimate = i - pos;
                break;
            }
            unchecked {
                ++i;
            }
        }
    }

    function _uncheckedIncrement(uint256 i) private pure returns (uint256) {
        unchecked {
            ++i;
        }
        return i;
    }
}

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

pragma solidity ^0.8.20;

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

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

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

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

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

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

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

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

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";

/**
 * @title IERC1363
 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
 *
 * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
 * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
 */
interface IERC1363 is IERC20, IERC165 {
    /*
     * Note: the ERC-165 identifier for this interface is 0xb0202a11.
     * 0xb0202a11 ===
     *   bytes4(keccak256('transferAndCall(address,uint256)')) ^
     *   bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
     *   bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256)')) ^
     *   bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
     */

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
     * and then calls {IERC1363Receiver-onTransferReceived} on `to`.
     * @param from The address which you want to send tokens from.
     * @param to The address which you want to transfer to.
     * @param value The amount of tokens to be transferred.
     * @param data Additional data with no specified format, sent in call to `to`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value) external returns (bool);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
     * @param spender The address which will spend the funds.
     * @param value The amount of tokens to be spent.
     * @param data Additional data with no specified format, sent in call to `spender`.
     * @return A boolean value indicating whether the operation succeeded unless throwing.
     */
    function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}

// SPDX-License-Identifier: GPL-3.0-only

pragma solidity ^0.8.16;

library CommandBuilder {
    uint256 constant IDX_VARIABLE_LENGTH = 0x80;
    uint256 constant IDX_VALUE_MASK = 0x7f;
    uint256 constant IDX_END_OF_ARGS = 0xff;
    uint256 constant IDX_USE_STATE = 0xfe;
    uint256 constant IDX_ARRAY_START = 0xfd;
    uint256 constant IDX_TUPLE_START = 0xfc;
    uint256 constant IDX_DYNAMIC_END = 0xfb;

    function buildInputs(
        bytes[] memory state,
        bytes4 selector,
        bytes32 indices,
        uint256 indicesLength
    ) internal view returns (bytes memory ret) {
        uint256 idx; // The current command index
        uint256 offsetIdx; // The index of the current free offset

        uint256 count; // Number of bytes in whole ABI encoded message
        uint256 free; // Pointer to first free byte in tail part of message
        uint256[] memory dynamicLengths = new uint256[](10); // Optionally store the length of all dynamic types (a command cannot fit more than 10 dynamic types)

        bytes memory stateData; // Optionally encode the current state if the call requires it

        // Determine the length of the encoded data
        for (uint256 i; i < indicesLength; ) {
            idx = uint8(indices[i]);
            if (idx == IDX_END_OF_ARGS) {
                indicesLength = i;
                break;
            }
            if (idx & IDX_VARIABLE_LENGTH != 0) {
                if (idx == IDX_USE_STATE) {
                    if (stateData.length == 0) {
                        stateData = abi.encode(state);
                    }
                    unchecked {
                        count += stateData.length;
                    }
                } else {
                    (dynamicLengths, offsetIdx, count, i) = setupDynamicType(
                        state,
                        indices,
                        dynamicLengths,
                        idx,
                        offsetIdx,
                        count,
                        i
                    );
                }
            } else {
                count = setupStaticVariable(state, count, idx);
            }
            unchecked {
                free += 32;
                ++i;
            }
        }

        // Encode it
        ret = new bytes(count + 4);
        assembly {
            mstore(add(ret, 32), selector)
        }
        offsetIdx = 0;
        // Use count to track current memory slot
        assembly {
            count := add(ret, 36)
        }
        for (uint256 i; i < indicesLength; ) {
            idx = uint8(indices[i]);
            if (idx & IDX_VARIABLE_LENGTH != 0) {
                if (idx == IDX_USE_STATE) {
                    assembly {
                        mstore(count, free)
                    }
                    memcpy(stateData, 32, ret, free + 4, stateData.length - 32);
                    unchecked {
                        free += stateData.length - 32;
                    }
                } else if (idx == IDX_ARRAY_START) {
                    // Start of dynamic type, put pointer in current slot
                    assembly {
                        mstore(count, free)
                    }
                    (offsetIdx, free, i, ) = encodeDynamicArray(
                        ret,
                        state,
                        indices,
                        dynamicLengths,
                        offsetIdx,
                        free,
                        i
                    );
                } else if (idx == IDX_TUPLE_START) {
                    // Start of dynamic type, put pointer in current slot
                    assembly {
                        mstore(count, free)
                    }
                    (offsetIdx, free, i, ) = encodeDynamicTuple(
                        ret,
                        state,
                        indices,
                        dynamicLengths,
                        offsetIdx,
                        free,
                        i
                    );
                } else {
                    // Variable length data
                    uint256 argLen = state[idx & IDX_VALUE_MASK].length;
                    // Put a pointer in the current slot and write the data to first free slot
                    assembly {
                        mstore(count, free)
                    }
                    memcpy(
                        state[idx & IDX_VALUE_MASK],
                        0,
                        ret,
                        free + 4,
                        argLen
                    );
                    unchecked {
                        free += argLen;
                    }
                }
            } else {
                // Fixed length data (length previously checked to be 32 bytes)
                bytes memory stateVar = state[idx & IDX_VALUE_MASK];
                // Write the data to current slot
                assembly {
                    mstore(count, mload(add(stateVar, 32)))
                }
            }
            unchecked {
                count += 32;
                ++i;
            }
        }
    }

    function setupStaticVariable(
        bytes[] memory state,
        uint256 count,
        uint256 idx
    ) internal pure returns (uint256 newCount) {
        require(
            state[idx & IDX_VALUE_MASK].length == 32,
            "Static state variables must be 32 bytes"
        );
        unchecked {
            newCount = count + 32;
        }
    }

    function setupDynamicVariable(
        bytes[] memory state,
        uint256 count,
        uint256 idx
    ) internal pure returns (uint256 newCount) {
        bytes memory arg = state[idx & IDX_VALUE_MASK];
        // Validate the length of the data in state is a multiple of 32
        uint256 argLen = arg.length;
        require(
            argLen != 0 && argLen % 32 == 0,
            "Dynamic state variables must be a multiple of 32 bytes"
        );
        // Add the length of the value, rounded up to the next word boundary, plus space for pointer
        unchecked {
            newCount = count + argLen + 32;
        }
    }

    function setupDynamicType(
        bytes[] memory state,
        bytes32 indices,
        uint256[] memory dynamicLengths,
        uint256 idx,
        uint256 offsetIdx,
        uint256 count,
        uint256 index
    ) internal view returns (
        uint256[] memory newDynamicLengths,
        uint256 newOffsetIdx,
        uint256 newCount,
        uint256 newIndex
    ) {
        if (idx == IDX_ARRAY_START) {
            (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicArray(
                state,
                indices,
                dynamicLengths,
                offsetIdx,
                count,
                index
            );
        } else if (idx == IDX_TUPLE_START) {
            (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple(
                state,
                indices,
                dynamicLengths,
                offsetIdx,
                count,
                index
            );
        } else {
            newDynamicLengths = dynamicLengths;
            newOffsetIdx = offsetIdx;
            newIndex = index;
            newCount = setupDynamicVariable(state, count, idx);
        }
    }

    function setupDynamicArray(
        bytes[] memory state,
        bytes32 indices,
        uint256[] memory dynamicLengths,
        uint256 offsetIdx,
        uint256 count,
        uint256 index
    ) internal view returns (
        uint256[] memory newDynamicLengths,
        uint256 newOffsetIdx,
        uint256 newCount,
        uint256 newIndex
    ) {
        // Current idx is IDX_ARRAY_START, next idx will contain the array length
        unchecked {
            newIndex = index + 1;
            newCount = count + 32;
        }
        uint256 idx = uint8(indices[newIndex]);
        require(
            state[idx & IDX_VALUE_MASK].length == 32,
            "Array length must be 32 bytes"
        );
        (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicTuple(
            state,
            indices,
            dynamicLengths,
            offsetIdx,
            newCount,
            newIndex
        );
    }

    function setupDynamicTuple(
        bytes[] memory state,
        bytes32 indices,
        uint256[] memory dynamicLengths,
        uint256 offsetIdx,
        uint256 count,
        uint256 index
    ) internal view returns (
        uint256[] memory newDynamicLengths,
        uint256 newOffsetIdx,
        uint256 newCount,
        uint256 newIndex
    ) {
        uint256 idx;
        uint256 offset;
        newDynamicLengths = dynamicLengths;
        // Progress to first index of the data and progress the next offset idx
        unchecked {
            newIndex = index + 1;
            newOffsetIdx = offsetIdx + 1;
            newCount = count + 32;
        }
        while (newIndex < 32) {
            idx = uint8(indices[newIndex]);
            if (idx & IDX_VARIABLE_LENGTH != 0) {
                if (idx == IDX_DYNAMIC_END) {
                    newDynamicLengths[offsetIdx] = offset;
                    // explicit return saves gas ¯\_(ツ)_/¯
                    return (newDynamicLengths, newOffsetIdx, newCount, newIndex);
                } else {
                    require(idx != IDX_USE_STATE, "Cannot use state from inside dynamic type");
                    (newDynamicLengths, newOffsetIdx, newCount, newIndex) = setupDynamicType(
                        state,
                        indices,
                        newDynamicLengths,
                        idx,
                        newOffsetIdx,
                        newCount,
                        newIndex
                    );
                }
            } else {
                newCount = setupStaticVariable(state, newCount, idx);
            }
            unchecked {
                offset += 32;
                ++newIndex;
            }
        }
        revert("Dynamic type was not properly closed");
    }

    function encodeDynamicArray(
        bytes memory ret,
        bytes[] memory state,
        bytes32 indices,
        uint256[] memory dynamicLengths,
        uint256 offsetIdx,
        uint256 currentSlot,
        uint256 index
    ) internal view returns (
        uint256 newOffsetIdx,
        uint256 newSlot,
        uint256 newIndex,
        uint256 length
    ) {
        // Progress to array length metadata
        unchecked {
            newIndex = index + 1;
            newSlot = currentSlot + 32;
        }
        // Encode array length
        uint256 idx = uint8(indices[newIndex]);
        // Array length value previously checked to be 32 bytes
        bytes memory stateVar = state[idx & IDX_VALUE_MASK];
        assembly {
            mstore(add(add(ret, 36), currentSlot), mload(add(stateVar, 32)))
        }
        (newOffsetIdx, newSlot, newIndex, length) = encodeDynamicTuple(
            ret,
            state,
            indices,
            dynamicLengths,
            offsetIdx,
            newSlot,
            newIndex
        );
        unchecked {
            length += 32; // Increase length to account for array length metadata
        }
    }

    function encodeDynamicTuple(
        bytes memory ret,
        bytes[] memory state,
        bytes32 indices,
        uint256[] memory dynamicLengths,
        uint256 offsetIdx,
        uint256 currentSlot,
        uint256 index
    ) internal view returns (
        uint256 newOffsetIdx,
        uint256 newSlot,
        uint256 newIndex,
        uint256 length
    ) {
        uint256 idx;
        uint256 argLen;
        uint256 freePointer = dynamicLengths[offsetIdx]; // The pointer to the next free slot
        unchecked {
            newSlot = currentSlot + freePointer; // Update the next slot
            newOffsetIdx = offsetIdx + 1; // Progress to next offsetIdx
            newIndex = index + 1; // Progress to first index of the data
        }
        // Shift currentSlot to correct location in memory
        assembly {
            currentSlot := add(add(ret, 36), currentSlot)
        }
        while (newIndex < 32) {
            idx = uint8(indices[newIndex]);
            if (idx & IDX_VARIABLE_LENGTH != 0) {
                if (idx == IDX_DYNAMIC_END) {
                    break;
                } else if (idx == IDX_ARRAY_START) {
                    // Start of dynamic type, put pointer in current slot
                    assembly {
                        mstore(currentSlot, freePointer)
                    }
                    (newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicArray(
                        ret,
                        state,
                        indices,
                        dynamicLengths,
                        newOffsetIdx,
                        newSlot,
                        newIndex
                    );
                    unchecked {
                        freePointer += argLen;
                        length += (argLen + 32); // data + pointer
                    }
                } else if (idx == IDX_TUPLE_START) {
                    // Start of dynamic type, put pointer in current slot
                    assembly {
                        mstore(currentSlot, freePointer)
                    }
                    (newOffsetIdx, newSlot, newIndex, argLen) = encodeDynamicTuple(
                        ret,
                        state,
                        indices,
                        dynamicLengths,
                        newOffsetIdx,
                        newSlot,
                        newIndex
                    );
                    unchecked {
                        freePointer += argLen;
                        length += (argLen + 32); // data + pointer
                    }
                } else  {
                    // Variable length data
                    argLen = state[idx & IDX_VALUE_MASK].length;
                    // Start of dynamic type, put pointer in current slot
                    assembly {
                        mstore(currentSlot, freePointer)
                    }
                    memcpy(
                        state[idx & IDX_VALUE_MASK],
                        0,
                        ret,
                        newSlot + 4,
                        argLen
                    );
                    unchecked {
                        newSlot += argLen;
                        freePointer += argLen;
                        length += (argLen + 32); // data + pointer
                    }
                }
            } else {
                // Fixed length data (length previously checked to be 32 bytes)
                bytes memory stateVar = state[idx & IDX_VALUE_MASK];
                // Write to first free slot
                assembly {
                    mstore(currentSlot, mload(add(stateVar, 32)))
                }
                unchecked {
                    length += 32;
                }
            }
            unchecked {
                currentSlot += 32;
                ++newIndex;
            }
        }
    }

    function writeOutputs(
        bytes[] memory state,
        bytes1 index,
        bytes memory output
    ) internal pure returns (bytes[] memory) {
        uint256 idx = uint8(index);
        if (idx == IDX_END_OF_ARGS) return state;

        if (idx & IDX_VARIABLE_LENGTH != 0) {
            if (idx == IDX_USE_STATE) {
                state = abi.decode(output, (bytes[]));
            } else {
                require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds");
                // Check the first field is 0x20 (because we have only a single return value)
                uint256 argPtr;
                assembly {
                    argPtr := mload(add(output, 32))
                }
                require(
                    argPtr == 32,
                    "Only one return value permitted (variable)"
                );

                assembly {
                    // Overwrite the first word of the return data with the length - 32
                    mstore(add(output, 32), sub(mload(output), 32))
                    // Insert a pointer to the return data, starting at the second word, into state
                    mstore(
                        add(add(state, 32), mul(and(idx, IDX_VALUE_MASK), 32)),
                        add(output, 32)
                    )
                }
            }
        } else {
            require(idx & IDX_VALUE_MASK < state.length, "Index out-of-bounds");
            // Single word
            require(
                output.length == 32,
                "Only one return value permitted (static)"
            );

            state[idx & IDX_VALUE_MASK] = output;
        }

        return state;
    }

    function writeTuple(
        bytes[] memory state,
        bytes1 index,
        bytes memory output
    ) internal view {
        uint256 idx = uint8(index);
        if (idx == IDX_END_OF_ARGS) return;

        bytes memory entry = state[idx & IDX_VALUE_MASK] = new bytes(output.length + 32);
        memcpy(output, 0, entry, 32, output.length);
        assembly {
            let l := mload(output)
            mstore(add(entry, 32), l)
        }
    }

    function memcpy(
        bytes memory src,
        uint256 srcIdx,
        bytes memory dest,
        uint256 destIdx,
        uint256 len
    ) internal view {
        assembly {
            pop(
                staticcall(
                    gas(),
                    4,
                    add(add(src, 32), srcIdx),
                    len,
                    add(add(dest, 32), destIdx),
                    len
                )
            )
        }
    }
}

File 9 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../token/ERC20/IERC20.sol";

File 10 of 11 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../utils/introspection/IERC165.sol";

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Settings
{
  "remappings": [
    "@ensdomains/=lib/shortcuts-contracts/node_modules/@ensdomains/",
    "@ensofinance/=lib/shortcuts-contracts/node_modules/@ensofinance/",
    "@layerzerolabs/oapp-evm/=lib/devtools/packages/oapp-evm/",
    "@layerzerolabs/lz-evm-protocol-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/protocol/",
    "@layerzerolabs/lz-evm-oapp-v2/=lib/layerzero-v2/packages/layerzero-v2/evm/oapp/",
    "@openzeppelin/=lib/shortcuts-contracts/node_modules/@openzeppelin/",
    "@rari-capital/=lib/shortcuts-contracts/node_modules/@rari-capital/",
    "@uniswap/v4-core/=lib/v4-core/",
    "@uniswap/v4-periphery/=lib/v4-periphery/",
    "clones-with-immutable-args/=lib/shortcuts-contracts/node_modules/clones-with-immutable-args/",
    "devtools/=lib/devtools/packages/toolbox-foundry/src/",
    "ds-test/=lib/forge-std/lib/ds-test/src/",
    "enso-weiroll/=lib/enso-weiroll/contracts/",
    "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
    "eth-gas-reporter/=lib/shortcuts-contracts/node_modules/eth-gas-reporter/",
    "forge-std/=lib/forge-std/src/",
    "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
    "hardhat-deploy/=lib/shortcuts-contracts/node_modules/hardhat-deploy/",
    "hardhat/=lib/shortcuts-contracts/node_modules/hardhat/",
    "layerzero-v2/=lib/layerzero-v2/",
    "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
    "safe-contracts/=lib/safe-tools/lib/safe-contracts/contracts/",
    "safe-tools/=lib/safe-tools/src/",
    "shortcuts-contracts/=lib/shortcuts-contracts/contracts/",
    "solady/=lib/solady/src/",
    "solmate/=lib/solady/lib/solmate/src/",
    "forge-gas-snapshot/=lib/v4-periphery/lib/permit2/lib/forge-gas-snapshot/src/",
    "permit2/=lib/v4-periphery/lib/permit2/",
    "v4-core/=lib/v4-core/src/",
    "v4-periphery/=lib/v4-periphery/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "ipfs",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "cancun",
  "viaIR": true,
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"_endpoint","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"uint256","name":"command_index","type":"uint256"},{"internalType":"address","name":"target","type":"address"},{"internalType":"string","name":"message","type":"string"}],"name":"ExecutionFailed","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"NotEndpoint","type":"error"},{"inputs":[],"name":"NotSelf","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[{"internalType":"bytes32","name":"guid","type":"bytes32"},{"internalType":"address","name":"receiver","type":"address"}],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"ShortcutExecutionFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"guid","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"requestId","type":"bytes32"}],"name":"ShortcutExecutionSuccessful","type":"event"},{"inputs":[],"name":"endpoint","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"commands","type":"bytes32[]"},{"internalType":"bytes[]","name":"state","type":"bytes[]"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"bytes32","name":"_guid","type":"bytes32"},{"internalType":"bytes","name":"_message","type":"bytes"},{"internalType":"address","name":"","type":"address"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"lzCompose","outputs":[],"stateMutability":"payable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a034606c57601f6116b838819003918201601f19168301916001600160401b03831184841017607057808492602094604052833981010312606c57516001600160a01b0381168103606c576080526040516116339081610085823960805181818160ac015261026e0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c80635e280f111461025c578063d0a10260146100445763de792d5f0361000e57610419565b60a03660031901126102455761005b6004356102aa565b6024356044356001600160401b0381116102455761007d9036906004016102bb565b906100896064356102aa565b6084356001600160401b038111610245576100a89036906004016102bb565b50507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03163303610249576100f66100e78383610a3c565b6020808251830101910161054d565b6001600160a01b039384169694909316949290303b156102455760405163de792d5f60e01b8152915f9183918291610132919060048401610688565b038183305af1908161022b575b506101e5576040805187815260208101929092526101829392917f22dfddf5479c684e1f8632e9adc62bd8c7066889e9b9045efb5d7331c37e861a9190a1610a58565b9073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036101d857505f80808093855af16101af6106d7565b50156101b757005b631cb7af6160e21b5f526004919091526001600160a01b031660245260445ffd5b6100189350919091610a67565b6040805196875260208701919091527f181a2c8dd5838ebdd373894af59f9e0689378ae0014ac13113d50110a549ca26959450849350830191506102269050565b0390a1005b806102395f61023f936102fc565b806102a0565b8761013f565b5f80fd5b6339e7e94b60e01b5f523360045260245ffd5b34610245575f366003190112610245577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166080908152602090f35b5f91031261024557565b6001600160a01b0381160361024557565b9181601f84011215610245578235916001600160401b038311610245576020838186019501011161024557565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761031d57604052565b6102e8565b6001600160401b03811161031d5760051b60200190565b6001600160401b03811161031d57601f01601f191660200190565b92919261036082610339565b9161036e60405193846102fc565b829481845281830111610245578281602093845f960137010152565b81601f82011215610245578035906103a182610322565b926103af60405194856102fc565b82845260208085019360051b830101918183116102455760208101935b8385106103db57505050505090565b84356001600160401b03811161024557820183603f820112156102455760209161040e8583604086809601359101610354565b8152019401936103cc565b34610245576040366003190112610245576004356001600160401b0381116102455736602382011215610245578060040135906001600160401b038211610245573660248360051b8301011161024557602435916001600160401b03831161024557602461048e61001894369060040161038a565b9201610706565b9080601f83011215610245578151916104ad83610322565b926104bb60405194856102fc565b80845260208085019160051b830101918383116102455760208101915b8383106104e757505050505090565b82516001600160401b03811161024557820185603f820112156102455760208101519161051383610339565b61052060405191826102fc565b8381526040838501018810610245575f602085819660408397018386015e830101528152019201916104d8565b91909160a081840312610245578051610565816102aa565b926020820151610574816102aa565b9260408301519260608101516001600160401b03811161024557810183601f82011215610245578051906105a782610322565b916105b560405193846102fc565b80835260208084019160051b8301019186831161024557602001905b8282106105fc575050509260808201516001600160401b038111610245576105f99201610495565b90565b81518152602091820191016105d1565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9080602083519182815201916020808360051b8301019401925f915b83831061065b57505050505090565b9091929394602080610679600193601f19868203018752895161060c565b9701930193019193929061064c565b9291604084019360408152825180955260206060820193015f955b8087106106bf5750506105f99394506020818403910152610630565b909360208060019287518152019501960195906106a3565b3d15610701573d906106e882610339565b916106f660405193846102fc565b82523d5f602084013e565b606090565b91303303610a2d575f905b82821061071e5750505050565b610729828486610b14565b359161075761075161074b61073e8660201b90565b6001600160f81b03191690565b60f81c90565b60ff1690565b9060408216159081610a175760010191610772838789610b14565b356020905b60038316600181036108d257505f91829190602085166108bb576107a6916001600160e01b03198a1689610c9b565b805190602001826001600160a01b038a165af1916107c26106d7565b925b83901561081d575050608016156107fc576107f0906107ea61073e6107f6959660581b90565b856110f0565b60010190565b90610711565b6107f69261081161073e610817949660581b90565b90611045565b916107f0565b869394925061082a610bda565b94604481511161087a575b505090610867915f1461086b57925b60405163ef3dcb2f60e01b81529384936001600160a01b03169060048501610bff565b0390fd5b61087490610bb8565b92610844565b6020610891600461088a84610ec8565b9301610b82565b03610835576108a260248301610b82565b146108ae575b80610835565b60440193506108676108a8565b50607f6108cc9160f81c1687610b29565b516107a6565b6002810361093557505f918291906020851661091e576108fd916001600160e01b03198a1689610c9b565b8051906020016001600160a01b0389165afa916109186106d7565b926107c4565b50607f61092f9160f81c1687610b29565b516108fd565b6003036109df575f9181610966610953607f869560f81c168a610b29565b516109616020825114610b3d565b610b82565b91602086161584146109b85761098861098261099a9360081b90565b91610bb8565b906001600160e01b03198b168a610c9b565b905b815191602001906001600160a01b038a165af1916109186106d7565b50607f6109d161075161074b61073e6109d89560081b90565b1688610b29565b519061099c565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b916006602886901b6001600160d01b0317610777565b6314e1dbf760e11b5f5260045ffd5b9080604c11610245576105f9913691604b190190604c01610354565b90602c1161024557600c013590565b60405163a9059cbb60e01b60208281019182526001600160a01b03909416602483015260448083019590955293815290925f91610aa56064826102fc565b519082855af115610af5575f513d610aec57506001600160a01b0381163b155b610acc5750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415610ac5565b6040513d5f823e3d90fd5b634e487b7160e01b5f52603260045260245ffd5b9190811015610b245760051b0190565b610b00565b8051821015610b245760209160051b010190565b15610b4457565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b602081519101519060208110610b96575090565b5f199060200360031b1b1690565b634e487b7160e01b5f52601160045260245ffd5b5f19810191908211610bc657565b610ba4565b601f19810191908211610bc657565b60405190610be96040836102fc565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b0390911660208201526060604082018190526105f99291019061060c565b6040516101609190610c3983826102fc565b600a815291601f1901366020840137565b9060206105f9928181520190610630565b9060048201809211610bc657565b90610c7382610339565b610c8060405191826102fc565b8281528092610c91601f1991610339565b0190602036910137565b91939290935f5f915f92610cad610c27565b906060935f905b878210610e09575b5050610cca610ccf91610c5b565b610c69565b9760208901525f9060248901925f955b878710610cf157505050505050505050565b6020871015610b2457888b83891a6080811615610de75760fe8103610d4c575050506020816001928752610d398d610d2883610c5b565b610d328b51610bcb565b918b61129e565b875101601f1901955b0196019593610cdf565b60fd819794959697145f14610d81575092610d7592868660019b948a9998978560209c526113f4565b50979195909594610d42565b60fc8103610da3575092610d7592868660019b948a9998978560209c526112b0565b93610de0888293610dcf602096607f6001999c9b9a1690610dc48282610b29565b515197889552610b29565b5190610dda85610c5b565b9161128c565b0195610d42565b60209250600193979150610dff607f8492168d610b29565b5101518152610d42565b909395916020851015610b245786851a60ff8114610eb4576080811615610e9f5760fe8103610e7f5750855115610e4f575b6020600191875101935b0196940190610cb4565b945060016020604051610e7681610e688d858301610c4a565b03601f1981018352826102fc565b96915050610e3b565b90610e939260019692602095968a8d6111bd565b95919390939294610e45565b610eae6020916001938c61114a565b93610e45565b509396509094929050610cca610ccf610cbc565b9081516043198101818111610bc6579260445b828110610ee757505050565b8151811015610b2457818101602001516001600160f81b03191615610f0e57600101610edb565b92935050506043198101908111610bc65790565b15610f2957565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15610f6b57565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b15610fc857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b906020828203126102455781516001600160401b038111610245576105f99201610495565b91908060f81c60ff81146110ea5760808116156110b25760fe810361107a5750506105f9915060208082518301019101611020565b602091611090610fe092607f8751911610610f22565b828401936110a084865114610fc1565b51601f1901845260f31c168301015290565b6110e6929150607f16906110c884518310610f22565b6110d56020825114610f64565b6110df8285610b29565b5282610b29565b5090565b50505090565b9060f81c60ff81146111455782519060208201809211610bc657602092607f61111b61112e94610c69565b9216916111288383610b29565b52610b29565b51918051604084018184840160045afa5051910152565b505050565b61115b90607f602093941690610b29565b5151036111685760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd81036111dd5750956111d79596611581565b90919293565b60fc81036111f15750956111d7959661149a565b919650919493929161120691607f1690610b29565b515180151580611281575b1561121d570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611211565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9193959692905f946112c28884610b29565b51936024600180878b019b019b0198820101915b602089106112e7575b505050505050565b80891a60808116156113cb5760fb810361130157506112df565b60fd819c92959a9499969b93979c145f1461135257509061132992918b89528a858b896113f4565b9260209a93926001928c969480919d939d97929d9e01970101985b0193019792919394906112d6565b60fc810361138c57509061136d92918b89528a858b896112b0565b9260209a93926001928c969480919d939d97929d9e0197010198611344565b6020898b8e6001959f9e9798966113bf607f869716948d610dcf6113b08888610b29565b51519788978897889552610b29565b019d0197010198611344565b60206001929397969499816113e888607f999e9983961690610b29565b5101518b520198611344565b939291909495600101946020861015610b2457602061142e978161141d607f868b1a1685610b29565b5101516024828901015201946112b0565b929391929091602090910190565b1561144357565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020909601960194935f929091905b602087106115085760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b80871a60808116156115695760fb8103611530575050506115299083610b29565b5293929190565b611550949561154960fe839c949a969b959c141561143c565b888b6111bd565b9197909692939192916001906020905b019301956114af565b61157b60209160019399969a8561114a565b98611560565b9291909394600101936020851015610b245760206115a4607f83881a1686610b29565b5151036115b85760206111d796019361149a565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fdfea264697066735822122066eecdcb1f8fa494e3a2cb6e27410ed0d35093280ed09ee8711b6a4f5853f7ce64736f6c634300081c00330000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b

Deployed Bytecode

0x6080604052600436101561001a575b3615610018575f80fd5b005b5f3560e01c80635e280f111461025c578063d0a10260146100445763de792d5f0361000e57610419565b60a03660031901126102455761005b6004356102aa565b6024356044356001600160401b0381116102455761007d9036906004016102bb565b906100896064356102aa565b6084356001600160401b038111610245576100a89036906004016102bb565b50507f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03163303610249576100f66100e78383610a3c565b6020808251830101910161054d565b6001600160a01b039384169694909316949290303b156102455760405163de792d5f60e01b8152915f9183918291610132919060048401610688565b038183305af1908161022b575b506101e5576040805187815260208101929092526101829392917f22dfddf5479c684e1f8632e9adc62bd8c7066889e9b9045efb5d7331c37e861a9190a1610a58565b9073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81036101d857505f80808093855af16101af6106d7565b50156101b757005b631cb7af6160e21b5f526004919091526001600160a01b031660245260445ffd5b6100189350919091610a67565b6040805196875260208701919091527f181a2c8dd5838ebdd373894af59f9e0689378ae0014ac13113d50110a549ca26959450849350830191506102269050565b0390a1005b806102395f61023f936102fc565b806102a0565b8761013f565b5f80fd5b6339e7e94b60e01b5f523360045260245ffd5b34610245575f366003190112610245577f0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b6001600160a01b03166080908152602090f35b5f91031261024557565b6001600160a01b0381160361024557565b9181601f84011215610245578235916001600160401b038311610245576020838186019501011161024557565b634e487b7160e01b5f52604160045260245ffd5b90601f801991011681019081106001600160401b0382111761031d57604052565b6102e8565b6001600160401b03811161031d5760051b60200190565b6001600160401b03811161031d57601f01601f191660200190565b92919261036082610339565b9161036e60405193846102fc565b829481845281830111610245578281602093845f960137010152565b81601f82011215610245578035906103a182610322565b926103af60405194856102fc565b82845260208085019360051b830101918183116102455760208101935b8385106103db57505050505090565b84356001600160401b03811161024557820183603f820112156102455760209161040e8583604086809601359101610354565b8152019401936103cc565b34610245576040366003190112610245576004356001600160401b0381116102455736602382011215610245578060040135906001600160401b038211610245573660248360051b8301011161024557602435916001600160401b03831161024557602461048e61001894369060040161038a565b9201610706565b9080601f83011215610245578151916104ad83610322565b926104bb60405194856102fc565b80845260208085019160051b830101918383116102455760208101915b8383106104e757505050505090565b82516001600160401b03811161024557820185603f820112156102455760208101519161051383610339565b61052060405191826102fc565b8381526040838501018810610245575f602085819660408397018386015e830101528152019201916104d8565b91909160a081840312610245578051610565816102aa565b926020820151610574816102aa565b9260408301519260608101516001600160401b03811161024557810183601f82011215610245578051906105a782610322565b916105b560405193846102fc565b80835260208084019160051b8301019186831161024557602001905b8282106105fc575050509260808201516001600160401b038111610245576105f99201610495565b90565b81518152602091820191016105d1565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b9080602083519182815201916020808360051b8301019401925f915b83831061065b57505050505090565b9091929394602080610679600193601f19868203018752895161060c565b9701930193019193929061064c565b9291604084019360408152825180955260206060820193015f955b8087106106bf5750506105f99394506020818403910152610630565b909360208060019287518152019501960195906106a3565b3d15610701573d906106e882610339565b916106f660405193846102fc565b82523d5f602084013e565b606090565b91303303610a2d575f905b82821061071e5750505050565b610729828486610b14565b359161075761075161074b61073e8660201b90565b6001600160f81b03191690565b60f81c90565b60ff1690565b9060408216159081610a175760010191610772838789610b14565b356020905b60038316600181036108d257505f91829190602085166108bb576107a6916001600160e01b03198a1689610c9b565b805190602001826001600160a01b038a165af1916107c26106d7565b925b83901561081d575050608016156107fc576107f0906107ea61073e6107f6959660581b90565b856110f0565b60010190565b90610711565b6107f69261081161073e610817949660581b90565b90611045565b916107f0565b869394925061082a610bda565b94604481511161087a575b505090610867915f1461086b57925b60405163ef3dcb2f60e01b81529384936001600160a01b03169060048501610bff565b0390fd5b61087490610bb8565b92610844565b6020610891600461088a84610ec8565b9301610b82565b03610835576108a260248301610b82565b146108ae575b80610835565b60440193506108676108a8565b50607f6108cc9160f81c1687610b29565b516107a6565b6002810361093557505f918291906020851661091e576108fd916001600160e01b03198a1689610c9b565b8051906020016001600160a01b0389165afa916109186106d7565b926107c4565b50607f61092f9160f81c1687610b29565b516108fd565b6003036109df575f9181610966610953607f869560f81c168a610b29565b516109616020825114610b3d565b610b82565b91602086161584146109b85761098861098261099a9360081b90565b91610bb8565b906001600160e01b03198b168a610c9b565b905b815191602001906001600160a01b038a165af1916109186106d7565b50607f6109d161075161074b61073e6109d89560081b90565b1688610b29565b519061099c565b60405162461bcd60e51b815260206004820152601060248201526f496e76616c69642063616c6c7479706560801b6044820152606490fd5b916006602886901b6001600160d01b0317610777565b6314e1dbf760e11b5f5260045ffd5b9080604c11610245576105f9913691604b190190604c01610354565b90602c1161024557600c013590565b60405163a9059cbb60e01b60208281019182526001600160a01b03909416602483015260448083019590955293815290925f91610aa56064826102fc565b519082855af115610af5575f513d610aec57506001600160a01b0381163b155b610acc5750565b635274afe760e01b5f9081526001600160a01b0391909116600452602490fd5b60011415610ac5565b6040513d5f823e3d90fd5b634e487b7160e01b5f52603260045260245ffd5b9190811015610b245760051b0190565b610b00565b8051821015610b245760209160051b010190565b15610b4457565b60405162461bcd60e51b815260206004820152601660248201527556616c7565206d75737420626520333220627974657360501b6044820152606490fd5b602081519101519060208110610b96575090565b5f199060200360031b1b1690565b634e487b7160e01b5f52601160045260245ffd5b5f19810191908211610bc657565b610ba4565b601f19810191908211610bc657565b60405190610be96040836102fc565b60078252662ab735b737bbb760c91b6020830152565b9081526001600160a01b0390911660208201526060604082018190526105f99291019061060c565b6040516101609190610c3983826102fc565b600a815291601f1901366020840137565b9060206105f9928181520190610630565b9060048201809211610bc657565b90610c7382610339565b610c8060405191826102fc565b8281528092610c91601f1991610339565b0190602036910137565b91939290935f5f915f92610cad610c27565b906060935f905b878210610e09575b5050610cca610ccf91610c5b565b610c69565b9760208901525f9060248901925f955b878710610cf157505050505050505050565b6020871015610b2457888b83891a6080811615610de75760fe8103610d4c575050506020816001928752610d398d610d2883610c5b565b610d328b51610bcb565b918b61129e565b875101601f1901955b0196019593610cdf565b60fd819794959697145f14610d81575092610d7592868660019b948a9998978560209c526113f4565b50979195909594610d42565b60fc8103610da3575092610d7592868660019b948a9998978560209c526112b0565b93610de0888293610dcf602096607f6001999c9b9a1690610dc48282610b29565b515197889552610b29565b5190610dda85610c5b565b9161128c565b0195610d42565b60209250600193979150610dff607f8492168d610b29565b5101518152610d42565b909395916020851015610b245786851a60ff8114610eb4576080811615610e9f5760fe8103610e7f5750855115610e4f575b6020600191875101935b0196940190610cb4565b945060016020604051610e7681610e688d858301610c4a565b03601f1981018352826102fc565b96915050610e3b565b90610e939260019692602095968a8d6111bd565b95919390939294610e45565b610eae6020916001938c61114a565b93610e45565b509396509094929050610cca610ccf610cbc565b9081516043198101818111610bc6579260445b828110610ee757505050565b8151811015610b2457818101602001516001600160f81b03191615610f0e57600101610edb565b92935050506043198101908111610bc65790565b15610f2957565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f75742d6f662d626f756e647360681b6044820152606490fd5b15610f6b57565b60405162461bcd60e51b815260206004820152602860248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015267287374617469632960c01b6064820152608490fd5b15610fc857565b60405162461bcd60e51b815260206004820152602a60248201527f4f6e6c79206f6e652072657475726e2076616c7565207065726d697474656420604482015269287661726961626c652960b01b6064820152608490fd5b906020828203126102455781516001600160401b038111610245576105f99201610495565b91908060f81c60ff81146110ea5760808116156110b25760fe810361107a5750506105f9915060208082518301019101611020565b602091611090610fe092607f8751911610610f22565b828401936110a084865114610fc1565b51601f1901845260f31c168301015290565b6110e6929150607f16906110c884518310610f22565b6110d56020825114610f64565b6110df8285610b29565b5282610b29565b5090565b50505090565b9060f81c60ff81146111455782519060208201809211610bc657602092607f61111b61112e94610c69565b9216916111288383610b29565b52610b29565b51918051604084018184840160045afa5051910152565b505050565b61115b90607f602093941690610b29565b5151036111685760200190565b60405162461bcd60e51b815260206004820152602760248201527f537461746963207374617465207661726961626c6573206d75737420626520336044820152663220627974657360c81b6064820152608490fd5b90969594939260fd81036111dd5750956111d79596611581565b90919293565b60fc81036111f15750956111d7959661149a565b919650919493929161120691607f1690610b29565b515180151580611281575b1561121d570160200191565b60405162461bcd60e51b815260206004820152603660248201527f44796e616d6963207374617465207661726961626c6573206d7573742062652060448201527561206d756c7469706c65206f6620333220627974657360501b6064820152608490fd5b50601f811615611211565b916020809185930101920160045afa50565b910160200190829060400160045afa50565b9193959692905f946112c28884610b29565b51936024600180878b019b019b0198820101915b602089106112e7575b505050505050565b80891a60808116156113cb5760fb810361130157506112df565b60fd819c92959a9499969b93979c145f1461135257509061132992918b89528a858b896113f4565b9260209a93926001928c969480919d939d97929d9e01970101985b0193019792919394906112d6565b60fc810361138c57509061136d92918b89528a858b896112b0565b9260209a93926001928c969480919d939d97929d9e0197010198611344565b6020898b8e6001959f9e9798966113bf607f869716948d610dcf6113b08888610b29565b51519788978897889552610b29565b019d0197010198611344565b60206001929397969499816113e888607f999e9983961690610b29565b5101518b520198611344565b939291909495600101946020861015610b2457602061142e978161141d607f868b1a1685610b29565b5101516024828901015201946112b0565b929391929091602090910190565b1561144357565b60405162461bcd60e51b815260206004820152602960248201527f43616e6e6f74207573652073746174652066726f6d20696e736964652064796e604482015268616d6963207479706560b81b6064820152608490fd5b6001808501976020909601960194935f929091905b602087106115085760405162461bcd60e51b8152602060048201526024808201527f44796e616d6963207479706520776173206e6f742070726f7065726c7920636c6044820152631bdcd95960e21b6064820152608490fd5b80871a60808116156115695760fb8103611530575050506115299083610b29565b5293929190565b611550949561154960fe839c949a969b959c141561143c565b888b6111bd565b9197909692939192916001906020905b019301956114af565b61157b60209160019399969a8561114a565b98611560565b9291909394600101936020851015610b245760206115a4607f83881a1686610b29565b5151036115b85760206111d796019361149a565b60405162461bcd60e51b815260206004820152601d60248201527f4172726179206c656e677468206d7573742062652033322062797465730000006044820152606490fdfea264697066735822122066eecdcb1f8fa494e3a2cb6e27410ed0d35093280ed09ee8711b6a4f5853f7ce64736f6c634300081c0033

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

0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b

-----Decoded View---------------
Arg [0] : _endpoint (address): 0x6F475642a6e85809B1c36Fa62763669b1b48DD5B

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000006f475642a6e85809b1c36fa62763669b1b48dd5b


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.