Holesky Testnet

Contract

0xdC7Fc18f0f12cbE67E7D1CBc1f3940F7ea5b4E65

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Submit33479992025-02-14 1:59:4864 days ago1739498388IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000015250.001
Submit33479902025-02-14 1:58:0064 days ago1739498280IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33426992025-02-13 6:58:2465 days ago1739429904IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100003
Submit33426342025-02-13 6:44:3665 days ago1739429076IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000015860.00100002
Submit33426342025-02-13 6:44:3665 days ago1739429076IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000015860.00100002
Submit33425282025-02-13 6:21:4865 days ago1739427708IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33425282025-02-13 6:21:4865 days ago1739427708IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33425282025-02-13 6:21:4865 days ago1739427708IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33425282025-02-13 6:21:4865 days ago1739427708IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33425282025-02-13 6:21:4865 days ago1739427708IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000017150.00100001
Submit33425272025-02-13 6:21:3665 days ago1739427696IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000015250.00100001
Submit33424792025-02-13 6:11:2465 days ago1739427084IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424792025-02-13 6:11:2465 days ago1739427084IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424792025-02-13 6:11:2465 days ago1739427084IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424792025-02-13 6:11:2465 days ago1739427084IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424762025-02-13 6:10:4865 days ago1739427048IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100001
Submit33424762025-02-13 6:10:4865 days ago1739427048IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100001
Submit33424762025-02-13 6:10:4865 days ago1739427048IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100001
Submit33424492025-02-13 6:04:4865 days ago1739426688IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424492025-02-13 6:04:4865 days ago1739426688IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000016490.00100002
Submit33424422025-02-13 6:03:0065 days ago1739426580IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000013560.00100002
Submit33424422025-02-13 6:03:0065 days ago1739426580IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000013560.00100002
Submit33424402025-02-13 6:02:3665 days ago1739426556IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000012050.00100002
Submit33424402025-02-13 6:02:3665 days ago1739426556IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000012050.00100002
Submit33424392025-02-13 6:02:2465 days ago1739426544IN
0xdC7Fc18f...7ea5b4E65
0 ETH0.000010720.00100002
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BundleHelper

Compiler Version
v0.8.26+commit.8a97fa7a

Optimization Enabled:
Yes with 200 runs

Other Settings:
cancun EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 19 : BundleHelper.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.26;

import {Zenith} from "zenith/src/Zenith.sol";
import {UsesPermit2} from "zenith/src/UsesPermit2.sol";
import {HostOrders} from "zenith/src/orders/HostOrders.sol";
import {IOrders} from "zenith/src/orders/IOrders.sol";
import {OrdersPermit2} from "zenith/src/orders/OrdersPermit2.sol";

contract BundleHelper {
    Zenith public immutable zenith;
    HostOrders public immutable orders;

    struct FillPermit2 {
        HostOrders.Output[] outputs;
        UsesPermit2.Permit2Batch permit2;
    }

    constructor(address _zenith, address _orders) {
        zenith = Zenith(_zenith);
        orders = HostOrders(_orders);
    }

    function submit(FillPermit2[] memory fills, Zenith.BlockHeader memory header, uint8 v, bytes32 r, bytes32 s)
        external
    {
        // submit fills
        for (uint256 i = 0; i < fills.length; i++) {
            orders.fillPermit2(fills[i].outputs, fills[i].permit2);
        }
        // submit block
        zenith.submitBlock(header, v, r, s, "");
    }
}

File 2 of 19 : Zenith.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

