// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)pragmasolidity ^0.8.1;/**
* @dev Collection of functions related to the address type
*/libraryAddress{
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*
* [IMPORTANT]
* ====
* You shouldn't rely on `isContract` to protect against flash loan attacks!
*
* Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets
* like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract
* constructor.
* ====
*/functionisContract(address account) internalviewreturns (bool) {
// This method relies on extcodesize/address.code.length, which returns 0// for contracts in construction, since the code is only stored at the end// of the constructor execution.return account.code.length>0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/functionsendValue(addresspayable recipient, uint256 amount) internal{
require(address(this).balance>= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/functionfunctionCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value
) internalreturns (bytesmemory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/functionfunctionCallWithValue(address target,
bytesmemory data,
uint256 value,
stringmemory errorMessage
) internalreturns (bytesmemory) {
require(address(this).balance>= value, "Address: insufficient balance for call");
(bool success, bytesmemory returndata) = target.call{value: value}(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target, bytesmemory data) internalviewreturns (bytesmemory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/functionfunctionStaticCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.staticcall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target, bytesmemory data) internalreturns (bytesmemory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/functionfunctionDelegateCall(address target,
bytesmemory data,
stringmemory errorMessage
) internalreturns (bytesmemory) {
(bool success, bytesmemory returndata) = target.delegatecall(data);
return verifyCallResultFromTarget(target, success, returndata, errorMessage);
}
/**
* @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
* the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.
*
* _Available since v4.8._
*/functionverifyCallResultFromTarget(address target,
bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalviewreturns (bytesmemory) {
if (success) {
if (returndata.length==0) {
// only check isContract if the call was successful and the return data is empty// otherwise we already know that it was a contractrequire(isContract(target), "Address: call to non-contract");
}
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
/**
* @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason or using the provided one.
*
* _Available since v4.3._
*/functionverifyCallResult(bool success,
bytesmemory returndata,
stringmemory errorMessage
) internalpurereturns (bytesmemory) {
if (success) {
return returndata;
} else {
_revert(returndata, errorMessage);
}
}
function_revert(bytesmemory returndata, stringmemory errorMessage) privatepure{
// Look for revert reason and bubble it up if presentif (returndata.length>0) {
// The easiest way to bubble the revert reason is using memory via assembly/// @solidity memory-safe-assemblyassembly {
let returndata_size :=mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
Contract Source Code
File 2 of 48: Base.sol
// 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 3 of 48: BasicRoyalties.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"@openzeppelin/contracts/token/common/ERC2981.sol";
/**
* @title BasicRoyaltiesBase
* @author Limit Break, Inc.
* @dev Base functionality of an NFT mix-in contract implementing the most basic form of programmable royalties.
*/abstractcontractBasicRoyaltiesBaseisERC2981{
eventDefaultRoyaltySet(addressindexed receiver, uint96 feeNumerator);
eventTokenRoyaltySet(uint256indexed tokenId, addressindexed receiver, uint96 feeNumerator);
function_setDefaultRoyalty(address receiver, uint96 feeNumerator) internalvirtualoverride{
super._setDefaultRoyalty(receiver, feeNumerator);
emit DefaultRoyaltySet(receiver, feeNumerator);
}
function_setTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) internalvirtualoverride{
super._setTokenRoyalty(tokenId, receiver, feeNumerator);
emit TokenRoyaltySet(tokenId, receiver, feeNumerator);
}
}
/**
* @title BasicRoyalties
* @author Limit Break, Inc.
* @notice Constructable BasicRoyalties Contract implementation.
*/abstractcontractBasicRoyaltiesisBasicRoyaltiesBase{
constructor(address receiver, uint96 feeNumerator) {
_setDefaultRoyalty(receiver, feeNumerator);
}
}
/**
* @title BasicRoyaltiesInitializable
* @author Limit Break, Inc.
* @notice Initializable BasicRoyalties Contract implementation to allow for EIP-1167 clones.
*/abstractcontractBasicRoyaltiesInitializableisBasicRoyaltiesBase{}
Contract Source Code
File 4 of 48: Context.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)pragmasolidity ^0.8.0;/**
* @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;
}
}
Contract Source Code
File 5 of 48: CreatorTokenBase.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"../access/OwnablePermissions.sol";
import"../interfaces/ICreatorToken.sol";
import"../interfaces/ICreatorTokenTransferValidator.sol";
import"../utils/TransferValidation.sol";
import"@openzeppelin/contracts/interfaces/IERC165.sol";
/**
* @title CreatorTokenBase
* @author Limit Break, Inc.
* @notice CreatorTokenBase is an abstract contract that provides basic functionality for managing token
* transfer policies through an implementation of ICreatorTokenTransferValidator. This contract is intended to be used
* as a base for creator-specific token contracts, enabling customizable transfer restrictions and security policies.
*
* <h4>Features:</h4>
* <ul>Ownable: This contract can have an owner who can set and update the transfer validator.</ul>
* <ul>TransferValidation: Implements the basic token transfer validation interface.</ul>
* <ul>ICreatorToken: Implements the interface for creator tokens, providing view functions for token security policies.</ul>
*
* <h4>Benefits:</h4>
* <ul>Provides a flexible and modular way to implement custom token transfer restrictions and security policies.</ul>
* <ul>Allows creators to enforce policies such as whitelisted operators and permitted contract receivers.</ul>
* <ul>Can be easily integrated into other token contracts as a base contract.</ul>
*
* <h4>Intended Usage:</h4>
* <ul>Use as a base contract for creator token implementations that require advanced transfer restrictions and
* security policies.</ul>
* <ul>Set and update the ICreatorTokenTransferValidator implementation contract to enforce desired policies for the
* creator token.</ul>
*/abstractcontractCreatorTokenBaseisOwnablePermissions, TransferValidation, ICreatorToken{
errorCreatorTokenBase__InvalidTransferValidatorContract();
errorCreatorTokenBase__SetTransferValidatorFirst();
addresspublicconstant DEFAULT_TRANSFER_VALIDATOR =address(0x0000721C310194CcfC01E523fc93C9cCcFa2A0Ac);
TransferSecurityLevels publicconstant DEFAULT_TRANSFER_SECURITY_LEVEL = TransferSecurityLevels.One;
uint120publicconstant DEFAULT_OPERATOR_WHITELIST_ID =uint120(1);
ICreatorTokenTransferValidator private transferValidator;
/**
* @notice Allows the contract owner to set the transfer validator to the official validator contract
* and set the security policy to the recommended default settings.
* @dev May be overridden to change the default behavior of an individual collection.
*/functionsetToDefaultSecurityPolicy() publicvirtual{
_requireCallerIsContractOwner();
setTransferValidator(DEFAULT_TRANSFER_VALIDATOR);
ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setTransferSecurityLevelOfCollection(address(this), DEFAULT_TRANSFER_SECURITY_LEVEL);
ICreatorTokenTransferValidator(DEFAULT_TRANSFER_VALIDATOR).setOperatorWhitelistOfCollection(address(this), DEFAULT_OPERATOR_WHITELIST_ID);
}
/**
* @notice Allows the contract owner to set the transfer validator to a custom validator contract
* and set the security policy to their own custom settings.
*/functionsetToCustomValidatorAndSecurityPolicy(address validator,
TransferSecurityLevels level,
uint120 operatorWhitelistId,
uint120 permittedContractReceiversAllowlistId) public{
_requireCallerIsContractOwner();
setTransferValidator(validator);
ICreatorTokenTransferValidator(validator).
setTransferSecurityLevelOfCollection(address(this), level);
ICreatorTokenTransferValidator(validator).
setOperatorWhitelistOfCollection(address(this), operatorWhitelistId);
ICreatorTokenTransferValidator(validator).
setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId);
}
/**
* @notice Allows the contract owner to set the security policy to their own custom settings.
* @dev Reverts if the transfer validator has not been set.
*/functionsetToCustomSecurityPolicy(
TransferSecurityLevels level,
uint120 operatorWhitelistId,
uint120 permittedContractReceiversAllowlistId) public{
_requireCallerIsContractOwner();
ICreatorTokenTransferValidator validator = getTransferValidator();
if (address(validator) ==address(0)) {
revert CreatorTokenBase__SetTransferValidatorFirst();
}
validator.setTransferSecurityLevelOfCollection(address(this), level);
validator.setOperatorWhitelistOfCollection(address(this), operatorWhitelistId);
validator.setPermittedContractReceiverAllowlistOfCollection(address(this), permittedContractReceiversAllowlistId);
}
/**
* @notice Sets the transfer validator for the token contract.
*
* @dev Throws when provided validator contract is not the zero address and doesn't support
* the ICreatorTokenTransferValidator interface.
* @dev Throws when the caller is not the contract owner.
*
* @dev <h4>Postconditions:</h4>
* 1. The transferValidator address is updated.
* 2. The `TransferValidatorUpdated` event is emitted.
*
* @param transferValidator_ The address of the transfer validator contract.
*/functionsetTransferValidator(address transferValidator_) public{
_requireCallerIsContractOwner();
bool isValidTransferValidator =false;
if(transferValidator_.code.length>0) {
try IERC165(transferValidator_).supportsInterface(type(ICreatorTokenTransferValidator).interfaceId)
returns (bool supportsInterface) {
isValidTransferValidator = supportsInterface;
} catch {}
}
if(transferValidator_ !=address(0) &&!isValidTransferValidator) {
revert CreatorTokenBase__InvalidTransferValidatorContract();
}
emit TransferValidatorUpdated(address(transferValidator), transferValidator_);
transferValidator = ICreatorTokenTransferValidator(transferValidator_);
}
/**
* @notice Returns the transfer validator contract address for this token contract.
*/functiongetTransferValidator() publicviewoverridereturns (ICreatorTokenTransferValidator) {
return transferValidator;
}
/**
* @notice Returns the security policy for this token contract, which includes:
* Transfer security level, operator whitelist id, permitted contract receiver allowlist id.
*/functiongetSecurityPolicy() publicviewoverridereturns (CollectionSecurityPolicy memory) {
if (address(transferValidator) !=address(0)) {
return transferValidator.getCollectionSecurityPolicy(address(this));
}
return CollectionSecurityPolicy({
transferSecurityLevel: TransferSecurityLevels.Zero,
operatorWhitelistId: 0,
permittedContractReceiversId: 0
});
}
/**
* @notice Returns the list of all whitelisted operators for this token contract.
* @dev This can be an expensive call and should only be used in view-only functions.
*/functiongetWhitelistedOperators() publicviewoverridereturns (address[] memory) {
if (address(transferValidator) !=address(0)) {
return transferValidator.getWhitelistedOperators(
transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId);
}
returnnewaddress[](0);
}
/**
* @notice Returns the list of permitted contract receivers for this token contract.
* @dev This can be an expensive call and should only be used in view-only functions.
*/functiongetPermittedContractReceivers() publicviewoverridereturns (address[] memory) {
if (address(transferValidator) !=address(0)) {
return transferValidator.getPermittedContractReceivers(
transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId);
}
returnnewaddress[](0);
}
/**
* @notice Checks if an operator is whitelisted for this token contract.
* @param operator The address of the operator to check.
*/functionisOperatorWhitelisted(address operator) publicviewoverridereturns (bool) {
if (address(transferValidator) !=address(0)) {
return transferValidator.isOperatorWhitelisted(
transferValidator.getCollectionSecurityPolicy(address(this)).operatorWhitelistId, operator);
}
returnfalse;
}
/**
* @notice Checks if a contract receiver is permitted for this token contract.
* @param receiver The address of the receiver to check.
*/functionisContractReceiverPermitted(address receiver) publicviewoverridereturns (bool) {
if (address(transferValidator) !=address(0)) {
return transferValidator.isContractReceiverPermitted(
transferValidator.getCollectionSecurityPolicy(address(this)).permittedContractReceiversId, receiver);
}
returnfalse;
}
/**
* @notice Determines if a transfer is allowed based on the token contract's security policy. Use this function
* to simulate whether or not a transfer made by the specified `caller` from the `from` address to the `to`
* address would be allowed by this token's security policy.
*
* @notice This function only checks the security policy restrictions and does not check whether token ownership
* or approvals are in place.
*
* @param caller The address of the simulated caller.
* @param from The address of the sender.
* @param to The address of the receiver.
* @return True if the transfer is allowed, false otherwise.
*/functionisTransferAllowed(address caller, addressfrom, address to) publicviewoverridereturns (bool) {
if (address(transferValidator) !=address(0)) {
try transferValidator.applyCollectionTransferPolicy(caller, from, to) {
returntrue;
} catch {
returnfalse;
}
}
returntrue;
}
/**
* @dev Pre-validates a token transfer, reverting if the transfer is not allowed by this token's security policy.
* Inheriting contracts are responsible for overriding the _beforeTokenTransfer function, or its equivalent
* and calling _validateBeforeTransfer so that checks can be properly applied during token transfers.
*
* @dev Throws when the transfer doesn't comply with the collection's transfer policy, if the transferValidator is
* set to a non-zero address.
*
* @param caller The address of the caller.
* @param from The address of the sender.
* @param to The address of the receiver.
*/function_preValidateTransfer(address caller,
addressfrom,
address to,
uint256/*tokenId*/,
uint256/*value*/) internalvirtualoverride{
if (address(transferValidator) !=address(0)) {
transferValidator.applyCollectionTransferPolicy(caller, from, to);
}
}
}
Contract Source Code
File 6 of 48: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)pragmasolidity ^0.8.0;import"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 7 of 48: ERC2981.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (token/common/ERC2981.sol)pragmasolidity ^0.8.0;import"../../interfaces/IERC2981.sol";
import"../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of the NFT Royalty Standard, a standardized way to retrieve royalty payment information.
*
* Royalty information can be specified globally for all token ids via {_setDefaultRoyalty}, and/or individually for
* specific token ids via {_setTokenRoyalty}. The latter takes precedence over the first.
*
* Royalty is specified as a fraction of sale price. {_feeDenominator} is overridable but defaults to 10000, meaning the
* fee is specified in basis points by default.
*
* IMPORTANT: ERC-2981 only specifies a way to signal royalty information and does not enforce its payment. See
* https://eips.ethereum.org/EIPS/eip-2981#optional-royalty-payments[Rationale] in the EIP. Marketplaces are expected to
* voluntarily pay royalties together with sales, but note that this standard is not yet widely supported.
*
* _Available since v4.5._
*/abstractcontractERC2981isIERC2981, ERC165{
structRoyaltyInfo {
address receiver;
uint96 royaltyFraction;
}
RoyaltyInfo private _defaultRoyaltyInfo;
mapping(uint256=> RoyaltyInfo) private _tokenRoyaltyInfo;
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(IERC165, ERC165) returns (bool) {
return interfaceId ==type(IERC2981).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @inheritdoc IERC2981
*/functionroyaltyInfo(uint256 _tokenId, uint256 _salePrice) publicviewvirtualoverridereturns (address, uint256) {
RoyaltyInfo memory royalty = _tokenRoyaltyInfo[_tokenId];
if (royalty.receiver ==address(0)) {
royalty = _defaultRoyaltyInfo;
}
uint256 royaltyAmount = (_salePrice * royalty.royaltyFraction) / _feeDenominator();
return (royalty.receiver, royaltyAmount);
}
/**
* @dev The denominator with which to interpret the fee set in {_setTokenRoyalty} and {_setDefaultRoyalty} as a
* fraction of the sale price. Defaults to 10000 so fees are expressed in basis points, but may be customized by an
* override.
*/function_feeDenominator() internalpurevirtualreturns (uint96) {
return10000;
}
/**
* @dev Sets the royalty information that all ids in this contract will default to.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setDefaultRoyalty(address receiver, uint96 feeNumerator) internalvirtual{
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver !=address(0), "ERC2981: invalid receiver");
_defaultRoyaltyInfo = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Removes default royalty information.
*/function_deleteDefaultRoyalty() internalvirtual{
delete _defaultRoyaltyInfo;
}
/**
* @dev Sets the royalty information for a specific token id, overriding the global default.
*
* Requirements:
*
* - `receiver` cannot be the zero address.
* - `feeNumerator` cannot be greater than the fee denominator.
*/function_setTokenRoyalty(uint256 tokenId,
address receiver,
uint96 feeNumerator
) internalvirtual{
require(feeNumerator <= _feeDenominator(), "ERC2981: royalty fee will exceed salePrice");
require(receiver !=address(0), "ERC2981: Invalid parameters");
_tokenRoyaltyInfo[tokenId] = RoyaltyInfo(receiver, feeNumerator);
}
/**
* @dev Resets royalty information for the token id back to the global default.
*/function_resetTokenRoyalty(uint256 tokenId) internalvirtual{
delete _tokenRoyaltyInfo[tokenId];
}
}
Contract Source Code
File 8 of 48: ERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.2) (token/ERC721/ERC721.sol)pragmasolidity ^0.8.0;import"./IERC721.sol";
import"./IERC721Receiver.sol";
import"./extensions/IERC721Metadata.sol";
import"../../utils/Address.sol";
import"../../utils/Context.sol";
import"../../utils/Strings.sol";
import"../../utils/introspection/ERC165.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/contractERC721isContext, ERC165, IERC721, IERC721Metadata{
usingAddressforaddress;
usingStringsforuint256;
// Token namestringprivate _name;
// Token symbolstringprivate _symbol;
// Mapping from token ID to owner addressmapping(uint256=>address) private _owners;
// Mapping owner address to token countmapping(address=>uint256) private _balances;
// Mapping from token ID to approved addressmapping(uint256=>address) private _tokenApprovals;
// Mapping from owner to operator approvalsmapping(address=>mapping(address=>bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165, IERC165) returns (bool) {
return
interfaceId ==type(IERC721).interfaceId||
interfaceId ==type(IERC721Metadata).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/functionbalanceOf(address owner) publicviewvirtualoverridereturns (uint256) {
require(owner !=address(0), "ERC721: address zero is not a valid owner");
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/functionownerOf(uint256 tokenId) publicviewvirtualoverridereturns (address) {
address owner = _ownerOf(tokenId);
require(owner !=address(0), "ERC721: invalid token ID");
return owner;
}
/**
* @dev See {IERC721Metadata-name}.
*/functionname() publicviewvirtualoverridereturns (stringmemory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewvirtualoverridereturns (stringmemory) {
_requireMinted(tokenId);
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length>0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : "";
}
/**
* @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, can be overridden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return"";
}
/**
* @dev See {IERC721-approve}.
*/functionapprove(address to, uint256 tokenId) publicvirtualoverride{
address owner = ERC721.ownerOf(tokenId);
require(to != owner, "ERC721: approval to current owner");
require(
_msgSender() == owner || isApprovedForAll(owner, _msgSender()),
"ERC721: approve caller is not token owner or approved for all"
);
_approve(to, tokenId);
}
/**
* @dev See {IERC721-getApproved}.
*/functiongetApproved(uint256 tokenId) publicviewvirtualoverridereturns (address) {
_requireMinted(tokenId);
return _tokenApprovals[tokenId];
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtualoverride{
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualoverridereturns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/functiontransferFrom(addressfrom,
address to,
uint256 tokenId
) publicvirtualoverride{
//solhint-disable-next-line max-line-lengthrequire(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_transfer(from, to, tokenId);
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId
) publicvirtualoverride{
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom,
address to,
uint256 tokenId,
bytesmemory data
) publicvirtualoverride{
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721: caller is not token owner or approved");
_safeTransfer(from, to, tokenId, data);
}
/**
* @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.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeTransfer(addressfrom,
address to,
uint256 tokenId,
bytesmemory data
) internalvirtual{
_transfer(from, to, tokenId);
require(_checkOnERC721Received(from, to, tokenId, data), "ERC721: transfer to non ERC721Receiver implementer");
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*/function_ownerOf(uint256 tokenId) internalviewvirtualreturns (address) {
return _owners[tokenId];
}
/**
* @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 (`_mint`),
* and stop existing when they are burned (`_burn`).
*/function_exists(uint256 tokenId) internalviewvirtualreturns (bool) {
return _ownerOf(tokenId) !=address(0);
}
/**
* @dev Returns whether `spender` is allowed to manage `tokenId`.
*
* Requirements:
*
* - `tokenId` must exist.
*/function_isApprovedOrOwner(address spender, uint256 tokenId) internalviewvirtualreturns (bool) {
address owner = ERC721.ownerOf(tokenId);
return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);
}
/**
* @dev Safely mints `tokenId` and transfers it to `to`.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeMint(address to, uint256 tokenId) internalvirtual{
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeMint(address to,
uint256 tokenId,
bytesmemory data
) internalvirtual{
_mint(to, tokenId);
require(
_checkOnERC721Received(address(0), to, tokenId, data),
"ERC721: transfer to non ERC721Receiver implementer"
);
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/function_mint(address to, uint256 tokenId) internalvirtual{
require(to !=address(0), "ERC721: mint to the zero address");
require(!_exists(tokenId), "ERC721: token already minted");
_beforeTokenTransfer(address(0), to, tokenId, 1);
// Check that tokenId was not minted by `_beforeTokenTransfer` hookrequire(!_exists(tokenId), "ERC721: token already minted");
unchecked {
// Will not overflow unless all 2**256 token ids are minted to the same owner.// Given that tokens are minted one by one, it is impossible in practice that// this ever happens. Might change if we allow batch minting.// The ERC fails to describe this case.
_balances[to] +=1;
}
_owners[tokenId] = to;
emit Transfer(address(0), to, tokenId);
_afterTokenTransfer(address(0), to, tokenId, 1);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/function_burn(uint256 tokenId) internalvirtual{
address owner = ERC721.ownerOf(tokenId);
_beforeTokenTransfer(owner, address(0), tokenId, 1);
// Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook
owner = ERC721.ownerOf(tokenId);
// Clear approvalsdelete _tokenApprovals[tokenId];
unchecked {
// Cannot overflow, as that would require more tokens to be burned/transferred// out than the owner initially received through minting and transferring in.
_balances[owner] -=1;
}
delete _owners[tokenId];
emit Transfer(owner, address(0), tokenId);
_afterTokenTransfer(owner, address(0), tokenId, 1);
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/function_transfer(addressfrom,
address to,
uint256 tokenId
) internalvirtual{
require(ERC721.ownerOf(tokenId) ==from, "ERC721: transfer from incorrect owner");
require(to !=address(0), "ERC721: transfer to the zero address");
_beforeTokenTransfer(from, to, tokenId, 1);
// Check that tokenId was not transferred by `_beforeTokenTransfer` hookrequire(ERC721.ownerOf(tokenId) ==from, "ERC721: transfer from incorrect owner");
// Clear approvals from the previous ownerdelete _tokenApprovals[tokenId];
unchecked {
// `_balances[from]` cannot overflow for the same reason as described in `_burn`:// `from`'s balance is the number of token held, which is at least one before the current// transfer.// `_balances[to]` could overflow in the conditions described in `_mint`. That would require// all 2**256 token ids to be minted, which in practice is impossible.
_balances[from] -=1;
_balances[to] +=1;
}
_owners[tokenId] = to;
emit Transfer(from, to, tokenId);
_afterTokenTransfer(from, to, tokenId, 1);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* Emits an {Approval} event.
*/function_approve(address to, uint256 tokenId) internalvirtual{
_tokenApprovals[tokenId] = to;
emit Approval(ERC721.ownerOf(tokenId), to, tokenId);
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Emits an {ApprovalForAll} event.
*/function_setApprovalForAll(address owner,
address operator,
bool approved
) internalvirtual{
require(owner != operator, "ERC721: approve to caller");
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` has not been minted yet.
*/function_requireMinted(uint256 tokenId) internalviewvirtual{
require(_exists(tokenId), "ERC721: invalid token ID");
}
/**
* @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.
* The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
* @return bool whether the call correctly returned the expected magic value
*/function_checkOnERC721Received(addressfrom,
address to,
uint256 tokenId,
bytesmemory data
) privatereturns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytesmemory reason) {
if (reason.length==0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assemblyassembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
returntrue;
}
}
/**
* @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`.
* - When `from` is zero, the tokens will be minted for `to`.
* - When `to` is zero, ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_beforeTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize
) internalvirtual{}
/**
* @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is
* used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1.
*
* Calling conditions:
*
* - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`.
* - When `from` is zero, the tokens were minted for `to`.
* - When `to` is zero, ``from``'s tokens were burned.
* - `from` and `to` are never both zero.
* - `batchSize` is non-zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/function_afterTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize
) internalvirtual{}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant
* being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such
* that `ownerOf(tokenId)` is `a`.
*/// solhint-disable-next-line func-name-mixedcasefunction__unsafe_increaseBalance(address account, uint256 amount) internal{
_balances[account] += amount;
}
}
Contract Source Code
File 9 of 48: ERC721C.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"../utils/CreatorTokenBase.sol";
import"../token/erc721/ERC721OpenZeppelin.sol";
/**
* @title ERC721C
* @author Limit Break, Inc.
* @notice Extends OpenZeppelin's ERC721 implementation with Creator Token functionality, which
* allows the contract owner to update the transfer validation logic by managing a security policy in
* an external transfer validation security policy registry. See {CreatorTokenTransferValidator}.
*/abstractcontractERC721CisERC721OpenZeppelin, CreatorTokenBase{
functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(ICreatorToken).interfaceId||super.supportsInterface(interfaceId);
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logicfunction_beforeTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize) internalvirtualoverride{
for (uint256 i =0; i < batchSize;) {
_validateBeforeTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logicfunction_afterTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize) internalvirtualoverride{
for (uint256 i =0; i < batchSize;) {
_validateAfterTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
}
/**
* @title ERC721CInitializable
* @author Limit Break, Inc.
* @notice Initializable implementation of ERC721C to allow for EIP-1167 proxy clones.
*/abstractcontractERC721CInitializableisERC721OpenZeppelinInitializable, CreatorTokenBase{
functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverridereturns (bool) {
return interfaceId ==type(ICreatorToken).interfaceId||super.supportsInterface(interfaceId);
}
/// @dev Ties the open-zeppelin _beforeTokenTransfer hook to more granular transfer validation logicfunction_beforeTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize) internalvirtualoverride{
for (uint256 i =0; i < batchSize;) {
_validateBeforeTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
/// @dev Ties the open-zeppelin _afterTokenTransfer hook to more granular transfer validation logicfunction_afterTokenTransfer(addressfrom,
address to,
uint256 firstTokenId,
uint256 batchSize) internalvirtualoverride{
for (uint256 i =0; i < batchSize;) {
_validateAfterTransfer(from, to, firstTokenId + i);
unchecked {
++i;
}
}
}
}
Contract Source Code
File 10 of 48: ERC721CWithBasicRoyalties.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"../../access/OwnableBasic.sol";
import"../../erc721c/ERC721C.sol";
import"../../programmable-royalties/BasicRoyalties.sol";
/**
* @title ERC721CWithBasicRoyalties
* @author Limit Break, Inc.
* @notice Extension of ERC721C that adds basic royalties support.
* @dev These contracts are intended for example use and are not intended for production deployments as-is.
*/contractERC721CWithBasicRoyaltiesisOwnableBasic, ERC721C, BasicRoyalties{
constructor(address royaltyReceiver_,
uint96 royaltyFeeNumerator_,
stringmemory name_,
stringmemory symbol_)
ERC721OpenZeppelin(name_, symbol_)
BasicRoyalties(royaltyReceiver_, royaltyFeeNumerator_) {
}
functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC721C, ERC2981) returns (bool) {
returnsuper.supportsInterface(interfaceId);
}
functionmint(address to, uint256 tokenId) external{
_mint(to, tokenId);
}
functionsafeMint(address to, uint256 tokenId) external{
_safeMint(to, tokenId);
}
functionburn(uint256 tokenId) external{
_burn(tokenId);
}
functionsetDefaultRoyalty(address receiver, uint96 feeNumerator) public{
_requireCallerIsContractOwner();
_setDefaultRoyalty(receiver, feeNumerator);
}
functionsetTokenRoyalty(uint256 tokenId, address receiver, uint96 feeNumerator) public{
_requireCallerIsContractOwner();
_setTokenRoyalty(tokenId, receiver, feeNumerator);
}
}
Contract Source Code
File 11 of 48: ERC721OpenZeppelin.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"../../access/OwnablePermissions.sol";
import"@openzeppelin/contracts/token/ERC721/ERC721.sol";
abstractcontractERC721OpenZeppelinBaseisERC721{
// Token namestringinternal _contractName;
// Token symbolstringinternal _contractSymbol;
functionname() publicviewvirtualoverridereturns (stringmemory) {
return _contractName;
}
functionsymbol() publicviewvirtualoverridereturns (stringmemory) {
return _contractSymbol;
}
function_setNameAndSymbol(stringmemory name_, stringmemory symbol_) internal{
_contractName = name_;
_contractSymbol = symbol_;
}
}
abstractcontractERC721OpenZeppelinisERC721OpenZeppelinBase{
constructor(stringmemory name_, stringmemory symbol_) ERC721("", "") {
_setNameAndSymbol(name_, symbol_);
}
}
abstractcontractERC721OpenZeppelinInitializableisOwnablePermissions, ERC721OpenZeppelinBase{
errorERC721OpenZeppelinInitializable__AlreadyInitializedERC721();
/// @notice Specifies whether or not the contract is initializedboolprivate _erc721Initialized;
/// @dev Initializes parameters of ERC721 tokens./// These cannot be set in the constructor because this contract is optionally compatible with EIP-1167.functioninitializeERC721(stringmemory name_, stringmemory symbol_) public{
_requireCallerIsContractOwner();
if(_erc721Initialized) {
revert ERC721OpenZeppelinInitializable__AlreadyInitializedERC721();
}
_erc721Initialized =true;
_setNameAndSymbol(name_, symbol_);
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (interfaces/IERC2981.sol)pragmasolidity ^0.8.0;import"../utils/introspection/IERC165.sol";
/**
* @dev Interface for the NFT Royalty Standard.
*
* A standardized way to retrieve royalty payment information for non-fungible tokens (NFTs) to enable universal
* support for royalty payments across all NFT marketplaces and ecosystem participants.
*
* _Available since v4.5._
*/interfaceIERC2981isIERC165{
/**
* @dev Returns how much royalty is owed and to whom, based on a sale price that may be denominated in any unit of
* exchange. The royalty amount is denominated and should be paid in that same unit of exchange.
*/functionroyaltyInfo(uint256 tokenId, uint256 salePrice)
externalviewreturns (address receiver, uint256 royaltyAmount);
}
Contract Source Code
File 17 of 48: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC721/IERC721.sol)pragmasolidity ^0.8.0;import"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @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`.
*
* 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,
bytescalldata data
) external;
/**
* @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 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
) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* 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
) external;
/**
* @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) external;
/**
* @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);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)pragmasolidity ^0.8.0;/**
* @title ERC721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)pragmasolidity ^0.8.0;/**
* @dev Standard math utilities missing in the Solidity language.
*/libraryMath{
enumRounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/functionmax(uint256 a, uint256 b) internalpurereturns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/functionmin(uint256 a, uint256 b) internalpurereturns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/functionaverage(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b) / 2 can overflow.return (a & b) + (a ^ b) /2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/functionceilDiv(uint256 a, uint256 b) internalpurereturns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.return a ==0 ? 0 : (a -1) / b +1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/functionmulDiv(uint256 x,
uint256 y,
uint256 denominator
) internalpurereturns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256// variables such that product = prod1 * 2^256 + prod0.uint256 prod0; // Least significant 256 bits of the productuint256 prod1; // Most significant 256 bits of the productassembly {
let mm :=mulmod(x, y, not(0))
prod0 :=mul(x, y)
prod1 :=sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.if (prod1 ==0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.require(denominator > prod1);
///////////////////////////////////////////////// 512 by 256 division.///////////////////////////////////////////////// Make division exact by subtracting the remainder from [prod1 prod0].uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder :=mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 :=sub(prod1, gt(remainder, prod0))
prod0 :=sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.// See https://cs.stackexchange.com/q/138556/92363.// Does not overflow because the denominator cannot be zero at this stage in the function.uint256 twos = denominator & (~denominator +1);
assembly {
// Divide denominator by twos.
denominator :=div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 :=div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos :=add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for// four bits. That is, denominator * inv = 1 mod 2^4.uint256 inverse = (3* denominator) ^2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works// in modular arithmetic, doubling the correct bits in each step.
inverse *=2- denominator * inverse; // inverse mod 2^8
inverse *=2- denominator * inverse; // inverse mod 2^16
inverse *=2- denominator * inverse; // inverse mod 2^32
inverse *=2- denominator * inverse; // inverse mod 2^64
inverse *=2- denominator * inverse; // inverse mod 2^128
inverse *=2- denominator * inverse; // inverse mod 2^256// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/functionmulDiv(uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internalpurereturns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up &&mulmod(x, y, denominator) >0) {
result +=1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/functionsqrt(uint256 a) internalpurereturns (uint256) {
if (a ==0) {
return0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.//// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.//// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`//// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.uint256 result =1<< (log2(a) >>1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision// into the expected uint128 result.unchecked {
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
result = (result + a / result) >>1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/functionsqrt(uint256 a, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=128;
}
if (value >>64>0) {
value >>=64;
result +=64;
}
if (value >>32>0) {
value >>=32;
result +=32;
}
if (value >>16>0) {
value >>=16;
result +=16;
}
if (value >>8>0) {
value >>=8;
result +=8;
}
if (value >>4>0) {
value >>=4;
result +=4;
}
if (value >>2>0) {
value >>=2;
result +=2;
}
if (value >>1>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog2(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result =log2(value);
return result + (rounding == Rounding.Up &&1<< result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >=10**64) {
value /=10**64;
result +=64;
}
if (value >=10**32) {
value /=10**32;
result +=32;
}
if (value >=10**16) {
value /=10**16;
result +=16;
}
if (value >=10**8) {
value /=10**8;
result +=8;
}
if (value >=10**4) {
value /=10**4;
result +=4;
}
if (value >=10**2) {
value /=10**2;
result +=2;
}
if (value >=10**1) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog10(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up &&10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/functionlog256(uint256 value) internalpurereturns (uint256) {
uint256 result =0;
unchecked {
if (value >>128>0) {
value >>=128;
result +=16;
}
if (value >>64>0) {
value >>=64;
result +=8;
}
if (value >>32>0) {
value >>=32;
result +=4;
}
if (value >>16>0) {
value >>=16;
result +=2;
}
if (value >>8>0) {
result +=1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/functionlog256(uint256 value, Rounding rounding) internalpurereturns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up &&1<< (result *8) < value ? 1 : 0);
}
}
}
Contract Source Code
File 24 of 48: MockERC20.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;/// @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.solcontractMockERC20{
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/eventTransfer(addressindexedfrom, addressindexed to, uint256 amount);
eventApproval(addressindexed owner, addressindexed spender, uint256 amount);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE
//////////////////////////////////////////////////////////////*/stringpublic name;
stringpublic symbol;
uint8public decimals;
/*//////////////////////////////////////////////////////////////
ERC20 STORAGE
//////////////////////////////////////////////////////////////*/uint256public totalSupply;
mapping(address=>uint256) public balanceOf;
mapping(address=>mapping(address=>uint256)) public allowance;
/*//////////////////////////////////////////////////////////////
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) publicvirtualreturns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
returntrue;
}
functiontransfer(address to, uint256 amount) publicvirtualreturns (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) publicvirtualreturns (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 25 of 48: MockERC721.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;/// @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.solcontractMockERC721{
/*//////////////////////////////////////////////////////////////
EVENTS
//////////////////////////////////////////////////////////////*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed id);
eventApproval(addressindexed owner, addressindexed spender, uint256indexed id);
eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/*//////////////////////////////////////////////////////////////
METADATA STORAGE/LOGIC
//////////////////////////////////////////////////////////////*/stringpublic name;
stringpublic symbol;
functiontokenURI(uint256 id) publicviewvirtualreturns (stringmemory) {}
/*//////////////////////////////////////////////////////////////
ERC721 BALANCE/OWNER STORAGE
//////////////////////////////////////////////////////////////*/mapping(uint256=>address) internal _ownerOf;
mapping(address=>uint256) internal _balanceOf;
functionownerOf(uint256 id) publicviewvirtualreturns (address owner) {
require((owner = _ownerOf[id]) !=address(0), "NOT_MINTED");
}
functionbalanceOf(address owner) publicviewvirtualreturns (uint256) {
require(owner !=address(0), "ZERO_ADDRESS");
return _balanceOf[owner];
}
/*//////////////////////////////////////////////////////////////
ERC721 APPROVAL STORAGE
//////////////////////////////////////////////////////////////*/mapping(uint256=>address) public getApproved;
mapping(address=>mapping(address=>bool)) public isApprovedForAll;
/*//////////////////////////////////////////////////////////////
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) publicvirtual{
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) publicvirtual{
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}
functiontransferFrom(addressfrom, address to, uint256 id) publicvirtual{
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) publicvirtual{
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) publicvirtual{
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) publicpurevirtualreturns (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 26 of 48: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)pragmasolidity ^0.8.0;import"../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.
*
* By default, the owner account will be the one that deploys the contract. 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;
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the deployer as the initial owner.
*/constructor() {
_transferOwnership(_msgSender());
}
/**
* @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{
require(owner() == _msgSender(), "Ownable: caller is not the owner");
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions anymore. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby removing 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{
require(newOwner !=address(0), "Ownable: new owner is the zero address");
_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 {DSTest} from"ds-test/test.sol";
import {stdMath} from"./StdMath.sol";
abstractcontractStdAssertionsisDSTest{
eventlog_array(uint256[] val);
eventlog_array(int256[] val);
eventlog_array(address[] val);
eventlog_named_array(string key, uint256[] val);
eventlog_named_array(string key, int256[] val);
eventlog_named_array(string key, address[] val);
functionfail(stringmemory err) internalvirtual{
emit log_named_string("Error", err);
fail();
}
functionassertFalse(bool data) internalvirtual{
assertTrue(!data);
}
functionassertFalse(bool data, stringmemory err) internalvirtual{
assertTrue(!data, err);
}
functionassertEq(bool a, bool b) internalvirtual{
if (a != b) {
emit log("Error: a == b not satisfied [bool]");
emit log_named_string(" Left", a ? "true" : "false");
emit log_named_string(" Right", b ? "true" : "false");
fail();
}
}
functionassertEq(bool a, bool b, stringmemory err) internalvirtual{
if (a != b) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertEq(bytesmemory a, bytesmemory b) internalvirtual{
assertEq0(a, b);
}
functionassertEq(bytesmemory a, bytesmemory b, stringmemory err) internalvirtual{
assertEq0(a, b, err);
}
functionassertEq(uint256[] memory a, uint256[] memory b) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log("Error: a == b not satisfied [uint[]]");
emit log_named_array(" Left", a);
emit log_named_array(" Right", b);
fail();
}
}
functionassertEq(int256[] memory a, int256[] memory b) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log("Error: a == b not satisfied [int[]]");
emit log_named_array(" Left", a);
emit log_named_array(" Right", b);
fail();
}
}
functionassertEq(address[] memory a, address[] memory b) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log("Error: a == b not satisfied [address[]]");
emit log_named_array(" Left", a);
emit log_named_array(" Right", b);
fail();
}
}
functionassertEq(uint256[] memory a, uint256[] memory b, stringmemory err) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertEq(int256[] memory a, int256[] memory b, stringmemory err) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertEq(address[] memory a, address[] memory b, stringmemory err) internalvirtual{
if (keccak256(abi.encode(a)) !=keccak256(abi.encode(b))) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
// Legacy helperfunctionassertEqUint(uint256 a, uint256 b) internalvirtual{
assertEq(uint256(a), uint256(b));
}
functionassertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log("Error: a ~= b not satisfied [uint]");
emit log_named_uint(" Left", a);
emit log_named_uint(" Right", b);
emit log_named_uint(" Max Delta", maxDelta);
emit log_named_uint(" Delta", delta);
fail();
}
}
functionassertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, stringmemory err) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log_named_string("Error", err);
assertApproxEqAbs(a, b, maxDelta);
}
}
functionassertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log("Error: a ~= b not satisfied [uint]");
emit log_named_decimal_uint(" Left", a, decimals);
emit log_named_decimal_uint(" Right", b, decimals);
emit log_named_decimal_uint(" Max Delta", maxDelta, decimals);
emit log_named_decimal_uint(" Delta", delta, decimals);
fail();
}
}
functionassertApproxEqAbsDecimal(uint256 a, uint256 b, uint256 maxDelta, uint256 decimals, stringmemory err)
internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log_named_string("Error", err);
assertApproxEqAbsDecimal(a, b, maxDelta, decimals);
}
}
functionassertApproxEqAbs(int256 a, int256 b, uint256 maxDelta) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log("Error: a ~= b not satisfied [int]");
emit log_named_int(" Left", a);
emit log_named_int(" Right", b);
emit log_named_uint(" Max Delta", maxDelta);
emit log_named_uint(" Delta", delta);
fail();
}
}
functionassertApproxEqAbs(int256 a, int256 b, uint256 maxDelta, stringmemory err) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log_named_string("Error", err);
assertApproxEqAbs(a, b, maxDelta);
}
}
functionassertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals) internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log("Error: a ~= b not satisfied [int]");
emit log_named_decimal_int(" Left", a, decimals);
emit log_named_decimal_int(" Right", b, decimals);
emit log_named_decimal_uint(" Max Delta", maxDelta, decimals);
emit log_named_decimal_uint(" Delta", delta, decimals);
fail();
}
}
functionassertApproxEqAbsDecimal(int256 a, int256 b, uint256 maxDelta, uint256 decimals, stringmemory err)
internalvirtual{
uint256 delta = stdMath.delta(a, b);
if (delta > maxDelta) {
emit log_named_string("Error", err);
assertApproxEqAbsDecimal(a, b, maxDelta, decimals);
}
}
functionassertApproxEqRel(uint256 a,
uint256 b,
uint256 maxPercentDelta // An 18 decimal fixed point number, where 1e18 == 100%) internalvirtual{
if (b ==0) return assertEq(a, b); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log("Error: a ~= b not satisfied [uint]");
emit log_named_uint(" Left", a);
emit log_named_uint(" Right", b);
emit log_named_decimal_uint(" Max % Delta", maxPercentDelta *100, 18);
emit log_named_decimal_uint(" % Delta", percentDelta *100, 18);
fail();
}
}
functionassertApproxEqRel(uint256 a,
uint256 b,
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%stringmemory err
) internalvirtual{
if (b ==0) return assertEq(a, b, err); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log_named_string("Error", err);
assertApproxEqRel(a, b, maxPercentDelta);
}
}
functionassertApproxEqRelDecimal(uint256 a,
uint256 b,
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%uint256 decimals
) internalvirtual{
if (b ==0) return assertEq(a, b); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log("Error: a ~= b not satisfied [uint]");
emit log_named_decimal_uint(" Left", a, decimals);
emit log_named_decimal_uint(" Right", b, decimals);
emit log_named_decimal_uint(" Max % Delta", maxPercentDelta *100, 18);
emit log_named_decimal_uint(" % Delta", percentDelta *100, 18);
fail();
}
}
functionassertApproxEqRelDecimal(uint256 a,
uint256 b,
uint256 maxPercentDelta, // An 18 decimal fixed point number, where 1e18 == 100%uint256 decimals,
stringmemory err
) internalvirtual{
if (b ==0) return assertEq(a, b, err); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log_named_string("Error", err);
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);
}
}
functionassertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta) internalvirtual{
if (b ==0) return assertEq(a, b); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log("Error: a ~= b not satisfied [int]");
emit log_named_int(" Left", a);
emit log_named_int(" Right", b);
emit log_named_decimal_uint(" Max % Delta", maxPercentDelta *100, 18);
emit log_named_decimal_uint(" % Delta", percentDelta *100, 18);
fail();
}
}
functionassertApproxEqRel(int256 a, int256 b, uint256 maxPercentDelta, stringmemory err) internalvirtual{
if (b ==0) return assertEq(a, b, err); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log_named_string("Error", err);
assertApproxEqRel(a, b, maxPercentDelta);
}
}
functionassertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals) internalvirtual{
if (b ==0) return assertEq(a, b); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log("Error: a ~= b not satisfied [int]");
emit log_named_decimal_int(" Left", a, decimals);
emit log_named_decimal_int(" Right", b, decimals);
emit log_named_decimal_uint(" Max % Delta", maxPercentDelta *100, 18);
emit log_named_decimal_uint(" % Delta", percentDelta *100, 18);
fail();
}
}
functionassertApproxEqRelDecimal(int256 a, int256 b, uint256 maxPercentDelta, uint256 decimals, stringmemory err)
internalvirtual{
if (b ==0) return assertEq(a, b, err); // If the left is 0, right must be too.uint256 percentDelta = stdMath.percentDelta(a, b);
if (percentDelta > maxPercentDelta) {
emit log_named_string("Error", err);
assertApproxEqRelDecimal(a, b, maxPercentDelta, decimals);
}
}
functionassertEqCall(address target, bytesmemory callDataA, bytesmemory callDataB) internalvirtual{
assertEqCall(target, callDataA, target, callDataB, true);
}
functionassertEqCall(address targetA, bytesmemory callDataA, address targetB, bytesmemory callDataB)
internalvirtual{
assertEqCall(targetA, callDataA, targetB, callDataB, true);
}
functionassertEqCall(address target, bytesmemory callDataA, bytesmemory callDataB, bool strictRevertData)
internalvirtual{
assertEqCall(target, callDataA, target, callDataB, strictRevertData);
}
functionassertEqCall(address targetA,
bytesmemory callDataA,
address targetB,
bytesmemory callDataB,
bool strictRevertData
) internalvirtual{
(bool successA, bytesmemory returnDataA) =address(targetA).call(callDataA);
(bool successB, bytesmemory returnDataB) =address(targetB).call(callDataB);
if (successA && successB) {
assertEq(returnDataA, returnDataB, "Call return data does not match");
}
if (!successA &&!successB && strictRevertData) {
assertEq(returnDataA, returnDataB, "Call revert data does not match");
}
if (!successA && successB) {
emit log("Error: Calls were not equal");
emit log_named_bytes(" Left call revert data", returnDataA);
emit log_named_bytes(" Right call return data", returnDataB);
fail();
}
if (successA &&!successB) {
emit log("Error: Calls were not equal");
emit log_named_bytes(" Left call return data", returnDataA);
emit log_named_bytes(" Right call revert data", returnDataB);
fail();
}
}
}
Contract Source Code
File 30 of 48: StdChains.sol
// 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://mainnet.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl(
"goerli", ChainData("Goerli", 5, "https://goerli.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl(
"sepolia", ChainData("Sepolia", 11155111, "https://sepolia.infura.io/v3/b9794ad1ddf84dfb8c34d6bb5dca2001")
);
setChainWithDefaultRpcUrl("optimism", ChainData("Optimism", 10, "https://mainnet.optimism.io"));
setChainWithDefaultRpcUrl("optimism_goerli", ChainData("Optimism Goerli", 420, "https://goerli.optimism.io"));
setChainWithDefaultRpcUrl("arbitrum_one", ChainData("Arbitrum One", 42161, "https://arb1.arbitrum.io/rpc"));
setChainWithDefaultRpcUrl(
"arbitrum_one_goerli", ChainData("Arbitrum One Goerli", 421613, "https://goerli-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_mumbai", ChainData("Polygon Mumbai", 80001, "https://rpc-mumbai.maticvigil.com")
);
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_goerli", ChainData("Base Goerli", 84531, "https://goerli.base.org"));
setChainWithDefaultRpcUrl("base", ChainData("Base", 8453, "https://mainnet.base.org"));
}
// 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 31 of 48: 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 32 of 48: 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 36 of 48: StdStorage.sol
// SPDX-License-Identifier: MITpragmasolidity >=0.6.2 <0.9.0;import {Vm} from"./Vm.sol";
structStdStorage {
mapping(address=>mapping(bytes4=>mapping(bytes32=>uint256))) slots;
mapping(address=>mapping(bytes4=>mapping(bytes32=>bool))) finds;
bytes32[] _keys;
bytes4 _sig;
uint256 _depth;
address _target;
bytes32 _set;
}
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")))));
functionsigs(stringmemory sigStr) internalpurereturns (bytes4) {
returnbytes4(keccak256(bytes(sigStr)));
}
/// @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) internalreturns (uint256) {
address who =self._target;
bytes4 fsig =self._sig;
uint256 field_depth =self._depth;
bytes32[] memory ins =self._keys;
// calldata to test againstif (self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
returnself.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))];
}
bytesmemory cald =abi.encodePacked(fsig, flatten(ins));
vm.record();
bytes32 fdat;
{
(, bytesmemory rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32* field_depth);
}
(bytes32[] memory reads,) = vm.accesses(address(who));
if (reads.length==1) {
bytes32 curr = vm.load(who, reads[0]);
if (curr ==bytes32(0)) {
emit WARNING_UninitedSlot(who, uint256(reads[0]));
}
if (fdat != curr) {
require(
false,
"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported."
);
}
emit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[0]));
self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] =uint256(reads[0]);
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] =true;
} elseif (reads.length>1) {
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 (prev != fdat) {
continue;
}
bytes32 new_val =~prev;
// store
vm.store(who, reads[i], new_val);
bool success;
{
bytesmemory rdat;
(success, rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32* field_depth);
}
if (success && fdat == new_val) {
// we found which of the slots is the actual oneemit SlotFound(who, fsig, keccak256(abi.encodePacked(ins, field_depth)), uint256(reads[i]));
self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] =uint256(reads[i]);
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))] =true;
vm.store(who, reads[i], prev);
break;
}
vm.store(who, reads[i], prev);
}
} else {
revert("stdStorage find(StdStorage): No storage use detected for target.");
}
require(
self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))],
"stdStorage find(StdStorage): Slot(s) not found."
);
deleteself._target;
deleteself._sig;
deleteself._keys;
deleteself._depth;
returnself.slots[who][fsig][keccak256(abi.encodePacked(ins, 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_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;
}
functiondepth(StdStorage storageself, uint256 _depth) internalreturns (StdStorage storage) {
self._depth = _depth;
returnself;
}
functionread(StdStorage storageself) privatereturns (bytesmemory) {
address t =self._target;
uint256 s = find(self);
returnabi.encode(vm.load(t, bytes32(s)));
}
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) - 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) - 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;
}
}
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 stdStorageSafe.find(self);
}
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);
}
functiondepth(StdStorage storageself, uint256 _depth) internalreturns (StdStorage storage) {
return stdStorageSafe.depth(self, _depth);
}
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;
bytes32[] memory ins =self._keys;
bytesmemory cald =abi.encodePacked(fsig, flatten(ins));
if (!self.finds[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]) {
find(self);
}
bytes32 slot =bytes32(self.slots[who][fsig][keccak256(abi.encodePacked(ins, field_depth))]);
bytes32 fdat;
{
(, bytesmemory rdat) = who.staticcall(cald);
fdat = bytesToBytes32(rdat, 32* field_depth);
}
bytes32 curr = vm.load(who, slot);
if (fdat != curr) {
require(
false,
"stdStorage find(StdStorage): Packed slot. This would cause dangerous overwriting and currently isn't supported."
);
}
vm.store(who, slot, set);
deleteself._target;
deleteself._sig;
deleteself._keys;
deleteself._depth;
}
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);
}
// Private function so needs to be copied overfunctionbytesToBytes32(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;
}
// Private function so needs to be copied overfunctionflatten(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;
}
}
// 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));
}
}
Contract Source Code
File 39 of 48: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)pragmasolidity ^0.8.0;import"./math/Math.sol";
/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant _SYMBOLS ="0123456789abcdef";
uint8privateconstant _ADDRESS_LENGTH =20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = _SYMBOLS[value &0xf];
value >>=4;
}
require(value ==0, "Strings: hex length insufficient");
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.4;import"@openzeppelin/contracts/utils/Context.sol";
/**
* @title TransferValidation
* @author Limit Break, Inc.
* @notice A mix-in that can be combined with ERC-721 contracts to provide more granular hooks.
* Openzeppelin's ERC721 contract only provides hooks for before and after transfer. This allows
* developers to validate or customize transfers within the context of a mint, a burn, or a transfer.
*/abstractcontractTransferValidationisContext{
errorShouldNotMintToBurnAddress();
/// @dev Inheriting contracts should call this function in the _beforeTokenTransfer function to get more granular hooks.function_validateBeforeTransfer(addressfrom, address to, uint256 tokenId) internalvirtual{
bool fromZeroAddress =from==address(0);
bool toZeroAddress = to ==address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} elseif(fromZeroAddress) {
_preValidateMint(_msgSender(), to, tokenId, msg.value);
} elseif(toZeroAddress) {
_preValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_preValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Inheriting contracts should call this function in the _afterTokenTransfer function to get more granular hooks.function_validateAfterTransfer(addressfrom, address to, uint256 tokenId) internalvirtual{
bool fromZeroAddress =from==address(0);
bool toZeroAddress = to ==address(0);
if(fromZeroAddress && toZeroAddress) {
revert ShouldNotMintToBurnAddress();
} elseif(fromZeroAddress) {
_postValidateMint(_msgSender(), to, tokenId, msg.value);
} elseif(toZeroAddress) {
_postValidateBurn(_msgSender(), from, tokenId, msg.value);
} else {
_postValidateTransfer(_msgSender(), from, to, tokenId, msg.value);
}
}
/// @dev Optional validation hook that fires before a mintfunction_preValidateMint(address caller, address to, uint256 tokenId, uint256 value) internalvirtual{}
/// @dev Optional validation hook that fires after a mintfunction_postValidateMint(address caller, address to, uint256 tokenId, uint256 value) internalvirtual{}
/// @dev Optional validation hook that fires before a burnfunction_preValidateBurn(address caller, addressfrom, uint256 tokenId, uint256 value) internalvirtual{}
/// @dev Optional validation hook that fires after a burnfunction_postValidateBurn(address caller, addressfrom, uint256 tokenId, uint256 value) internalvirtual{}
/// @dev Optional validation hook that fires before a transferfunction_preValidateTransfer(address caller, addressfrom, address to, uint256 tokenId, uint256 value) internalvirtual{}
/// @dev Optional validation hook that fires after a transferfunction_postValidateTransfer(address caller, addressfrom, address to, uint256 tokenId, uint256 value) internalvirtual{}
}
Contract Source Code
File 43 of 48: Uncanny.sol
// SPDX-License-Identifier: MITpragmasolidity 0.8.20;/*
!!!!!!!!!!!!!!!!~!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!!!!7!!!!!!!!!!!!!!!!!!!!~~!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!~!!!!~~!!!!!!!!!!!!!!!!!!!~G?~!!!!!!~!!!!!!!!!~~?7~!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~?J~~!!!!!!!!!~~!!!!!~!BY~!!!!!~!!!!!!!!!~!5G!~!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~7GG7~~!!!!!!~JJ~!!!!~!#G~!!!!~7B7~!!!!!~7GB!~!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~!5#Y!~!!!!!~?&J~!!!~!G5~!!!!~YP!~!!!!~?BB!~!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~~J#B?~!!!!!~YY~~~~~~~~~~~~~~!!~~~~!~?#B7~!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!~~!!!!~~7GB7~!!!~~~~!777??????777!!!777!!~?Y!~!!!~~~!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!~77!~~!!!~~!!!~~!7?JJ?77!~~~~~~~!77?J?!7?J?!~~!!!~!YJ~!!!!!!!!~~~!!!!!!!!!!!
!!!!!!!!!!!!!!!~~~!!!!!!~75PY!~!!~~~~!7JJ7~:................::::~^~J7~!!!~55!~!!!!!~~~7J5J!!!!!!!!!!
!!!!!!!!!!!!!~!J?7!~~~~!!~~7Y?~!!!~~7J7^........................7^^?J!~~!!!~~!!!~~~7JPPY7~!!!!!!!!!!
!!!!!!!!~~!!!!!7J5P5Y?!~~~~~~~~~~~~J?:..........................~^..~??!~!!!!!~~!JPB5?!~~!!!!!!!!!!!
!!!!!!~!!!!!!!!~~~!?5GBGY?????????JJ:...........................~^....~J?~~!!~?PBGJ!~~!!!!!!!!!~!!!!
!!!!!!!!!!!!!!!!~!7?JJJJ?777!!!!777!!!!!!~~^^:..................~:.....:?J~!!~Y57~~~!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!~7Y7~^:...............:::^^~!!!!!~^::...........:~........?J~!!~~~~~~~~!!!!!!!!!!!!!!
!!!!!!!!!!!!~!!!Y:............................:^~!!!!~^:.......~..........J7~!!~~!7?Y?!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!J.................^~7?JYYYYJJ?7!^^^^~~!!~^:...^:..........^Y~!~7PGPY?!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!~7?:............:?PB#&&&&&&&&&&&##BG5Y?7!~~~~^:.............J7~~!?7~~~!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!~7?!:.........^B&&###############&&&&&#BPY?!~~:............77~!~~~!!!!!!!!!!!!!!!!!!
~!!!!!!!!!!!!!!!!~~7?7~:......?&#######################&&&##P?7~...........77~!!!!!!!!!!!!!!!!!!!!!!
~!!!!!!!!!!!!!!!!!!~~!7?7!^:. J&############################&&#GY^.........?!~!!!~!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!~!!!!!!~~~!77?7!5&###############################&&BY^......:J~!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!~~~~!!P&#################################&&#GG5?^.?7~!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~~G&####################################&&&&BY?~!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~!B&########################################~!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~7##########################################&B!~!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~?########################################&&G7~!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!~!!!!!!!~?###################################&&&##GJ!~!!!!!!!!!!!!!!!!!!~!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!~7###&#############################??7!~~~!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!~Y&###&&&&&&&&&&#################&B?~~~~~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!~!!!!!!!!!!!!~~Y#&############################B7~~~!!!!!!!!!!!!!!!!!!!!!!~!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!~~~~~~!!~~75B&&&#######################&?~!77!~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!~!7JJ7!~!!!~~!JPB#&&&&&&&#############&&#^..:~?!~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!~~~~~~!~?G#&&#B?~!!!!~~~!7?Y5GGPPB########&&&#B5?:....~J!~!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!~!?YJ?!~7#&####&B!~~~~~~~!!7?!^. ~B&###&&&#GY7~:.......~???~~!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!~~~?B&&&#BYJ&#####&BJJ7!77??JJ~:..^!GBB#&&BY7^...........~?7!?J!~~~!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!~~!77G&####&&###B###G55PPJY5Y??:...~J?777JB7:............^7?777!?J7!!~~~!!!!!!!!!!!!!!!!!!!!!
!!!!!!~!5B#####&&#BPY7^:^^!PGB###&&#B?...:?7?7!7!?~..........:~7?7!7777!Y?????!!~!~!!!!!!!!!!!~!!!!!
!!!!!!~P&#####BP?~:.... .^?#&#######&B:..^?!J?77!J!.......^!7??777777!!?Y7!777?J7~~!!!!!!!!!!!!!~!!!
!!!!!!~P&#####BGP?....^7P#&######&&#G5!...77YY!77!.....^!??777!!!!777?JJ777777!7?J!~!!!!!!!!!!!!!!!!
!!!!!!~!YB####B55#J:75#&&######&#PY?77!~~~?7777~~:...^7?7777777????J??7!77777777!?J~!!!!!!!!!!!!!!!!
!!!!!!!~~5&#######BB&&#########57!!!77...!?77!?~.~^^7?7!77777!YY7777!777777777777!J7~!!!!!!!!~!!!!!!
!!!!!!!!~5&########&#########&G!!77777..!?!?7777..!J7!7777777!?J!7777777777777777!J?~!!~!!!!!!!!!!!!
!!!!!!!!~Y&##################&P77777?!.7?!?7777J.!?!77777777!7JJ!77777777777777777J?~!!!!!!!!!!!!!!!
!!!!!!!!~!B&################&BYJ!7777???!7?777!JJ?!7777777!7JJ?!77777777777777777!J7~!!!!!!!!!!!!!!!
!!!!!!!!!~7G&###############BJJY?!77757!77?7777J?!77777!77JJ7!7J7777777777777777777J~!!!!!!!!!!!!!!!
!!!!!!!!!!~!Y##############B7?J7Y?!7!J?!777777??!7777!7?J?7!77!JJ!7777777777777777!Y7~!!!!!!!!!!!!!!
!!!!!!!!!!!~~P&###########&P!J?!7Y?77?Y!777777?!77777JJ?7!7777!?Y!7777777777777777!J?~!!!!!!!!!!!!!!
Contract by @backseats_eth
*/import"@limitbreak/creator-token-contracts/contracts/examples/erc721c/ERC721CWithBasicRoyalties.sol";
import { console2 } from"forge-std/Test.sol"; // DEPLOYinterfaceIUncanny{
functionmint(address _to) external;
functionpaidMint(address _to, uint _amount) external;
}
// ERC721CWithBasicRoyalties contains OwnableBasiccontractUncannyV2isIUncanny, ERC721CWithBasicRoyalties{
// The address of the minting contractaddresspublic uncannyMinter;
addresspublic teamWallet =0x7AA0F5c54c1c52745E1ddc34DB82ee7FA816B6C3;
// The base URI for the tokenstringpublic baseTokenURI;
// The total supply of the collectionuintpublic totalSupply;
// The next token id to mintuintpublic nextTokenId;
// The max supply of the collectionuintpublicconstant MAX_SUPPLY =2_462;
/// ErrorserrorArrayEmpty();
errorCantMintThatMany();
errorLengthsDontMatch();
errorOnlyMinter();
/// Modifier// Only the minter contract can mintmodifieronlyMinter() {
if (msg.sender!= uncannyMinter) revert OnlyMinter();
_;
}
/// Constructorconstructor(address _royaltyReceiver, uint96 _royaltyFeeNumerator)
ERC721CWithBasicRoyalties(_royaltyReceiver, _royaltyFeeNumerator, "Uncanny", "UCC") {
// V1 had a bug with the counter, 616 have been minted to date. First one minted here will be 617.// https://www.contractreader.io/contract/mainnet/0x3eab42f5bf2f775e00b535ceab6555eb8a20a837// Mint missing commons between 1 and 616
_mint(teamWallet, 1);
_mint(teamWallet, 43);
_mint(teamWallet, 150);
_mint(teamWallet, 262);
_mint(teamWallet, 513);
_mint(teamWallet, 606);
_mint(teamWallet, 609);
// Mint all the 1/1s to the team walletfor(uint i =2383; i <=2462;) {
_mint(teamWallet, i);
unchecked { ++i; }
}
totalSupply =87;
nextTokenId =618;
}
/// Mintingfunctionmint(address _to) publiconlyMinter() {
if (totalSupply +1> MAX_SUPPLY) revert CantMintThatMany();
_regularMint(_to);
}
functionpaidMint(address _to, uint _amount) publiconlyMinter() {
if (totalSupply + _amount > MAX_SUPPLY) revert CantMintThatMany();
for (uint i; i < _amount;) {
_regularMint(_to);
unchecked { ++i; }
}
}
function_regularMint(address _to) internal{
uint nextIndex = nextTokenId;
_mint(_to, nextIndex);
unchecked {
++totalSupply;
nextTokenId = nextIndex +1;
}
}
// Airdrop/// @dev Example input data: [0xabc123, 0xdef456, 0xghi789], [[1,2,3], [4,5], [9]]functionairdrop(address[] calldata _addresses, uint[][] calldata _tokenIds) externalonlyOwner{
if (_addresses.length!= _tokenIds.length) revert LengthsDontMatch();
uint length = _addresses.length;
for (uint i; i < length;) {
for (uint n; n < _tokenIds[i].length;) {
_mint(_addresses[i], _tokenIds[i][n]);
unchecked { ++n; }
}
unchecked {
totalSupply += _tokenIds[i].length;
++i;
}
}
}
/// Virtualfunction_baseURI() internalviewvirtualoverridereturns (stringmemory) {
return baseTokenURI;
}
/// SettersfunctionsetMinterAddress(address _newMinter) externalonlyOwner{
uncannyMinter = _newMinter;
}
// Sets the location of the metadatafunctionsetBaseURI(stringcalldata _uri) externalonlyOwner{
baseTokenURI = _uri;
}
// Changes the mint address that can call this contractfunctionchangeMinterAddress(address _newMinter) externalonlyOwner{
uncannyMinter = _newMinter;
}
}
Contract Source Code
File 44 of 48: Vm.sol
// 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
}
/// 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;
}
/// 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;
}
// ======== 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 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);
/// 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.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);
/// 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);
/// 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.functiongetCode(stringcalldata artifactPath) externalviewreturns (bytesmemory creationBytecode);
/// Gets the deployed bytecode from an artifact file. Takes in the relative path to the json file.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);
/// 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.functionkeyExists(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`.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 ========/// Using the address that calls the test contract, has the next call (at this call depth only)/// create a transaction that can later be signed and sent onchain.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;
/// Using the address that calls the test contract, has all subsequent calls/// (at this call depth only) create transactions that can later be signed and sent onchain.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 ========/// 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);
/// 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);
// ======== Testing ========/// 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;
// ======== 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);
/// 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.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;
/// 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;
/// 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;
}
// SPDX-License-Identifier: GPL-3.0-or-later// This program is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.// You should have received a copy of the GNU General Public License// along with this program. If not, see <http://www.gnu.org/licenses/>.pragmasolidity >=0.5.0;contractDSTest{
eventlog (string);
eventlogs (bytes);
eventlog_address (address);
eventlog_bytes32 (bytes32);
eventlog_int (int);
eventlog_uint (uint);
eventlog_bytes (bytes);
eventlog_string (string);
eventlog_named_address (string key, address val);
eventlog_named_bytes32 (string key, bytes32 val);
eventlog_named_decimal_int (string key, int val, uint decimals);
eventlog_named_decimal_uint (string key, uint val, uint decimals);
eventlog_named_int (string key, int val);
eventlog_named_uint (string key, uint val);
eventlog_named_bytes (string key, bytes val);
eventlog_named_string (string key, string val);
boolpublic IS_TEST =true;
boolprivate _failed;
addressconstant HEVM_ADDRESS =address(bytes20(uint160(uint256(keccak256('hevm cheat code')))));
modifiermayRevert() { _; }
modifiertestopts(stringmemory) { _; }
functionfailed() publicreturns (bool) {
if (_failed) {
return _failed;
} else {
bool globalFailed =false;
if (hasHEVMContext()) {
(, bytesmemory retdata) = HEVM_ADDRESS.call(
abi.encodePacked(
bytes4(keccak256("load(address,bytes32)")),
abi.encode(HEVM_ADDRESS, bytes32("failed"))
)
);
globalFailed =abi.decode(retdata, (bool));
}
return globalFailed;
}
}
functionfail() internalvirtual{
if (hasHEVMContext()) {
(bool status, ) = HEVM_ADDRESS.call(
abi.encodePacked(
bytes4(keccak256("store(address,bytes32,bytes32)")),
abi.encode(HEVM_ADDRESS, bytes32("failed"), bytes32(uint256(0x01)))
)
);
status; // Silence compiler warnings
}
_failed =true;
}
functionhasHEVMContext() internalviewreturns (bool) {
uint256 hevmCodeSize =0;
assembly {
hevmCodeSize :=extcodesize(0x7109709ECfa91a80626fF3989D68f67F5b1DD12D)
}
return hevmCodeSize >0;
}
modifierlogs_gas() {
uint startGas =gasleft();
_;
uint endGas =gasleft();
emit log_named_uint("gas", startGas - endGas);
}
functionassertTrue(bool condition) internal{
if (!condition) {
emit log("Error: Assertion Failed");
fail();
}
}
functionassertTrue(bool condition, stringmemory err) internal{
if (!condition) {
emit log_named_string("Error", err);
assertTrue(condition);
}
}
functionassertEq(address a, address b) internal{
if (a != b) {
emit log("Error: a == b not satisfied [address]");
emit log_named_address(" Left", a);
emit log_named_address(" Right", b);
fail();
}
}
functionassertEq(address a, address b, stringmemory err) internal{
if (a != b) {
emit log_named_string ("Error", err);
assertEq(a, b);
}
}
functionassertEq(bytes32 a, bytes32 b) internal{
if (a != b) {
emit log("Error: a == b not satisfied [bytes32]");
emit log_named_bytes32(" Left", a);
emit log_named_bytes32(" Right", b);
fail();
}
}
functionassertEq(bytes32 a, bytes32 b, stringmemory err) internal{
if (a != b) {
emit log_named_string ("Error", err);
assertEq(a, b);
}
}
functionassertEq32(bytes32 a, bytes32 b) internal{
assertEq(a, b);
}
functionassertEq32(bytes32 a, bytes32 b, stringmemory err) internal{
assertEq(a, b, err);
}
functionassertEq(int a, int b) internal{
if (a != b) {
emit log("Error: a == b not satisfied [int]");
emit log_named_int(" Left", a);
emit log_named_int(" Right", b);
fail();
}
}
functionassertEq(int a, int b, stringmemory err) internal{
if (a != b) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertEq(uint a, uint b) internal{
if (a != b) {
emit log("Error: a == b not satisfied [uint]");
emit log_named_uint(" Left", a);
emit log_named_uint(" Right", b);
fail();
}
}
functionassertEq(uint a, uint b, stringmemory err) internal{
if (a != b) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertEqDecimal(int a, int b, uint decimals) internal{
if (a != b) {
emit log("Error: a == b not satisfied [decimal int]");
emit log_named_decimal_int(" Left", a, decimals);
emit log_named_decimal_int(" Right", b, decimals);
fail();
}
}
functionassertEqDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a != b) {
emit log_named_string("Error", err);
assertEqDecimal(a, b, decimals);
}
}
functionassertEqDecimal(uint a, uint b, uint decimals) internal{
if (a != b) {
emit log("Error: a == b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Left", a, decimals);
emit log_named_decimal_uint(" Right", b, decimals);
fail();
}
}
functionassertEqDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a != b) {
emit log_named_string("Error", err);
assertEqDecimal(a, b, decimals);
}
}
functionassertNotEq(address a, address b) internal{
if (a == b) {
emit log("Error: a != b not satisfied [address]");
emit log_named_address(" Left", a);
emit log_named_address(" Right", b);
fail();
}
}
functionassertNotEq(address a, address b, stringmemory err) internal{
if (a == b) {
emit log_named_string ("Error", err);
assertNotEq(a, b);
}
}
functionassertNotEq(bytes32 a, bytes32 b) internal{
if (a == b) {
emit log("Error: a != b not satisfied [bytes32]");
emit log_named_bytes32(" Left", a);
emit log_named_bytes32(" Right", b);
fail();
}
}
functionassertNotEq(bytes32 a, bytes32 b, stringmemory err) internal{
if (a == b) {
emit log_named_string ("Error", err);
assertNotEq(a, b);
}
}
functionassertNotEq32(bytes32 a, bytes32 b) internal{
assertNotEq(a, b);
}
functionassertNotEq32(bytes32 a, bytes32 b, stringmemory err) internal{
assertNotEq(a, b, err);
}
functionassertNotEq(int a, int b) internal{
if (a == b) {
emit log("Error: a != b not satisfied [int]");
emit log_named_int(" Left", a);
emit log_named_int(" Right", b);
fail();
}
}
functionassertNotEq(int a, int b, stringmemory err) internal{
if (a == b) {
emit log_named_string("Error", err);
assertNotEq(a, b);
}
}
functionassertNotEq(uint a, uint b) internal{
if (a == b) {
emit log("Error: a != b not satisfied [uint]");
emit log_named_uint(" Left", a);
emit log_named_uint(" Right", b);
fail();
}
}
functionassertNotEq(uint a, uint b, stringmemory err) internal{
if (a == b) {
emit log_named_string("Error", err);
assertNotEq(a, b);
}
}
functionassertNotEqDecimal(int a, int b, uint decimals) internal{
if (a == b) {
emit log("Error: a != b not satisfied [decimal int]");
emit log_named_decimal_int(" Left", a, decimals);
emit log_named_decimal_int(" Right", b, decimals);
fail();
}
}
functionassertNotEqDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a == b) {
emit log_named_string("Error", err);
assertNotEqDecimal(a, b, decimals);
}
}
functionassertNotEqDecimal(uint a, uint b, uint decimals) internal{
if (a == b) {
emit log("Error: a != b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Left", a, decimals);
emit log_named_decimal_uint(" Right", b, decimals);
fail();
}
}
functionassertNotEqDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a == b) {
emit log_named_string("Error", err);
assertNotEqDecimal(a, b, decimals);
}
}
functionassertGt(uint a, uint b) internal{
if (a <= b) {
emit log("Error: a > b not satisfied [uint]");
emit log_named_uint(" Value a", a);
emit log_named_uint(" Value b", b);
fail();
}
}
functionassertGt(uint a, uint b, stringmemory err) internal{
if (a <= b) {
emit log_named_string("Error", err);
assertGt(a, b);
}
}
functionassertGt(int a, int b) internal{
if (a <= b) {
emit log("Error: a > b not satisfied [int]");
emit log_named_int(" Value a", a);
emit log_named_int(" Value b", b);
fail();
}
}
functionassertGt(int a, int b, stringmemory err) internal{
if (a <= b) {
emit log_named_string("Error", err);
assertGt(a, b);
}
}
functionassertGtDecimal(int a, int b, uint decimals) internal{
if (a <= b) {
emit log("Error: a > b not satisfied [decimal int]");
emit log_named_decimal_int(" Value a", a, decimals);
emit log_named_decimal_int(" Value b", b, decimals);
fail();
}
}
functionassertGtDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a <= b) {
emit log_named_string("Error", err);
assertGtDecimal(a, b, decimals);
}
}
functionassertGtDecimal(uint a, uint b, uint decimals) internal{
if (a <= b) {
emit log("Error: a > b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Value a", a, decimals);
emit log_named_decimal_uint(" Value b", b, decimals);
fail();
}
}
functionassertGtDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a <= b) {
emit log_named_string("Error", err);
assertGtDecimal(a, b, decimals);
}
}
functionassertGe(uint a, uint b) internal{
if (a < b) {
emit log("Error: a >= b not satisfied [uint]");
emit log_named_uint(" Value a", a);
emit log_named_uint(" Value b", b);
fail();
}
}
functionassertGe(uint a, uint b, stringmemory err) internal{
if (a < b) {
emit log_named_string("Error", err);
assertGe(a, b);
}
}
functionassertGe(int a, int b) internal{
if (a < b) {
emit log("Error: a >= b not satisfied [int]");
emit log_named_int(" Value a", a);
emit log_named_int(" Value b", b);
fail();
}
}
functionassertGe(int a, int b, stringmemory err) internal{
if (a < b) {
emit log_named_string("Error", err);
assertGe(a, b);
}
}
functionassertGeDecimal(int a, int b, uint decimals) internal{
if (a < b) {
emit log("Error: a >= b not satisfied [decimal int]");
emit log_named_decimal_int(" Value a", a, decimals);
emit log_named_decimal_int(" Value b", b, decimals);
fail();
}
}
functionassertGeDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a < b) {
emit log_named_string("Error", err);
assertGeDecimal(a, b, decimals);
}
}
functionassertGeDecimal(uint a, uint b, uint decimals) internal{
if (a < b) {
emit log("Error: a >= b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Value a", a, decimals);
emit log_named_decimal_uint(" Value b", b, decimals);
fail();
}
}
functionassertGeDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a < b) {
emit log_named_string("Error", err);
assertGeDecimal(a, b, decimals);
}
}
functionassertLt(uint a, uint b) internal{
if (a >= b) {
emit log("Error: a < b not satisfied [uint]");
emit log_named_uint(" Value a", a);
emit log_named_uint(" Value b", b);
fail();
}
}
functionassertLt(uint a, uint b, stringmemory err) internal{
if (a >= b) {
emit log_named_string("Error", err);
assertLt(a, b);
}
}
functionassertLt(int a, int b) internal{
if (a >= b) {
emit log("Error: a < b not satisfied [int]");
emit log_named_int(" Value a", a);
emit log_named_int(" Value b", b);
fail();
}
}
functionassertLt(int a, int b, stringmemory err) internal{
if (a >= b) {
emit log_named_string("Error", err);
assertLt(a, b);
}
}
functionassertLtDecimal(int a, int b, uint decimals) internal{
if (a >= b) {
emit log("Error: a < b not satisfied [decimal int]");
emit log_named_decimal_int(" Value a", a, decimals);
emit log_named_decimal_int(" Value b", b, decimals);
fail();
}
}
functionassertLtDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a >= b) {
emit log_named_string("Error", err);
assertLtDecimal(a, b, decimals);
}
}
functionassertLtDecimal(uint a, uint b, uint decimals) internal{
if (a >= b) {
emit log("Error: a < b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Value a", a, decimals);
emit log_named_decimal_uint(" Value b", b, decimals);
fail();
}
}
functionassertLtDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a >= b) {
emit log_named_string("Error", err);
assertLtDecimal(a, b, decimals);
}
}
functionassertLe(uint a, uint b) internal{
if (a > b) {
emit log("Error: a <= b not satisfied [uint]");
emit log_named_uint(" Value a", a);
emit log_named_uint(" Value b", b);
fail();
}
}
functionassertLe(uint a, uint b, stringmemory err) internal{
if (a > b) {
emit log_named_string("Error", err);
assertLe(a, b);
}
}
functionassertLe(int a, int b) internal{
if (a > b) {
emit log("Error: a <= b not satisfied [int]");
emit log_named_int(" Value a", a);
emit log_named_int(" Value b", b);
fail();
}
}
functionassertLe(int a, int b, stringmemory err) internal{
if (a > b) {
emit log_named_string("Error", err);
assertLe(a, b);
}
}
functionassertLeDecimal(int a, int b, uint decimals) internal{
if (a > b) {
emit log("Error: a <= b not satisfied [decimal int]");
emit log_named_decimal_int(" Value a", a, decimals);
emit log_named_decimal_int(" Value b", b, decimals);
fail();
}
}
functionassertLeDecimal(int a, int b, uint decimals, stringmemory err) internal{
if (a > b) {
emit log_named_string("Error", err);
assertLeDecimal(a, b, decimals);
}
}
functionassertLeDecimal(uint a, uint b, uint decimals) internal{
if (a > b) {
emit log("Error: a <= b not satisfied [decimal uint]");
emit log_named_decimal_uint(" Value a", a, decimals);
emit log_named_decimal_uint(" Value b", b, decimals);
fail();
}
}
functionassertLeDecimal(uint a, uint b, uint decimals, stringmemory err) internal{
if (a > b) {
emit log_named_string("Error", err);
assertLeDecimal(a, b, decimals);
}
}
functionassertEq(stringmemory a, stringmemory b) internal{
if (keccak256(abi.encodePacked(a)) !=keccak256(abi.encodePacked(b))) {
emit log("Error: a == b not satisfied [string]");
emit log_named_string(" Left", a);
emit log_named_string(" Right", b);
fail();
}
}
functionassertEq(stringmemory a, stringmemory b, stringmemory err) internal{
if (keccak256(abi.encodePacked(a)) !=keccak256(abi.encodePacked(b))) {
emit log_named_string("Error", err);
assertEq(a, b);
}
}
functionassertNotEq(stringmemory a, stringmemory b) internal{
if (keccak256(abi.encodePacked(a)) ==keccak256(abi.encodePacked(b))) {
emit log("Error: a != b not satisfied [string]");
emit log_named_string(" Left", a);
emit log_named_string(" Right", b);
fail();
}
}
functionassertNotEq(stringmemory a, stringmemory b, stringmemory err) internal{
if (keccak256(abi.encodePacked(a)) ==keccak256(abi.encodePacked(b))) {
emit log_named_string("Error", err);
assertNotEq(a, b);
}
}
functioncheckEq0(bytesmemory a, bytesmemory b) internalpurereturns (bool ok) {
ok =true;
if (a.length== b.length) {
for (uint i =0; i < a.length; i++) {
if (a[i] != b[i]) {
ok =false;
}
}
} else {
ok =false;
}
}
functionassertEq0(bytesmemory a, bytesmemory b) internal{
if (!checkEq0(a, b)) {
emit log("Error: a == b not satisfied [bytes]");
emit log_named_bytes(" Left", a);
emit log_named_bytes(" Right", b);
fail();
}
}
functionassertEq0(bytesmemory a, bytesmemory b, stringmemory err) internal{
if (!checkEq0(a, b)) {
emit log_named_string("Error", err);
assertEq0(a, b);
}
}
functionassertNotEq0(bytesmemory a, bytesmemory b) internal{
if (checkEq0(a, b)) {
emit log("Error: a != b not satisfied [bytes]");
emit log_named_bytes(" Left", a);
emit log_named_bytes(" Right", b);
fail();
}
}
functionassertNotEq0(bytesmemory a, bytesmemory b, stringmemory err) internal{
if (checkEq0(a, b)) {
emit log_named_string("Error", err);
assertNotEq0(a, b);
}
}
}