Source Code
Overview
ETH Balance
0 ETH
More Info
ContractCreator
Multichain Info
N/A
Latest 25 from a total of 4,116 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Submit | 3347999 | 64 days ago | IN | 0 ETH | 0.00001525 | ||||
Submit | 3347990 | 64 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342699 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342634 | 65 days ago | IN | 0 ETH | 0.00001586 | ||||
Submit | 3342634 | 65 days ago | IN | 0 ETH | 0.00001586 | ||||
Submit | 3342528 | 65 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342528 | 65 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342528 | 65 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342528 | 65 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342528 | 65 days ago | IN | 0 ETH | 0.00001715 | ||||
Submit | 3342527 | 65 days ago | IN | 0 ETH | 0.00001525 | ||||
Submit | 3342479 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342479 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342479 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342479 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342476 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342476 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342476 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342449 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342449 | 65 days ago | IN | 0 ETH | 0.00001649 | ||||
Submit | 3342442 | 65 days ago | IN | 0 ETH | 0.00001356 | ||||
Submit | 3342442 | 65 days ago | IN | 0 ETH | 0.00001356 | ||||
Submit | 3342440 | 65 days ago | IN | 0 ETH | 0.00001205 | ||||
Submit | 3342440 | 65 days ago | IN | 0 ETH | 0.00001205 | ||||
Submit | 3342439 | 65 days ago | IN | 0 ETH | 0.00001072 |
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)
// 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, ""); } }
// 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); } }
// 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; } }
// 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) {} }
// 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; } }
// 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); } } }
// 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; }
// 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); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.0; interface IEIP712 { function DOMAIN_SEPARATOR() external view returns (bytes32); }
// 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); }
// 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; } }
// 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(); } } }
// 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(); } }
// 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); }
// 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(); }
// 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) } } }
// 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";
// 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.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); }
{ "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"}]
Contract Creation Code
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
Loading...
Loading
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.