contract Zenith {
    /// @notice The address that is allowed to set/remove sequencers.
    address public immutable sequencerAdmin;

    /// @notice The block number at which the Zenith contract was deployed.
    uint256 public deployBlockNumber;

    /// @notice Block header information for the rollup block, signed by the sequencer.
    /// @param rollupChainId - the chainId of the rollup chain. Any chainId is accepted by the contract.
    /// @param hostBlockNumber - the host block number in which the rollup block must be submitted. Enforced by the contract.
    /// @param gasLimit - the gas limit for the rollup block. Ignored by the contract; enforced by the Node.
    /// @param rewardAddress - the address to receive the rollup block reward. Ignored by the contract; enforced by the Node.
    /// @param blockDataHash - keccak256(rlp-encoded transactions). the Node will discard the block if the hash doens't match.
    ///                        this allows the sequencer to sign over finalized set of transactions,
    ///                        without the Zenith contract needing to interact with raw transaction data (which may be provided via blobs or calldata).
    struct BlockHeader {
        uint256 rollupChainId;
        uint256 hostBlockNumber;
        uint256 gasLimit;
        address rewardAddress;
        bytes32 blockDataHash;
    }

    /// @notice The host block number that a block was last submitted at for a given rollup chainId.
    /// rollupChainId => host blockNumber that block was last submitted at
    mapping(uint256 => uint256) public lastSubmittedAtBlock;

    /// @notice Registry of permissioned sequencers.
    /// address => TRUE if it's a permissioned sequencer
    mapping(address => bool) public isSequencer;

    /// @notice Thrown when a block submission is attempted in the incorrect host block.
    error IncorrectHostBlock();

    /// @notice Thrown when a block submission is attempted with a signature by a non-permissioned sequencer,
    ///         OR when signature is produced over different block header than is provided.
    /// @param derivedSequencer - the derived signer of the block header that is not a permissioned sequencer.
    error BadSignature(address derivedSequencer);

    /// @notice Thrown when attempting to submit more than one rollup block per host block
    error OneRollupBlockPerHostBlock();

    /// @notice Thrown when attempting to modify sequencer roles if not sequencerAdmin.
    error OnlySequencerAdmin();

    /// @notice Emitted when a new rollup block is successfully submitted.
    /// @param sequencer - the address of the sequencer that signed the block.
    /// @param rollupChainId - the chainId of the rollup chain.
    /// @param gasLimit - the gas limit for the rollup block.
    /// @param rewardAddress - the address to receive the rollup block reward.
    /// @param blockDataHash - keccak256(rlp-encoded transactions). the Node will discard the block if the hash doens't match transactions provided.
    /// @dev including blockDataHash allows the sequencer to sign over finalized block data, without needing to calldatacopy the `blockData` param.
    event BlockSubmitted(
        address indexed sequencer,
        uint256 indexed rollupChainId,
        uint256 gasLimit,
        address rewardAddress,
        bytes32 blockDataHash
    );

    /// @notice Emitted when a sequencer is added or removed.
    event SequencerSet(address indexed sequencer, bool indexed permissioned);

    constructor(address _sequencerAdmin) {
        sequencerAdmin = _sequencerAdmin;
        deployBlockNumber = block.number;
    }

    /// @notice Add a sequencer to the permissioned sequencer list.
    /// @param sequencer - the address of the sequencer to add.
    /// @custom:emits SequencerSet if the sequencer is added.
    /// @custom:reverts OnlySequencerAdmin if the caller is not the sequencerAdmin.
    function addSequencer(address sequencer) external {
        if (msg.sender != sequencerAdmin) revert OnlySequencerAdmin();
        if (isSequencer[sequencer]) return;
        isSequencer[sequencer] = true;
        emit SequencerSet(sequencer, true);
    }

    /// @notice Remove a sequencer from the permissioned sequencer list.
    /// @param sequencer - the address of the sequencer to remove.
    /// @custom:emits SequencerSet if the sequencer is removed.
    /// @custom:reverts OnlySequencerAdmin if the caller is not the sequencerAdmin.
    function removeSequencer(address sequencer) external {
        if (msg.sender != sequencerAdmin) revert OnlySequencerAdmin();
        if (!isSequencer[sequencer]) return;
        delete isSequencer[sequencer];
        emit SequencerSet(sequencer, false);
    }

    /// @notice Submit a rollup block.
    /// @dev Blocks are submitted by Builders, with an attestation to the block signed by a Sequencer.
    /// @param header - the header information for the rollup block.
    /// @param v - the v component of the Sequencer's ECSDA signature over the block header.
    /// @param r - the r component of the Sequencer's ECSDA signature over the block header.
    /// @param s - the s component of the Sequencer's ECSDA signature over the block header.
    /// @custom:reverts IncorrectHostBlock if the hostBlockNumber does not match the current block.
    /// @custom:reverts BadSignature if the signer is not a permissioned sequencer,
    ///                 OR if the signature provided commits to a different header.
    /// @custom:reverts OneRollupBlockPerHostBlock if attempting to submit a second rollup block within one host block.
    /// @custom:emits BlockSubmitted if the block is successfully submitted.
    function submitBlock(BlockHeader memory header, uint8 v, bytes32 r, bytes32 s, bytes calldata) external {
        // assert that the host block number matches the current block
        if (block.number != header.hostBlockNumber) revert IncorrectHostBlock();

        // derive sequencer from signature over block header
        bytes32 blockCommit = blockCommitment(header);
        address sequencer = ecrecover(blockCommit, v, r, s);

        // assert that signature is valid && sequencer is permissioned
        if (sequencer == address(0) || !isSequencer[sequencer]) revert BadSignature(sequencer);

        // assert this is the first rollup block submitted for this host block
        if (lastSubmittedAtBlock[header.rollupChainId] == block.number) revert OneRollupBlockPerHostBlock();
        lastSubmittedAtBlock[header.rollupChainId] = block.number;

        // emit event
        emit BlockSubmitted(
            sequencer, header.rollupChainId, header.gasLimit, header.rewardAddress, header.blockDataHash
        );
    }

    /// @notice Construct hash of block details that the sequencer signs.
    /// @param header - the header information for the rollup block.
    /// @return commit - the hash of the encoded block details.
    function blockCommitment(BlockHeader memory header) public view returns (bytes32 commit) {
        bytes memory encoded = abi.encodePacked(
            "init4.sequencer.v0",
            block.chainid,
            header.rollupChainId,
            header.hostBlockNumber,
            header.gasLimit,
            header.rewardAddress,
            header.blockDataHash
        );
        commit = keccak256(encoded);
    }
}

