// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {StdStorage} from"./StdStorage.sol";
import {Vm, VmSafe} from"./Vm.sol";
abstractcontractCommonBase{
// Cheat code address, 0x7109709ECfa91a80626fF3989D68f67F5b1DD12D.addressinternalconstant VM_ADDRESS =address(uint160(uint256(keccak256("hevm cheat code"))));
// console.sol and console2.sol work by executing a staticcall to this address.addressinternalconstant CONSOLE =0x000000000000000000636F6e736F6c652e6c6f67;
// Used when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.addressinternalconstant CREATE2_FACTORY =0x4e59b44847b379578588920cA78FbF26c0B4956C;
// Default address for tx.origin and msg.sender, 0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38.addressinternalconstant DEFAULT_SENDER =address(uint160(uint256(keccak256("foundry default caller"))));
// Address of the test contract, deployed by the DEFAULT_SENDER.addressinternalconstant DEFAULT_TEST_CONTRACT =0x5615dEB798BB3E4dFa0139dFa1b3D433Cc23b72f;
// Deterministic deployment address of the Multicall3 contract.addressinternalconstant MULTICALL3_ADDRESS =0xcA11bde05977b3631167028862bE2a173976CA11;
// The order of the secp256k1 curve.uint256internalconstant SECP256K1_ORDER =115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256internalconstant UINT256_MAX =115792089237316195423570985008687907853269984665640564039457584007913129639935;
Vm internalconstant vm = Vm(VM_ADDRESS);
StdStorage internal stdstore;
}
abstractcontractTestBaseisCommonBase{}
abstractcontractScriptBaseisCommonBase{
VmSafe internalconstant vmSafe = VmSafe(VM_ADDRESS);
}
Contract Source Code
File 2 of 29: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
function_contextSuffixLength() internalviewvirtualreturns (uint256) {
return0;
}
}
Contract Source Code
File 3 of 29: ERC721A.sol
// SPDX-License-Identifier: MIT// ERC721A Contracts v4.3.0// Creator: Chiru Labspragmasolidity ^0.8.4;import'./IERC721A.sol';
/**
* @dev Interface of ERC721 token receiver.
*/interfaceERC721A__IERC721Receiver{
functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
/**
* @title ERC721A
*
* @dev Implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721)
* Non-Fungible Token Standard, including the Metadata extension.
* Optimized for lower gas during batch mints.
*
* Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...)
* starting from `_startTokenId()`.
*
* The `_sequentialUpTo()` function can be overriden to enable spot mints
* (i.e. non-consecutive mints) for `tokenId`s greater than `_sequentialUpTo()`.
*
* Assumptions:
*
* - An owner cannot have more than 2**64 - 1 (max value of uint64) of supply.
* - The maximum token ID cannot exceed 2**256 - 1 (max value of uint256).
*/contractERC721AisIERC721A{
// Bypass for a `--via-ir` bug (https://github.com/chiru-labs/ERC721A/pull/364).structTokenApprovalRef {
address value;
}
// =============================================================// CONSTANTS// =============================================================// Mask of an entry in packed address data.uint256privateconstant _BITMASK_ADDRESS_DATA_ENTRY = (1<<64) -1;
// The bit position of `numberMinted` in packed address data.uint256privateconstant _BITPOS_NUMBER_MINTED =64;
// The bit position of `numberBurned` in packed address data.uint256privateconstant _BITPOS_NUMBER_BURNED =128;
// The bit position of `aux` in packed address data.uint256privateconstant _BITPOS_AUX =192;
// Mask of all 256 bits in packed address data except the 64 bits for `aux`.uint256privateconstant _BITMASK_AUX_COMPLEMENT = (1<<192) -1;
// The bit position of `startTimestamp` in packed ownership.uint256privateconstant _BITPOS_START_TIMESTAMP =160;
// The bit mask of the `burned` bit in packed ownership.uint256privateconstant _BITMASK_BURNED =1<<224;
// The bit position of the `nextInitialized` bit in packed ownership.uint256privateconstant _BITPOS_NEXT_INITIALIZED =225;
// The bit mask of the `nextInitialized` bit in packed ownership.uint256privateconstant _BITMASK_NEXT_INITIALIZED =1<<225;
// The bit position of `extraData` in packed ownership.uint256privateconstant _BITPOS_EXTRA_DATA =232;
// Mask of all 256 bits in a packed ownership except the 24 bits for `extraData`.uint256privateconstant _BITMASK_EXTRA_DATA_COMPLEMENT = (1<<232) -1;
// The mask of the lower 160 bits for addresses.uint256privateconstant _BITMASK_ADDRESS = (1<<160) -1;
// The maximum `quantity` that can be minted with {_mintERC2309}.// This limit is to prevent overflows on the address data entries.// For a limit of 5000, a total of 3.689e15 calls to {_mintERC2309}// is required to cause an overflow, which is unrealistic.uint256privateconstant _MAX_MINT_ERC2309_QUANTITY_LIMIT =5000;
// The `Transfer` event signature is given by:// `keccak256(bytes("Transfer(address,address,uint256)"))`.bytes32privateconstant _TRANSFER_EVENT_SIGNATURE =0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
// =============================================================// STORAGE// =============================================================// The next token ID to be minted.uint256private _currentIndex;
// The number of tokens burned.uint256private _burnCounter;
// Token namestringprivate _name;
// Token symbolstringprivate _symbol;
// Mapping from token ID to ownership details// An empty struct value does not necessarily mean the token is unowned.// See {_packedOwnershipOf} implementation for details.//// Bits Layout:// - [0..159] `addr`// - [160..223] `startTimestamp`// - [224] `burned`// - [225] `nextInitialized`// - [232..255] `extraData`mapping(uint256=>uint256) private _packedOwnerships;
// Mapping owner address to address data.//// Bits Layout:// - [0..63] `balance`// - [64..127] `numberMinted`// - [128..191] `numberBurned`// - [192..255] `aux`mapping(address=>uint256) private _packedAddressData;
// Mapping from token ID to approved address.mapping(uint256=> TokenApprovalRef) private _tokenApprovals;
// Mapping from owner to operator approvalsmapping(address=>mapping(address=>bool)) private _operatorApprovals;
// The amount of tokens minted above `_sequentialUpTo()`.// We call these spot mints (i.e. non-sequential mints).uint256private _spotMinted;
// =============================================================// CONSTRUCTOR// =============================================================constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
_currentIndex = _startTokenId();
if (_sequentialUpTo() < _startTokenId()) _revert(SequentialUpToTooSmall.selector);
}
// =============================================================// TOKEN COUNTING OPERATIONS// =============================================================/**
* @dev Returns the starting token ID for sequential mints.
*
* Override this function to change the starting token ID for sequential mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/function_startTokenId() internalviewvirtualreturns (uint256) {
return0;
}
/**
* @dev Returns the maximum token ID (inclusive) for sequential mints.
*
* Override this function to return a value less than 2**256 - 1,
* but greater than `_startTokenId()`, to enable spot (non-sequential) mints.
*
* Note: The value returned must never change after any tokens have been minted.
*/function_sequentialUpTo() internalviewvirtualreturns (uint256) {
returntype(uint256).max;
}
/**
* @dev Returns the next token ID to be minted.
*/function_nextTokenId() internalviewvirtualreturns (uint256) {
return _currentIndex;
}
/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/functiontotalSupply() publicviewvirtualoverridereturns (uint256 result) {
// Counter underflow is impossible as `_burnCounter` cannot be incremented// more than `_currentIndex + _spotMinted - _startTokenId()` times.unchecked {
// With spot minting, the intermediate `result` can be temporarily negative,// and the computation must be unchecked.
result = _currentIndex - _burnCounter - _startTokenId();
if (_sequentialUpTo() !=type(uint256).max) result += _spotMinted;
}
}
/**
* @dev Returns the total amount of tokens minted in the contract.
*/function_totalMinted() internalviewvirtualreturns (uint256 result) {
// Counter underflow is impossible as `_currentIndex` does not decrement,// and it is initialized to `_startTokenId()`.unchecked {
result = _currentIndex - _startTokenId();
if (_sequentialUpTo() !=type(uint256).max) result += _spotMinted;
}
}
/**
* @dev Returns the total number of tokens burned.
*/function_totalBurned() internalviewvirtualreturns (uint256) {
return _burnCounter;
}
/**
* @dev Returns the total number of tokens that are spot-minted.
*/function_totalSpotMinted() internalviewvirtualreturns (uint256) {
return _spotMinted;
}
// =============================================================// ADDRESS DATA OPERATIONS// =============================================================/**
* @dev Returns the number of tokens in `owner`'s account.
*/functionbalanceOf(address owner) publicviewvirtualoverridereturns (uint256) {
if (owner ==address(0)) _revert(BalanceQueryForZeroAddress.selector);
return _packedAddressData[owner] & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens minted by `owner`.
*/function_numberMinted(address owner) internalviewreturns (uint256) {
return (_packedAddressData[owner] >> _BITPOS_NUMBER_MINTED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the number of tokens burned by or on behalf of `owner`.
*/function_numberBurned(address owner) internalviewreturns (uint256) {
return (_packedAddressData[owner] >> _BITPOS_NUMBER_BURNED) & _BITMASK_ADDRESS_DATA_ENTRY;
}
/**
* Returns the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
*/function_getAux(address owner) internalviewreturns (uint64) {
returnuint64(_packedAddressData[owner] >> _BITPOS_AUX);
}
/**
* Sets the auxiliary data for `owner`. (e.g. number of whitelist mint slots used).
* If there are multiple variables, please pack them into a uint64.
*/function_setAux(address owner, uint64 aux) internalvirtual{
uint256 packed = _packedAddressData[owner];
uint256 auxCasted;
// Cast `aux` with assembly to avoid redundant masking.assembly {
auxCasted := aux
}
packed = (packed & _BITMASK_AUX_COMPLEMENT) | (auxCasted << _BITPOS_AUX);
_packedAddressData[owner] = packed;
}
// =============================================================// IERC165// =============================================================/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
// The interface IDs are constants representing the first 4 bytes// of the XOR of all function selectors in the interface.// See: [ERC165](https://eips.ethereum.org/EIPS/eip-165)// (e.g. `bytes4(i.functionA.selector ^ i.functionB.selector ^ ...)`)return
interfaceId ==0x01ffc9a7||// ERC165 interface ID for ERC165.
interfaceId ==0x80ac58cd||// ERC165 interface ID for ERC721.
interfaceId ==0x5b5e139f; // ERC165 interface ID for ERC721Metadata.
}
// =============================================================// IERC721Metadata// =============================================================/**
* @dev Returns the token collection name.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev Returns the token collection symbol.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _symbol;
}
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/functiontokenURI(uint256 tokenId) publicviewvirtualoverridereturns (stringmemory) {
if (!_exists(tokenId)) _revert(URIQueryForNonexistentToken.selector);
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length!=0 ? string(abi.encodePacked(baseURI, _toString(tokenId))) : '';
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, it can be overridden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return'';
}
// =============================================================// OWNERSHIPS OPERATIONS// =============================================================/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) publicviewvirtualoverridereturns (address) {
returnaddress(uint160(_packedOwnershipOf(tokenId)));
}
/**
* @dev Gas spent here starts off proportional to the maximum mint batch size.
* It gradually moves to O(1) as tokens get transferred around over time.
*/function_ownershipOf(uint256 tokenId) internalviewvirtualreturns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnershipOf(tokenId));
}
/**
* @dev Returns the unpacked `TokenOwnership` struct at `index`.
*/function_ownershipAt(uint256 index) internalviewvirtualreturns (TokenOwnership memory) {
return _unpackedOwnership(_packedOwnerships[index]);
}
/**
* @dev Returns whether the ownership slot at `index` is initialized.
* An uninitialized slot does not necessarily mean that the slot has no owner.
*/function_ownershipIsInitialized(uint256 index) internalviewvirtualreturns (bool) {
return _packedOwnerships[index] !=0;
}
/**
* @dev Initializes the ownership slot minted at `index` for efficiency purposes.
*/function_initializeOwnershipAt(uint256 index) internalvirtual{
if (_packedOwnerships[index] ==0) {
_packedOwnerships[index] = _packedOwnershipOf(index);
}
}
/**
* @dev Returns the packed ownership data of `tokenId`.
*/function_packedOwnershipOf(uint256 tokenId) privateviewreturns (uint256 packed) {
if (_startTokenId() <= tokenId) {
packed = _packedOwnerships[tokenId];
if (tokenId > _sequentialUpTo()) {
if (_packedOwnershipExists(packed)) return packed;
_revert(OwnerQueryForNonexistentToken.selector);
}
// If the data at the starting slot does not exist, start the scan.if (packed ==0) {
if (tokenId >= _currentIndex) _revert(OwnerQueryForNonexistentToken.selector);
// Invariant:// There will always be an initialized ownership slot// (i.e. `ownership.addr != address(0) && ownership.burned == false`)// before an unintialized ownership slot// (i.e. `ownership.addr == address(0) && ownership.burned == false`)// Hence, `tokenId` will not underflow.//// We can directly compare the packed value.// If the address is zero, packed will be zero.for (;;) {
unchecked {
packed = _packedOwnerships[--tokenId];
}
if (packed ==0) continue;
if (packed & _BITMASK_BURNED ==0) return packed;
// Otherwise, the token is burned, and we must revert.// This handles the case of batch burned tokens, where only the burned bit// of the starting slot is set, and remaining slots are left uninitialized.
_revert(OwnerQueryForNonexistentToken.selector);
}
}
// Otherwise, the data exists and we can skip the scan.// This is possible because we have already achieved the target condition.// This saves 2143 gas on transfers of initialized tokens.// If the token is not burned, return `packed`. Otherwise, revert.if (packed & _BITMASK_BURNED ==0) return packed;
}
_revert(OwnerQueryForNonexistentToken.selector);
}
/**
* @dev Returns the unpacked `TokenOwnership` struct from `packed`.
*/function_unpackedOwnership(uint256 packed) privatepurereturns (TokenOwnership memory ownership) {
ownership.addr =address(uint160(packed));
ownership.startTimestamp =uint64(packed >> _BITPOS_START_TIMESTAMP);
ownership.burned = packed & _BITMASK_BURNED !=0;
ownership.extraData =uint24(packed >> _BITPOS_EXTRA_DATA);
}
/**
* @dev Packs ownership data into a single uint256.
*/function_packOwnershipData(address owner, uint256 flags) privateviewreturns (uint256 result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner :=and(owner, _BITMASK_ADDRESS)
// `owner | (block.timestamp << _BITPOS_START_TIMESTAMP) | flags`.
result :=or(owner, or(shl(_BITPOS_START_TIMESTAMP, timestamp()), flags))
}
}
/**
* @dev Returns the `nextInitialized` flag set if `quantity` equals 1.
*/function_nextInitializedFlag(uint256 quantity) privatepurereturns (uint256 result) {
// For branchless setting of the `nextInitialized` flag.assembly {
// `(quantity == 1) << _BITPOS_NEXT_INITIALIZED`.
result :=shl(_BITPOS_NEXT_INITIALIZED, eq(quantity, 1))
}
}
// =============================================================// APPROVAL OPERATIONS// =============================================================/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account. See {ERC721A-_approve}.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
*/functionapprove(address to, uint256 tokenId) publicpayablevirtualoverride{
_approve(to, tokenId, true);
}
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) publicviewvirtualoverridereturns (address) {
if (!_exists(tokenId)) _revert(ApprovalQueryForNonexistentToken.selector);
return _tokenApprovals[tokenId].value;
}
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtualoverride{
_operatorApprovals[_msgSenderERC721A()][operator] = approved;
emit ApprovalForAll(_msgSenderERC721A(), operator, approved);
}
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualoverridereturns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev Returns whether `tokenId` exists.
*
* Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.
*
* Tokens start existing when they are minted. See {_mint}.
*/function_exists(uint256 tokenId) internalviewvirtualreturns (bool result) {
if (_startTokenId() <= tokenId) {
if (tokenId > _sequentialUpTo()) return _packedOwnershipExists(_packedOwnerships[tokenId]);
if (tokenId < _currentIndex) {
uint256 packed;
while ((packed = _packedOwnerships[tokenId]) ==0) --tokenId;
result = packed & _BITMASK_BURNED ==0;
}
}
}
/**
* @dev Returns whether `packed` represents a token that exists.
*/function_packedOwnershipExists(uint256 packed) privatepurereturns (bool result) {
assembly {
// The following is equivalent to `owner != address(0) && burned == false`.// Symbolically tested.
result :=gt(and(packed, _BITMASK_ADDRESS), and(packed, _BITMASK_BURNED))
}
}
/**
* @dev Returns whether `msgSender` is equal to `approvedAddress` or `owner`.
*/function_isSenderApprovedOrOwner(address approvedAddress,
address owner,
address msgSender
) privatepurereturns (bool result) {
assembly {
// Mask `owner` to the lower 160 bits, in case the upper bits somehow aren't clean.
owner :=and(owner, _BITMASK_ADDRESS)
// Mask `msgSender` to the lower 160 bits, in case the upper bits somehow aren't clean.
msgSender :=and(msgSender, _BITMASK_ADDRESS)
// `msgSender == owner || msgSender == approvedAddress`.
result :=or(eq(msgSender, owner), eq(msgSender, approvedAddress))
}
}
/**
* @dev Returns the storage slot and value for the approved address of `tokenId`.
*/function_getApprovedSlotAndAddress(uint256 tokenId)
privateviewreturns (uint256 approvedAddressSlot, address approvedAddress)
{
TokenApprovalRef storage tokenApproval = _tokenApprovals[tokenId];
// The following is equivalent to `approvedAddress = _tokenApprovals[tokenId].value`.assembly {
approvedAddressSlot := tokenApproval.slot
approvedAddress :=sload(approvedAddressSlot)
}
}
// =============================================================// TRANSFER OPERATIONS// =============================================================/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) publicpayablevirtualoverride{
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
// Mask `from` to the lower 160 bits, in case the upper bits somehow aren't clean.from=address(uint160(uint256(uint160(from)) & _BITMASK_ADDRESS));
if (address(uint160(prevOwnershipPacked)) !=from) _revert(TransferFromIncorrectOwner.selector);
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
// The nested ifs save around 20+ gas over a compound boolean condition.if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
_beforeTokenTransfers(from, to, tokenId, 1);
// Clear approvals from the previous owner.assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for// ownership above and the recipient's balance can't realistically overflow.// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.unchecked {
// We can directly increment and decrement the balances.--_packedAddressData[from]; // Updates: `balance -= 1`.++_packedAddressData[to]; // Updates: `balance += 1`.// Updates:// - `address` to the next owner.// - `startTimestamp` to the timestamp of transfering.// - `burned` to `false`.// - `nextInitialized` to `true`.
_packedOwnerships[tokenId] = _packOwnershipData(
to,
_BITMASK_NEXT_INITIALIZED | _nextExtraData(from, to, prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED ==0) {
uint256 nextTokenId = tokenId +1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).if (_packedOwnerships[nextTokenId] ==0) {
// If the next slot is within bounds.if (nextTokenId != _currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.uint256 toMasked =uint256(uint160(to)) & _BITMASK_ADDRESS;
assembly {
// Emit the `Transfer` event.log4(
0, // Start of data (0, since no data).0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.
from, // `from`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
if (toMasked ==0) _revert(TransferToZeroAddress.selector);
_afterTokenTransfers(from, to, tokenId, 1);
}
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) publicpayablevirtualoverride{
safeTransferFrom(from, to, tokenId, '');
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytesmemory _data
) publicpayablevirtualoverride{
transferFrom(from, to, tokenId);
if (to.code.length!=0)
if (!_checkContractOnERC721Received(from, to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
}
/**
* @dev Hook that is called before a set of serially-ordered token IDs
* are about to be transferred. This includes minting.
* And also called before burning one token.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/function_beforeTokenTransfers(addressfrom,
address to,
uint256 startTokenId,
uint256 quantity
) internalvirtual{}
/**
* @dev Hook that is called after a set of serially-ordered token IDs
* have been transferred. This includes minting.
* And also called after one token has been burned.
*
* `startTokenId` - the first token ID to be transferred.
* `quantity` - the amount to be transferred.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` has been
* transferred to `to`.
* - When `from` is zero, `tokenId` has been minted for `to`.
* - When `to` is zero, `tokenId` has been burned by `from`.
* - `from` and `to` are never both zero.
*/function_afterTokenTransfers(addressfrom,
address to,
uint256 startTokenId,
uint256 quantity
) internalvirtual{}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target contract.
*
* `from` - Previous owner of the given token ID.
* `to` - Target address that will receive the token.
* `tokenId` - Token ID to be transferred.
* `_data` - Optional data to send along with the call.
*
* Returns whether the call correctly returned the expected magic value.
*/function_checkContractOnERC721Received(addressfrom,
address to,
uint256 tokenId,
bytesmemory _data
) privatereturns (bool) {
try ERC721A__IERC721Receiver(to).onERC721Received(_msgSenderERC721A(), from, tokenId, _data) returns (
bytes4 retval
) {
return retval == ERC721A__IERC721Receiver(to).onERC721Received.selector;
} catch (bytesmemory reason) {
if (reason.length==0) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
assembly {
revert(add(32, reason), mload(reason))
}
}
}
// =============================================================// MINT OPERATIONS// =============================================================/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {Transfer} event for each mint.
*/function_mint(address to, uint256 quantity) internalvirtual{
uint256 startTokenId = _currentIndex;
if (quantity ==0) _revert(MintZeroQuantity.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are incredibly unrealistic.// `balance` and `numberMinted` have a maximum limit of 2**64.// `tokenId` has a maximum limit of 2**256.unchecked {
// Updates:// - `address` to the owner.// - `startTimestamp` to the timestamp of minting.// - `burned` to `false`.// - `nextInitialized` to `quantity == 1`.
_packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
// Updates:// - `balance += quantity`.// - `numberMinted += quantity`.//// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += quantity * ((1<< _BITPOS_NUMBER_MINTED) |1);
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.uint256 toMasked =uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked ==0) _revert(MintToZeroAddress.selector);
uint256 end = startTokenId + quantity;
uint256 tokenId = startTokenId;
if (end -1> _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
do {
assembly {
// Emit the `Transfer` event.log4(
0, // Start of data (0, since no data).0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
// The `!=` check ensures that large values of `quantity`// that overflows uint256 will make the loop run out of gas.
} while (++tokenId != end);
_currentIndex = end;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Mints `quantity` tokens and transfers them to `to`.
*
* This function is intended for efficient minting only during contract creation.
*
* It emits only one {ConsecutiveTransfer} as defined in
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309),
* instead of a sequence of {Transfer} event(s).
*
* Calling this function outside of contract creation WILL make your contract
* non-compliant with the ERC721 standard.
* For full ERC721 compliance, substituting ERC721 {Transfer} event(s) with the ERC2309
* {ConsecutiveTransfer} event is only permissible during contract creation.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `quantity` must be greater than 0.
*
* Emits a {ConsecutiveTransfer} event.
*/function_mintERC2309(address to, uint256 quantity) internalvirtual{
uint256 startTokenId = _currentIndex;
if (to ==address(0)) _revert(MintToZeroAddress.selector);
if (quantity ==0) _revert(MintZeroQuantity.selector);
if (quantity > _MAX_MINT_ERC2309_QUANTITY_LIMIT) _revert(MintERC2309QuantityExceedsLimit.selector);
_beforeTokenTransfers(address(0), to, startTokenId, quantity);
// Overflows are unrealistic due to the above check for `quantity` to be below the limit.unchecked {
// Updates:// - `balance += quantity`.// - `numberMinted += quantity`.//// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += quantity * ((1<< _BITPOS_NUMBER_MINTED) |1);
// Updates:// - `address` to the owner.// - `startTimestamp` to the timestamp of minting.// - `burned` to `false`.// - `nextInitialized` to `quantity == 1`.
_packedOwnerships[startTokenId] = _packOwnershipData(
to,
_nextInitializedFlag(quantity) | _nextExtraData(address(0), to, 0)
);
if (startTokenId + quantity -1> _sequentialUpTo()) _revert(SequentialMintExceedsLimit.selector);
emit ConsecutiveTransfer(startTokenId, startTokenId + quantity -1, address(0), to);
_currentIndex = startTokenId + quantity;
}
_afterTokenTransfers(address(0), to, startTokenId, quantity);
}
/**
* @dev Safely mints `quantity` tokens and transfers them to `to`.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called for each safe transfer.
* - `quantity` must be greater than 0.
*
* See {_mint}.
*
* Emits a {Transfer} event for each mint.
*/function_safeMint(address to,
uint256 quantity,
bytesmemory _data
) internalvirtual{
_mint(to, quantity);
unchecked {
if (to.code.length!=0) {
uint256 end = _currentIndex;
uint256 index = end - quantity;
do {
if (!_checkContractOnERC721Received(address(0), to, index++, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
} while (index < end);
// This prevents reentrancy to `_safeMint`.// It does not prevent reentrancy to `_safeMintSpot`.if (_currentIndex != end) revert();
}
}
}
/**
* @dev Equivalent to `_safeMint(to, quantity, '')`.
*/function_safeMint(address to, uint256 quantity) internalvirtual{
_safeMint(to, quantity, '');
}
/**
* @dev Mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* Emits a {Transfer} event for each mint.
*/function_mintSpot(address to, uint256 tokenId) internalvirtual{
if (tokenId <= _sequentialUpTo()) _revert(SpotMintTokenIdTooSmall.selector);
uint256 prevOwnershipPacked = _packedOwnerships[tokenId];
if (_packedOwnershipExists(prevOwnershipPacked)) _revert(TokenAlreadyExists.selector);
_beforeTokenTransfers(address(0), to, tokenId, 1);
// Overflows are incredibly unrealistic.// The `numberMinted` for `to` is incremented by 1, and has a max limit of 2**64 - 1.// `_spotMinted` is incremented by 1, and has a max limit of 2**256 - 1.unchecked {
// Updates:// - `address` to the owner.// - `startTimestamp` to the timestamp of minting.// - `burned` to `false`.// - `nextInitialized` to `true` (as `quantity == 1`).
_packedOwnerships[tokenId] = _packOwnershipData(
to,
_nextInitializedFlag(1) | _nextExtraData(address(0), to, prevOwnershipPacked)
);
// Updates:// - `balance += 1`.// - `numberMinted += 1`.//// We can directly add to the `balance` and `numberMinted`.
_packedAddressData[to] += (1<< _BITPOS_NUMBER_MINTED) |1;
// Mask `to` to the lower 160 bits, in case the upper bits somehow aren't clean.uint256 toMasked =uint256(uint160(to)) & _BITMASK_ADDRESS;
if (toMasked ==0) _revert(MintToZeroAddress.selector);
assembly {
// Emit the `Transfer` event.log4(
0, // Start of data (0, since no data).0, // End of data (0, since no data).
_TRANSFER_EVENT_SIGNATURE, // Signature.0, // `address(0)`.
toMasked, // `to`.
tokenId // `tokenId`.
)
}
++_spotMinted;
}
_afterTokenTransfers(address(0), to, tokenId, 1);
}
/**
* @dev Safely mints a single token at `tokenId`.
*
* Note: A spot-minted `tokenId` that has been burned can be re-minted again.
*
* Requirements:
*
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}.
* - `tokenId` must be greater than `_sequentialUpTo()`.
* - `tokenId` must not exist.
*
* See {_mintSpot}.
*
* Emits a {Transfer} event.
*/function_safeMintSpot(address to,
uint256 tokenId,
bytesmemory _data
) internalvirtual{
_mintSpot(to, tokenId);
unchecked {
if (to.code.length!=0) {
uint256 currentSpotMinted = _spotMinted;
if (!_checkContractOnERC721Received(address(0), to, tokenId, _data)) {
_revert(TransferToNonERC721ReceiverImplementer.selector);
}
// This prevents reentrancy to `_safeMintSpot`.// It does not prevent reentrancy to `_safeMint`.if (_spotMinted != currentSpotMinted) revert();
}
}
}
/**
* @dev Equivalent to `_safeMintSpot(to, tokenId, '')`.
*/function_safeMintSpot(address to, uint256 tokenId) internalvirtual{
_safeMintSpot(to, tokenId, '');
}
// =============================================================// APPROVAL OPERATIONS// =============================================================/**
* @dev Equivalent to `_approve(to, tokenId, false)`.
*/function_approve(address to, uint256 tokenId) internalvirtual{
_approve(to, tokenId, false);
}
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/function_approve(address to,
uint256 tokenId,
bool approvalCheck
) internalvirtual{
address owner = ownerOf(tokenId);
if (approvalCheck && _msgSenderERC721A() != owner)
if (!isApprovedForAll(owner, _msgSenderERC721A())) {
_revert(ApprovalCallerNotOwnerNorApproved.selector);
}
_tokenApprovals[tokenId].value= to;
emit Approval(owner, to, tokenId);
}
// =============================================================// BURN OPERATIONS// =============================================================/**
* @dev Equivalent to `_burn(tokenId, false)`.
*/function_burn(uint256 tokenId) internalvirtual{
_burn(tokenId, false);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/function_burn(uint256 tokenId, bool approvalCheck) internalvirtual{
uint256 prevOwnershipPacked = _packedOwnershipOf(tokenId);
addressfrom=address(uint160(prevOwnershipPacked));
(uint256 approvedAddressSlot, address approvedAddress) = _getApprovedSlotAndAddress(tokenId);
if (approvalCheck) {
// The nested ifs save around 20+ gas over a compound boolean condition.if (!_isSenderApprovedOrOwner(approvedAddress, from, _msgSenderERC721A()))
if (!isApprovedForAll(from, _msgSenderERC721A())) _revert(TransferCallerNotOwnerNorApproved.selector);
}
_beforeTokenTransfers(from, address(0), tokenId, 1);
// Clear approvals from the previous owner.assembly {
if approvedAddress {
// This is equivalent to `delete _tokenApprovals[tokenId]`.sstore(approvedAddressSlot, 0)
}
}
// Underflow of the sender's balance is impossible because we check for// ownership above and the recipient's balance can't realistically overflow.// Counter overflow is incredibly unrealistic as `tokenId` would have to be 2**256.unchecked {
// Updates:// - `balance -= 1`.// - `numberBurned += 1`.//// We can directly decrement the balance, and increment the number burned.// This is equivalent to `packed -= 1; packed += 1 << _BITPOS_NUMBER_BURNED;`.
_packedAddressData[from] += (1<< _BITPOS_NUMBER_BURNED) -1;
// Updates:// - `address` to the last owner.// - `startTimestamp` to the timestamp of burning.// - `burned` to `true`.// - `nextInitialized` to `true`.
_packedOwnerships[tokenId] = _packOwnershipData(
from,
(_BITMASK_BURNED | _BITMASK_NEXT_INITIALIZED) | _nextExtraData(from, address(0), prevOwnershipPacked)
);
// If the next slot may not have been initialized (i.e. `nextInitialized == false`) .if (prevOwnershipPacked & _BITMASK_NEXT_INITIALIZED ==0) {
uint256 nextTokenId = tokenId +1;
// If the next slot's address is zero and not burned (i.e. packed value is zero).if (_packedOwnerships[nextTokenId] ==0) {
// If the next slot is within bounds.if (nextTokenId != _currentIndex) {
// Initialize the next slot to maintain correctness for `ownerOf(tokenId + 1)`.
_packedOwnerships[nextTokenId] = prevOwnershipPacked;
}
}
}
}
emit Transfer(from, address(0), tokenId);
_afterTokenTransfers(from, address(0), tokenId, 1);
// Overflow not possible, as `_burnCounter` cannot be exceed `_currentIndex + _spotMinted` times.unchecked {
_burnCounter++;
}
}
// =============================================================// EXTRA DATA OPERATIONS// =============================================================/**
* @dev Directly sets the extra data for the ownership data `index`.
*/function_setExtraDataAt(uint256 index, uint24 extraData) internalvirtual{
uint256 packed = _packedOwnerships[index];
if (packed ==0) _revert(OwnershipNotInitializedForExtraData.selector);
uint256 extraDataCasted;
// Cast `extraData` with assembly to avoid redundant masking.assembly {
extraDataCasted := extraData
}
packed = (packed & _BITMASK_EXTRA_DATA_COMPLEMENT) | (extraDataCasted << _BITPOS_EXTRA_DATA);
_packedOwnerships[index] = packed;
}
/**
* @dev Called during each token transfer to set the 24bit `extraData` field.
* Intended to be overridden by the cosumer contract.
*
* `previousExtraData` - the value of `extraData` before transfer.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, `from`'s `tokenId` will be
* transferred to `to`.
* - When `from` is zero, `tokenId` will be minted for `to`.
* - When `to` is zero, `tokenId` will be burned by `from`.
* - `from` and `to` are never both zero.
*/function_extraData(addressfrom,
address to,
uint24 previousExtraData
) internalviewvirtualreturns (uint24) {}
/**
* @dev Returns the next extra data for the packed ownership data.
* The returned result is shifted into position.
*/function_nextExtraData(addressfrom,
address to,
uint256 prevOwnershipPacked
) privateviewreturns (uint256) {
uint24 extraData =uint24(prevOwnershipPacked >> _BITPOS_EXTRA_DATA);
returnuint256(_extraData(from, to, extraData)) << _BITPOS_EXTRA_DATA;
}
// =============================================================// OTHER OPERATIONS// =============================================================/**
* @dev Returns the message sender (defaults to `msg.sender`).
*
* If you are writing GSN compatible contracts, you need to override this function.
*/function_msgSenderERC721A() internalviewvirtualreturns (address) {
returnmsg.sender;
}
/**
* @dev Converts a uint256 to its ASCII string decimal representation.
*/function_toString(uint256 value) internalpurevirtualreturns (stringmemory str) {
assembly {
// The maximum value of a uint256 contains 78 digits (1 byte per digit), but// we allocate 0xa0 bytes to keep the free memory pointer 32-byte word aligned.// We will need 1 word for the trailing zeros padding, 1 word for the length,// and 3 words for a maximum of 78 digits. Total: 5 * 0x20 = 0xa0.let m :=add(mload(0x40), 0xa0)
// Update the free memory pointer to allocate.mstore(0x40, m)
// Assign the `str` to the end.
str :=sub(m, 0x20)
// Zeroize the slot after the string.mstore(str, 0)
// Cache the end of the memory to calculate the length later.let end := str
// We write the string from rightmost digit to leftmost digit.// The following is essentially a do-while loop that also handles the zero case.// prettier-ignorefor { let temp := value } 1 {} {
str :=sub(str, 1)
// Write the character to the pointer.// The ASCII index of the '0' character is 48.mstore8(str, add(48, mod(temp, 10)))
// Keep dividing `temp` until zero.
temp :=div(temp, 10)
// prettier-ignoreifiszero(temp) { break }
}
let length :=sub(end, str)
// Move the pointer 32 bytes leftwards to make room for the length.
str :=sub(str, 0x20)
// Store the length.mstore(str, length)
}
}
/**
* @dev For more efficient reverts.
*/function_revert(bytes4 errorSelector) internalpure{
assembly {
mstore(0x00, errorSelector)
revert(0x00, 0x04)
}
}
}
Contract Source Code
File 4 of 29: IERC165.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2;interfaceIERC165{
/// @notice Query if a contract implements an interface/// @param interfaceID The interface identifier, as specified in ERC-165/// @dev Interface identification is specified in ERC-165. This function/// uses less than 30,000 gas./// @return `true` if the contract implements `interfaceID` and/// `interfaceID` is not 0xffffffff, `false` otherwisefunctionsupportsInterface(bytes4 interfaceID) externalviewreturns (bool);
}
Contract Source Code
File 5 of 29: IERC20.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2;/// @dev Interface of the ERC20 standard as defined in the EIP./// @dev This includes the optional name, symbol, and decimals metadata.interfaceIERC20{
/// @dev Emitted when `value` tokens are moved from one account (`from`) to another (`to`).eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/// @dev Emitted when the allowance of a `spender` for an `owner` is set, where `value`/// is the new allowance.eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/// @notice Returns the amount of tokens in existence.functiontotalSupply() externalviewreturns (uint256);
/// @notice Returns the amount of tokens owned by `account`.functionbalanceOf(address account) externalviewreturns (uint256);
/// @notice Moves `amount` tokens from the caller's account to `to`.functiontransfer(address to, uint256 amount) externalreturns (bool);
/// @notice Returns the remaining number of tokens that `spender` is allowed/// to spend on behalf of `owner`functionallowance(address owner, address spender) externalviewreturns (uint256);
/// @notice Sets `amount` as the allowance of `spender` over the caller's tokens./// @dev Be aware of front-running risks: https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729functionapprove(address spender, uint256 amount) externalreturns (bool);
/// @notice Moves `amount` tokens from `from` to `to` using the allowance mechanism./// `amount` is then deducted from the caller's allowance.functiontransferFrom(addressfrom, address to, uint256 amount) externalreturns (bool);
/// @notice Returns the name of the token.functionname() externalviewreturns (stringmemory);
/// @notice Returns the symbol of the token.functionsymbol() externalviewreturns (stringmemory);
/// @notice Returns the decimals places of the token.functiondecimals() externalviewreturns (uint8);
}
Contract Source Code
File 6 of 29: IERC721.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2;import"./IERC165.sol";
/// @title ERC-721 Non-Fungible Token Standard/// @dev See https://eips.ethereum.org/EIPS/eip-721/// Note: the ERC-165 identifier for this interface is 0x80ac58cd.interfaceIERC721isIERC165{
/// @dev This emits when ownership of any NFT changes by any mechanism./// This event emits when NFTs are created (`from` == 0) and destroyed/// (`to` == 0). Exception: during contract creation, any number of NFTs/// may be created and assigned without emitting Transfer. At the time of/// any transfer, the approved address for that NFT (if any) is reset to none.eventTransfer(addressindexed _from, addressindexed _to, uint256indexed _tokenId);
/// @dev This emits when the approved address for an NFT is changed or/// reaffirmed. The zero address indicates there is no approved address./// When a Transfer event emits, this also indicates that the approved/// address for that NFT (if any) is reset to none.eventApproval(addressindexed _owner, addressindexed _approved, uint256indexed _tokenId);
/// @dev This emits when an operator is enabled or disabled for an owner./// The operator can manage all NFTs of the owner.eventApprovalForAll(addressindexed _owner, addressindexed _operator, bool _approved);
/// @notice Count all NFTs assigned to an owner/// @dev NFTs assigned to the zero address are considered invalid, and this/// function throws for queries about the zero address./// @param _owner An address for whom to query the balance/// @return The number of NFTs owned by `_owner`, possibly zerofunctionbalanceOf(address _owner) externalviewreturns (uint256);
/// @notice Find the owner of an NFT/// @dev NFTs assigned to zero address are considered invalid, and queries/// about them do throw./// @param _tokenId The identifier for an NFT/// @return The address of the owner of the NFTfunctionownerOf(uint256 _tokenId) externalviewreturns (address);
/// @notice Transfers the ownership of an NFT from one address to another address/// @dev Throws unless `msg.sender` is the current owner, an authorized/// operator, or the approved address for this NFT. Throws if `_from` is/// not the current owner. Throws if `_to` is the zero address. Throws if/// `_tokenId` is not a valid NFT. When transfer is complete, this function/// checks if `_to` is a smart contract (code size > 0). If so, it calls/// `onERC721Received` on `_to` and throws if the return value is not/// `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`./// @param _from The current owner of the NFT/// @param _to The new owner/// @param _tokenId The NFT to transfer/// @param data Additional data with no specified format, sent in call to `_to`functionsafeTransferFrom(address _from, address _to, uint256 _tokenId, bytescalldata data) externalpayable;
/// @notice Transfers the ownership of an NFT from one address to another address/// @dev This works identically to the other function with an extra data parameter,/// except this function just sets data to ""./// @param _from The current owner of the NFT/// @param _to The new owner/// @param _tokenId The NFT to transferfunctionsafeTransferFrom(address _from, address _to, uint256 _tokenId) externalpayable;
/// @notice Transfer ownership of an NFT -- THE CALLER IS RESPONSIBLE/// TO CONFIRM THAT `_to` IS CAPABLE OF RECEIVING NFTS OR ELSE/// THEY MAY BE PERMANENTLY LOST/// @dev Throws unless `msg.sender` is the current owner, an authorized/// operator, or the approved address for this NFT. Throws if `_from` is/// not the current owner. Throws if `_to` is the zero address. Throws if/// `_tokenId` is not a valid NFT./// @param _from The current owner of the NFT/// @param _to The new owner/// @param _tokenId The NFT to transferfunctiontransferFrom(address _from, address _to, uint256 _tokenId) externalpayable;
/// @notice Change or reaffirm the approved address for an NFT/// @dev The zero address indicates there is no approved address./// Throws unless `msg.sender` is the current NFT owner, or an authorized/// operator of the current owner./// @param _approved The new approved NFT controller/// @param _tokenId The NFT to approvefunctionapprove(address _approved, uint256 _tokenId) externalpayable;
/// @notice Enable or disable approval for a third party ("operator") to manage/// all of `msg.sender`'s assets/// @dev Emits the ApprovalForAll event. The contract MUST allow/// multiple operators per owner./// @param _operator Address to add to the set of authorized operators/// @param _approved True if the operator is approved, false to revoke approvalfunctionsetApprovalForAll(address _operator, bool _approved) external;
/// @notice Get the approved address for a single NFT/// @dev Throws if `_tokenId` is not a valid NFT./// @param _tokenId The NFT to find the approved address for/// @return The approved address for this NFT, or the zero address if there is nonefunctiongetApproved(uint256 _tokenId) externalviewreturns (address);
/// @notice Query if an address is an authorized operator for another address/// @param _owner The address that owns the NFTs/// @param _operator The address that acts on behalf of the owner/// @return True if `_operator` is an approved operator for `_owner`, false otherwisefunctionisApprovedForAll(address _owner, address _operator) externalviewreturns (bool);
}
/// @dev Note: the ERC-165 identifier for this interface is 0x150b7a02.interfaceIERC721TokenReceiver{
/// @notice Handle the receipt of an NFT/// @dev The ERC721 smart contract calls this function on the recipient/// after a `transfer`. This function MAY throw to revert and reject the/// transfer. Return of other than the magic value MUST result in the/// transaction being reverted./// Note: the contract address is always the message sender./// @param _operator The address which called `safeTransferFrom` function/// @param _from The address which previously owned the token/// @param _tokenId The NFT identifier which is being transferred/// @param _data Additional data with no specified format/// @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`/// unless throwingfunctiononERC721Received(address _operator, address _from, uint256 _tokenId, bytescalldata _data)
externalreturns (bytes4);
}
/// @title ERC-721 Non-Fungible Token Standard, optional metadata extension/// @dev See https://eips.ethereum.org/EIPS/eip-721/// Note: the ERC-165 identifier for this interface is 0x5b5e139f.interfaceIERC721MetadataisIERC721{
/// @notice A descriptive name for a collection of NFTs in this contractfunctionname() externalviewreturns (stringmemory _name);
/// @notice An abbreviated name for NFTs in this contractfunctionsymbol() externalviewreturns (stringmemory _symbol);
/// @notice A distinct Uniform Resource Identifier (URI) for a given asset./// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC/// 3986. The URI may point to a JSON file that conforms to the "ERC721/// Metadata JSON Schema".functiontokenURI(uint256 _tokenId) externalviewreturns (stringmemory);
}
/// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension/// @dev See https://eips.ethereum.org/EIPS/eip-721/// Note: the ERC-165 identifier for this interface is 0x780e9d63.interfaceIERC721EnumerableisIERC721{
/// @notice Count NFTs tracked by this contract/// @return A count of valid NFTs tracked by this contract, where each one of/// them has an assigned and queryable owner not equal to the zero addressfunctiontotalSupply() externalviewreturns (uint256);
/// @notice Enumerate valid NFTs/// @dev Throws if `_index` >= `totalSupply()`./// @param _index A counter less than `totalSupply()`/// @return The token identifier for the `_index`th NFT,/// (sort order not specified)functiontokenByIndex(uint256 _index) externalviewreturns (uint256);
/// @notice Enumerate NFTs assigned to an owner/// @dev Throws if `_index` >= `balanceOf(_owner)` or if/// `_owner` is the zero address, representing invalid NFTs./// @param _owner An address where we are interested in NFTs owned by them/// @param _index A counter less than `balanceOf(_owner)`/// @return The token identifier for the `_index`th NFT assigned to `_owner`,/// (sort order not specified)functiontokenOfOwnerByIndex(address _owner, uint256 _index) externalviewreturns (uint256);
}
Contract Source Code
File 7 of 29: IERC721A.sol
// SPDX-License-Identifier: MIT// ERC721A Contracts v4.3.0// Creator: Chiru Labspragmasolidity ^0.8.4;/**
* @dev Interface of ERC721A.
*/interfaceIERC721A{
/**
* The caller must own the token or be an approved operator.
*/errorApprovalCallerNotOwnerNorApproved();
/**
* The token does not exist.
*/errorApprovalQueryForNonexistentToken();
/**
* Cannot query the balance for the zero address.
*/errorBalanceQueryForZeroAddress();
/**
* Cannot mint to the zero address.
*/errorMintToZeroAddress();
/**
* The quantity of tokens minted must be more than zero.
*/errorMintZeroQuantity();
/**
* The token does not exist.
*/errorOwnerQueryForNonexistentToken();
/**
* The caller must own the token or be an approved operator.
*/errorTransferCallerNotOwnerNorApproved();
/**
* The token must be owned by `from`.
*/errorTransferFromIncorrectOwner();
/**
* Cannot safely transfer to a contract that does not implement the
* ERC721Receiver interface.
*/errorTransferToNonERC721ReceiverImplementer();
/**
* Cannot transfer to the zero address.
*/errorTransferToZeroAddress();
/**
* The token does not exist.
*/errorURIQueryForNonexistentToken();
/**
* The `quantity` minted with ERC2309 exceeds the safety limit.
*/errorMintERC2309QuantityExceedsLimit();
/**
* The `extraData` cannot be set on an unintialized ownership slot.
*/errorOwnershipNotInitializedForExtraData();
/**
* `_sequentialUpTo()` must be greater than `_startTokenId()`.
*/errorSequentialUpToTooSmall();
/**
* The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`.
*/errorSequentialMintExceedsLimit();
/**
* Spot minting requires a `tokenId` greater than `_sequentialUpTo()`.
*/errorSpotMintTokenIdTooSmall();
/**
* Cannot mint over a token that already exists.
*/errorTokenAlreadyExists();
/**
* The feature is not compatible with spot mints.
*/errorNotCompatibleWithSpotMints();
// =============================================================// STRUCTS// =============================================================structTokenOwnership {
// The address of the owner.address addr;
// Stores the start time of ownership with minimal overhead for tokenomics.uint64 startTimestamp;
// Whether the token has been burned.bool burned;
// Arbitrary data similar to `startTimestamp` that can be set via {_extraData}.uint24 extraData;
}
// =============================================================// TOKEN COUNTERS// =============================================================/**
* @dev Returns the total number of tokens in existence.
* Burned tokens will reduce the count.
* To get the total number of tokens minted, please see {_totalMinted}.
*/functiontotalSupply() externalviewreturns (uint256);
// =============================================================// IERC165// =============================================================/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified)
* to learn more about how these ids are created.
*
* This function call must use less than 30000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
// =============================================================// IERC721// =============================================================/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables
* (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in `owner`'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`,
* checking first that contract recipients are aware of the ERC721 protocol
* to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be have been allowed to move
* this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement
* {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytescalldata data
) externalpayable;
/**
* @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) externalpayable;
/**
* @dev Transfers `tokenId` from `from` to `to`.
*
* WARNING: Usage of this method is discouraged, use {safeTransferFrom}
* whenever possible.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token
* by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) externalpayable;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the
* zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/functionapprove(address to, uint256 tokenId) externalpayable;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom}
* for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the caller.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool _approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}.
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
// =============================================================// IERC721Metadata// =============================================================/**
* @dev Returns the token collection name.
*/functionname() externalviewreturns (stringmemory);
/**
* @dev Returns the token collection symbol.
*/functionsymbol() externalviewreturns (stringmemory);
/**
* @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.
*/functiontokenURI(uint256 tokenId) externalviewreturns (stringmemory);
// =============================================================// IERC2309// =============================================================/**
* @dev Emitted when tokens in `fromTokenId` to `toTokenId`
* (inclusive) is transferred from `from` to `to`, as defined in the
* [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard.
*
* See {_mintERC2309} for more details.
*/eventConsecutiveTransfer(uint256indexed fromTokenId, uint256 toTokenId, addressindexedfrom, addressindexed to);
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {IERC20} from"../interfaces/IERC20.sol";
/// @notice This is a mock contract of the ERC20 standard for testing purposes only, it SHOULD NOT be used in production./// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC20.solcontractMockERC20isIERC20{
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/stringinternal _name;
stringinternal _symbol;
uint8internal _decimals;
functionname() externalviewoverridereturns (stringmemory) {
return _name;
}
functionsymbol() externalviewoverridereturns (stringmemory) {
return _symbol;
}
functiondecimals() externalviewoverridereturns (uint8) {
return _decimals;
}
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/uint256internal _totalSupply;
mapping(address=>uint256) internal _balanceOf;
mapping(address=>mapping(address=>uint256)) internal _allowance;
functiontotalSupply() externalviewoverridereturns (uint256) {
return _totalSupply;
}
functionbalanceOf(address owner) externalviewoverridereturns (uint256) {
return _balanceOf[owner];
}
functionallowance(address owner, address spender) externalviewoverridereturns (uint256) {
return _allowance[owner][spender];
}
/*//////////////////////////////////////////////////////////////
EIP-2612 STORAGE
//////////////////////////////////////////////////////////////*/uint256internal INITIAL_CHAIN_ID;
bytes32internal INITIAL_DOMAIN_SEPARATOR;
mapping(address=>uint256) public nonces;
/*//////////////////////////////////////////////////////////////
INITIALIZE
//////////////////////////////////////////////////////////////*//// @dev A bool to track whether the contract has been initialized.boolprivate initialized;
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and/// syntaxes, we add an initialization function that can be called only once.functioninitialize(stringmemory name_, stringmemory symbol_, uint8 decimals_) public{
require(!initialized, "ALREADY_INITIALIZED");
_name = name_;
_symbol = symbol_;
_decimals = decimals_;
INITIAL_CHAIN_ID = _pureChainId();
INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
initialized =true;
}
/*//////////////////////////////////////////////////////////////
ERC20 LOGIC
//////////////////////////////////////////////////////////////*/functionapprove(address spender, uint256 amount) publicvirtualoverridereturns (bool) {
_allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
returntrue;
}
functiontransfer(address to, uint256 amount) publicvirtualoverridereturns (bool) {
_balanceOf[msg.sender] = _sub(_balanceOf[msg.sender], amount);
_balanceOf[to] = _add(_balanceOf[to], amount);
emit Transfer(msg.sender, to, amount);
returntrue;
}
functiontransferFrom(addressfrom, address to, uint256 amount) publicvirtualoverridereturns (bool) {
uint256 allowed = _allowance[from][msg.sender]; // Saves gas for limited approvals.if (allowed !=~uint256(0)) _allowance[from][msg.sender] = _sub(allowed, amount);
_balanceOf[from] = _sub(_balanceOf[from], amount);
_balanceOf[to] = _add(_balanceOf[to], amount);
emit Transfer(from, to, amount);
returntrue;
}
/*//////////////////////////////////////////////////////////////
EIP-2612 LOGIC
//////////////////////////////////////////////////////////////*/functionpermit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
publicvirtual{
require(deadline >=block.timestamp, "PERMIT_DEADLINE_EXPIRED");
address recoveredAddress =ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
),
v,
r,
s
);
require(recoveredAddress !=address(0) && recoveredAddress == owner, "INVALID_SIGNER");
_allowance[recoveredAddress][spender] = value;
emit Approval(owner, spender, value);
}
functionDOMAIN_SEPARATOR() publicviewvirtualreturns (bytes32) {
return _pureChainId() == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
}
functioncomputeDomainSeparator() internalviewvirtualreturns (bytes32) {
returnkeccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(_name)),
keccak256("1"),
_pureChainId(),
address(this)
)
);
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/function_mint(address to, uint256 amount) internalvirtual{
_totalSupply = _add(_totalSupply, amount);
_balanceOf[to] = _add(_balanceOf[to], amount);
emit Transfer(address(0), to, amount);
}
function_burn(addressfrom, uint256 amount) internalvirtual{
_balanceOf[from] = _sub(_balanceOf[from], amount);
_totalSupply = _sub(_totalSupply, amount);
emit Transfer(from, address(0), amount);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MATH LOGIC
//////////////////////////////////////////////////////////////*/function_add(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 c = a + b;
require(c >= a, "ERC20: addition overflow");
return c;
}
function_sub(uint256 a, uint256 b) internalpurereturns (uint256) {
require(a >= b, "ERC20: subtraction underflow");
return a - b;
}
/*//////////////////////////////////////////////////////////////
HELPERS
//////////////////////////////////////////////////////////////*/// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We// can't simply access the chain ID in a normal view or pure function because the solc View Pure// Checker changed `chainid` from pure to view in 0.8.0.function_viewChainId() privateviewreturns (uint256 chainId) {
// Assembly required since `block.chainid` was introduced in 0.8.0.assembly {
chainId :=chainid()
}
address(this); // Silence warnings in older Solc versions.
}
function_pureChainId() privatepurereturns (uint256 chainId) {
function() internalviewreturns (uint256) fnIn = _viewChainId;
function() internalpurereturns (uint256) pureChainId;
assembly {
pureChainId := fnIn
}
chainId = pureChainId();
}
}
Contract Source Code
File 10 of 29: MockERC721.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {IERC721Metadata} from"../interfaces/IERC721.sol";
/// @notice This is a mock contract of the ERC721 standard for testing purposes only, it SHOULD NOT be used in production./// @dev Forked from: https://github.com/transmissions11/solmate/blob/0384dbaaa4fcb5715738a9254a7c0a4cb62cf458/src/tokens/ERC721.solcontractMockERC721isIERC721Metadata{
/*//////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/stringinternal _name;
stringinternal _symbol;
functionname() externalviewoverridereturns (stringmemory) {
return _name;
}
functionsymbol() externalviewoverridereturns (stringmemory) {
return _symbol;
}
functiontokenURI(uint256 id) publicviewvirtualoverridereturns (stringmemory) {}
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/mapping(uint256=>address) internal _ownerOf;
mapping(address=>uint256) internal _balanceOf;
functionownerOf(uint256 id) publicviewvirtualoverridereturns (address owner) {
require((owner = _ownerOf[id]) !=address(0), "NOT_MINTED");
}
functionbalanceOf(address owner) publicviewvirtualoverridereturns (uint256) {
require(owner !=address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/mapping(uint256=>address) internal _getApproved;
mapping(address=>mapping(address=>bool)) internal _isApprovedForAll;
functiongetApproved(uint256 id) publicviewvirtualoverridereturns (address) {
return _getApproved[id];
}
functionisApprovedForAll(address owner, address operator) publicviewvirtualoverridereturns (bool) {
return _isApprovedForAll[owner][operator];
}
/*//////////////////////////////////////////////////////////////
INITIALIZE
//////////////////////////////////////////////////////////////*//// @dev A bool to track whether the contract has been initialized.boolprivate initialized;
/// @dev To hide constructor warnings across solc versions due to different constructor visibility requirements and/// syntaxes, we add an initialization function that can be called only once.functioninitialize(stringmemory name_, stringmemory symbol_) public{
require(!initialized, "ALREADY_INITIALIZED");
_name = name_;
_symbol = symbol_;
initialized =true;
}
/*//////////////////////////////////////////////////////////////
ERC721 LOGIC
//////////////////////////////////////////////////////////////*/functionapprove(address spender, uint256 id) publicpayablevirtualoverride{
address owner = _ownerOf[id];
require(msg.sender== owner || _isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED");
_getApproved[id] = spender;
emit Approval(owner, spender, id);
}
functionsetApprovalForAll(address operator, bool approved) publicvirtualoverride{
_isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functiontransferFrom(addressfrom, address to, uint256 id) publicpayablevirtualoverride{
require(from== _ownerOf[id], "WRONG_FROM");
require(to !=address(0), "INVALID_RECIPIENT");
require(
msg.sender==from|| _isApprovedForAll[from][msg.sender] ||msg.sender== _getApproved[id],
"NOT_AUTHORIZED"
);
// Underflow of the sender's balance is impossible because we check for// ownership above and the recipient's balance can't realistically overflow.
_balanceOf[from]--;
_balanceOf[to]++;
_ownerOf[id] = to;
delete _getApproved[id];
emit Transfer(from, to, id);
}
functionsafeTransferFrom(addressfrom, address to, uint256 id) publicpayablevirtualoverride{
transferFrom(from, to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "")
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
functionsafeTransferFrom(addressfrom, address to, uint256 id, bytesmemory data)
publicpayablevirtualoverride{
transferFrom(from, to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data)
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
ERC165 LOGIC
//////////////////////////////////////////////////////////////*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==0x01ffc9a7// ERC165 Interface ID for ERC165|| interfaceId ==0x80ac58cd// ERC165 Interface ID for ERC721|| interfaceId ==0x5b5e139f; // ERC165 Interface ID for ERC721Metadata
}
/*//////////////////////////////////////////////////////////////
INTERNAL MINT/BURN LOGIC
//////////////////////////////////////////////////////////////*/function_mint(address to, uint256 id) internalvirtual{
require(to !=address(0), "INVALID_RECIPIENT");
require(_ownerOf[id] ==address(0), "ALREADY_MINTED");
// Counter overflow is incredibly unrealistic.
_balanceOf[to]++;
_ownerOf[id] = to;
emit Transfer(address(0), to, id);
}
function_burn(uint256 id) internalvirtual{
address owner = _ownerOf[id];
require(owner !=address(0), "NOT_MINTED");
_balanceOf[owner]--;
delete _ownerOf[id];
delete _getApproved[id];
emit Transfer(owner, address(0), id);
}
/*//////////////////////////////////////////////////////////////
INTERNAL SAFE MINT LOGIC
//////////////////////////////////////////////////////////////*/function_safeMint(address to, uint256 id) internalvirtual{
_mint(to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "")
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
function_safeMint(address to, uint256 id, bytesmemory data) internalvirtual{
_mint(to, id);
require(
!_isContract(to)
|| IERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data)
== IERC721TokenReceiver.onERC721Received.selector,
"UNSAFE_RECIPIENT"
);
}
/*//////////////////////////////////////////////////////////////
HELPERS
//////////////////////////////////////////////////////////////*/function_isContract(address _addr) privateviewreturns (bool) {
uint256 codeLength;
// Assembly required for versions < 0.8.0 to check extcodesize.assembly {
codeLength :=extcodesize(_addr)
}
return codeLength >0;
}
}
interfaceIERC721TokenReceiver{
functiononERC721Received(address, address, uint256, bytescalldata) externalreturns (bytes4);
}
Contract Source Code
File 11 of 29: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragmasolidity ^0.8.20;import {Context} from"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/errorOwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/errorOwnableInvalidOwner(address owner);
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/constructor(address initialOwner) {
if (initialOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
if (newOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {VmSafe} from"./Vm.sol";
/**
* StdChains provides information about EVM compatible chains that can be used in scripts/tests.
* For each chain, the chain's name, chain ID, and a default RPC URL are provided. Chains are
* identified by their alias, which is the same as the alias in the `[rpc_endpoints]` section of
* the `foundry.toml` file. For best UX, ensure the alias in the `foundry.toml` file match the
* alias used in this contract, which can be found as the first argument to the
* `setChainWithDefaultRpcUrl` call in the `initializeStdChains` function.
*
* There are two main ways to use this contract:
* 1. Set a chain with `setChain(string memory chainAlias, ChainData memory chain)` or
* `setChain(string memory chainAlias, Chain memory chain)`
* 2. Get a chain with `getChain(string memory chainAlias)` or `getChain(uint256 chainId)`.
*
* The first time either of those are used, chains are initialized with the default set of RPC URLs.
* This is done in `initializeStdChains`, which uses `setChainWithDefaultRpcUrl`. Defaults are recorded in
* `defaultRpcUrls`.
*
* The `setChain` function is straightforward, and it simply saves off the given chain data.
*
* The `getChain` methods use `getChainWithUpdatedRpcUrl` to return a chain. For example, let's say
* we want to retrieve the RPC URL for `mainnet`:
* - If you have specified data with `setChain`, it will return that.
* - If you have configured a mainnet RPC URL in `foundry.toml`, it will return the URL, provided it
* is valid (e.g. a URL is specified, or an environment variable is given and exists).
* - If neither of the above conditions is met, the default data is returned.
*
* Summarizing the above, the prioritization hierarchy is `setChain` -> `foundry.toml` -> environment variable -> defaults.
*/abstractcontractStdChains{
VmSafe privateconstant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
boolprivate stdChainsInitialized;
structChainData {
string name;
uint256 chainId;
string rpcUrl;
}
structChain {
// The chain name.string name;
// The chain's Chain ID.uint256 chainId;
// The chain's alias. (i.e. what gets specified in `foundry.toml`).string chainAlias;
// A default RPC endpoint for this chain.// NOTE: This default RPC URL is included for convenience to facilitate quick tests and// experimentation. Do not use this RPC URL for production test suites, CI, or other heavy// usage as you will be throttled and this is a disservice to others who need this endpoint.string rpcUrl;
}
// Maps from the chain's alias (matching the alias in the `foundry.toml` file) to chain data.mapping(string=> Chain) private chains;
// Maps from the chain's alias to it's default RPC URL.mapping(string=>string) private defaultRpcUrls;
// Maps from a chain ID to it's alias.mapping(uint256=>string) private idToAlias;
boolprivate fallbackToDefaultRpcUrls =true;
// The RPC URL will be fetched from config or defaultRpcUrls if possible.functiongetChain(stringmemory chainAlias) internalvirtualreturns (Chain memory chain) {
require(bytes(chainAlias).length!=0, "StdChains getChain(string): Chain alias cannot be the empty string.");
initializeStdChains();
chain = chains[chainAlias];
require(
chain.chainId !=0,
string(abi.encodePacked("StdChains getChain(string): Chain with alias \"", chainAlias, "\" not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
functiongetChain(uint256 chainId) internalvirtualreturns (Chain memory chain) {
require(chainId !=0, "StdChains getChain(uint256): Chain ID cannot be 0.");
initializeStdChains();
stringmemory chainAlias = idToAlias[chainId];
chain = chains[chainAlias];
require(
chain.chainId !=0,
string(abi.encodePacked("StdChains getChain(uint256): Chain with ID ", vm.toString(chainId), " not found."))
);
chain = getChainWithUpdatedRpcUrl(chainAlias, chain);
}
// set chain info, with priority to argument's rpcUrl field.functionsetChain(stringmemory chainAlias, ChainData memory chain) internalvirtual{
require(
bytes(chainAlias).length!=0,
"StdChains setChain(string,ChainData): Chain alias cannot be the empty string."
);
require(chain.chainId !=0, "StdChains setChain(string,ChainData): Chain ID cannot be 0.");
initializeStdChains();
stringmemory foundAlias = idToAlias[chain.chainId];
require(
bytes(foundAlias).length==0||keccak256(bytes(foundAlias)) ==keccak256(bytes(chainAlias)),
string(
abi.encodePacked(
"StdChains setChain(string,ChainData): Chain ID ",
vm.toString(chain.chainId),
" already used by \"",
foundAlias,
"\"."
)
)
);
uint256 oldChainId = chains[chainAlias].chainId;
delete idToAlias[oldChainId];
chains[chainAlias] =
Chain({name: chain.name, chainId: chain.chainId, chainAlias: chainAlias, rpcUrl: chain.rpcUrl});
idToAlias[chain.chainId] = chainAlias;
}
// set chain info, with priority to argument's rpcUrl field.functionsetChain(stringmemory chainAlias, Chain memory chain) internalvirtual{
setChain(chainAlias, ChainData({name: chain.name, chainId: chain.chainId, rpcUrl: chain.rpcUrl}));
}
function_toUpper(stringmemory str) privatepurereturns (stringmemory) {
bytesmemory strb =bytes(str);
bytesmemory copy =newbytes(strb.length);
for (uint256 i =0; i < strb.length; i++) {
bytes1 b = strb[i];
if (b >=0x61&& b <=0x7A) {
copy[i] =bytes1(uint8(b) -32);
} else {
copy[i] = b;
}
}
returnstring(copy);
}
// lookup rpcUrl, in descending order of priority:// current -> config (foundry.toml) -> environment variable -> defaultfunctiongetChainWithUpdatedRpcUrl(stringmemory chainAlias, Chain memory chain)
privateviewreturns (Chain memory)
{
if (bytes(chain.rpcUrl).length==0) {
try vm.rpcUrl(chainAlias) returns (stringmemory configRpcUrl) {
chain.rpcUrl = configRpcUrl;
} catch (bytesmemory err) {
stringmemory envName =string(abi.encodePacked(_toUpper(chainAlias), "_RPC_URL"));
if (fallbackToDefaultRpcUrls) {
chain.rpcUrl = vm.envOr(envName, defaultRpcUrls[chainAlias]);
} else {
chain.rpcUrl = vm.envString(envName);
}
// Distinguish 'not found' from 'cannot read'// The upstream error thrown by forge for failing cheats changed so we check both the old and new versionsbytesmemory oldNotFoundError =abi.encodeWithSignature("CheatCodeError", string(abi.encodePacked("invalid rpc url ", chainAlias)));
bytesmemory newNotFoundError =abi.encodeWithSignature(
"CheatcodeError(string)", string(abi.encodePacked("invalid rpc url: ", chainAlias))
);
bytes32 errHash =keccak256(err);
if (
(errHash !=keccak256(oldNotFoundError) && errHash !=keccak256(newNotFoundError))
||bytes(chain.rpcUrl).length==0
) {
/// @solidity memory-safe-assemblyassembly {
revert(add(32, err), mload(err))
}
}
}
}
return chain;
}
functionsetFallbackToDefaultRpcUrls(bool useDefault) internal{
fallbackToDefaultRpcUrls = useDefault;
}
functioninitializeStdChains() private{
if (stdChainsInitialized) return;
stdChainsInitialized =true;
// If adding an RPC here, make sure to test the default RPC URL in `testRpcs`
setChainWithDefaultRpcUrl("anvil", ChainData("Anvil", 31337, "http://127.0.0.1:8545"));
setChainWithDefaultRpcUrl(
"mainnet", ChainData("Mainnet", 1, "https://eth-mainnet.alchemyapi.io/v2/pwc5rmJhrdoaSEfimoKEmsvOjKSmPDrP")
);
setChainWithDefaultRpcUrl(
"sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl("holesky", ChainData("Holesky", 17000, "https://rpc.holesky.ethpandaops.io"));
setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
setChainWithDefaultRpcUrl(
"optimism_sepolia", ChainData("Optimism Sepolia", 11155420, "https://sepolia.optimism.io")
);
setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl(
"arbitrum_one_sepolia", ChainData("Arbitrum One Sepolia", 421614, "https://sepolia-rollup.arbitrum.io/rpc")
);
setChainWithDefaultRpcUrl("arbitrum_nova", ChainData("Arbitrum Nova", 42170, "https://nova.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl("polygon", ChainData("Polygon", 137, "https://polygon-rpc.com"));
setChainWithDefaultRpcUrl(
"polygon_amoy", ChainData("Polygon Amoy", 80002, "https://rpc-amoy.polygon.technology")
);
setChainWithDefaultRpcUrl("avalanche", ChainData("Avalanche", 43114, "https://api.avax.network/ext/bc/C/rpc"));
setChainWithDefaultRpcUrl(
"avalanche_fuji", ChainData("Avalanche Fuji", 43113, "https://api.avax-test.network/ext/bc/C/rpc")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain", ChainData("BNB Smart Chain", 56, "https://bsc-dataseed1.binance.org")
);
setChainWithDefaultRpcUrl(
"bnb_smart_chain_testnet",
ChainData("BNB Smart Chain Testnet", 97, "https://rpc.ankr.com/bsc_testnet_chapel")
);
setChainWithDefaultRpcUrl("gnosis_chain", ChainData("Gnosis Chain", 100, "https://rpc.gnosischain.com"));
setChainWithDefaultRpcUrl("moonbeam", ChainData("Moonbeam", 1284, "https://rpc.api.moonbeam.network"));
setChainWithDefaultRpcUrl(
"moonriver", ChainData("Moonriver", 1285, "https://rpc.api.moonriver.moonbeam.network")
);
setChainWithDefaultRpcUrl("moonbase", ChainData("Moonbase", 1287, "https://rpc.testnet.moonbeam.network"));
setChainWithDefaultRpcUrl("base_sepolia", ChainData("Base Sepolia", 84532, "https://sepolia.base.org"));
setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
setChainWithDefaultRpcUrl("fraxtal", ChainData("Fraxtal", 252, "https://rpc.frax.com"));
setChainWithDefaultRpcUrl("fraxtal_testnet", ChainData("Fraxtal Testnet", 2522, "https://rpc.testnet.frax.com"));
}
// set chain info, with priority to chainAlias' rpc url in foundry.tomlfunctionsetChainWithDefaultRpcUrl(stringmemory chainAlias, ChainData memory chain) private{
stringmemory rpcUrl = chain.rpcUrl;
defaultRpcUrls[chainAlias] = rpcUrl;
chain.rpcUrl ="";
setChain(chainAlias, chain);
chain.rpcUrl = rpcUrl; // restore argument
}
}
Contract Source Code
File 16 of 29: StdCheats.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;pragmaexperimentalABIEncoderV2;import {StdStorage, stdStorage} from"./StdStorage.sol";
import {console2} from"./console2.sol";
import {Vm} from"./Vm.sol";
abstractcontractStdCheatsSafe{
Vm privateconstant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
uint256privateconstant UINT256_MAX =115792089237316195423570985008687907853269984665640564039457584007913129639935;
boolprivate gasMeteringOff;
// Data structures to parse Transaction objects from the broadcast artifact// that conform to EIP1559. The Raw structs is what is parsed from the JSON// and then converted to the one that is used by the user for better UX.structRawTx1559 {
string[] arguments;
address contractAddress;
string contractName;
// json value name = functionstring functionSig;
bytes32 hash;
// json value name = tx
RawTx1559Detail txDetail;
// json value name = typestring opcode;
}
structRawTx1559Detail {
AccessList[] accessList;
bytes data;
addressfrom;
bytes gas;
bytes nonce;
address to;
bytes txType;
bytes value;
}
structTx1559 {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
bytes32 hash;
Tx1559Detail txDetail;
string opcode;
}
structTx1559Detail {
AccessList[] accessList;
bytes data;
addressfrom;
uint256 gas;
uint256 nonce;
address to;
uint256 txType;
uint256 value;
}
// Data structures to parse Transaction objects from the broadcast artifact// that DO NOT conform to EIP1559. The Raw structs is what is parsed from the JSON// and then converted to the one that is used by the user for better UX.structTxLegacy {
string[] arguments;
address contractAddress;
string contractName;
string functionSig;
string hash;
string opcode;
TxDetailLegacy transaction;
}
structTxDetailLegacy {
AccessList[] accessList;
uint256 chainId;
bytes data;
addressfrom;
uint256 gas;
uint256 gasPrice;
bytes32 hash;
uint256 nonce;
bytes1 opcode;
bytes32 r;
bytes32 s;
uint256 txType;
address to;
uint8 v;
uint256 value;
}
structAccessList {
address accessAddress;
bytes32[] storageKeys;
}
// Data structures to parse Receipt objects from the broadcast artifact.// The Raw structs is what is parsed from the JSON// and then converted to the one that is used by the user for better UX.structRawReceipt {
bytes32 blockHash;
bytes blockNumber;
address contractAddress;
bytes cumulativeGasUsed;
bytes effectiveGasPrice;
addressfrom;
bytes gasUsed;
RawReceiptLog[] logs;
bytes logsBloom;
bytes status;
address to;
bytes32 transactionHash;
bytes transactionIndex;
}
structReceipt {
bytes32 blockHash;
uint256 blockNumber;
address contractAddress;
uint256 cumulativeGasUsed;
uint256 effectiveGasPrice;
addressfrom;
uint256 gasUsed;
ReceiptLog[] logs;
bytes logsBloom;
uint256 status;
address to;
bytes32 transactionHash;
uint256 transactionIndex;
}
// Data structures to parse the entire broadcast artifact, assuming the// transactions conform to EIP1559.structEIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
Receipt[] receipts;
uint256 timestamp;
Tx1559[] transactions;
TxReturn[] txReturns;
}
structRawEIP1559ScriptArtifact {
string[] libraries;
string path;
string[] pending;
RawReceipt[] receipts;
TxReturn[] txReturns;
uint256 timestamp;
RawTx1559[] transactions;
}
structRawReceiptLog {
// json value = addressaddress logAddress;
bytes32 blockHash;
bytes blockNumber;
bytes data;
bytes logIndex;
bool removed;
bytes32[] topics;
bytes32 transactionHash;
bytes transactionIndex;
bytes transactionLogIndex;
}
structReceiptLog {
// json value = addressaddress logAddress;
bytes32 blockHash;
uint256 blockNumber;
bytes data;
uint256 logIndex;
bytes32[] topics;
uint256 transactionIndex;
uint256 transactionLogIndex;
bool removed;
}
structTxReturn {
string internalType;
string value;
}
structAccount {
address addr;
uint256 key;
}
enumAddressType {
Payable,
NonPayable,
ZeroAddress,
Precompile,
ForgeAddress
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.functionassumeNotBlacklisted(address token, address addr) internalviewvirtual{
// Nothing to check if `token` is not a contract.uint256 tokenCodeSize;
assembly {
tokenCodeSize :=extcodesize(token)
}
require(tokenCodeSize >0, "StdCheats assumeNotBlacklisted(address,address): Token address is not a contract.");
bool success;
bytesmemory returnData;
// 4-byte selector for `isBlacklisted(address)`, used by USDC.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xfe575a87, addr));
vm.assume(!success ||abi.decode(returnData, (bool)) ==false);
// 4-byte selector for `isBlackListed(address)`, used by USDT.
(success, returnData) = token.staticcall(abi.encodeWithSelector(0xe47d6060, addr));
vm.assume(!success ||abi.decode(returnData, (bool)) ==false);
}
// Checks that `addr` is not blacklisted by token contracts that have a blacklist.// This is identical to `assumeNotBlacklisted(address,address)` but with a different name, for// backwards compatibility, since this name was used in the original PR which has already has// a release. This function can be removed in a future release once we want a breaking change.functionassumeNoBlacklisted(address token, address addr) internalviewvirtual{
assumeNotBlacklisted(token, addr);
}
functionassumeAddressIsNot(address addr, AddressType addressType) internalvirtual{
if (addressType == AddressType.Payable) {
assumeNotPayable(addr);
} elseif (addressType == AddressType.NonPayable) {
assumePayable(addr);
} elseif (addressType == AddressType.ZeroAddress) {
assumeNotZeroAddress(addr);
} elseif (addressType == AddressType.Precompile) {
assumeNotPrecompile(addr);
} elseif (addressType == AddressType.ForgeAddress) {
assumeNotForgeAddress(addr);
}
}
functionassumeAddressIsNot(address addr, AddressType addressType1, AddressType addressType2) internalvirtual{
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
}
functionassumeAddressIsNot(address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3
) internalvirtual{
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
}
functionassumeAddressIsNot(address addr,
AddressType addressType1,
AddressType addressType2,
AddressType addressType3,
AddressType addressType4
) internalvirtual{
assumeAddressIsNot(addr, addressType1);
assumeAddressIsNot(addr, addressType2);
assumeAddressIsNot(addr, addressType3);
assumeAddressIsNot(addr, addressType4);
}
// This function checks whether an address, `addr`, is payable. It works by sending 1 wei to// `addr` and checking the `success` return value.// NOTE: This function may result in state changes depending on the fallback/receive logic// implemented by `addr`, which should be taken into account when this function is used.function_isPayable(address addr) privatereturns (bool) {
require(
addr.balance< UINT256_MAX,
"StdCheats _isPayable(address): Balance equals max uint256, so it cannot receive any more funds"
);
uint256 origBalanceTest =address(this).balance;
uint256 origBalanceAddr =address(addr).balance;
vm.deal(address(this), 1);
(bool success,) =payable(addr).call{value: 1}("");
// reset balances
vm.deal(address(this), origBalanceTest);
vm.deal(addr, origBalanceAddr);
return success;
}
// NOTE: This function may result in state changes depending on the fallback/receive logic// implemented by `addr`, which should be taken into account when this function is used. See the// `_isPayable` method for more information.functionassumePayable(address addr) internalvirtual{
vm.assume(_isPayable(addr));
}
functionassumeNotPayable(address addr) internalvirtual{
vm.assume(!_isPayable(addr));
}
functionassumeNotZeroAddress(address addr) internalpurevirtual{
vm.assume(addr !=address(0));
}
functionassumeNotPrecompile(address addr) internalpurevirtual{
assumeNotPrecompile(addr, _pureChainId());
}
functionassumeNotPrecompile(address addr, uint256 chainId) internalpurevirtual{
// Note: For some chains like Optimism these are technically predeploys (i.e. bytecode placed at a specific// address), but the same rationale for excluding them applies so we include those too.// These should be present on all EVM-compatible chains.
vm.assume(addr <address(0x1) || addr >address(0x9));
// forgefmt: disable-startif (chainId ==10|| chainId ==420) {
// https://github.com/ethereum-optimism/optimism/blob/eaa371a0184b56b7ca6d9eb9cb0a2b78b2ccd864/op-bindings/predeploys/addresses.go#L6-L21
vm.assume(addr <address(0x4200000000000000000000000000000000000000) || addr >address(0x4200000000000000000000000000000000000800));
} elseif (chainId ==42161|| chainId ==421613) {
// https://developer.arbitrum.io/useful-addresses#arbitrum-precompiles-l2-same-on-all-arb-chains
vm.assume(addr <address(0x0000000000000000000000000000000000000064) || addr >address(0x0000000000000000000000000000000000000068));
} elseif (chainId ==43114|| chainId ==43113) {
// https://github.com/ava-labs/subnet-evm/blob/47c03fd007ecaa6de2c52ea081596e0a88401f58/precompile/params.go#L18-L59
vm.assume(addr <address(0x0100000000000000000000000000000000000000) || addr >address(0x01000000000000000000000000000000000000ff));
vm.assume(addr <address(0x0200000000000000000000000000000000000000) || addr >address(0x02000000000000000000000000000000000000FF));
vm.assume(addr <address(0x0300000000000000000000000000000000000000) || addr >address(0x03000000000000000000000000000000000000Ff));
}
// forgefmt: disable-end
}
functionassumeNotForgeAddress(address addr) internalpurevirtual{
// vm, console, and Create2Deployer addresses
vm.assume(
addr !=address(vm) && addr !=0x000000000000000000636F6e736F6c652e6c6f67&& addr !=0x4e59b44847b379578588920cA78FbF26c0B4956C
);
}
functionreadEIP1559ScriptArtifact(stringmemory path)
internalviewvirtualreturns (EIP1559ScriptArtifact memory)
{
stringmemory data = vm.readFile(path);
bytesmemory parsedData = vm.parseJson(data);
RawEIP1559ScriptArtifact memory rawArtifact =abi.decode(parsedData, (RawEIP1559ScriptArtifact));
EIP1559ScriptArtifact memory artifact;
artifact.libraries = rawArtifact.libraries;
artifact.path = rawArtifact.path;
artifact.timestamp = rawArtifact.timestamp;
artifact.pending = rawArtifact.pending;
artifact.txReturns = rawArtifact.txReturns;
artifact.receipts = rawToConvertedReceipts(rawArtifact.receipts);
artifact.transactions = rawToConvertedEIPTx1559s(rawArtifact.transactions);
return artifact;
}
functionrawToConvertedEIPTx1559s(RawTx1559[] memory rawTxs) internalpurevirtualreturns (Tx1559[] memory) {
Tx1559[] memory txs =new Tx1559[](rawTxs.length);
for (uint256 i; i < rawTxs.length; i++) {
txs[i] = rawToConvertedEIPTx1559(rawTxs[i]);
}
return txs;
}
functionrawToConvertedEIPTx1559(RawTx1559 memory rawTx) internalpurevirtualreturns (Tx1559 memory) {
Tx1559 memory transaction;
transaction.arguments = rawTx.arguments;
transaction.contractName = rawTx.contractName;
transaction.functionSig = rawTx.functionSig;
transaction.hash = rawTx.hash;
transaction.txDetail = rawToConvertedEIP1559Detail(rawTx.txDetail);
transaction.opcode = rawTx.opcode;
return transaction;
}
functionrawToConvertedEIP1559Detail(RawTx1559Detail memory rawDetail)
internalpurevirtualreturns (Tx1559Detail memory)
{
Tx1559Detail memory txDetail;
txDetail.data = rawDetail.data;
txDetail.from = rawDetail.from;
txDetail.to = rawDetail.to;
txDetail.nonce = _bytesToUint(rawDetail.nonce);
txDetail.txType = _bytesToUint(rawDetail.txType);
txDetail.value= _bytesToUint(rawDetail.value);
txDetail.gas= _bytesToUint(rawDetail.gas);
txDetail.accessList = rawDetail.accessList;
return txDetail;
}
functionreadTx1559s(stringmemory path) internalviewvirtualreturns (Tx1559[] memory) {
stringmemory deployData = vm.readFile(path);
bytesmemory parsedDeployData = vm.parseJson(deployData, ".transactions");
RawTx1559[] memory rawTxs =abi.decode(parsedDeployData, (RawTx1559[]));
return rawToConvertedEIPTx1559s(rawTxs);
}
functionreadTx1559(stringmemory path, uint256 index) internalviewvirtualreturns (Tx1559 memory) {
stringmemory deployData = vm.readFile(path);
stringmemory key =string(abi.encodePacked(".transactions[", vm.toString(index), "]"));
bytesmemory parsedDeployData = vm.parseJson(deployData, key);
RawTx1559 memory rawTx =abi.decode(parsedDeployData, (RawTx1559));
return rawToConvertedEIPTx1559(rawTx);
}
// Analogous to readTransactions, but for receipts.functionreadReceipts(stringmemory path) internalviewvirtualreturns (Receipt[] memory) {
stringmemory deployData = vm.readFile(path);
bytesmemory parsedDeployData = vm.parseJson(deployData, ".receipts");
RawReceipt[] memory rawReceipts =abi.decode(parsedDeployData, (RawReceipt[]));
return rawToConvertedReceipts(rawReceipts);
}
functionreadReceipt(stringmemory path, uint256 index) internalviewvirtualreturns (Receipt memory) {
stringmemory deployData = vm.readFile(path);
stringmemory key =string(abi.encodePacked(".receipts[", vm.toString(index), "]"));
bytesmemory parsedDeployData = vm.parseJson(deployData, key);
RawReceipt memory rawReceipt =abi.decode(parsedDeployData, (RawReceipt));
return rawToConvertedReceipt(rawReceipt);
}
functionrawToConvertedReceipts(RawReceipt[] memory rawReceipts) internalpurevirtualreturns (Receipt[] memory) {
Receipt[] memory receipts =new Receipt[](rawReceipts.length);
for (uint256 i; i < rawReceipts.length; i++) {
receipts[i] = rawToConvertedReceipt(rawReceipts[i]);
}
return receipts;
}
functionrawToConvertedReceipt(RawReceipt memory rawReceipt) internalpurevirtualreturns (Receipt memory) {
Receipt memory receipt;
receipt.blockHash = rawReceipt.blockHash;
receipt.to = rawReceipt.to;
receipt.from = rawReceipt.from;
receipt.contractAddress = rawReceipt.contractAddress;
receipt.effectiveGasPrice = _bytesToUint(rawReceipt.effectiveGasPrice);
receipt.cumulativeGasUsed = _bytesToUint(rawReceipt.cumulativeGasUsed);
receipt.gasUsed = _bytesToUint(rawReceipt.gasUsed);
receipt.status = _bytesToUint(rawReceipt.status);
receipt.transactionIndex = _bytesToUint(rawReceipt.transactionIndex);
receipt.blockNumber = _bytesToUint(rawReceipt.blockNumber);
receipt.logs = rawToConvertedReceiptLogs(rawReceipt.logs);
receipt.logsBloom = rawReceipt.logsBloom;
receipt.transactionHash = rawReceipt.transactionHash;
return receipt;
}
functionrawToConvertedReceiptLogs(RawReceiptLog[] memory rawLogs)
internalpurevirtualreturns (ReceiptLog[] memory)
{
ReceiptLog[] memory logs =new ReceiptLog[](rawLogs.length);
for (uint256 i; i < rawLogs.length; i++) {
logs[i].logAddress = rawLogs[i].logAddress;
logs[i].blockHash = rawLogs[i].blockHash;
logs[i].blockNumber = _bytesToUint(rawLogs[i].blockNumber);
logs[i].data = rawLogs[i].data;
logs[i].logIndex = _bytesToUint(rawLogs[i].logIndex);
logs[i].topics = rawLogs[i].topics;
logs[i].transactionIndex = _bytesToUint(rawLogs[i].transactionIndex);
logs[i].transactionLogIndex = _bytesToUint(rawLogs[i].transactionLogIndex);
logs[i].removed = rawLogs[i].removed;
}
return logs;
}
// Deploy a contract by fetching the contract bytecode from// the artifacts directory// e.g. `deployCode(code, abi.encode(arg1,arg2,arg3))`functiondeployCode(stringmemory what, bytesmemory args) internalvirtualreturns (address addr) {
bytesmemory bytecode =abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assemblyassembly {
addr :=create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr !=address(0), "StdCheats deployCode(string,bytes): Deployment failed.");
}
functiondeployCode(stringmemory what) internalvirtualreturns (address addr) {
bytesmemory bytecode = vm.getCode(what);
/// @solidity memory-safe-assemblyassembly {
addr :=create(0, add(bytecode, 0x20), mload(bytecode))
}
require(addr !=address(0), "StdCheats deployCode(string): Deployment failed.");
}
/// @dev deploy contract with value on constructionfunctiondeployCode(stringmemory what, bytesmemory args, uint256 val) internalvirtualreturns (address addr) {
bytesmemory bytecode =abi.encodePacked(vm.getCode(what), args);
/// @solidity memory-safe-assemblyassembly {
addr :=create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr !=address(0), "StdCheats deployCode(string,bytes,uint256): Deployment failed.");
}
functiondeployCode(stringmemory what, uint256 val) internalvirtualreturns (address addr) {
bytesmemory bytecode = vm.getCode(what);
/// @solidity memory-safe-assemblyassembly {
addr :=create(val, add(bytecode, 0x20), mload(bytecode))
}
require(addr !=address(0), "StdCheats deployCode(string,uint256): Deployment failed.");
}
// creates a labeled address and the corresponding private keyfunctionmakeAddrAndKey(stringmemory name) internalvirtualreturns (address addr, uint256 privateKey) {
privateKey =uint256(keccak256(abi.encodePacked(name)));
addr = vm.addr(privateKey);
vm.label(addr, name);
}
// creates a labeled addressfunctionmakeAddr(stringmemory name) internalvirtualreturns (address addr) {
(addr,) = makeAddrAndKey(name);
}
// Destroys an account immediately, sending the balance to beneficiary.// Destroying means: balance will be zero, code will be empty, and nonce will be 0// This is similar to selfdestruct but not identical: selfdestruct destroys code and nonce// only after tx ends, this will run immediately.functiondestroyAccount(address who, address beneficiary) internalvirtual{
uint256 currBalance = who.balance;
vm.etch(who, abi.encode());
vm.deal(who, 0);
vm.resetNonce(who);
uint256 beneficiaryBalance = beneficiary.balance;
vm.deal(beneficiary, currBalance + beneficiaryBalance);
}
// creates a struct containing both a labeled address and the corresponding private keyfunctionmakeAccount(stringmemory name) internalvirtualreturns (Account memory account) {
(account.addr, account.key) = makeAddrAndKey(name);
}
functionderiveRememberKey(stringmemory mnemonic, uint32 index)
internalvirtualreturns (address who, uint256 privateKey)
{
privateKey = vm.deriveKey(mnemonic, index);
who = vm.rememberKey(privateKey);
}
function_bytesToUint(bytesmemory b) privatepurereturns (uint256) {
require(b.length<=32, "StdCheats _bytesToUint(bytes): Bytes length exceeds 32.");
returnabi.decode(abi.encodePacked(newbytes(32- b.length), b), (uint256));
}
functionisFork() internalviewvirtualreturns (bool status) {
try vm.activeFork() {
status =true;
} catch (bytesmemory) {}
}
modifierskipWhenForking() {
if (!isFork()) {
_;
}
}
modifierskipWhenNotForking() {
if (isFork()) {
_;
}
}
modifiernoGasMetering() {
vm.pauseGasMetering();
// To prevent turning gas monitoring back on with nested functions that use this modifier,// we check if gasMetering started in the off position. If it did, we don't want to turn// it back on until we exit the top level function that used the modifier//// i.e. funcA() noGasMetering { funcB() }, where funcB has noGasMetering as well.// funcA will have `gasStartedOff` as false, funcB will have it as true,// so we only turn metering back on at the end of the funcAbool gasStartedOff = gasMeteringOff;
gasMeteringOff =true;
_;
// if gas metering was on when this modifier was called, turn it back on at the endif (!gasStartedOff) {
gasMeteringOff =false;
vm.resumeGasMetering();
}
}
// We use this complex approach of `_viewChainId` and `_pureChainId` to ensure there are no// compiler warnings when accessing chain ID in any solidity version supported by forge-std. We// can't simply access the chain ID in a normal view or pure function because the solc View Pure// Checker changed `chainid` from pure to view in 0.8.0.function_viewChainId() privateviewreturns (uint256 chainId) {
// Assembly required since `block.chainid` was introduced in 0.8.0.assembly {
chainId :=chainid()
}
address(this); // Silence warnings in older Solc versions.
}
function_pureChainId() privatepurereturns (uint256 chainId) {
function() internalviewreturns (uint256) fnIn = _viewChainId;
function() internalpurereturns (uint256) pureChainId;
assembly {
pureChainId := fnIn
}
chainId = pureChainId();
}
}
// Wrappers around cheatcodes to avoid footgunsabstractcontractStdCheatsisStdCheatsSafe{
usingstdStorageforStdStorage;
StdStorage private stdstore;
Vm privateconstant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
addressprivateconstant CONSOLE2_ADDRESS =0x000000000000000000636F6e736F6c652e6c6f67;
// Skip forward or rewind time by the specified number of secondsfunctionskip(uint256 time) internalvirtual{
vm.warp(block.timestamp+ time);
}
functionrewind(uint256 time) internalvirtual{
vm.warp(block.timestamp- time);
}
// Setup a prank from an address that has some etherfunctionhoax(address msgSender) internalvirtual{
vm.deal(msgSender, 1<<128);
vm.prank(msgSender);
}
functionhoax(address msgSender, uint256 give) internalvirtual{
vm.deal(msgSender, give);
vm.prank(msgSender);
}
functionhoax(address msgSender, address origin) internalvirtual{
vm.deal(msgSender, 1<<128);
vm.prank(msgSender, origin);
}
functionhoax(address msgSender, address origin, uint256 give) internalvirtual{
vm.deal(msgSender, give);
vm.prank(msgSender, origin);
}
// Start perpetual prank from an address that has some etherfunctionstartHoax(address msgSender) internalvirtual{
vm.deal(msgSender, 1<<128);
vm.startPrank(msgSender);
}
functionstartHoax(address msgSender, uint256 give) internalvirtual{
vm.deal(msgSender, give);
vm.startPrank(msgSender);
}
// Start perpetual prank from an address that has some ether// tx.origin is set to the origin parameterfunctionstartHoax(address msgSender, address origin) internalvirtual{
vm.deal(msgSender, 1<<128);
vm.startPrank(msgSender, origin);
}
functionstartHoax(address msgSender, address origin, uint256 give) internalvirtual{
vm.deal(msgSender, give);
vm.startPrank(msgSender, origin);
}
functionchangePrank(address msgSender) internalvirtual{
console2_log_StdCheats("changePrank is deprecated. Please use vm.startPrank instead.");
vm.stopPrank();
vm.startPrank(msgSender);
}
functionchangePrank(address msgSender, address txOrigin) internalvirtual{
vm.stopPrank();
vm.startPrank(msgSender, txOrigin);
}
// The same as Vm's `deal`// Use the alternative signature for ERC20 tokensfunctiondeal(address to, uint256 give) internalvirtual{
vm.deal(to, give);
}
// Set the balance of an account for any ERC20 token// Use the alternative signature to update `totalSupply`functiondeal(address token, address to, uint256 give) internalvirtual{
deal(token, to, give, false);
}
// Set the balance of an account for any ERC1155 token// Use the alternative signature to update `totalSupply`functiondealERC1155(address token, address to, uint256 id, uint256 give) internalvirtual{
dealERC1155(token, to, id, give, false);
}
functiondeal(address token, address to, uint256 give, bool adjust) internalvirtual{
// get current balance
(, bytesmemory balData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 prevBal =abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(give);
// update total supplyif (adjust) {
(, bytesmemory totSupData) = token.staticcall(abi.encodeWithSelector(0x18160ddd));
uint256 totSup =abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0x18160ddd).checked_write(totSup);
}
}
functiondealERC1155(address token, address to, uint256 id, uint256 give, bool adjust) internalvirtual{
// get current balance
(, bytesmemory balData) = token.staticcall(abi.encodeWithSelector(0x00fdd58e, to, id));
uint256 prevBal =abi.decode(balData, (uint256));
// update balance
stdstore.target(token).sig(0x00fdd58e).with_key(to).with_key(id).checked_write(give);
// update total supplyif (adjust) {
(, bytesmemory totSupData) = token.staticcall(abi.encodeWithSelector(0xbd85b039, id));
require(
totSupData.length!=0,
"StdCheats deal(address,address,uint,uint,bool): target contract is not ERC1155Supply."
);
uint256 totSup =abi.decode(totSupData, (uint256));
if (give < prevBal) {
totSup -= (prevBal - give);
} else {
totSup += (give - prevBal);
}
stdstore.target(token).sig(0xbd85b039).with_key(id).checked_write(totSup);
}
}
functiondealERC721(address token, address to, uint256 id) internalvirtual{
// check if token id is already minted and the actual owner.
(bool successMinted, bytesmemory ownerData) = token.staticcall(abi.encodeWithSelector(0x6352211e, id));
require(successMinted, "StdCheats deal(address,address,uint,bool): id not minted.");
// get owner current balance
(, bytesmemory fromBalData) =
token.staticcall(abi.encodeWithSelector(0x70a08231, abi.decode(ownerData, (address))));
uint256 fromPrevBal =abi.decode(fromBalData, (uint256));
// get new user current balance
(, bytesmemory toBalData) = token.staticcall(abi.encodeWithSelector(0x70a08231, to));
uint256 toPrevBal =abi.decode(toBalData, (uint256));
// update balances
stdstore.target(token).sig(0x70a08231).with_key(abi.decode(ownerData, (address))).checked_write(--fromPrevBal);
stdstore.target(token).sig(0x70a08231).with_key(to).checked_write(++toPrevBal);
// update owner
stdstore.target(token).sig(0x6352211e).with_key(id).checked_write(to);
}
functiondeployCodeTo(stringmemory what, address where) internalvirtual{
deployCodeTo(what, "", 0, where);
}
functiondeployCodeTo(stringmemory what, bytesmemory args, address where) internalvirtual{
deployCodeTo(what, args, 0, where);
}
functiondeployCodeTo(stringmemory what, bytesmemory args, uint256 value, address where) internalvirtual{
bytesmemory creationCode = vm.getCode(what);
vm.etch(where, abi.encodePacked(creationCode, args));
(bool success, bytesmemory runtimeBytecode) = where.call{value: value}("");
require(success, "StdCheats deployCodeTo(string,bytes,uint256,address): Failed to create runtime bytecode.");
vm.etch(where, runtimeBytecode);
}
// Used to prevent the compilation of console, which shortens the compilation time when console is not used elsewhere.functionconsole2_log_StdCheats(stringmemory p0) privateview{
(bool status,) =address(CONSOLE2_ADDRESS).staticcall(abi.encodeWithSignature("log(string)", p0));
status;
}
}
Contract Source Code
File 17 of 29: StdError.sol
// SPDX-License-Identifier: MIT// Panics work for versions >=0.8.0, but we lowered the pragma to make this compatible with Testpragmasolidity >=0.6.2 <0.9.0;librarystdError{
bytespublicconstant assertionError =abi.encodeWithSignature("Panic(uint256)", 0x01);
bytespublicconstant arithmeticError =abi.encodeWithSignature("Panic(uint256)", 0x11);
bytespublicconstant divisionError =abi.encodeWithSignature("Panic(uint256)", 0x12);
bytespublicconstant enumConversionError =abi.encodeWithSignature("Panic(uint256)", 0x21);
bytespublicconstant encodeStorageError =abi.encodeWithSignature("Panic(uint256)", 0x22);
bytespublicconstant popError =abi.encodeWithSignature("Panic(uint256)", 0x31);
bytespublicconstant indexOOBError =abi.encodeWithSignature("Panic(uint256)", 0x32);
bytespublicconstant memOverflowError =abi.encodeWithSignature("Panic(uint256)", 0x41);
bytespublicconstant zeroVarError =abi.encodeWithSignature("Panic(uint256)", 0x51);
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;librarystdMath{
int256privateconstant INT256_MIN =-57896044618658097711785492504343953926634992332820282019728792003956564819968;
functionabs(int256 a) internalpurereturns (uint256) {
// Required or it will fail when `a = type(int256).min`if (a == INT256_MIN) {
return57896044618658097711785492504343953926634992332820282019728792003956564819968;
}
returnuint256(a >0 ? a : -a);
}
functiondelta(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a - b : b - a;
}
functiondelta(int256 a, int256 b) internalpurereturns (uint256) {
// a and b are of the same sign// this works thanks to two's complement, the left-most bit is the sign bitif ((a ^ b) >-1) {
return delta(abs(a), abs(b));
}
// a and b are of opposite signsreturn abs(a) + abs(b);
}
functionpercentDelta(uint256 a, uint256 b) internalpurereturns (uint256) {
uint256 absDelta = delta(a, b);
return absDelta *1e18/ b;
}
functionpercentDelta(int256 a, int256 b) internalpurereturns (uint256) {
uint256 absDelta = delta(a, b);
uint256 absB = abs(b);
return absDelta *1e18/ absB;
}
}
Contract Source Code
File 21 of 29: StdStorage.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {Vm} from"./Vm.sol";
structFindData {
uint256 slot;
uint256 offsetLeft;
uint256 offsetRight;
bool found;
}
structStdStorage {
mapping(address=>mapping(bytes4=>mapping(bytes32=> FindData))) finds;
bytes32[] _keys;
bytes4 _sig;
uint256 _depth;
address _target;
bytes32 _set;
bool _enable_packed_slots;
bytes _calldata;
}
librarystdStorageSafe{
eventSlotFound(address who, bytes4 fsig, bytes32 keysHash, uint256 slot);
eventWARNING_UninitedSlot(address who, uint256 slot);
Vm privateconstant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
uint256constant UINT256_MAX =115792089237316195423570985008687907853269984665640564039457584007913129639935;
functionsigs(stringmemory sigStr) internalpurereturns (bytes4) {
returnbytes4(keccak256(bytes(sigStr)));
}
functiongetCallParams(StdStorage storageself) internalviewreturns (bytesmemory) {
if (self._calldata.length==0) {
return flatten(self._keys);
} else {
returnself._calldata;
}
}
// Calls target contract with configured parametersfunctioncallTarget(StdStorage storageself) internalviewreturns (bool, bytes32) {
bytesmemory cald =abi.encodePacked(self._sig, getCallParams(self));
(bool success, bytesmemory rdat) =self._target.staticcall(cald);
bytes32 result = bytesToBytes32(rdat, 32*self._depth);
return (success, result);
}
// Tries mutating slot value to determine if the targeted value is stored in it.// If current value is 0, then we are setting slot value to type(uint256).max// Otherwise, we set it to 0. That way, return value should always be affected.functioncheckSlotMutatesCall(StdStorage storageself, bytes32 slot) internalreturns (bool) {
bytes32 prevSlotValue = vm.load(self._target, slot);
(bool success, bytes32 prevReturnValue) = callTarget(self);
bytes32 testVal = prevReturnValue ==bytes32(0) ? bytes32(UINT256_MAX) : bytes32(0);
vm.store(self._target, slot, testVal);
(, bytes32 newReturnValue) = callTarget(self);
vm.store(self._target, slot, prevSlotValue);
return (success && (prevReturnValue != newReturnValue));
}
// Tries setting one of the bits in slot to 1 until return value changes.// Index of resulted bit is an offset packed slot has from left/right sidefunctionfindOffset(StdStorage storageself, bytes32 slot, bool left) internalreturns (bool, uint256) {
for (uint256 offset =0; offset <256; offset++) {
uint256 valueToPut = left ? (1<< (255- offset)) : (1<< offset);
vm.store(self._target, slot, bytes32(valueToPut));
(bool success, bytes32 data) = callTarget(self);
if (success && (uint256(data) >0)) {
return (true, offset);
}
}
return (false, 0);
}
functionfindOffsets(StdStorage storageself, bytes32 slot) internalreturns (bool, uint256, uint256) {
bytes32 prevSlotValue = vm.load(self._target, slot);
(bool foundLeft, uint256 offsetLeft) = findOffset(self, slot, true);
(bool foundRight, uint256 offsetRight) = findOffset(self, slot, false);
// `findOffset` may mutate slot value, so we are setting it to initial value
vm.store(self._target, slot, prevSlotValue);
return (foundLeft && foundRight, offsetLeft, offsetRight);
}
functionfind(StdStorage storageself) internalreturns (FindData storage) {
return find(self, true);
}
/// @notice find an arbitrary storage slot given a function sig, input data, address of the contract and a value to check against// slot complexity:// if flat, will be bytes32(uint256(uint));// if map, will be keccak256(abi.encode(key, uint(slot)));// if deep map, will be keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))));// if map struct, will be bytes32(uint256(keccak256(abi.encode(key1, keccak256(abi.encode(key0, uint(slot)))))) + structFieldDepth);functionfind(StdStorage storageself, bool _clear) internalreturns (FindData storage) {
address who =self._target;
bytes4 fsig =self._sig;
uint256 field_depth =self._depth;
bytesmemory params = getCallParams(self);
// calldata to test againstif (self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
if (_clear) {
clear(self);
}
returnself.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
}
vm.record();
(, bytes32 callResult) = callTarget(self);
(bytes32[] memory reads,) = vm.accesses(address(who));
if (reads.length==0) {
revert("stdStorage find(StdStorage): No storage use detected for target.");
} else {
for (uint256 i =0; i < reads.length; i++) {
bytes32 prev = vm.load(who, reads[i]);
if (prev ==bytes32(0)) {
emit WARNING_UninitedSlot(who, uint256(reads[i]));
}
if (!checkSlotMutatesCall(self, reads[i])) {
continue;
}
(uint256 offsetLeft, uint256 offsetRight) = (0, 0);
if (self._enable_packed_slots) {
bool found;
(found, offsetLeft, offsetRight) = findOffsets(self, reads[i]);
if (!found) {
continue;
}
}
// Check that value between found offsets is equal to the current call resultuint256 curVal = (uint256(prev) & getMaskByOffsets(offsetLeft, offsetRight)) >> offsetRight;
if (uint256(callResult) != curVal) {
continue;
}
emit SlotFound(who, fsig, keccak256(abi.encodePacked(params, field_depth)), uint256(reads[i]));
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))] =
FindData(uint256(reads[i]), offsetLeft, offsetRight, true);
break;
}
}
require(
self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found,
"stdStorage find(StdStorage): Slot(s) not found."
);
if (_clear) {
clear(self);
}
returnself.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
}
functiontarget(StdStorage storageself, address _target) internalreturns (StdStorage storage) {
self._target = _target;
returnself;
}
functionsig(StdStorage storageself, bytes4 _sig) internalreturns (StdStorage storage) {
self._sig = _sig;
returnself;
}
functionsig(StdStorage storageself, stringmemory _sig) internalreturns (StdStorage storage) {
self._sig = sigs(_sig);
returnself;
}
functionwith_calldata(StdStorage storageself, bytesmemory _calldata) internalreturns (StdStorage storage) {
self._calldata = _calldata;
returnself;
}
functionwith_key(StdStorage storageself, address who) internalreturns (StdStorage storage) {
self._keys.push(bytes32(uint256(uint160(who))));
returnself;
}
functionwith_key(StdStorage storageself, uint256 amt) internalreturns (StdStorage storage) {
self._keys.push(bytes32(amt));
returnself;
}
functionwith_key(StdStorage storageself, bytes32 key) internalreturns (StdStorage storage) {
self._keys.push(key);
returnself;
}
functionenable_packed_slots(StdStorage storageself) internalreturns (StdStorage storage) {
self._enable_packed_slots =true;
returnself;
}
functiondepth(StdStorage storageself, uint256 _depth) internalreturns (StdStorage storage) {
self._depth = _depth;
returnself;
}
functionread(StdStorage storageself) privatereturns (bytesmemory) {
FindData storage data = find(self, false);
uint256 mask = getMaskByOffsets(data.offsetLeft, data.offsetRight);
uint256 value = (uint256(vm.load(self._target, bytes32(data.slot))) & mask) >> data.offsetRight;
clear(self);
returnabi.encode(value);
}
functionread_bytes32(StdStorage storageself) internalreturns (bytes32) {
returnabi.decode(read(self), (bytes32));
}
functionread_bool(StdStorage storageself) internalreturns (bool) {
int256 v = read_int(self);
if (v ==0) returnfalse;
if (v ==1) returntrue;
revert("stdStorage read_bool(StdStorage): Cannot decode. Make sure you are reading a bool.");
}
functionread_address(StdStorage storageself) internalreturns (address) {
returnabi.decode(read(self), (address));
}
functionread_uint(StdStorage storageself) internalreturns (uint256) {
returnabi.decode(read(self), (uint256));
}
functionread_int(StdStorage storageself) internalreturns (int256) {
returnabi.decode(read(self), (int256));
}
functionparent(StdStorage storageself) internalreturns (uint256, bytes32) {
address who =self._target;
uint256 field_depth =self._depth;
vm.startMappingRecording();
uint256 child = find(self, true).slot - field_depth;
(bool found, bytes32 key, bytes32 parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
return (uint256(parent_slot), key);
}
functionroot(StdStorage storageself) internalreturns (uint256) {
address who =self._target;
uint256 field_depth =self._depth;
vm.startMappingRecording();
uint256 child = find(self, true).slot - field_depth;
bool found;
bytes32 root_slot;
bytes32 parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(child));
if (!found) {
revert(
"stdStorage read_bool(StdStorage): Cannot find parent. Make sure you give a slot and startMappingRecording() has been called."
);
}
while (found) {
root_slot = parent_slot;
(found,, parent_slot) = vm.getMappingKeyAndParentOf(who, bytes32(root_slot));
}
returnuint256(root_slot);
}
functionbytesToBytes32(bytesmemory b, uint256 offset) privatepurereturns (bytes32) {
bytes32 out;
uint256 max = b.length>32 ? 32 : b.length;
for (uint256 i =0; i < max; i++) {
out |=bytes32(b[offset + i] &0xFF) >> (i *8);
}
return out;
}
functionflatten(bytes32[] memory b) privatepurereturns (bytesmemory) {
bytesmemory result =newbytes(b.length*32);
for (uint256 i =0; i < b.length; i++) {
bytes32 k = b[i];
/// @solidity memory-safe-assemblyassembly {
mstore(add(result, add(32, mul(32, i))), k)
}
}
return result;
}
functionclear(StdStorage storageself) internal{
deleteself._target;
deleteself._sig;
deleteself._keys;
deleteself._depth;
deleteself._enable_packed_slots;
deleteself._calldata;
}
// Returns mask which contains non-zero bits for values between `offsetLeft` and `offsetRight`// (slotValue & mask) >> offsetRight will be the value of the given packed variablefunctiongetMaskByOffsets(uint256 offsetLeft, uint256 offsetRight) internalpurereturns (uint256 mask) {
// mask = ((1 << (256 - (offsetRight + offsetLeft))) - 1) << offsetRight;// using assembly because (1 << 256) causes overflowassembly {
mask :=shl(offsetRight, sub(shl(sub(256, add(offsetRight, offsetLeft)), 1), 1))
}
}
// Returns slot value with updated packed variable.functiongetUpdatedSlotValue(bytes32 curValue, uint256 varValue, uint256 offsetLeft, uint256 offsetRight)
internalpurereturns (bytes32 newValue)
{
returnbytes32((uint256(curValue) &~getMaskByOffsets(offsetLeft, offsetRight)) | (varValue << offsetRight));
}
}
librarystdStorage{
Vm privateconstant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
functionsigs(stringmemory sigStr) internalpurereturns (bytes4) {
return stdStorageSafe.sigs(sigStr);
}
functionfind(StdStorage storageself) internalreturns (uint256) {
return find(self, true);
}
functionfind(StdStorage storageself, bool _clear) internalreturns (uint256) {
return stdStorageSafe.find(self, _clear).slot;
}
functiontarget(StdStorage storageself, address _target) internalreturns (StdStorage storage) {
return stdStorageSafe.target(self, _target);
}
functionsig(StdStorage storageself, bytes4 _sig) internalreturns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
functionsig(StdStorage storageself, stringmemory _sig) internalreturns (StdStorage storage) {
return stdStorageSafe.sig(self, _sig);
}
functionwith_key(StdStorage storageself, address who) internalreturns (StdStorage storage) {
return stdStorageSafe.with_key(self, who);
}
functionwith_key(StdStorage storageself, uint256 amt) internalreturns (StdStorage storage) {
return stdStorageSafe.with_key(self, amt);
}
functionwith_key(StdStorage storageself, bytes32 key) internalreturns (StdStorage storage) {
return stdStorageSafe.with_key(self, key);
}
functionwith_calldata(StdStorage storageself, bytesmemory _calldata) internalreturns (StdStorage storage) {
return stdStorageSafe.with_calldata(self, _calldata);
}
functionenable_packed_slots(StdStorage storageself) internalreturns (StdStorage storage) {
return stdStorageSafe.enable_packed_slots(self);
}
functiondepth(StdStorage storageself, uint256 _depth) internalreturns (StdStorage storage) {
return stdStorageSafe.depth(self, _depth);
}
functionclear(StdStorage storageself) internal{
stdStorageSafe.clear(self);
}
functionchecked_write(StdStorage storageself, address who) internal{
checked_write(self, bytes32(uint256(uint160(who))));
}
functionchecked_write(StdStorage storageself, uint256 amt) internal{
checked_write(self, bytes32(amt));
}
functionchecked_write_int(StdStorage storageself, int256 val) internal{
checked_write(self, bytes32(uint256(val)));
}
functionchecked_write(StdStorage storageself, bool write) internal{
bytes32 t;
/// @solidity memory-safe-assemblyassembly {
t := write
}
checked_write(self, t);
}
functionchecked_write(StdStorage storageself, bytes32 set) internal{
address who =self._target;
bytes4 fsig =self._sig;
uint256 field_depth =self._depth;
bytesmemory params = stdStorageSafe.getCallParams(self);
if (!self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))].found) {
find(self, false);
}
FindData storage data =self.finds[who][fsig][keccak256(abi.encodePacked(params, field_depth))];
if ((data.offsetLeft + data.offsetRight) >0) {
uint256 maxVal =2** (256- (data.offsetLeft + data.offsetRight));
require(
uint256(set) < maxVal,
string(
abi.encodePacked(
"stdStorage find(StdStorage): Packed slot. We can't fit value greater than ",
vm.toString(maxVal)
)
)
);
}
bytes32 curVal = vm.load(who, bytes32(data.slot));
bytes32 valToSet = stdStorageSafe.getUpdatedSlotValue(curVal, uint256(set), data.offsetLeft, data.offsetRight);
vm.store(who, bytes32(data.slot), valToSet);
(bool success, bytes32 callResult) = stdStorageSafe.callTarget(self);
if (!success || callResult != set) {
vm.store(who, bytes32(data.slot), curVal);
revert("stdStorage find(StdStorage): Failed to write value.");
}
clear(self);
}
functionread_bytes32(StdStorage storageself) internalreturns (bytes32) {
return stdStorageSafe.read_bytes32(self);
}
functionread_bool(StdStorage storageself) internalreturns (bool) {
return stdStorageSafe.read_bool(self);
}
functionread_address(StdStorage storageself) internalreturns (address) {
return stdStorageSafe.read_address(self);
}
functionread_uint(StdStorage storageself) internalreturns (uint256) {
return stdStorageSafe.read_uint(self);
}
functionread_int(StdStorage storageself) internalreturns (int256) {
return stdStorageSafe.read_int(self);
}
functionparent(StdStorage storageself) internalreturns (uint256, bytes32) {
return stdStorageSafe.parent(self);
}
functionroot(StdStorage storageself) internalreturns (uint256) {
return stdStorageSafe.root(self);
}
}
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;pragmaexperimentalABIEncoderV2;import {IMulticall3} from"./interfaces/IMulticall3.sol";
import {MockERC20} from"./mocks/MockERC20.sol";
import {MockERC721} from"./mocks/MockERC721.sol";
import {VmSafe} from"./Vm.sol";
abstractcontractStdUtils{
/*//////////////////////////////////////////////////////////////////////////
CONSTANTS
//////////////////////////////////////////////////////////////////////////*/
IMulticall3 privateconstant multicall = IMulticall3(0xcA11bde05977b3631167028862bE2a173976CA11);
VmSafe privateconstant vm = VmSafe(address(uint160(uint256(keccak256("hevm cheat code")))));
addressprivateconstant CONSOLE2_ADDRESS =0x000000000000000000636F6e736F6c652e6c6f67;
uint256privateconstant INT256_MIN_ABS =57896044618658097711785492504343953926634992332820282019728792003956564819968;
uint256privateconstant SECP256K1_ORDER =115792089237316195423570985008687907852837564279074904382605163141518161494337;
uint256privateconstant UINT256_MAX =115792089237316195423570985008687907853269984665640564039457584007913129639935;
// Used by default when deploying with create2, https://github.com/Arachnid/deterministic-deployment-proxy.addressprivateconstant CREATE2_FACTORY =0x4e59b44847b379578588920cA78FbF26c0B4956C;
/*//////////////////////////////////////////////////////////////////////////
INTERNAL FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/function_bound(uint256 x, uint256 min, uint256 max) internalpurevirtualreturns (uint256 result) {
require(min <= max, "StdUtils bound(uint256,uint256,uint256): Max is less than min.");
// If x is between min and max, return x directly. This is to ensure that dictionary values// do not get shifted if the min is nonzero. More info: https://github.com/foundry-rs/forge-std/issues/188if (x >= min && x <= max) return x;
uint256 size = max - min +1;
// If the value is 0, 1, 2, 3, wrap that to min, min+1, min+2, min+3. Similarly for the UINT256_MAX side.// This helps ensure coverage of the min/max values.if (x <=3&& size > x) return min + x;
if (x >= UINT256_MAX -3&& size > UINT256_MAX - x) return max - (UINT256_MAX - x);
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.if (x > max) {
uint256 diff = x - max;
uint256 rem = diff % size;
if (rem ==0) return max;
result = min + rem -1;
} elseif (x < min) {
uint256 diff = min - x;
uint256 rem = diff % size;
if (rem ==0) return min;
result = max - rem +1;
}
}
functionbound(uint256 x, uint256 min, uint256 max) internalpurevirtualreturns (uint256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound result", result);
}
function_bound(int256 x, int256 min, int256 max) internalpurevirtualreturns (int256 result) {
require(min <= max, "StdUtils bound(int256,int256,int256): Max is less than min.");
// Shifting all int256 values to uint256 to use _bound function. The range of two types are:// int256 : -(2**255) ~ (2**255 - 1)// uint256: 0 ~ (2**256 - 1)// So, add 2**255, INT256_MIN_ABS to the integer values.//// If the given integer value is -2**255, we cannot use `-uint256(-x)` because of the overflow.// So, use `~uint256(x) + 1` instead.uint256 _x = x <0 ? (INT256_MIN_ABS -~uint256(x) -1) : (uint256(x) + INT256_MIN_ABS);
uint256 _min = min <0 ? (INT256_MIN_ABS -~uint256(min) -1) : (uint256(min) + INT256_MIN_ABS);
uint256 _max = max <0 ? (INT256_MIN_ABS -~uint256(max) -1) : (uint256(max) + INT256_MIN_ABS);
uint256 y = _bound(_x, _min, _max);
// To move it back to int256 value, subtract INT256_MIN_ABS at here.
result = y < INT256_MIN_ABS ? int256(~(INT256_MIN_ABS - y) +1) : int256(y - INT256_MIN_ABS);
}
functionbound(int256 x, int256 min, int256 max) internalpurevirtualreturns (int256 result) {
result = _bound(x, min, max);
console2_log_StdUtils("Bound result", vm.toString(result));
}
functionboundPrivateKey(uint256 privateKey) internalpurevirtualreturns (uint256 result) {
result = _bound(privateKey, 1, SECP256K1_ORDER -1);
}
functionbytesToUint(bytesmemory b) internalpurevirtualreturns (uint256) {
require(b.length<=32, "StdUtils bytesToUint(bytes): Bytes length exceeds 32.");
returnabi.decode(abi.encodePacked(newbytes(32- b.length), b), (uint256));
}
/// @dev Compute the address a contract will be deployed at for a given deployer address and nonce/// @notice adapted from Solmate implementation (https://github.com/Rari-Capital/solmate/blob/main/src/utils/LibRLP.sol)functioncomputeCreateAddress(address deployer, uint256 nonce) internalpurevirtualreturns (address) {
console2_log_StdUtils("computeCreateAddress is deprecated. Please use vm.computeCreateAddress instead.");
return vm.computeCreateAddress(deployer, nonce);
}
functioncomputeCreate2Address(bytes32 salt, bytes32 initcodeHash, address deployer)
internalpurevirtualreturns (address)
{
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initcodeHash, deployer);
}
/// @dev returns the address of a contract created with CREATE2 using the default CREATE2 deployerfunctioncomputeCreate2Address(bytes32 salt, bytes32 initCodeHash) internalpurereturns (address) {
console2_log_StdUtils("computeCreate2Address is deprecated. Please use vm.computeCreate2Address instead.");
return vm.computeCreate2Address(salt, initCodeHash);
}
/// @dev returns an initialized mock ERC20 contractfunctiondeployMockERC20(stringmemory name, stringmemory symbol, uint8 decimals)
internalreturns (MockERC20 mock)
{
mock =new MockERC20();
mock.initialize(name, symbol, decimals);
}
/// @dev returns an initialized mock ERC721 contractfunctiondeployMockERC721(stringmemory name, stringmemory symbol) internalreturns (MockERC721 mock) {
mock =new MockERC721();
mock.initialize(name, symbol);
}
/// @dev returns the hash of the init code (creation code + no args) used in CREATE2 with no constructor arguments/// @param creationCode the creation code of a contract C, as returned by type(C).creationCodefunctionhashInitCode(bytesmemory creationCode) internalpurereturns (bytes32) {
return hashInitCode(creationCode, "");
}
/// @dev returns the hash of the init code (creation code + ABI-encoded args) used in CREATE2/// @param creationCode the creation code of a contract C, as returned by type(C).creationCode/// @param args the ABI-encoded arguments to the constructor of CfunctionhashInitCode(bytesmemory creationCode, bytesmemory args) internalpurereturns (bytes32) {
returnkeccak256(abi.encodePacked(creationCode, args));
}
// Performs a single call with Multicall3 to query the ERC-20 token balances of the given addresses.functiongetTokenBalances(address token, address[] memory addresses)
internalvirtualreturns (uint256[] memory balances)
{
uint256 tokenCodeSize;
assembly {
tokenCodeSize :=extcodesize(token)
}
require(tokenCodeSize >0, "StdUtils getTokenBalances(address,address[]): Token address is not a contract.");
// ABI encode the aggregate call to Multicall3.uint256 length = addresses.length;
IMulticall3.Call[] memory calls =new IMulticall3.Call[](length);
for (uint256 i =0; i < length; ++i) {
// 0x70a08231 = bytes4("balanceOf(address)"))
calls[i] = IMulticall3.Call({target: token, callData: abi.encodeWithSelector(0x70a08231, (addresses[i]))});
}
// Make the aggregate call.
(, bytes[] memory returnData) = multicall.aggregate(calls);
// ABI decode the return data and return the balances.
balances =newuint256[](length);
for (uint256 i =0; i < length; ++i) {
balances[i] =abi.decode(returnData[i], (uint256));
}
}
/*//////////////////////////////////////////////////////////////////////////
PRIVATE FUNCTIONS
//////////////////////////////////////////////////////////////////////////*/functionaddressFromLast20Bytes(bytes32 bytesValue) privatepurereturns (address) {
returnaddress(uint160(uint256(bytesValue)));
}
// This section is used to prevent the compilation of console, which shortens the compilation time when console is// not used elsewhere. We also trick the compiler into letting us make the console log methods as `pure` to avoid// any breaking changes to function signatures.function_castLogPayloadViewToPure(function(bytesmemory) internalview fnIn)
internalpurereturns (function(bytesmemory) internalpure fnOut)
{
assembly {
fnOut := fnIn
}
}
function_sendLogPayload(bytesmemory payload) internalpure{
_castLogPayloadViewToPure(_sendLogPayloadView)(payload);
}
function_sendLogPayloadView(bytesmemory payload) privateview{
uint256 payloadLength = payload.length;
address consoleAddress = CONSOLE2_ADDRESS;
/// @solidity memory-safe-assemblyassembly {
let payloadStart :=add(payload, 32)
let r :=staticcall(gas(), consoleAddress, payloadStart, payloadLength, 0, 0)
}
}
functionconsole2_log_StdUtils(stringmemory p0) privatepure{
_sendLogPayload(abi.encodeWithSignature("log(string)", p0));
}
functionconsole2_log_StdUtils(stringmemory p0, uint256 p1) privatepure{
_sendLogPayload(abi.encodeWithSignature("log(string,uint256)", p0, p1));
}
functionconsole2_log_StdUtils(stringmemory p0, stringmemory p1) privatepure{
_sendLogPayload(abi.encodeWithSignature("log(string,string)", p0, p1));
}
}
// Automatically @generated by scripts/vm.py. Do not modify manually.// SPDX-License-Identifier: MIT OR Apache-2.0pragmasolidity >=0.6.2 <0.9.0;pragmaexperimentalABIEncoderV2;/// The `VmSafe` interface does not allow manipulation of the EVM state or other actions that may/// result in Script simulations differing from on-chain execution. It is recommended to only use/// these cheats in scripts.interfaceVmSafe{
/// A modification applied to either `msg.sender` or `tx.origin`. Returned by `readCallers`.enumCallerMode {
// No caller modification is currently active.
None,
// A one time broadcast triggered by a `vm.broadcast()` call is currently active.
Broadcast,
// A recurrent broadcast triggered by a `vm.startBroadcast()` call is currently active.
RecurrentBroadcast,
// A one time prank triggered by a `vm.prank()` call is currently active.
Prank,
// A recurrent prank triggered by a `vm.startPrank()` call is currently active.
RecurrentPrank
}
/// The kind of account access that occurred.enumAccountAccessKind {
// The account was called.
Call,
// The account was called via delegatecall.
DelegateCall,
// The account was called via callcode.
CallCode,
// The account was called via staticcall.
StaticCall,
// The account was created.
Create,
// The account was selfdestructed.
SelfDestruct,
// Synthetic access indicating the current context has resumed after a previous sub-context (AccountAccess).
Resume,
// The account's balance was read.
Balance,
// The account's codesize was read.
Extcodesize,
// The account's codehash was read.
Extcodehash,
// The account's code was copied.
Extcodecopy
}
/// Forge execution contexts.enumForgeContext {
// Test group execution context (test, coverage or snapshot).
TestGroup,
// `forge test` execution context.
Test,
// `forge coverage` execution context.
Coverage,
// `forge snapshot` execution context.
Snapshot,
// Script group execution context (dry run, broadcast or resume).
ScriptGroup,
// `forge script` execution context.
ScriptDryRun,
// `forge script --broadcast` execution context.
ScriptBroadcast,
// `forge script --resume` execution context.
ScriptResume,
// Unknown `forge` execution context.
Unknown
}
/// An Ethereum log. Returned by `getRecordedLogs`.structLog {
// The topics of the log, including the signature, if any.bytes32[] topics;
// The raw data of the log.bytes data;
// The address of the log's emitter.address emitter;
}
/// An RPC URL and its alias. Returned by `rpcUrlStructs`.structRpc {
// The alias of the RPC URL.string key;
// The RPC URL.string url;
}
/// An RPC log object. Returned by `eth_getLogs`.structEthGetLogs {
// The address of the log's emitter.address emitter;
// The topics of the log, including the signature, if any.bytes32[] topics;
// The raw data of the log.bytes data;
// The block hash.bytes32 blockHash;
// The block number.uint64 blockNumber;
// The transaction hash.bytes32 transactionHash;
// The transaction index in the block.uint64 transactionIndex;
// The log index.uint256 logIndex;
// Whether the log was removed.bool removed;
}
/// A single entry in a directory listing. Returned by `readDir`.structDirEntry {
// The error message, if any.string errorMessage;
// The path of the entry.string path;
// The depth of the entry.uint64 depth;
// Whether the entry is a directory.bool isDir;
// Whether the entry is a symlink.bool isSymlink;
}
/// Metadata information about a file./// This structure is returned from the `fsMetadata` function and represents known/// metadata about a file such as its permissions, size, modification/// times, etc.structFsMetadata {
// True if this metadata is for a directory.bool isDir;
// True if this metadata is for a symlink.bool isSymlink;
// The size of the file, in bytes, this metadata is for.uint256 length;
// True if this metadata is for a readonly (unwritable) file.bool readOnly;
// The last modification time listed in this metadata.uint256 modified;
// The last access time of this metadata.uint256 accessed;
// The creation time listed in this metadata.uint256 created;
}
/// A wallet with a public and private key.structWallet {
// The wallet's address.address addr;
// The wallet's public key `X`.uint256 publicKeyX;
// The wallet's public key `Y`.uint256 publicKeyY;
// The wallet's private key.uint256 privateKey;
}
/// The result of a `tryFfi` call.structFfiResult {
// The exit code of the call.int32 exitCode;
// The optionally hex-decoded `stdout` data.bytes stdout;
// The `stderr` data.bytes stderr;
}
/// Information on the chain and fork.structChainInfo {
// The fork identifier. Set to zero if no fork is active.uint256 forkId;
// The chain ID of the current fork.uint256 chainId;
}
/// The result of a `stopAndReturnStateDiff` call.structAccountAccess {
// The chain and fork the access occurred.
ChainInfo chainInfo;
// The kind of account access that determines what the account is.// If kind is Call, DelegateCall, StaticCall or CallCode, then the account is the callee.// If kind is Create, then the account is the newly created account.// If kind is SelfDestruct, then the account is the selfdestruct recipient.// If kind is a Resume, then account represents a account context that has resumed.
AccountAccessKind kind;
// The account that was accessed.// It's either the account created, callee or a selfdestruct recipient for CREATE, CALL or SELFDESTRUCT.address account;
// What accessed the account.address accessor;
// If the account was initialized or empty prior to the access.// An account is considered initialized if it has code, a// non-zero nonce, or a non-zero balance.bool initialized;
// The previous balance of the accessed account.uint256 oldBalance;
// The potential new balance of the accessed account.// That is, all balance changes are recorded here, even if reverts occurred.uint256 newBalance;
// Code of the account deployed by CREATE.bytes deployedCode;
// Value passed along with the account accessuint256 value;
// Input data provided to the CREATE or CALLbytes data;
// If this access reverted in either the current or parent context.bool reverted;
// An ordered list of storage accesses made during an account access operation.
StorageAccess[] storageAccesses;
// Call depth traversed during the recording of state differencesuint64 depth;
}
/// The storage accessed during an `AccountAccess`.structStorageAccess {
// The account whose storage was accessed.address account;
// The slot that was accessed.bytes32 slot;
// If the access was a write.bool isWrite;
// The previous value of the slot.bytes32 previousValue;
// The new value of the slot.bytes32 newValue;
// If the access was reverted.bool reverted;
}
/// Gas used. Returned by `lastCallGas`.structGas {
// The gas limit of the call.uint64 gasLimit;
// The total gas used.uint64 gasTotalUsed;
// The amount of gas used for memory expansion.uint64 gasMemoryUsed;
// The amount of gas refunded.int64 gasRefunded;
// The amount of gas remaining.uint64 gasRemaining;
}
// ======== Environment ========/// Gets the environment variable `name` and parses it as `address`./// Reverts if the variable was not found or could not be parsed.functionenvAddress(stringcalldata name) externalviewreturns (address value);
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvAddress(stringcalldata name, stringcalldata delim) externalviewreturns (address[] memory value);
/// Gets the environment variable `name` and parses it as `bool`./// Reverts if the variable was not found or could not be parsed.functionenvBool(stringcalldata name) externalviewreturns (bool value);
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvBool(stringcalldata name, stringcalldata delim) externalviewreturns (bool[] memory value);
/// Gets the environment variable `name` and parses it as `bytes32`./// Reverts if the variable was not found or could not be parsed.functionenvBytes32(stringcalldata name) externalviewreturns (bytes32 value);
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvBytes32(stringcalldata name, stringcalldata delim) externalviewreturns (bytes32[] memory value);
/// Gets the environment variable `name` and parses it as `bytes`./// Reverts if the variable was not found or could not be parsed.functionenvBytes(stringcalldata name) externalviewreturns (bytesmemory value);
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvBytes(stringcalldata name, stringcalldata delim) externalviewreturns (bytes[] memory value);
/// Gets the environment variable `name` and returns true if it exists, else returns false.functionenvExists(stringcalldata name) externalviewreturns (bool result);
/// Gets the environment variable `name` and parses it as `int256`./// Reverts if the variable was not found or could not be parsed.functionenvInt(stringcalldata name) externalviewreturns (int256 value);
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvInt(stringcalldata name, stringcalldata delim) externalviewreturns (int256[] memory value);
/// Gets the environment variable `name` and parses it as `bool`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, bool defaultValue) externalviewreturns (bool value);
/// Gets the environment variable `name` and parses it as `uint256`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, uint256 defaultValue) externalviewreturns (uint256 value);
/// Gets the environment variable `name` and parses it as an array of `address`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, address[] calldata defaultValue)
externalviewreturns (address[] memory value);
/// Gets the environment variable `name` and parses it as an array of `bytes32`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, bytes32[] calldata defaultValue)
externalviewreturns (bytes32[] memory value);
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, string[] calldata defaultValue)
externalviewreturns (string[] memory value);
/// Gets the environment variable `name` and parses it as an array of `bytes`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, bytes[] calldata defaultValue)
externalviewreturns (bytes[] memory value);
/// Gets the environment variable `name` and parses it as `int256`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, int256 defaultValue) externalviewreturns (int256 value);
/// Gets the environment variable `name` and parses it as `address`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, address defaultValue) externalviewreturns (address value);
/// Gets the environment variable `name` and parses it as `bytes32`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, bytes32 defaultValue) externalviewreturns (bytes32 value);
/// Gets the environment variable `name` and parses it as `string`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata defaultValue) externalviewreturns (stringmemory value);
/// Gets the environment variable `name` and parses it as `bytes`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, bytescalldata defaultValue) externalviewreturns (bytesmemory value);
/// Gets the environment variable `name` and parses it as an array of `bool`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, bool[] calldata defaultValue)
externalviewreturns (bool[] memory value);
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, uint256[] calldata defaultValue)
externalviewreturns (uint256[] memory value);
/// Gets the environment variable `name` and parses it as an array of `int256`, delimited by `delim`./// Reverts if the variable could not be parsed./// Returns `defaultValue` if the variable was not found.functionenvOr(stringcalldata name, stringcalldata delim, int256[] calldata defaultValue)
externalviewreturns (int256[] memory value);
/// Gets the environment variable `name` and parses it as `string`./// Reverts if the variable was not found or could not be parsed.functionenvString(stringcalldata name) externalviewreturns (stringmemory value);
/// Gets the environment variable `name` and parses it as an array of `string`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvString(stringcalldata name, stringcalldata delim) externalviewreturns (string[] memory value);
/// Gets the environment variable `name` and parses it as `uint256`./// Reverts if the variable was not found or could not be parsed.functionenvUint(stringcalldata name) externalviewreturns (uint256 value);
/// Gets the environment variable `name` and parses it as an array of `uint256`, delimited by `delim`./// Reverts if the variable was not found or could not be parsed.functionenvUint(stringcalldata name, stringcalldata delim) externalviewreturns (uint256[] memory value);
/// Returns true if `forge` command was executed in given context.functionisContext(ForgeContext context) externalviewreturns (bool result);
/// Sets environment variables.functionsetEnv(stringcalldata name, stringcalldata value) external;
// ======== EVM ========/// Gets all accessed reads and write slot from a `vm.record` session, for a given address.functionaccesses(address target) externalreturns (bytes32[] memory readSlots, bytes32[] memory writeSlots);
/// Gets the address for a given private key.functionaddr(uint256 privateKey) externalpurereturns (address keyAddr);
/// Gets all the logs according to specified filter.functioneth_getLogs(uint256 fromBlock, uint256 toBlock, address target, bytes32[] calldata topics)
externalreturns (EthGetLogs[] memory logs);
/// Gets the current `block.blobbasefee`./// You should use this instead of `block.blobbasefee` if you use `vm.blobBaseFee`, as `block.blobbasefee` is assumed to be constant across a transaction,/// and as a result will get optimized out by the compiler./// See https://github.com/foundry-rs/foundry/issues/6180functiongetBlobBaseFee() externalviewreturns (uint256 blobBaseFee);
/// Gets the current `block.number`./// You should use this instead of `block.number` if you use `vm.roll`, as `block.number` is assumed to be constant across a transaction,/// and as a result will get optimized out by the compiler./// See https://github.com/foundry-rs/foundry/issues/6180functiongetBlockNumber() externalviewreturns (uint256 height);
/// Gets the current `block.timestamp`./// You should use this instead of `block.timestamp` if you use `vm.warp`, as `block.timestamp` is assumed to be constant across a transaction,/// and as a result will get optimized out by the compiler./// See https://github.com/foundry-rs/foundry/issues/6180functiongetBlockTimestamp() externalviewreturns (uint256 timestamp);
/// Gets the map key and parent of a mapping at a given slot, for a given address.functiongetMappingKeyAndParentOf(address target, bytes32 elementSlot)
externalreturns (bool found, bytes32 key, bytes32 parent);
/// Gets the number of elements in the mapping at the given slot, for a given address.functiongetMappingLength(address target, bytes32 mappingSlot) externalreturns (uint256 length);
/// Gets the elements at index idx of the mapping at the given slot, for a given address. The/// index must be less than the length of the mapping (i.e. the number of keys in the mapping).functiongetMappingSlotAt(address target, bytes32 mappingSlot, uint256 idx) externalreturns (bytes32 value);
/// Gets the nonce of an account.functiongetNonce(address account) externalviewreturns (uint64 nonce);
/// Gets all the recorded logs.functiongetRecordedLogs() externalreturns (Log[] memory logs);
/// Gets the gas used in the last call.functionlastCallGas() externalviewreturns (Gas memory gas);
/// Loads a storage slot from an address.functionload(address target, bytes32 slot) externalviewreturns (bytes32 data);
/// Pauses gas metering (i.e. gas usage is not counted). Noop if already paused.functionpauseGasMetering() external;
/// Records all storage reads and writes.functionrecord() external;
/// Record all the transaction logs.functionrecordLogs() external;
/// Resumes gas metering (i.e. gas usage is counted again). Noop if already on.functionresumeGasMetering() external;
/// Performs an Ethereum JSON-RPC request to the current fork URL.functionrpc(stringcalldata method, stringcalldata params) externalreturns (bytesmemory data);
/// Signs `digest` with `privateKey` using the secp256r1 curve.functionsignP256(uint256 privateKey, bytes32 digest) externalpurereturns (bytes32 r, bytes32 s);
/// Signs `digest` with `privateKey` using the secp256k1 curve.functionsign(uint256 privateKey, bytes32 digest) externalpurereturns (uint8 v, bytes32 r, bytes32 s);
/// Signs `digest` with signer provided to script using the secp256k1 curve./// If `--sender` is provided, the signer with provided address is used, otherwise,/// if exactly one signer is provided to the script, that signer is used./// Raises error if signer passed through `--sender` does not match any unlocked signers or/// if `--sender` is not provided and not exactly one signer is passed to the script.functionsign(bytes32 digest) externalpurereturns (uint8 v, bytes32 r, bytes32 s);
/// Signs `digest` with signer provided to script using the secp256k1 curve./// Raises error if none of the signers passed into the script have provided address.functionsign(address signer, bytes32 digest) externalpurereturns (uint8 v, bytes32 r, bytes32 s);
/// Starts recording all map SSTOREs for later retrieval.functionstartMappingRecording() external;
/// Record all account accesses as part of CREATE, CALL or SELFDESTRUCT opcodes in order,/// along with the context of the callsfunctionstartStateDiffRecording() external;
/// Returns an ordered array of all account accesses from a `vm.startStateDiffRecording` session.functionstopAndReturnStateDiff() externalreturns (AccountAccess[] memory accountAccesses);
/// Stops recording all map SSTOREs for later retrieval and clears the recorded data.functionstopMappingRecording() external;
// ======== Filesystem ========/// Closes file for reading, resetting the offset and allowing to read it from beginning with readLine./// `path` is relative to the project root.functioncloseFile(stringcalldata path) external;
/// Copies the contents of one file to another. This function will **overwrite** the contents of `to`./// On success, the total number of bytes copied is returned and it is equal to the length of the `to` file as reported by `metadata`./// Both `from` and `to` are relative to the project root.functioncopyFile(stringcalldatafrom, stringcalldata to) externalreturns (uint64 copied);
/// Creates a new, empty directory at the provided path./// This cheatcode will revert in the following situations, but is not limited to just these cases:/// - User lacks permissions to modify `path`./// - A parent of the given path doesn't exist and `recursive` is false./// - `path` already exists and `recursive` is false./// `path` is relative to the project root.functioncreateDir(stringcalldata path, bool recursive) external;
/// Returns true if the given path points to an existing entity, else returns false.functionexists(stringcalldata path) externalreturns (bool result);
/// Performs a foreign function call via the terminal.functionffi(string[] calldata commandInput) externalreturns (bytesmemory result);
/// Given a path, query the file system to get information about a file, directory, etc.functionfsMetadata(stringcalldata path) externalviewreturns (FsMetadata memory metadata);
/// Gets the creation bytecode from an artifact file. Takes in the relative path to the json file or the path to the/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.functiongetCode(stringcalldata artifactPath) externalviewreturns (bytesmemory creationBytecode);
/// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file or the path to the/// artifact in the form of <path>:<contract>:<version> where <contract> and <version> parts are optional.functiongetDeployedCode(stringcalldata artifactPath) externalviewreturns (bytesmemory runtimeBytecode);
/// Returns true if the path exists on disk and is pointing at a directory, else returns false.functionisDir(stringcalldata path) externalreturns (bool result);
/// Returns true if the path exists on disk and is pointing at a regular file, else returns false.functionisFile(stringcalldata path) externalreturns (bool result);
/// Get the path of the current project root.functionprojectRoot() externalviewreturns (stringmemory path);
/// Prompts the user for a string value in the terminal.functionprompt(stringcalldata promptText) externalreturns (stringmemory input);
/// Prompts the user for an address in the terminal.functionpromptAddress(stringcalldata promptText) externalreturns (address);
/// Prompts the user for a hidden string value in the terminal.functionpromptSecret(stringcalldata promptText) externalreturns (stringmemory input);
/// Prompts the user for uint256 in the terminal.functionpromptUint(stringcalldata promptText) externalreturns (uint256);
/// Reads the directory at the given path recursively, up to `maxDepth`./// `maxDepth` defaults to 1, meaning only the direct children of the given directory will be returned./// Follows symbolic links if `followLinks` is true.functionreadDir(stringcalldata path) externalviewreturns (DirEntry[] memory entries);
/// See `readDir(string)`.functionreadDir(stringcalldata path, uint64 maxDepth) externalviewreturns (DirEntry[] memory entries);
/// See `readDir(string)`.functionreadDir(stringcalldata path, uint64 maxDepth, bool followLinks)
externalviewreturns (DirEntry[] memory entries);
/// Reads the entire content of file to string. `path` is relative to the project root.functionreadFile(stringcalldata path) externalviewreturns (stringmemory data);
/// Reads the entire content of file as binary. `path` is relative to the project root.functionreadFileBinary(stringcalldata path) externalviewreturns (bytesmemory data);
/// Reads next line of file to string.functionreadLine(stringcalldata path) externalviewreturns (stringmemory line);
/// Reads a symbolic link, returning the path that the link points to./// This cheatcode will revert in the following situations, but is not limited to just these cases:/// - `path` is not a symbolic link./// - `path` does not exist.functionreadLink(stringcalldata linkPath) externalviewreturns (stringmemory targetPath);
/// Removes a directory at the provided path./// This cheatcode will revert in the following situations, but is not limited to just these cases:/// - `path` doesn't exist./// - `path` isn't a directory./// - User lacks permissions to modify `path`./// - The directory is not empty and `recursive` is false./// `path` is relative to the project root.functionremoveDir(stringcalldata path, bool recursive) external;
/// Removes a file from the filesystem./// This cheatcode will revert in the following situations, but is not limited to just these cases:/// - `path` points to a directory./// - The file doesn't exist./// - The user lacks permissions to remove the file./// `path` is relative to the project root.functionremoveFile(stringcalldata path) external;
/// Performs a foreign function call via terminal and returns the exit code, stdout, and stderr.functiontryFfi(string[] calldata commandInput) externalreturns (FfiResult memory result);
/// Returns the time since unix epoch in milliseconds.functionunixTime() externalreturns (uint256 milliseconds);
/// Writes data to file, creating a file if it does not exist, and entirely replacing its contents if it does./// `path` is relative to the project root.functionwriteFile(stringcalldata path, stringcalldata data) external;
/// Writes binary data to a file, creating a file if it does not exist, and entirely replacing its contents if it does./// `path` is relative to the project root.functionwriteFileBinary(stringcalldata path, bytescalldata data) external;
/// Writes line to file, creating a file if it does not exist./// `path` is relative to the project root.functionwriteLine(stringcalldata path, stringcalldata data) external;
// ======== JSON ========/// Checks if `key` exists in a JSON object/// `keyExists` is being deprecated in favor of `keyExistsJson`. It will be removed in future versions.functionkeyExists(stringcalldata json, stringcalldata key) externalviewreturns (bool);
/// Checks if `key` exists in a JSON object.functionkeyExistsJson(stringcalldata json, stringcalldata key) externalviewreturns (bool);
/// Parses a string of JSON data at `key` and coerces it to `address`.functionparseJsonAddress(stringcalldata json, stringcalldata key) externalpurereturns (address);
/// Parses a string of JSON data at `key` and coerces it to `address[]`.functionparseJsonAddressArray(stringcalldata json, stringcalldata key)
externalpurereturns (address[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bool`.functionparseJsonBool(stringcalldata json, stringcalldata key) externalpurereturns (bool);
/// Parses a string of JSON data at `key` and coerces it to `bool[]`.functionparseJsonBoolArray(stringcalldata json, stringcalldata key) externalpurereturns (bool[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bytes`.functionparseJsonBytes(stringcalldata json, stringcalldata key) externalpurereturns (bytesmemory);
/// Parses a string of JSON data at `key` and coerces it to `bytes32`.functionparseJsonBytes32(stringcalldata json, stringcalldata key) externalpurereturns (bytes32);
/// Parses a string of JSON data at `key` and coerces it to `bytes32[]`.functionparseJsonBytes32Array(stringcalldata json, stringcalldata key)
externalpurereturns (bytes32[] memory);
/// Parses a string of JSON data at `key` and coerces it to `bytes[]`.functionparseJsonBytesArray(stringcalldata json, stringcalldata key) externalpurereturns (bytes[] memory);
/// Parses a string of JSON data at `key` and coerces it to `int256`.functionparseJsonInt(stringcalldata json, stringcalldata key) externalpurereturns (int256);
/// Parses a string of JSON data at `key` and coerces it to `int256[]`.functionparseJsonIntArray(stringcalldata json, stringcalldata key) externalpurereturns (int256[] memory);
/// Returns an array of all the keys in a JSON object.functionparseJsonKeys(stringcalldata json, stringcalldata key) externalpurereturns (string[] memory keys);
/// Parses a string of JSON data at `key` and coerces it to `string`.functionparseJsonString(stringcalldata json, stringcalldata key) externalpurereturns (stringmemory);
/// Parses a string of JSON data at `key` and coerces it to `string[]`.functionparseJsonStringArray(stringcalldata json, stringcalldata key) externalpurereturns (string[] memory);
/// Parses a string of JSON data at `key` and coerces it to `uint256`.functionparseJsonUint(stringcalldata json, stringcalldata key) externalpurereturns (uint256);
/// Parses a string of JSON data at `key` and coerces it to `uint256[]`.functionparseJsonUintArray(stringcalldata json, stringcalldata key) externalpurereturns (uint256[] memory);
/// ABI-encodes a JSON object.functionparseJson(stringcalldata json) externalpurereturns (bytesmemory abiEncodedData);
/// ABI-encodes a JSON object at `key`.functionparseJson(stringcalldata json, stringcalldata key) externalpurereturns (bytesmemory abiEncodedData);
/// See `serializeJson`.functionserializeAddress(stringcalldata objectKey, stringcalldata valueKey, address value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeAddress(stringcalldata objectKey, stringcalldata valueKey, address[] calldata values)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBool(stringcalldata objectKey, stringcalldata valueKey, bool value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBool(stringcalldata objectKey, stringcalldata valueKey, bool[] calldata values)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBytes32(stringcalldata objectKey, stringcalldata valueKey, bytes32 value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBytes32(stringcalldata objectKey, stringcalldata valueKey, bytes32[] calldata values)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBytes(stringcalldata objectKey, stringcalldata valueKey, bytescalldata value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeBytes(stringcalldata objectKey, stringcalldata valueKey, bytes[] calldata values)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeInt(stringcalldata objectKey, stringcalldata valueKey, int256 value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeInt(stringcalldata objectKey, stringcalldata valueKey, int256[] calldata values)
externalreturns (stringmemory json);
/// Serializes a key and value to a JSON object stored in-memory that can be later written to a file./// Returns the stringified version of the specific JSON file up to that moment.functionserializeJson(stringcalldata objectKey, stringcalldata value) externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeString(stringcalldata objectKey, stringcalldata valueKey, stringcalldata value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeString(stringcalldata objectKey, stringcalldata valueKey, string[] calldata values)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeUintToHex(stringcalldata objectKey, stringcalldata valueKey, uint256 value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeUint(stringcalldata objectKey, stringcalldata valueKey, uint256 value)
externalreturns (stringmemory json);
/// See `serializeJson`.functionserializeUint(stringcalldata objectKey, stringcalldata valueKey, uint256[] calldata values)
externalreturns (stringmemory json);
/// Write a serialized JSON object to a file. If the file exists, it will be overwritten.functionwriteJson(stringcalldata json, stringcalldata path) external;
/// Write a serialized JSON object to an **existing** JSON file, replacing a value with key = <value_key.>/// This is useful to replace a specific value of a JSON file, without having to parse the entire thing.functionwriteJson(stringcalldata json, stringcalldata path, stringcalldata valueKey) external;
// ======== Scripting ========/// Has the next call (at this call depth only) create transactions that can later be signed and sent onchain./// Broadcasting address is determined by checking the following in order:/// 1. If `--sender` argument was provided, that address is used./// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used./// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.functionbroadcast() external;
/// Has the next call (at this call depth only) create a transaction with the address provided/// as the sender that can later be signed and sent onchain.functionbroadcast(address signer) external;
/// Has the next call (at this call depth only) create a transaction with the private key/// provided as the sender that can later be signed and sent onchain.functionbroadcast(uint256 privateKey) external;
/// Has all subsequent calls (at this call depth only) create transactions that can later be signed and sent onchain./// Broadcasting address is determined by checking the following in order:/// 1. If `--sender` argument was provided, that address is used./// 2. If exactly one signer (e.g. private key, hw wallet, keystore) is set when `forge broadcast` is invoked, that signer is used./// 3. Otherwise, default foundry sender (1804c8AB1F12E6bbf3894d4083f33e07309d1f38) is used.functionstartBroadcast() external;
/// Has all subsequent calls (at this call depth only) create transactions with the address/// provided that can later be signed and sent onchain.functionstartBroadcast(address signer) external;
/// Has all subsequent calls (at this call depth only) create transactions with the private key/// provided that can later be signed and sent onchain.functionstartBroadcast(uint256 privateKey) external;
/// Stops collecting onchain transactions.functionstopBroadcast() external;
// ======== String ========/// Returns the index of the first occurrence of a `key` in an `input` string./// Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `key` is not found./// Returns 0 in case of an empty `key`.functionindexOf(stringcalldata input, stringcalldata key) externalpurereturns (uint256);
/// Parses the given `string` into an `address`.functionparseAddress(stringcalldata stringifiedValue) externalpurereturns (address parsedValue);
/// Parses the given `string` into a `bool`.functionparseBool(stringcalldata stringifiedValue) externalpurereturns (bool parsedValue);
/// Parses the given `string` into `bytes`.functionparseBytes(stringcalldata stringifiedValue) externalpurereturns (bytesmemory parsedValue);
/// Parses the given `string` into a `bytes32`.functionparseBytes32(stringcalldata stringifiedValue) externalpurereturns (bytes32 parsedValue);
/// Parses the given `string` into a `int256`.functionparseInt(stringcalldata stringifiedValue) externalpurereturns (int256 parsedValue);
/// Parses the given `string` into a `uint256`.functionparseUint(stringcalldata stringifiedValue) externalpurereturns (uint256 parsedValue);
/// Replaces occurrences of `from` in the given `string` with `to`.functionreplace(stringcalldata input, stringcalldatafrom, stringcalldata to)
externalpurereturns (stringmemory output);
/// Splits the given `string` into an array of strings divided by the `delimiter`.functionsplit(stringcalldata input, stringcalldata delimiter) externalpurereturns (string[] memory outputs);
/// Converts the given `string` value to Lowercase.functiontoLowercase(stringcalldata input) externalpurereturns (stringmemory output);
/// Converts the given value to a `string`.functiontoString(address value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given value to a `string`.functiontoString(bytescalldata value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given value to a `string`.functiontoString(bytes32 value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given value to a `string`.functiontoString(bool value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given value to a `string`.functiontoString(uint256 value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given value to a `string`.functiontoString(int256 value) externalpurereturns (stringmemory stringifiedValue);
/// Converts the given `string` value to Uppercase.functiontoUppercase(stringcalldata input) externalpurereturns (stringmemory output);
/// Trims leading and trailing whitespace from the given `string` value.functiontrim(stringcalldata input) externalpurereturns (stringmemory output);
// ======== Testing ========/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`./// Formats values with decimals in failure message.functionassertApproxEqAbsDecimal(uint256 left, uint256 right, uint256 maxDelta, uint256 decimals) externalpure;
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertApproxEqAbsDecimal(uint256 left,
uint256 right,
uint256 maxDelta,
uint256 decimals,
stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`./// Formats values with decimals in failure message.functionassertApproxEqAbsDecimal(int256 left, int256 right, uint256 maxDelta, uint256 decimals) externalpure;
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertApproxEqAbsDecimal(int256 left,
int256 right,
uint256 maxDelta,
uint256 decimals,
stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`.functionassertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta) externalpure;
/// Compares two `uint256` values. Expects difference to be less than or equal to `maxDelta`./// Includes error message into revert string on failure.functionassertApproxEqAbs(uint256 left, uint256 right, uint256 maxDelta, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`.functionassertApproxEqAbs(int256 left, int256 right, uint256 maxDelta) externalpure;
/// Compares two `int256` values. Expects difference to be less than or equal to `maxDelta`./// Includes error message into revert string on failure.functionassertApproxEqAbs(int256 left, int256 right, uint256 maxDelta, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Formats values with decimals in failure message.functionassertApproxEqRelDecimal(uint256 left, uint256 right, uint256 maxPercentDelta, uint256 decimals)
externalpure;
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertApproxEqRelDecimal(uint256 left,
uint256 right,
uint256 maxPercentDelta,
uint256 decimals,
stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Formats values with decimals in failure message.functionassertApproxEqRelDecimal(int256 left, int256 right, uint256 maxPercentDelta, uint256 decimals)
externalpure;
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertApproxEqRelDecimal(int256 left,
int256 right,
uint256 maxPercentDelta,
uint256 decimals,
stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%functionassertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta) externalpure;
/// Compares two `uint256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Includes error message into revert string on failure.functionassertApproxEqRel(uint256 left, uint256 right, uint256 maxPercentDelta, stringcalldataerror)
externalpure;
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%functionassertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta) externalpure;
/// Compares two `int256` values. Expects relative difference in percents to be less than or equal to `maxPercentDelta`./// `maxPercentDelta` is an 18 decimal fixed point number, where 1e18 == 100%/// Includes error message into revert string on failure.functionassertApproxEqRel(int256 left, int256 right, uint256 maxPercentDelta, stringcalldataerror)
externalpure;
/// Asserts that two `uint256` values are equal, formatting them with decimals in failure message.functionassertEqDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Asserts that two `uint256` values are equal, formatting them with decimals in failure message./// Includes error message into revert string on failure.functionassertEqDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Asserts that two `int256` values are equal, formatting them with decimals in failure message.functionassertEqDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Asserts that two `int256` values are equal, formatting them with decimals in failure message./// Includes error message into revert string on failure.functionassertEqDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Asserts that two `bool` values are equal.functionassertEq(bool left, bool right) externalpure;
/// Asserts that two `bool` values are equal and includes error message into revert string on failure.functionassertEq(bool left, bool right, stringcalldataerror) externalpure;
/// Asserts that two `string` values are equal.functionassertEq(stringcalldata left, stringcalldata right) externalpure;
/// Asserts that two `string` values are equal and includes error message into revert string on failure.functionassertEq(stringcalldata left, stringcalldata right, stringcalldataerror) externalpure;
/// Asserts that two `bytes` values are equal.functionassertEq(bytescalldata left, bytescalldata right) externalpure;
/// Asserts that two `bytes` values are equal and includes error message into revert string on failure.functionassertEq(bytescalldata left, bytescalldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bool` values are equal.functionassertEq(bool[] calldata left, bool[] calldata right) externalpure;
/// Asserts that two arrays of `bool` values are equal and includes error message into revert string on failure.functionassertEq(bool[] calldata left, bool[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `uint256 values are equal.functionassertEq(uint256[] calldata left, uint256[] calldata right) externalpure;
/// Asserts that two arrays of `uint256` values are equal and includes error message into revert string on failure.functionassertEq(uint256[] calldata left, uint256[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `int256` values are equal.functionassertEq(int256[] calldata left, int256[] calldata right) externalpure;
/// Asserts that two arrays of `int256` values are equal and includes error message into revert string on failure.functionassertEq(int256[] calldata left, int256[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two `uint256` values are equal.functionassertEq(uint256 left, uint256 right) externalpure;
/// Asserts that two arrays of `address` values are equal.functionassertEq(address[] calldata left, address[] calldata right) externalpure;
/// Asserts that two arrays of `address` values are equal and includes error message into revert string on failure.functionassertEq(address[] calldata left, address[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bytes32` values are equal.functionassertEq(bytes32[] calldata left, bytes32[] calldata right) externalpure;
/// Asserts that two arrays of `bytes32` values are equal and includes error message into revert string on failure.functionassertEq(bytes32[] calldata left, bytes32[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `string` values are equal.functionassertEq(string[] calldata left, string[] calldata right) externalpure;
/// Asserts that two arrays of `string` values are equal and includes error message into revert string on failure.functionassertEq(string[] calldata left, string[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bytes` values are equal.functionassertEq(bytes[] calldata left, bytes[] calldata right) externalpure;
/// Asserts that two arrays of `bytes` values are equal and includes error message into revert string on failure.functionassertEq(bytes[] calldata left, bytes[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two `uint256` values are equal and includes error message into revert string on failure.functionassertEq(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Asserts that two `int256` values are equal.functionassertEq(int256 left, int256 right) externalpure;
/// Asserts that two `int256` values are equal and includes error message into revert string on failure.functionassertEq(int256 left, int256 right, stringcalldataerror) externalpure;
/// Asserts that two `address` values are equal.functionassertEq(address left, address right) externalpure;
/// Asserts that two `address` values are equal and includes error message into revert string on failure.functionassertEq(address left, address right, stringcalldataerror) externalpure;
/// Asserts that two `bytes32` values are equal.functionassertEq(bytes32 left, bytes32 right) externalpure;
/// Asserts that two `bytes32` values are equal and includes error message into revert string on failure.functionassertEq(bytes32 left, bytes32 right, stringcalldataerror) externalpure;
/// Asserts that the given condition is false.functionassertFalse(bool condition) externalpure;
/// Asserts that the given condition is false and includes error message into revert string on failure.functionassertFalse(bool condition, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than or equal to second./// Formats values with decimals in failure message.functionassertGeDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than or equal to second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertGeDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be greater than or equal to second./// Formats values with decimals in failure message.functionassertGeDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Compares two `int256` values. Expects first value to be greater than or equal to second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertGeDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than or equal to second.functionassertGe(uint256 left, uint256 right) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than or equal to second./// Includes error message into revert string on failure.functionassertGe(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be greater than or equal to second.functionassertGe(int256 left, int256 right) externalpure;
/// Compares two `int256` values. Expects first value to be greater than or equal to second./// Includes error message into revert string on failure.functionassertGe(int256 left, int256 right, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than second./// Formats values with decimals in failure message.functionassertGtDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertGtDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be greater than second./// Formats values with decimals in failure message.functionassertGtDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Compares two `int256` values. Expects first value to be greater than second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertGtDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than second.functionassertGt(uint256 left, uint256 right) externalpure;
/// Compares two `uint256` values. Expects first value to be greater than second./// Includes error message into revert string on failure.functionassertGt(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be greater than second.functionassertGt(int256 left, int256 right) externalpure;
/// Compares two `int256` values. Expects first value to be greater than second./// Includes error message into revert string on failure.functionassertGt(int256 left, int256 right, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be less than or equal to second./// Formats values with decimals in failure message.functionassertLeDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Compares two `uint256` values. Expects first value to be less than or equal to second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertLeDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be less than or equal to second./// Formats values with decimals in failure message.functionassertLeDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Compares two `int256` values. Expects first value to be less than or equal to second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertLeDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be less than or equal to second.functionassertLe(uint256 left, uint256 right) externalpure;
/// Compares two `uint256` values. Expects first value to be less than or equal to second./// Includes error message into revert string on failure.functionassertLe(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be less than or equal to second.functionassertLe(int256 left, int256 right) externalpure;
/// Compares two `int256` values. Expects first value to be less than or equal to second./// Includes error message into revert string on failure.functionassertLe(int256 left, int256 right, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be less than second./// Formats values with decimals in failure message.functionassertLtDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Compares two `uint256` values. Expects first value to be less than second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertLtDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be less than second./// Formats values with decimals in failure message.functionassertLtDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Compares two `int256` values. Expects first value to be less than second./// Formats values with decimals in failure message. Includes error message into revert string on failure.functionassertLtDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Compares two `uint256` values. Expects first value to be less than second.functionassertLt(uint256 left, uint256 right) externalpure;
/// Compares two `uint256` values. Expects first value to be less than second./// Includes error message into revert string on failure.functionassertLt(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Compares two `int256` values. Expects first value to be less than second.functionassertLt(int256 left, int256 right) externalpure;
/// Compares two `int256` values. Expects first value to be less than second./// Includes error message into revert string on failure.functionassertLt(int256 left, int256 right, stringcalldataerror) externalpure;
/// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message.functionassertNotEqDecimal(uint256 left, uint256 right, uint256 decimals) externalpure;
/// Asserts that two `uint256` values are not equal, formatting them with decimals in failure message./// Includes error message into revert string on failure.functionassertNotEqDecimal(uint256 left, uint256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Asserts that two `int256` values are not equal, formatting them with decimals in failure message.functionassertNotEqDecimal(int256 left, int256 right, uint256 decimals) externalpure;
/// Asserts that two `int256` values are not equal, formatting them with decimals in failure message./// Includes error message into revert string on failure.functionassertNotEqDecimal(int256 left, int256 right, uint256 decimals, stringcalldataerror) externalpure;
/// Asserts that two `bool` values are not equal.functionassertNotEq(bool left, bool right) externalpure;
/// Asserts that two `bool` values are not equal and includes error message into revert string on failure.functionassertNotEq(bool left, bool right, stringcalldataerror) externalpure;
/// Asserts that two `string` values are not equal.functionassertNotEq(stringcalldata left, stringcalldata right) externalpure;
/// Asserts that two `string` values are not equal and includes error message into revert string on failure.functionassertNotEq(stringcalldata left, stringcalldata right, stringcalldataerror) externalpure;
/// Asserts that two `bytes` values are not equal.functionassertNotEq(bytescalldata left, bytescalldata right) externalpure;
/// Asserts that two `bytes` values are not equal and includes error message into revert string on failure.functionassertNotEq(bytescalldata left, bytescalldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bool` values are not equal.functionassertNotEq(bool[] calldata left, bool[] calldata right) externalpure;
/// Asserts that two arrays of `bool` values are not equal and includes error message into revert string on failure.functionassertNotEq(bool[] calldata left, bool[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `uint256` values are not equal.functionassertNotEq(uint256[] calldata left, uint256[] calldata right) externalpure;
/// Asserts that two arrays of `uint256` values are not equal and includes error message into revert string on failure.functionassertNotEq(uint256[] calldata left, uint256[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `int256` values are not equal.functionassertNotEq(int256[] calldata left, int256[] calldata right) externalpure;
/// Asserts that two arrays of `int256` values are not equal and includes error message into revert string on failure.functionassertNotEq(int256[] calldata left, int256[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two `uint256` values are not equal.functionassertNotEq(uint256 left, uint256 right) externalpure;
/// Asserts that two arrays of `address` values are not equal.functionassertNotEq(address[] calldata left, address[] calldata right) externalpure;
/// Asserts that two arrays of `address` values are not equal and includes error message into revert string on failure.functionassertNotEq(address[] calldata left, address[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bytes32` values are not equal.functionassertNotEq(bytes32[] calldata left, bytes32[] calldata right) externalpure;
/// Asserts that two arrays of `bytes32` values are not equal and includes error message into revert string on failure.functionassertNotEq(bytes32[] calldata left, bytes32[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `string` values are not equal.functionassertNotEq(string[] calldata left, string[] calldata right) externalpure;
/// Asserts that two arrays of `string` values are not equal and includes error message into revert string on failure.functionassertNotEq(string[] calldata left, string[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two arrays of `bytes` values are not equal.functionassertNotEq(bytes[] calldata left, bytes[] calldata right) externalpure;
/// Asserts that two arrays of `bytes` values are not equal and includes error message into revert string on failure.functionassertNotEq(bytes[] calldata left, bytes[] calldata right, stringcalldataerror) externalpure;
/// Asserts that two `uint256` values are not equal and includes error message into revert string on failure.functionassertNotEq(uint256 left, uint256 right, stringcalldataerror) externalpure;
/// Asserts that two `int256` values are not equal.functionassertNotEq(int256 left, int256 right) externalpure;
/// Asserts that two `int256` values are not equal and includes error message into revert string on failure.functionassertNotEq(int256 left, int256 right, stringcalldataerror) externalpure;
/// Asserts that two `address` values are not equal.functionassertNotEq(address left, address right) externalpure;
/// Asserts that two `address` values are not equal and includes error message into revert string on failure.functionassertNotEq(address left, address right, stringcalldataerror) externalpure;
/// Asserts that two `bytes32` values are not equal.functionassertNotEq(bytes32 left, bytes32 right) externalpure;
/// Asserts that two `bytes32` values are not equal and includes error message into revert string on failure.functionassertNotEq(bytes32 left, bytes32 right, stringcalldataerror) externalpure;
/// Asserts that the given condition is true.functionassertTrue(bool condition) externalpure;
/// Asserts that the given condition is true and includes error message into revert string on failure.functionassertTrue(bool condition, stringcalldataerror) externalpure;
/// If the condition is false, discard this run's fuzz inputs and generate new ones.functionassume(bool condition) externalpure;
/// Writes a breakpoint to jump to in the debugger.functionbreakpoint(stringcalldata char) external;
/// Writes a conditional breakpoint to jump to in the debugger.functionbreakpoint(stringcalldata char, bool value) external;
/// Returns the RPC url for the given alias.functionrpcUrl(stringcalldata rpcAlias) externalviewreturns (stringmemory json);
/// Returns all rpc urls and their aliases as structs.functionrpcUrlStructs() externalviewreturns (Rpc[] memory urls);
/// Returns all rpc urls and their aliases `[alias, url][]`.functionrpcUrls() externalviewreturns (string[2][] memory urls);
/// Suspends execution of the main thread for `duration` milliseconds.functionsleep(uint256 duration) external;
// ======== Toml ========/// Checks if `key` exists in a TOML table.functionkeyExistsToml(stringcalldata toml, stringcalldata key) externalviewreturns (bool);
/// Parses a string of TOML data at `key` and coerces it to `address`.functionparseTomlAddress(stringcalldata toml, stringcalldata key) externalpurereturns (address);
/// Parses a string of TOML data at `key` and coerces it to `address[]`.functionparseTomlAddressArray(stringcalldata toml, stringcalldata key)
externalpurereturns (address[] memory);
/// Parses a string of TOML data at `key` and coerces it to `bool`.functionparseTomlBool(stringcalldata toml, stringcalldata key) externalpurereturns (bool);
/// Parses a string of TOML data at `key` and coerces it to `bool[]`.functionparseTomlBoolArray(stringcalldata toml, stringcalldata key) externalpurereturns (bool[] memory);
/// Parses a string of TOML data at `key` and coerces it to `bytes`.functionparseTomlBytes(stringcalldata toml, stringcalldata key) externalpurereturns (bytesmemory);
/// Parses a string of TOML data at `key` and coerces it to `bytes32`.functionparseTomlBytes32(stringcalldata toml, stringcalldata key) externalpurereturns (bytes32);
/// Parses a string of TOML data at `key` and coerces it to `bytes32[]`.functionparseTomlBytes32Array(stringcalldata toml, stringcalldata key)
externalpurereturns (bytes32[] memory);
/// Parses a string of TOML data at `key` and coerces it to `bytes[]`.functionparseTomlBytesArray(stringcalldata toml, stringcalldata key) externalpurereturns (bytes[] memory);
/// Parses a string of TOML data at `key` and coerces it to `int256`.functionparseTomlInt(stringcalldata toml, stringcalldata key) externalpurereturns (int256);
/// Parses a string of TOML data at `key` and coerces it to `int256[]`.functionparseTomlIntArray(stringcalldata toml, stringcalldata key) externalpurereturns (int256[] memory);
/// Returns an array of all the keys in a TOML table.functionparseTomlKeys(stringcalldata toml, stringcalldata key) externalpurereturns (string[] memory keys);
/// Parses a string of TOML data at `key` and coerces it to `string`.functionparseTomlString(stringcalldata toml, stringcalldata key) externalpurereturns (stringmemory);
/// Parses a string of TOML data at `key` and coerces it to `string[]`.functionparseTomlStringArray(stringcalldata toml, stringcalldata key) externalpurereturns (string[] memory);
/// Parses a string of TOML data at `key` and coerces it to `uint256`.functionparseTomlUint(stringcalldata toml, stringcalldata key) externalpurereturns (uint256);
/// Parses a string of TOML data at `key` and coerces it to `uint256[]`.functionparseTomlUintArray(stringcalldata toml, stringcalldata key) externalpurereturns (uint256[] memory);
/// ABI-encodes a TOML table.functionparseToml(stringcalldata toml) externalpurereturns (bytesmemory abiEncodedData);
/// ABI-encodes a TOML table at `key`.functionparseToml(stringcalldata toml, stringcalldata key) externalpurereturns (bytesmemory abiEncodedData);
/// Takes serialized JSON, converts to TOML and write a serialized TOML to a file.functionwriteToml(stringcalldata json, stringcalldata path) external;
/// Takes serialized JSON, converts to TOML and write a serialized TOML table to an **existing** TOML file, replacing a value with key = <value_key.>/// This is useful to replace a specific value of a TOML file, without having to parse the entire thing.functionwriteToml(stringcalldata json, stringcalldata path, stringcalldata valueKey) external;
// ======== Utilities ========/// Compute the address of a contract created with CREATE2 using the given CREATE2 deployer.functioncomputeCreate2Address(bytes32 salt, bytes32 initCodeHash, address deployer)
externalpurereturns (address);
/// Compute the address of a contract created with CREATE2 using the default CREATE2 deployer.functioncomputeCreate2Address(bytes32 salt, bytes32 initCodeHash) externalpurereturns (address);
/// Compute the address a contract will be deployed at for a given deployer address and nonce.functioncomputeCreateAddress(address deployer, uint256 nonce) externalpurereturns (address);
/// Derives a private key from the name, labels the account with that name, and returns the wallet.functioncreateWallet(stringcalldata walletLabel) externalreturns (Wallet memory wallet);
/// Generates a wallet from the private key and returns the wallet.functioncreateWallet(uint256 privateKey) externalreturns (Wallet memory wallet);
/// Generates a wallet from the private key, labels the account with that name, and returns the wallet.functioncreateWallet(uint256 privateKey, stringcalldata walletLabel) externalreturns (Wallet memory wallet);
/// Derive a private key from a provided mnenomic string (or mnenomic file path)/// at the derivation path `m/44'/60'/0'/0/{index}`.functionderiveKey(stringcalldata mnemonic, uint32 index) externalpurereturns (uint256 privateKey);
/// Derive a private key from a provided mnenomic string (or mnenomic file path)/// at `{derivationPath}{index}`.functionderiveKey(stringcalldata mnemonic, stringcalldata derivationPath, uint32 index)
externalpurereturns (uint256 privateKey);
/// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language/// at the derivation path `m/44'/60'/0'/0/{index}`.functionderiveKey(stringcalldata mnemonic, uint32 index, stringcalldata language)
externalpurereturns (uint256 privateKey);
/// Derive a private key from a provided mnenomic string (or mnenomic file path) in the specified language/// at `{derivationPath}{index}`.functionderiveKey(stringcalldata mnemonic, stringcalldata derivationPath, uint32 index, stringcalldata language)
externalpurereturns (uint256 privateKey);
/// Returns ENS namehash for provided string.functionensNamehash(stringcalldata name) externalpurereturns (bytes32);
/// Gets the label for the specified address.functiongetLabel(address account) externalviewreturns (stringmemory currentLabel);
/// Get a `Wallet`'s nonce.functiongetNonce(Wallet calldata wallet) externalreturns (uint64 nonce);
/// Labels an address in call traces.functionlabel(address account, stringcalldata newLabel) external;
/// Adds a private key to the local forge wallet and returns the address.functionrememberKey(uint256 privateKey) externalreturns (address keyAddr);
/// Signs data with a `Wallet`.functionsign(Wallet calldata wallet, bytes32 digest) externalreturns (uint8 v, bytes32 r, bytes32 s);
/// Encodes a `bytes` value to a base64url string.functiontoBase64URL(bytescalldata data) externalpurereturns (stringmemory);
/// Encodes a `string` value to a base64url string.functiontoBase64URL(stringcalldata data) externalpurereturns (stringmemory);
/// Encodes a `bytes` value to a base64 string.functiontoBase64(bytescalldata data) externalpurereturns (stringmemory);
/// Encodes a `string` value to a base64 string.functiontoBase64(stringcalldata data) externalpurereturns (stringmemory);
}
/// The `Vm` interface does allow manipulation of the EVM state. These are all intended to be used/// in tests, but it is not recommended to use these cheats in scripts.interfaceVmisVmSafe{
// ======== EVM ========/// Returns the identifier of the currently active fork. Reverts if no fork is currently active.functionactiveFork() externalviewreturns (uint256 forkId);
/// In forking mode, explicitly grant the given address cheatcode access.functionallowCheatcodes(address account) external;
/// Sets `block.blobbasefee`functionblobBaseFee(uint256 newBlobBaseFee) external;
/// Sets the blobhashes in the transaction./// Not available on EVM versions before Cancun./// If used on unsupported EVM versions it will revert.functionblobhashes(bytes32[] calldata hashes) external;
/// Sets `block.chainid`.functionchainId(uint256 newChainId) external;
/// Clears all mocked calls.functionclearMockedCalls() external;
/// Sets `block.coinbase`.functioncoinbase(address newCoinbase) external;
/// Creates a new fork with the given endpoint and the _latest_ block and returns the identifier of the fork.functioncreateFork(stringcalldata urlOrAlias) externalreturns (uint256 forkId);
/// Creates a new fork with the given endpoint and block and returns the identifier of the fork.functioncreateFork(stringcalldata urlOrAlias, uint256 blockNumber) externalreturns (uint256 forkId);
/// Creates a new fork with the given endpoint and at the block the given transaction was mined in,/// replays all transaction mined in the block before the transaction, and returns the identifier of the fork.functioncreateFork(stringcalldata urlOrAlias, bytes32 txHash) externalreturns (uint256 forkId);
/// Creates and also selects a new fork with the given endpoint and the latest block and returns the identifier of the fork.functioncreateSelectFork(stringcalldata urlOrAlias) externalreturns (uint256 forkId);
/// Creates and also selects a new fork with the given endpoint and block and returns the identifier of the fork.functioncreateSelectFork(stringcalldata urlOrAlias, uint256 blockNumber) externalreturns (uint256 forkId);
/// Creates and also selects new fork with the given endpoint and at the block the given transaction was mined in,/// replays all transaction mined in the block before the transaction, returns the identifier of the fork.functioncreateSelectFork(stringcalldata urlOrAlias, bytes32 txHash) externalreturns (uint256 forkId);
/// Sets an address' balance.functiondeal(address account, uint256 newBalance) external;
/// Removes the snapshot with the given ID created by `snapshot`./// Takes the snapshot ID to delete./// Returns `true` if the snapshot was successfully deleted./// Returns `false` if the snapshot does not exist.functiondeleteSnapshot(uint256 snapshotId) externalreturns (bool success);
/// Removes _all_ snapshots previously created by `snapshot`.functiondeleteSnapshots() external;
/// Sets `block.difficulty`./// Not available on EVM versions from Paris onwards. Use `prevrandao` instead./// Reverts if used on unsupported EVM versions.functiondifficulty(uint256 newDifficulty) external;
/// Dump a genesis JSON file's `allocs` to disk.functiondumpState(stringcalldata pathToStateJson) external;
/// Sets an address' code.functionetch(address target, bytescalldata newRuntimeBytecode) external;
/// Sets `block.basefee`.functionfee(uint256 newBasefee) external;
/// Gets the blockhashes from the current transaction./// Not available on EVM versions before Cancun./// If used on unsupported EVM versions it will revert.functiongetBlobhashes() externalviewreturns (bytes32[] memory hashes);
/// Returns true if the account is marked as persistent.functionisPersistent(address account) externalviewreturns (bool persistent);
/// Load a genesis JSON file's `allocs` into the in-memory revm state.functionloadAllocs(stringcalldata pathToAllocsJson) external;
/// Marks that the account(s) should use persistent storage across fork swaps in a multifork setup/// Meaning, changes made to the state of this account will be kept when switching forks.functionmakePersistent(address account) external;
/// See `makePersistent(address)`.functionmakePersistent(address account0, address account1) external;
/// See `makePersistent(address)`.functionmakePersistent(address account0, address account1, address account2) external;
/// See `makePersistent(address)`.functionmakePersistent(address[] calldata accounts) external;
/// Reverts a call to an address with specified revert data.functionmockCallRevert(address callee, bytescalldata data, bytescalldata revertData) external;
/// Reverts a call to an address with a specific `msg.value`, with specified revert data.functionmockCallRevert(address callee, uint256 msgValue, bytescalldata data, bytescalldata revertData)
external;
/// Mocks a call to an address, returning specified data./// Calldata can either be strict or a partial match, e.g. if you only/// pass a Solidity selector to the expected calldata, then the entire Solidity/// function will be mocked.functionmockCall(address callee, bytescalldata data, bytescalldata returnData) external;
/// Mocks a call to an address with a specific `msg.value`, returning specified data./// Calldata match takes precedence over `msg.value` in case of ambiguity.functionmockCall(address callee, uint256 msgValue, bytescalldata data, bytescalldata returnData) external;
/// Sets the *next* call's `msg.sender` to be the input address.functionprank(address msgSender) external;
/// Sets the *next* call's `msg.sender` to be the input address, and the `tx.origin` to be the second input.functionprank(address msgSender, address txOrigin) external;
/// Sets `block.prevrandao`./// Not available on EVM versions before Paris. Use `difficulty` instead./// If used on unsupported EVM versions it will revert.functionprevrandao(bytes32 newPrevrandao) external;
/// Sets `block.prevrandao`./// Not available on EVM versions before Paris. Use `difficulty` instead./// If used on unsupported EVM versions it will revert.functionprevrandao(uint256 newPrevrandao) external;
/// Reads the current `msg.sender` and `tx.origin` from state and reports if there is any active caller modification.functionreadCallers() externalreturns (CallerMode callerMode, address msgSender, address txOrigin);
/// Resets the nonce of an account to 0 for EOAs and 1 for contract accounts.functionresetNonce(address account) external;
/// Revert the state of the EVM to a previous snapshot/// Takes the snapshot ID to revert to./// Returns `true` if the snapshot was successfully reverted./// Returns `false` if the snapshot does not exist./// **Note:** This does not automatically delete the snapshot. To delete the snapshot use `deleteSnapshot`.functionrevertTo(uint256 snapshotId) externalreturns (bool success);
/// Revert the state of the EVM to a previous snapshot and automatically deletes the snapshots/// Takes the snapshot ID to revert to./// Returns `true` if the snapshot was successfully reverted and deleted./// Returns `false` if the snapshot does not exist.functionrevertToAndDelete(uint256 snapshotId) externalreturns (bool success);
/// Revokes persistent status from the address, previously added via `makePersistent`.functionrevokePersistent(address account) external;
/// See `revokePersistent(address)`.functionrevokePersistent(address[] calldata accounts) external;
/// Sets `block.height`.functionroll(uint256 newHeight) external;
/// Updates the currently active fork to given block number/// This is similar to `roll` but for the currently active fork.functionrollFork(uint256 blockNumber) external;
/// Updates the currently active fork to given transaction. This will `rollFork` with the number/// of the block the transaction was mined in and replays all transaction mined before it in the block.functionrollFork(bytes32 txHash) external;
/// Updates the given fork to given block number.functionrollFork(uint256 forkId, uint256 blockNumber) external;
/// Updates the given fork to block number of the given transaction and replays all transaction mined before it in the block.functionrollFork(uint256 forkId, bytes32 txHash) external;
/// Takes a fork identifier created by `createFork` and sets the corresponding forked state as active.functionselectFork(uint256 forkId) external;
/// Sets the nonce of an account. Must be higher than the current nonce of the account.functionsetNonce(address account, uint64 newNonce) external;
/// Sets the nonce of an account to an arbitrary value.functionsetNonceUnsafe(address account, uint64 newNonce) external;
/// Snapshot the current state of the evm./// Returns the ID of the snapshot that was created./// To revert a snapshot use `revertTo`.functionsnapshot() externalreturns (uint256 snapshotId);
/// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called.functionstartPrank(address msgSender) external;
/// Sets all subsequent calls' `msg.sender` to be the input address until `stopPrank` is called, and the `tx.origin` to be the second input.functionstartPrank(address msgSender, address txOrigin) external;
/// Resets subsequent calls' `msg.sender` to be `address(this)`.functionstopPrank() external;
/// Stores a value to an address' storage slot.functionstore(address target, bytes32 slot, bytes32 value) external;
/// Fetches the given transaction from the active fork and executes it on the current state.functiontransact(bytes32 txHash) external;
/// Fetches the given transaction from the given fork and executes it on the current state.functiontransact(uint256 forkId, bytes32 txHash) external;
/// Sets `tx.gasprice`.functiontxGasPrice(uint256 newGasPrice) external;
/// Sets `block.timestamp`.functionwarp(uint256 newTimestamp) external;
// ======== Testing ========/// Expect a call to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.functionexpectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytescalldata data) external;
/// Expect given number of calls to an address with the specified `msg.value` and calldata, and a *minimum* amount of gas.functionexpectCallMinGas(address callee, uint256 msgValue, uint64 minGas, bytescalldata data, uint64 count)
external;
/// Expects a call to an address with the specified calldata./// Calldata can either be a strict or a partial match.functionexpectCall(address callee, bytescalldata data) external;
/// Expects given number of calls to an address with the specified calldata.functionexpectCall(address callee, bytescalldata data, uint64 count) external;
/// Expects a call to an address with the specified `msg.value` and calldata.functionexpectCall(address callee, uint256 msgValue, bytescalldata data) external;
/// Expects given number of calls to an address with the specified `msg.value` and calldata.functionexpectCall(address callee, uint256 msgValue, bytescalldata data, uint64 count) external;
/// Expect a call to an address with the specified `msg.value`, gas, and calldata.functionexpectCall(address callee, uint256 msgValue, uint64 gas, bytescalldata data) external;
/// Expects given number of calls to an address with the specified `msg.value`, gas, and calldata.functionexpectCall(address callee, uint256 msgValue, uint64 gas, bytescalldata data, uint64 count) external;
/// Prepare an expected log with (bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData.)./// Call this function, then emit an event, then call a function. Internally after the call, we check if/// logs were emitted in the expected order with the expected topics and data (as specified by the booleans).functionexpectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData) external;
/// Same as the previous method, but also checks supplied address against emitting contract.functionexpectEmit(bool checkTopic1, bool checkTopic2, bool checkTopic3, bool checkData, address emitter)
external;
/// Prepare an expected log with all topic and data checks enabled./// Call this function, then emit an event, then call a function. Internally after the call, we check if/// logs were emitted in the expected order with the expected topics and data.functionexpectEmit() external;
/// Same as the previous method, but also checks supplied address against emitting contract.functionexpectEmit(address emitter) external;
/// Expects an error on next call with any revert data.functionexpectRevert() external;
/// Expects an error on next call that starts with the revert data.functionexpectRevert(bytes4 revertData) external;
/// Expects an error on next call that exactly matches the revert data.functionexpectRevert(bytescalldata revertData) external;
/// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the current subcontext. If any other/// memory is written to, the test will fail. Can be called multiple times to add more ranges to the set.functionexpectSafeMemory(uint64 min, uint64 max) external;
/// Only allows memory writes to offsets [0x00, 0x60) ∪ [min, max) in the next created subcontext./// If any other memory is written to, the test will fail. Can be called multiple times to add more ranges/// to the set.functionexpectSafeMemoryCall(uint64 min, uint64 max) external;
/// Marks a test as skipped. Must be called at the top of the test.functionskip(bool skipTest) external;
/// Stops all safe memory expectation in the current subcontext.functionstopExpectSafeMemory() external;
}