File 3 of 19 : UsesPermit2.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {IOrders} from "./orders/IOrders.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

abstract contract UsesPermit2 {
    /// @param permit - the permit2 single token transfer details. includes a `deadline` and an unordered `nonce`.
    /// @param signer - the signer of the permit2 info; the owner of the tokens.
    /// @param signature - the signature over the permit + witness.
    struct Permit2 {
        ISignatureTransfer.PermitTransferFrom permit;
        address owner;
        bytes signature;
    }

    /// @param permit - the permit2 batch token transfer details. includes a `deadline` and an unordered `nonce`.
    /// @param signer - the signer of the permit2 info; the owner of the tokens.
    /// @param signature - the signature over the permit + witness.
    struct Permit2Batch {
        ISignatureTransfer.PermitBatchTransferFrom permit;
        address owner;
        bytes signature;
    }

    /// @notice Struct to hold the pre-hashed witness field and the witness type string.
    struct Witness {
        bytes32 witnessHash;
        string witnessTypeString;
    }

    /// @notice The Permit2 contract address.
    address immutable permit2Contract;

    constructor(address _permit2) {
        permit2Contract = _permit2;
    }
}

File 4 of 19 : HostOrders.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {OrderDestination} from "./OrderDestination.sol";
import {UsesPermit2} from "../UsesPermit2.sol";

contract HostOrders is OrderDestination {
    constructor(address _permit2) UsesPermit2(_permit2) {}
}

File 5 of 19 : IOrders.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

interface IOrders {
    /// @notice Tokens sent by the swapper as inputs to the order
    /// @dev From ERC-7683
    struct Input {
        /// @dev The address of the ERC20 token on the origin chain
        address token;
        /// @dev The amount of the token to be sent
        uint256 amount;
    }

    /// @notice Tokens that must be receive for a valid order fulfillment
    /// @dev From ERC-7683
    struct Output {
        /// @dev The address of the ERC20 token on the destination chain
        /// @dev address(0) used as a sentinel for the native token
        address token;
        /// @dev The amount of the token to be sent
        uint256 amount;
        /// @dev The address to receive the output tokens
        address recipient;
        /// @dev When emitted on the origin chain, the destination chain for the Output.
        ///      When emitted on the destination chain, the origin chain for the Order containing the Output.
        uint32 chainId;
    }
}

File 6 of 19 : OrdersPermit2.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {IOrders} from "./IOrders.sol";
import {UsesPermit2} from "../UsesPermit2.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

abstract contract OrdersPermit2 is UsesPermit2 {
    string constant _OUTPUT_WITNESS_TYPESTRING =
        "Output[] outputs)Output(address token,uint256 amount,address recipient,uint32 chainId)TokenPermissions(address token,uint256 amount)";

    bytes32 constant _OUTPUT_TYPEHASH =
        keccak256("Output(address token,uint256 amount,address recipient,uint32 chainId)");

    /// @notice Thrown when a signed Output does not match the corresponding TokenPermissions.
    error OutputMismatch();

    /// @notice Encode the Output array according to EIP-712 for use as a permit2 witness.
    /// @param outputs - the Outputs to encode.
    /// @return _witness - the encoded witness field.
    function outputWitness(IOrders.Output[] memory outputs) public pure returns (Witness memory _witness) {
        uint256 num = outputs.length;
        bytes32[] memory hashes = new bytes32[](num);
        for (uint256 i = 0; i < num; ++i) {
            hashes[i] = keccak256(abi.encode(_OUTPUT_TYPEHASH, outputs[i]));
        }
        _witness.witnessHash = keccak256(abi.encodePacked(hashes));
        _witness.witnessTypeString = _OUTPUT_WITNESS_TYPESTRING;
    }

    /// @notice Transfer a batch of tokens using permit2.
    /// @param _witness - the hashed witness and its typestring.
    /// @param transferDetails - the TokenPermissions for the transfer, generated based on the use-case (see `_initiateTransferDetails` and `_fillTransferDetails`).
    /// @param permit2 - the Permit2Batch information.
    function _permitWitnessTransferFrom(
        Witness memory _witness,
        ISignatureTransfer.SignatureTransferDetails[] memory transferDetails,
        Permit2Batch calldata permit2
    ) internal {
        ISignatureTransfer(permit2Contract).permitWitnessTransferFrom(
            permit2.permit,
            transferDetails,
            permit2.owner,
            _witness.witnessHash,
            _witness.witnessTypeString,
            permit2.signature
        );
    }

    /// @notice transform Output and TokenPermissions structs to TransferDetails structs, for passing to permit2.
    /// @dev always transfers the full permitted amount.
    /// @param outputs - the Outputs to transform.
    /// @param permitted - the TokenPermissions to transform.
    /// @return transferDetails - the SignatureTransferDetails generated.
    function _fillTransferDetails(
        IOrders.Output[] memory outputs,
        ISignatureTransfer.TokenPermissions[] calldata permitted
    ) internal pure returns (ISignatureTransfer.SignatureTransferDetails[] memory transferDetails) {
        if (permitted.length != outputs.length) revert ISignatureTransfer.LengthMismatch();
        transferDetails = new ISignatureTransfer.SignatureTransferDetails[](permitted.length);
        for (uint256 i; i < permitted.length; i++) {
            if (permitted[i].token != outputs[i].token) revert OutputMismatch();
            if (permitted[i].amount != outputs[i].amount) revert OutputMismatch();
            transferDetails[i] = ISignatureTransfer.SignatureTransferDetails(outputs[i].recipient, outputs[i].amount);
        }
    }

    /// @notice transform TokenPermissions structs to TransferDetails structs, for passing to permit2.
    /// @dev always transfers the full permitted amount.
    /// @param tokenRecipient - recipient of all the permitted tokens.
    /// @param permitted - the TokenPermissions to transform.
    /// @return transferDetails - the SignatureTransferDetails generated.
    function _initiateTransferDetails(address tokenRecipient, ISignatureTransfer.TokenPermissions[] calldata permitted)
        internal
        pure
        returns (ISignatureTransfer.SignatureTransferDetails[] memory transferDetails)
    {
        transferDetails = new ISignatureTransfer.SignatureTransferDetails[](permitted.length);
        for (uint256 i; i < permitted.length; i++) {
            transferDetails[i] = ISignatureTransfer.SignatureTransferDetails(tokenRecipient, permitted[i].amount);
        }
    }

    /// @notice transform permit2 TokenPermissions to Inputs structs, for emitting.
    /// @dev TokenPermissions and Inputs structs contain identical fields - (address token, uint256 amount).
    /// @param permitted - the TokenPermissions to transform.
    /// @return inputs - the Inputs generated.
    function _inputs(ISignatureTransfer.TokenPermissions[] calldata permitted)
        internal
        pure
        returns (IOrders.Input[] memory inputs)
    {
        inputs = new IOrders.Input[](permitted.length);
        for (uint256 i; i < permitted.length; i++) {
            inputs[i] = IOrders.Input(permitted[i].token, permitted[i].amount);
        }
    }
}

File 7 of 19 : ISignatureTransfer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {IEIP712} from "./IEIP712.sol";

/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer is IEIP712 {
    /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
    /// @param maxAmount The maximum amount a spender can request to transfer
    error InvalidAmount(uint256 maxAmount);

    /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
    /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
    error LengthMismatch();

    /// @notice Emits an event when the owner successfully invalidates an unordered nonce.
    event UnorderedNonceInvalidation(address indexed owner, uint256 word, uint256 mask);

    /// @notice The token and amount details for a transfer signed in the permit transfer signature
    struct TokenPermissions {
        // ERC20 token address
        address token;
        // the maximum amount that can be spent
        uint256 amount;
    }

    /// @notice The signed permit message for a single token transfer
    struct PermitTransferFrom {
        TokenPermissions permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice Specifies the recipient address and amount for batched transfers.
    /// @dev Recipients and amounts correspond to the index of the signed token permissions array.
    /// @dev Reverts if the requested amount is greater than the permitted signed amount.
    struct SignatureTransferDetails {
        // recipient address
        address to;
        // spender requested amount
        uint256 requestedAmount;
    }

    /// @notice Used to reconstruct the signed permit message for multiple token transfers
    /// @dev Do not need to pass in spender address as it is required that it is msg.sender
    /// @dev Note that a user still signs over a spender address
    struct PermitBatchTransferFrom {
        // the tokens and corresponding amounts permitted for a transfer
        TokenPermissions[] permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
    /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
    /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
    /// @dev It returns a uint256 bitmap
    /// @dev The index, or wordPosition is capped at type(uint248).max
    function nonceBitmap(address, uint256) external view returns (uint256);

    /// @notice Transfers a token using a signed permit message
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers a token using a signed permit message
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Invalidates the bits specified in mask for the bitmap at the word position
    /// @dev The wordPos is maxed at type(uint248).max
    /// @param wordPos A number to index the nonceBitmap at
    /// @param mask A bitmap masked against msg.sender's current bitmap at the word position
    function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}

File 8 of 19 : OrderDestination.sol
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity 0.8.26;

import {OrdersPermit2} from "./OrdersPermit2.sol";
import {IOrders} from "./IOrders.sol";
import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol";
import {Address} from "openzeppelin-contracts/contracts/utils/Address.sol";
import {ReentrancyGuardTransient} from "openzeppelin-contracts/contracts/utils/ReentrancyGuardTransient.sol";

/// @notice Contract capable of processing fulfillment of intent-based Orders.
abstract contract OrderDestination is IOrders, OrdersPermit2, ReentrancyGuardTransient {
    using SafeERC20 for IERC20;
    using Address for address payable;

    /// @notice Emitted when Order Outputs are sent to their recipients.
    /// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
    event Filled(Output[] outputs);

    /// @notice Fill any number of Order(s), by transferring their Output(s).
    /// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
    /// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
    /// @param outputs - The Outputs to be transferred.
    /// @custom:emits Filled
    function fill(Output[] memory outputs) external payable nonReentrant {
        // transfer outputs
        _transferOutputs(outputs);

        // emit
        emit Filled(outputs);
    }

    /// @notice Fill any number of Order(s), by transferring their Output(s) via permit2 signed batch transfer.
    /// @dev Can only provide ERC20 tokens as Outputs.
    /// @dev Filler may aggregate multiple Outputs with the same (`chainId`, `recipient`, `token`) into a single Output with the summed `amount`.
    /// @dev the permit2 signer is the Filler providing the Outputs.
    /// @dev the permit2 `permitted` tokens MUST match provided Outputs.
    /// @dev Filler MUST submit `fill` and `intitiate` within an atomic bundle.
    /// @dev NOTE that here, Output.chainId denotes the *origin* chainId.
    /// @param outputs - The Outputs to be transferred. signed over via permit2 witness.
    /// @param permit2 - the permit2 details, signer, and signature.
    /// @custom:emits Filled
    function fillPermit2(Output[] memory outputs, OrdersPermit2.Permit2Batch calldata permit2) external nonReentrant {
        // transfer all tokens to the Output recipients via permit2 (includes check on nonce & deadline)
        _permitWitnessTransferFrom(
            outputWitness(outputs), _fillTransferDetails(outputs, permit2.permit.permitted), permit2
        );

        // emit
        emit Filled(outputs);
    }

    /// @notice Transfer the Order Outputs to their recipients.
    function _transferOutputs(Output[] memory outputs) internal {
        uint256 value = msg.value;
        for (uint256 i; i < outputs.length; i++) {
            if (outputs[i].token == address(0)) {
                // this line should underflow if there's an attempt to spend more ETH than is attached to the transaction
                value -= outputs[i].amount;
                payable(outputs[i].recipient).sendValue(outputs[i].amount);
            } else {
                IERC20(outputs[i].token).safeTransferFrom(msg.sender, outputs[i].recipient, outputs[i].amount);
            }
        }
    }
}

File 9 of 19 : IEIP712.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IEIP712 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 10 of 19 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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);
}

File 11 of 19 : SafeERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
import {Address} from "../../../utils/Address.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 {
    using Address for address;

    /**
     * @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.
     */
    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.
     */
    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.
     */
    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).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data);
        if (returndata.length != 0 && !abi.decode(returndata, (bool))) {
            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 silents catches all reverts and returns a bool instead.
     */
    function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false
        // and not revert is the subcall reverts.

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

File 12 of 19 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

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

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert Errors.FailedCall();
        }
    }

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

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

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

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

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

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

File 13 of 19 : ReentrancyGuardTransient.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.24;

import {StorageSlot} from "./StorageSlot.sol";

/**
 * @dev Variant of {ReentrancyGuard} that uses transient storage.
 *
 * NOTE: This variant only works on networks where EIP-1153 is available.
 */
abstract contract ReentrancyGuardTransient {
    using StorageSlot for *;

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

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

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(true);
    }

    function _nonReentrantAfter() private {
        REENTRANCY_GUARD_STORAGE.asBoolean().tstore(false);
    }

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

File 14 of 19 : IERC1363.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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);
}

File 15 of 19 : Errors.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();
}

File 16 of 19 : StorageSlot.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.24;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC-1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 *
 * Since version 5.1, this library also support writing and reading value types to and from transient storage.
 *
 *  * Example using transient storage:
 * ```solidity
 * contract Lock {
 *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
 *     bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
 *
 *     modifier locked() {
 *         require(!_LOCK_SLOT.asBoolean().tload());
 *
 *         _LOCK_SLOT.asBoolean().tstore(true);
 *         _;
 *         _LOCK_SLOT.asBoolean().tstore(false);
 *     }
 * }
 * ```
 *
 * TIP: Consider using this library along with {SlotDerivation}.
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev UDVT that represent a slot holding a address.
     */
    type AddressSlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a AddressSlotType.
     */
    function asAddress(bytes32 slot) internal pure returns (AddressSlotType) {
        return AddressSlotType.wrap(slot);
    }

    /**
     * @dev UDVT that represent a slot holding a bool.
     */
    type BooleanSlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a BooleanSlotType.
     */
    function asBoolean(bytes32 slot) internal pure returns (BooleanSlotType) {
        return BooleanSlotType.wrap(slot);
    }

    /**
     * @dev UDVT that represent a slot holding a bytes32.
     */
    type Bytes32SlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Bytes32SlotType.
     */
    function asBytes32(bytes32 slot) internal pure returns (Bytes32SlotType) {
        return Bytes32SlotType.wrap(slot);
    }

    /**
     * @dev UDVT that represent a slot holding a uint256.
     */
    type Uint256SlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Uint256SlotType.
     */
    function asUint256(bytes32 slot) internal pure returns (Uint256SlotType) {
        return Uint256SlotType.wrap(slot);
    }

    /**
     * @dev UDVT that represent a slot holding a int256.
     */
    type Int256SlotType is bytes32;

    /**
     * @dev Cast an arbitrary slot to a Int256SlotType.
     */
    function asInt256(bytes32 slot) internal pure returns (Int256SlotType) {
        return Int256SlotType.wrap(slot);
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(AddressSlotType slot) internal view returns (address value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(AddressSlotType slot, address value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(BooleanSlotType slot) internal view returns (bool value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(BooleanSlotType slot, bool value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Bytes32SlotType slot) internal view returns (bytes32 value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Bytes32SlotType slot, bytes32 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Uint256SlotType slot) internal view returns (uint256 value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Uint256SlotType slot, uint256 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }

    /**
     * @dev Load the value held at location `slot` in transient storage.
     */
    function tload(Int256SlotType slot) internal view returns (int256 value) {
        /// @solidity memory-safe-assembly
        assembly {
            value := tload(slot)
        }
    }

    /**
     * @dev Store `value` at location `slot` in transient storage.
     */
    function tstore(Int256SlotType slot, int256 value) internal {
        /// @solidity memory-safe-assembly
        assembly {
            tstore(slot, value)
        }
    }
}

File 17 of 19 : 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 18 of 19 : 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";

File 19 of 19 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.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": [
    "@openzeppelin/contracts/=lib/zenith/lib/openzeppelin-contracts/contracts/",
    "ds-test/=lib/zenith/lib/forge-std/lib/ds-test/src/",
    "erc4626-tests/=lib/zenith/lib/openzeppelin-contracts/lib/erc4626-tests/",
    "forge-gas-snapshot/=lib/zenith/lib/permit2/lib/forge-gas-snapshot/src/",
    "forge-std/=lib/forge-std/src/",
    "openzeppelin-contracts/=lib/zenith/lib/openzeppelin-contracts/",
    "permit2/=lib/zenith/lib/permit2/",
    "solmate/=lib/zenith/lib/permit2/lib/solmate/",
    "zenith/=lib/zenith/"
  ],
  "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 ABI

API
[{"inputs":[{"internalType":"address","name":"_zenith","type":"address"},{"internalType":"address","name":"_orders","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"orders","outputs":[{"internalType":"contract HostOrders","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint32","name":"chainId","type":"uint32"}],"internalType":"struct IOrders.Output[]","name":"outputs","type":"tuple[]"},{"components":[{"components":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"internalType":"struct ISignatureTransfer.TokenPermissions[]","name":"permitted","type":"tuple[]"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"internalType":"struct ISignatureTransfer.PermitBatchTransferFrom","name":"permit","type":"tuple"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct UsesPermit2.Permit2Batch","name":"permit2","type":"tuple"}],"internalType":"struct BundleHelper.FillPermit2[]","name":"fills","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"rollupChainId","type":"uint256"},{"internalType":"uint256","name":"hostBlockNumber","type":"uint256"},{"internalType":"uint256","name":"gasLimit","type":"uint256"},{"internalType":"address","name":"rewardAddress","type":"address"},{"internalType":"bytes32","name":"blockDataHash","type":"bytes32"}],"internalType":"struct Zenith.BlockHeader","name":"header","type":"tuple"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"submit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"zenith","outputs":[{"internalType":"contract Zenith","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

60c034608c57601f61088038819003918201601f19168301916001600160401b038311848410176090578084926040948552833981010312608c57604b602060458360a4565b920160a4565b6001600160a01b039182166080521660a0526040516107c890816100b8823960805181818161030201526106b9015260a05181818161012301526106780152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b0382168203608c5756fe6080806040526004361015610012575f80fd5b5f3560e01c908163225c1628146106a7575080634fb764c9146106635763628db5211461003d575f80fd5b346102fa576101203660031901126102fa576004356001600160401b0381116102fa57366023820112156102fa5780600401356100798161073f565b91610087604051938461071e565b8183526024602084019260051b820101903682116102fa5760248101925b8284106103c6578460a03660231901126102fa5760405160a081018181106001600160401b038211176103b25760405260243581526020810160443581526040820160643581526084359160018060a01b03831683036102fa5760608401928352608084019060a435825260c4359160ff83168093036102fa5793947f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031694905f5b88518110156102fe57610162818a61076a565b5151906020610171828c61076a565b510151883b156102fa57916040518093630377e07560e31b8252604482016040600484015283518091526020606484019401905f905b8082106102aa575050506003198284030160248301528051906060845260c08401918051926060808701528351809152602060e087019401905f905b808210610279575050509160205f9560408694818785809901516080860152015160a084015260018060a01b0384820151168484015201519060408185039101528051918291828552018584015e8181018401869052601f01601f191601030181838c5af191821561026e5760019261025e575b500161014f565b5f6102689161071e565b8a610257565b6040513d5f823e3d90fd5b825180516001600160a01b03168752602090810151818801528a9750604090960195909201916001909101906101e3565b91935091936020608060019263ffffffff60608851868060a01b0381511684528581015186850152868060a01b0360408201511660408501520151166060820152019401920186939492916101a7565b5f80fd5b50867f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316803b156102fa575f95610144948793604051998a9889976388b673d360e01b895251600489015251602488015251604487015260018060a01b03905116606486015251608485015260a484015260e43560c48401526101043560e4840152610120610104840152816101248401525af1801561026e576103a657005b5f6103b09161071e565b005b634e487b7160e01b5f52604160045260245ffd5b83356001600160401b0381116102fa578201604060231982360301126102fa57604051906103f3826106e8565b60248101356001600160401b0381116102fa5760249082010136601f820112156102fa5780356104228161073f565b91610430604051938461071e565b81835260208084019260071b820101903682116102fa57602001915b8183106105ed57505050825260448101356001600160401b0381116102fa576024910101916060833603126102fa576040519261048884610703565b80356001600160401b0381116102fa5781016060813603126102fa57604051906104b182610703565b80356001600160401b0381116102fa57810136601f820112156102fa5780356104d98161073f565b916104e7604051938461071e565b81835260208084019260061b820101903682116102fa57602001915b8183106105b5575050509060409183526020810135602084015201356040820152845261053260208201610756565b60208501526040810135906001600160401b0382116102fa57019136601f840112156102fa578235936001600160401b0385116103b257604051610580601f8701601f19166020018261071e565b85815236602087870101116102fa575f60208781988280990183860137830101526040820152838201528152019301926100a5565b6040833603126102fa57602060409182516105cf816106e8565b6105d886610756565b81528286013583820152815201920191610503565b6080833603126102fa5760405190608082018281106001600160401b038211176103b25760405261061d84610756565b82526020840135602083015261063560408501610756565b604083015260608401359063ffffffff821682036102fa57826020926060608095015281520192019161044c565b346102fa575f3660031901126102fa576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b346102fa575f3660031901126102fa577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b604081019081106001600160401b038211176103b257604052565b606081019081106001600160401b038211176103b257604052565b90601f801991011681019081106001600160401b038211176103b257604052565b6001600160401b0381116103b25760051b60200190565b35906001600160a01b03821682036102fa57565b805182101561077e5760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220bd00dc84c7f91aa15c90a33d4bebdaa7b447af61460c6409bb427f93fb7c180d64736f6c634300081a0033000000000000000000000000f8c9d5a1b5ea87411fa72079f748441fedd0896700000000000000000000000036a0c8a503f812bd1c31996e9b73358fbed2dede

Deployed Bytecode

0x6080806040526004361015610012575f80fd5b5f3560e01c908163225c1628146106a7575080634fb764c9146106635763628db5211461003d575f80fd5b346102fa576101203660031901126102fa576004356001600160401b0381116102fa57366023820112156102fa5780600401356100798161073f565b91610087604051938461071e565b8183526024602084019260051b820101903682116102fa5760248101925b8284106103c6578460a03660231901126102fa5760405160a081018181106001600160401b038211176103b25760405260243581526020810160443581526040820160643581526084359160018060a01b03831683036102fa5760608401928352608084019060a435825260c4359160ff83168093036102fa5793947f00000000000000000000000036a0c8a503f812bd1c31996e9b73358fbed2dede6001600160a01b031694905f5b88518110156102fe57610162818a61076a565b5151906020610171828c61076a565b510151883b156102fa57916040518093630377e07560e31b8252604482016040600484015283518091526020606484019401905f905b8082106102aa575050506003198284030160248301528051906060845260c08401918051926060808701528351809152602060e087019401905f905b808210610279575050509160205f9560408694818785809901516080860152015160a084015260018060a01b0384820151168484015201519060408185039101528051918291828552018584015e8181018401869052601f01601f191601030181838c5af191821561026e5760019261025e575b500161014f565b5f6102689161071e565b8a610257565b6040513d5f823e3d90fd5b825180516001600160a01b03168752602090810151818801528a9750604090960195909201916001909101906101e3565b91935091936020608060019263ffffffff60608851868060a01b0381511684528581015186850152868060a01b0360408201511660408501520151166060820152019401920186939492916101a7565b5f80fd5b50867f000000000000000000000000f8c9d5a1b5ea87411fa72079f748441fedd089676001600160a01b0316803b156102fa575f95610144948793604051998a9889976388b673d360e01b895251600489015251602488015251604487015260018060a01b03905116606486015251608485015260a484015260e43560c48401526101043560e4840152610120610104840152816101248401525af1801561026e576103a657005b5f6103b09161071e565b005b634e487b7160e01b5f52604160045260245ffd5b83356001600160401b0381116102fa578201604060231982360301126102fa57604051906103f3826106e8565b60248101356001600160401b0381116102fa5760249082010136601f820112156102fa5780356104228161073f565b91610430604051938461071e565b81835260208084019260071b820101903682116102fa57602001915b8183106105ed57505050825260448101356001600160401b0381116102fa576024910101916060833603126102fa576040519261048884610703565b80356001600160401b0381116102fa5781016060813603126102fa57604051906104b182610703565b80356001600160401b0381116102fa57810136601f820112156102fa5780356104d98161073f565b916104e7604051938461071e565b81835260208084019260061b820101903682116102fa57602001915b8183106105b5575050509060409183526020810135602084015201356040820152845261053260208201610756565b60208501526040810135906001600160401b0382116102fa57019136601f840112156102fa578235936001600160401b0385116103b257604051610580601f8701601f19166020018261071e565b85815236602087870101116102fa575f60208781988280990183860137830101526040820152838201528152019301926100a5565b6040833603126102fa57602060409182516105cf816106e8565b6105d886610756565b81528286013583820152815201920191610503565b6080833603126102fa5760405190608082018281106001600160401b038211176103b25760405261061d84610756565b82526020840135602083015261063560408501610756565b604083015260608401359063ffffffff821682036102fa57826020926060608095015281520192019161044c565b346102fa575f3660031901126102fa576040517f00000000000000000000000036a0c8a503f812bd1c31996e9b73358fbed2dede6001600160a01b03168152602090f35b346102fa575f3660031901126102fa577f000000000000000000000000f8c9d5a1b5ea87411fa72079f748441fedd089676001600160a01b03168152602090f35b604081019081106001600160401b038211176103b257604052565b606081019081106001600160401b038211176103b257604052565b90601f801991011681019081106001600160401b038211176103b257604052565b6001600160401b0381116103b25760051b60200190565b35906001600160a01b03821682036102fa57565b805182101561077e5760209160051b010190565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220bd00dc84c7f91aa15c90a33d4bebdaa7b447af61460c6409bb427f93fb7c180d64736f6c634300081a0033

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

000000000000000000000000f8c9d5a1b5ea87411fa72079f748441fedd0896700000000000000000000000036a0c8a503f812bd1c31996e9b73358fbed2dede

-----Decoded View---------------
Arg [0] : _zenith (address): 0xf8c9D5a1B5eA87411FA72079F748441FEDD08967
Arg [1] : _orders (address): 0x36A0C8A503f812BD1c31996e9b73358fBED2Dede

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000f8c9d5a1b5ea87411fa72079f748441fedd08967
Arg [1] : 00000000000000000000000036a0c8a503f812bd1c31996e9b73358fbed2dede


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
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.