diff --git a/.gas-snapshot b/.gas-snapshot index 59fb47f8b..faf694686 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,61 +1,3 @@ -AABenchmarkPrepare:test_prepareBenchmarkFile() (gas: 2926370) -AccountBenchmarkTest:test_state_accountReceivesNativeTokens() (gas: 11037) -AccountBenchmarkTest:test_state_addAndWithdrawDeposit() (gas: 83332) -AccountBenchmarkTest:test_state_contractMetadata() (gas: 56507) -AccountBenchmarkTest:test_state_createAccount_viaEntrypoint() (gas: 432040) -AccountBenchmarkTest:test_state_createAccount_viaFactory() (gas: 334122) -AccountBenchmarkTest:test_state_executeBatchTransaction() (gas: 39874) -AccountBenchmarkTest:test_state_executeBatchTransaction_viaAccountSigner() (gas: 392782) -AccountBenchmarkTest:test_state_executeBatchTransaction_viaEntrypoint() (gas: 82915) -AccountBenchmarkTest:test_state_executeTransaction() (gas: 35735) -AccountBenchmarkTest:test_state_executeTransaction_viaAccountSigner() (gas: 378632) -AccountBenchmarkTest:test_state_executeTransaction_viaEntrypoint() (gas: 75593) -AccountBenchmarkTest:test_state_receiveERC1155NFT() (gas: 39343) -AccountBenchmarkTest:test_state_receiveERC721NFT() (gas: 78624) -AccountBenchmarkTest:test_state_transferOutsNativeTokens() (gas: 81713) -AirdropERC1155BenchmarkTest:test_benchmark_airdropERC1155_airdrop() (gas: 38083572) -AirdropERC20BenchmarkTest:test_benchmark_airdropERC20_airdrop() (gas: 32068413) -AirdropERC721BenchmarkTest:test_benchmark_airdropERC721_airdrop() (gas: 41912536) -DropERC1155BenchmarkTest:test_benchmark_dropERC1155_claim() (gas: 185032) -DropERC1155BenchmarkTest:test_benchmark_dropERC1155_lazyMint() (gas: 123913) -DropERC1155BenchmarkTest:test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 492121) -DropERC20BenchmarkTest:test_benchmark_dropERC20_claim() (gas: 230505) -DropERC20BenchmarkTest:test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 500858) -DropERC721BenchmarkTest:test_benchmark_dropERC721_claim_five_tokens() (gas: 210967) -DropERC721BenchmarkTest:test_benchmark_dropERC721_lazyMint() (gas: 124540) -DropERC721BenchmarkTest:test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 226149) -DropERC721BenchmarkTest:test_benchmark_dropERC721_reveal() (gas: 13732) -DropERC721BenchmarkTest:test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 500494) -EditionStakeBenchmarkTest:test_benchmark_editionStake_claimRewards() (gas: 65081) -EditionStakeBenchmarkTest:test_benchmark_editionStake_stake() (gas: 185144) -EditionStakeBenchmarkTest:test_benchmark_editionStake_withdraw() (gas: 46364) -MultiwrapBenchmarkTest:test_benchmark_multiwrap_unwrap() (gas: 88950) -MultiwrapBenchmarkTest:test_benchmark_multiwrap_wrap() (gas: 473462) -NFTStakeBenchmarkTest:test_benchmark_nftStake_claimRewards() (gas: 68287) -NFTStakeBenchmarkTest:test_benchmark_nftStake_stake_five_tokens() (gas: 539145) -NFTStakeBenchmarkTest:test_benchmark_nftStake_withdraw() (gas: 38076) -PackBenchmarkTest:test_benchmark_pack_addPackContents() (gas: 219188) -PackBenchmarkTest:test_benchmark_pack_createPack() (gas: 1412868) -PackBenchmarkTest:test_benchmark_pack_openPack() (gas: 141860) -PackVRFDirectBenchmarkTest:test_benchmark_packvrf_createPack() (gas: 1379604) -PackVRFDirectBenchmarkTest:test_benchmark_packvrf_openPack() (gas: 119953) -PackVRFDirectBenchmarkTest:test_benchmark_packvrf_openPackAndClaimRewards() (gas: 3621) -SignatureDropBenchmarkTest:test_benchmark_signatureDrop_claim_five_tokens() (gas: 140517) -SignatureDropBenchmarkTest:test_benchmark_signatureDrop_lazyMint() (gas: 124311) -SignatureDropBenchmarkTest:test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 225891) -SignatureDropBenchmarkTest:test_benchmark_signatureDrop_reveal() (gas: 10647) -SignatureDropBenchmarkTest:test_benchmark_signatureDrop_setClaimConditions() (gas: 73699) -TokenERC1155BenchmarkTest:test_benchmark_tokenERC1155_burn() (gas: 5728) -TokenERC1155BenchmarkTest:test_benchmark_tokenERC1155_mintTo() (gas: 122286) -TokenERC1155BenchmarkTest:test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 267175) -TokenERC1155BenchmarkTest:test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 296172) -TokenERC20BenchmarkTest:test_benchmark_tokenERC20_mintTo() (gas: 118586) -TokenERC20BenchmarkTest:test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 183032) -TokenERC20BenchmarkTest:test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 207694) -TokenERC721BenchmarkTest:test_benchmark_tokenERC721_burn() (gas: 8954) -TokenERC721BenchmarkTest:test_benchmark_tokenERC721_mintTo() (gas: 151552) -TokenERC721BenchmarkTest:test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 262344) -TokenERC721BenchmarkTest:test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 286914) -TokenStakeBenchmarkTest:test_benchmark_tokenStake_claimRewards() (gas: 67554) -TokenStakeBenchmarkTest:test_benchmark_tokenStake_stake() (gas: 177180) -TokenStakeBenchmarkTest:test_benchmark_tokenStake_withdraw() (gas: 47396) \ No newline at end of file +TokenERC721AltBenchmarkTest:test_benchmark_tokenERC721Alt_mintWithSignature_fiveTokensMulticall() (gas: 821248) +TokenERC721AltBenchmarkTest:test_benchmark_tokenERC721Alt_mintWithSignature_oneToken() (gas: 184372) +TokenERC721AltBenchmarkTest:test_benchmark_tokenERC721Alt_mintWithSignature_tenTokensMulticall() (gas: 1607588) \ No newline at end of file diff --git a/contracts/prebuilts/interface/token/ITokenERC721Alt.sol b/contracts/prebuilts/interface/token/ITokenERC721Alt.sol new file mode 100644 index 000000000..a02c96aa9 --- /dev/null +++ b/contracts/prebuilts/interface/token/ITokenERC721Alt.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.11; + +import "@openzeppelin/contracts-upgradeable/token/ERC721/IERC721Upgradeable.sol"; + +/** + * `SignatureMint` is an ERC 721 contract. It lets anyone mint NFTs by producing a mint request + * and a signature (produced by an account with MINTER_ROLE, signing the mint request). + */ +interface ITokenERC721Alt is IERC721Upgradeable { + /** + * @notice The body of a request to mint NFTs. + * + * @param to The receiver of the NFTs to mint. + * @param uri The URI of the NFT to mint. + * @param price Price to pay for minting with the signature. + * @param currency The currency in which the price per token must be paid. + * @param validityStartTimestamp The unix timestamp after which the request is valid. + * @param validityEndTimestamp The unix timestamp after which the request expires. + * @param uid A unique identifier for the request. + */ + struct MintRequest { + address to; + uint128 validityStartTimestamp; + uint128 validityEndTimestamp; + bytes32 uid; + } + + /// @dev Emitted when an account with MINTER_ROLE mints an NFT. + event TokensMinted(address indexed mintedTo, uint256 indexed tokenIdMinted, string uri); + + /// @dev Emitted when tokens are minted. + event TokensMintedWithSignature( + address indexed signer, + address indexed mintedTo, + uint256 indexed tokenIdMinted, + MintRequest mintRequest + ); + + /** + * @notice Verifies that a mint request is signed by an account holding + * MINTER_ROLE (at the time of the function call). + * + * @param req The mint request. + * @param signature The signature produced by an account signing the mint request. + * + * returns (success, signer) Result of verification and the recovered address. + */ + function verify( + MintRequest calldata req, + bytes calldata signature + ) external view returns (bool success, address signer); + + /** + * @notice Lets an account with MINTER_ROLE mint an NFT. + * + * @param to The address to mint the NFT to. + * @param uri The URI to assign to the NFT. + * + * @return tokenId of the NFT minted. + */ + function mintTo(address to, string calldata uri) external returns (uint256); + + /** + * @notice Mints an NFT according to the provided mint request. + * + * @param req The mint request. + * @param signature he signature produced by an account signing the mint request. + */ + function mintWithSignature(MintRequest calldata req, bytes calldata signature) external payable returns (uint256); +} diff --git a/contracts/prebuilts/token/TokenERC721Alt.sol b/contracts/prebuilts/token/TokenERC721Alt.sol new file mode 100644 index 000000000..9a6b6ebe4 --- /dev/null +++ b/contracts/prebuilts/token/TokenERC721Alt.sol @@ -0,0 +1,375 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.11; + +/// @author thirdweb + +// $$\ $$\ $$\ $$\ $$\ +// $$ | $$ | \__| $$ | $$ | +// $$$$$$\ $$$$$$$\ $$\ $$$$$$\ $$$$$$$ |$$\ $$\ $$\ $$$$$$\ $$$$$$$\ +// \_$$ _| $$ __$$\ $$ |$$ __$$\ $$ __$$ |$$ | $$ | $$ |$$ __$$\ $$ __$$\ +// $$ | $$ | $$ |$$ |$$ | \__|$$ / $$ |$$ | $$ | $$ |$$$$$$$$ |$$ | $$ | +// $$ |$$\ $$ | $$ |$$ |$$ | $$ | $$ |$$ | $$ | $$ |$$ ____|$$ | $$ | +// \$$$$ |$$ | $$ |$$ |$$ | \$$$$$$$ |\$$$$$\$$$$ |\$$$$$$$\ $$$$$$$ | +// \____/ \__| \__|\__|\__| \_______| \_____\____/ \_______|\_______/ + +// Interface +import { ITokenERC721Alt } from "../interface/token/ITokenERC721Alt.sol"; + +import "../../infra/interface/IThirdwebContract.sol"; +import "../../extension/interface/IRoyalty.sol"; +import "../../extension/interface/IOwnable.sol"; + +//Extensions +import "../../extension/NFTMetadata.sol"; + +// Token +import "@openzeppelin/contracts-upgradeable/token/ERC721/extensions/ERC721EnumerableUpgradeable.sol"; + +// Signature utils +import "@openzeppelin/contracts-upgradeable/utils/cryptography/ECDSAUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/utils/cryptography/draft-EIP712Upgradeable.sol"; + +// Access Control + security +import "@openzeppelin/contracts-upgradeable/access/AccessControlEnumerableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; + +// Meta transactions +import "../../external-deps/openzeppelin/metatx/ERC2771ContextUpgradeable.sol"; + +// Utils +import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; +import "../../extension/Multicall.sol"; +import "../../lib/CurrencyTransferLib.sol"; +import "../../lib/FeeType.sol"; + +// Helper interfaces +import "@openzeppelin/contracts-upgradeable/interfaces/IERC2981Upgradeable.sol"; + +contract TokenERC721Alt is + Initializable, + IThirdwebContract, + IOwnable, + IRoyalty, + ReentrancyGuardUpgradeable, + EIP712Upgradeable, + ERC2771ContextUpgradeable, + Multicall, + AccessControlEnumerableUpgradeable, + ERC721EnumerableUpgradeable, + ITokenERC721Alt, + NFTMetadata +{ + using ECDSAUpgradeable for bytes32; + using StringsUpgradeable for uint256; + + bytes32 private constant MODULE_TYPE = bytes32("TokenERC721"); + uint256 private constant VERSION = 1; + + bytes32 private constant TYPEHASH = + keccak256("MintRequest(address to,uint128 validityStartTimestamp,uint128 validityEndTimestamp,bytes32 uid)"); + + /// @dev Only TRANSFER_ROLE holders can have tokens transferred from or to them, during restricted transfers. + bytes32 private constant TRANSFER_ROLE = keccak256("TRANSFER_ROLE"); + /// @dev Only MINTER_ROLE holders can sign off on `MintRequest`s. + bytes32 private constant MINTER_ROLE = keccak256("MINTER_ROLE"); + /// @dev Only METADATA_ROLE holders can update NFT metadata. + bytes32 private constant METADATA_ROLE = keccak256("METADATA_ROLE"); + + /// @dev Max bps in the thirdweb system + uint256 private constant MAX_BPS = 10_000; + + /// @dev Owner of the contract (purpose: OpenSea compatibility, etc.) + address private _owner; + + /// @dev The token ID of the next token to mint. + uint256 public nextTokenIdToMint; + + /// @dev The recipient of who gets the royalty. + address private royaltyRecipient; + + /// @dev The percentage of royalty how much royalty in basis points. + uint128 private royaltyBps; + + /// @dev Contract level metadata. + string public contractURI; + + /// @dev Mapping from mint request UID => whether the mint request is processed. + mapping(bytes32 => bool) private minted; + + /// @dev Token ID => royalty recipient and bps for token + mapping(uint256 => RoyaltyInfo) private royaltyInfoForToken; + + constructor() initializer {} + + /// @dev Initializes the contract, like a constructor. + function initialize( + address _defaultAdmin, + string memory _name, + string memory _symbol, + string memory _contractURI, + address[] memory _trustedForwarders, + address _royaltyRecipient, + uint128 _royaltyBps + ) external initializer { + // Initialize inherited contracts, most base-like -> most derived. + __ReentrancyGuard_init(); + __EIP712_init("TokenERC721", "1"); + __ERC2771Context_init(_trustedForwarders); + __ERC721_init(_name, _symbol); + + // Initialize this contract's state. + royaltyRecipient = _royaltyRecipient; + royaltyBps = _royaltyBps; + contractURI = _contractURI; + + _owner = _defaultAdmin; + _setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin); + _setupRole(MINTER_ROLE, _defaultAdmin); + + _setupRole(METADATA_ROLE, _defaultAdmin); + _setRoleAdmin(METADATA_ROLE, METADATA_ROLE); + + _setupRole(TRANSFER_ROLE, _defaultAdmin); + _setupRole(TRANSFER_ROLE, address(0)); + + emit DefaultRoyalty(_royaltyRecipient, _royaltyBps); + } + + /// ===== Public functions ===== + + /// @dev Returns the module type of the contract. + function contractType() external pure returns (bytes32) { + return MODULE_TYPE; + } + + /// @dev Returns the version of the contract. + function contractVersion() external pure returns (uint8) { + return uint8(VERSION); + } + + /** + * @dev Returns the address of the current owner. + */ + function owner() public view returns (address) { + return hasRole(DEFAULT_ADMIN_ROLE, _owner) ? _owner : address(0); + } + + /// @dev Verifies that a mint request is signed by an account holding MINTER_ROLE (at the time of the function call). + function verify(MintRequest calldata _req, bytes calldata _signature) public view returns (bool, address) { + address signer = recoverAddress(_req, _signature); + return (!minted[_req.uid] && hasRole(MINTER_ROLE, signer), signer); + } + + /// @dev Returns the URI for a tokenId + function tokenURI(uint256 _tokenId) public view override returns (string memory) { + return _tokenURI[_tokenId]; + } + + /// @dev Lets an account with MINTER_ROLE mint an NFT. + function mintTo(address _to, string calldata _uri) external nonReentrant onlyRole(MINTER_ROLE) returns (uint256) { + // `_mintTo` is re-used. `mintTo` just adds a minter role check. + return _mintTo(_to); + } + + /// ===== External functions ===== + + /// @dev See EIP-2981 + function royaltyInfo( + uint256 tokenId, + uint256 salePrice + ) external view virtual returns (address receiver, uint256 royaltyAmount) { + (address recipient, uint256 bps) = getRoyaltyInfoForToken(tokenId); + receiver = recipient; + royaltyAmount = (salePrice * bps) / MAX_BPS; + } + + /// @dev Mints an NFT according to the provided mint request. + function mintWithSignature( + MintRequest calldata _req, + bytes calldata _signature + ) external payable nonReentrant returns (uint256 tokenIdMinted) { + address signer = verifyRequest(_req, _signature); + address receiver = _req.to; + + tokenIdMinted = _mintTo(receiver); + + // if (_req.to != address(0)) { + // royaltyInfoForToken[tokenIdMinted] = RoyaltyInfo({ recipient: _req.to, bps: 100 }); + // } + + // collectPrice(_req); + + emit TokensMintedWithSignature(signer, receiver, tokenIdMinted, _req); + } + + /// @dev Collects and distributes the primary sale value of tokens being claimed. + function collectPrice(MintRequest calldata _req) internal { + if (_req.uid != bytes32(0)) { + require(_req.uid != bytes32(0), "!Value"); + return; + } + } + + // ===== Setter functions ===== + + /// @dev Lets a module admin update the royalty bps and recipient. + function setDefaultRoyaltyInfo( + address _royaltyRecipient, + uint256 _royaltyBps + ) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(_royaltyBps <= MAX_BPS, "exceed royalty bps"); + + royaltyRecipient = _royaltyRecipient; + royaltyBps = uint128(_royaltyBps); + + emit DefaultRoyalty(_royaltyRecipient, _royaltyBps); + } + + /// @dev Lets a module admin set the royalty recipient for a particular token Id. + function setRoyaltyInfoForToken( + uint256 _tokenId, + address _recipient, + uint256 _bps + ) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(_bps <= MAX_BPS, "exceed royalty bps"); + + royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps }); + + emit RoyaltyForToken(_tokenId, _recipient, _bps); + } + + /// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin. + function setOwner(address _newOwner) external onlyRole(DEFAULT_ADMIN_ROLE) { + require(hasRole(DEFAULT_ADMIN_ROLE, _newOwner), "new owner not module admin."); + address _prevOwner = _owner; + _owner = _newOwner; + + emit OwnerUpdated(_prevOwner, _newOwner); + } + + /// @dev Lets a module admin set the URI for contract-level metadata. + function setContractURI(string calldata _uri) external onlyRole(DEFAULT_ADMIN_ROLE) { + contractURI = _uri; + } + + /// ===== Getter functions ===== + + /// @dev Returns the platform fee bps and recipient. + function getDefaultRoyaltyInfo() external view returns (address, uint16) { + return (royaltyRecipient, uint16(royaltyBps)); + } + + /// @dev Returns the royalty recipient for a particular token Id. + function getRoyaltyInfoForToken(uint256 _tokenId) public view returns (address, uint16) { + RoyaltyInfo memory royaltyForToken = royaltyInfoForToken[_tokenId]; + + return + royaltyForToken.recipient == address(0) + ? (royaltyRecipient, uint16(royaltyBps)) + : (royaltyForToken.recipient, uint16(royaltyForToken.bps)); + } + + /// ===== Internal functions ===== + + /// @dev Mints an NFT to `to` + function _mintTo(address _to) internal returns (uint256 tokenIdToMint) { + tokenIdToMint = nextTokenIdToMint; + nextTokenIdToMint += 1; + + _safeMint(_to, tokenIdToMint); + + emit TokensMinted(_to, tokenIdToMint, ""); + } + + /// @dev Returns the address of the signer of the mint request. + function recoverAddress(MintRequest calldata _req, bytes calldata _signature) private view returns (address) { + return _hashTypedDataV4(keccak256(_encodeRequest(_req))).recover(_signature); + } + + /// @dev Resolves 'stack too deep' error in `recoverAddress`. + function _encodeRequest(MintRequest calldata _req) private pure returns (bytes memory) { + return abi.encode(TYPEHASH, _req.to, _req.validityStartTimestamp, _req.validityEndTimestamp, _req.uid); + } + + /// @dev Verifies that a mint request is valid. + function verifyRequest(MintRequest calldata _req, bytes calldata _signature) internal returns (address) { + (bool success, address signer) = verify(_req, _signature); + require(success, "invalid signature"); + + require( + _req.validityStartTimestamp <= block.timestamp && _req.validityEndTimestamp >= block.timestamp, + "request expired" + ); + require(_req.to != address(0), "recipient undefined"); + + minted[_req.uid] = true; + + return signer; + } + + /// ===== Low-level overrides ===== + + /// @dev Burns `tokenId`. See {ERC721-_burn}. + function burn(uint256 tokenId) public virtual { + //solhint-disable-next-line max-line-length + require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved"); + _burn(tokenId); + } + + /// @dev See {ERC721-_beforeTokenTransfer}. + function _beforeTokenTransfer( + address from, + address to, + uint256 tokenId, + uint256 batchSize + ) internal virtual override(ERC721EnumerableUpgradeable) { + super._beforeTokenTransfer(from, to, tokenId, batchSize); + + // if transfer is restricted on the contract, we still want to allow burning and minting + if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) { + require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "restricted to TRANSFER_ROLE holders"); + } + } + + /// @dev Returns whether metadata can be set in the given execution context. + function _canSetMetadata() internal view virtual override returns (bool) { + return hasRole(METADATA_ROLE, _msgSender()); + } + + /// @dev Returns whether metadata can be frozen in the given execution context. + function _canFreezeMetadata() internal view virtual override returns (bool) { + return hasRole(METADATA_ROLE, _msgSender()); + } + + function supportsInterface( + bytes4 interfaceId + ) + public + view + virtual + override(AccessControlEnumerableUpgradeable, ERC721EnumerableUpgradeable, IERC165Upgradeable, IERC165) + returns (bool) + { + return super.supportsInterface(interfaceId) || interfaceId == type(IERC2981Upgradeable).interfaceId; + } + + function _msgSender() + internal + view + virtual + override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall) + returns (address sender) + { + return ERC2771ContextUpgradeable._msgSender(); + } + + function _msgData() + internal + view + virtual + override(ContextUpgradeable, ERC2771ContextUpgradeable) + returns (bytes calldata) + { + return ERC2771ContextUpgradeable._msgData(); + } +} diff --git a/foundry.toml b/foundry.toml index a86fc9b13..426464df2 100644 --- a/foundry.toml +++ b/foundry.toml @@ -10,6 +10,7 @@ gas_reports = [ "DropERC1155Benchmark", "TokenERC20Benchmark", "TokenERC721Benchmark", + "TokenERC721AltBenchmark", "TokenERC1155Benchmark", "MultiwrapBenchmark", "SignatureDropBenchmark", diff --git a/gasreport.txt b/gasreport.txt index ea8d57ffc..eddd15f50 100644 --- a/gasreport.txt +++ b/gasreport.txt @@ -1,181 +1,176 @@ No files changed, compilation skipped -Running 2 tests for src/test/benchmark/MultiwrapBenchmark.t.sol:MultiwrapBenchmarkTest -[32m[PASS][0m test_benchmark_multiwrap_unwrap() (gas: 88950) -[32m[PASS][0m test_benchmark_multiwrap_wrap() (gas: 473462) -Test result: [32mok[0m. [32m2[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 236.08ms - -Running 3 tests for src/test/benchmark/EditionStakeBenchmark.t.sol:EditionStakeBenchmarkTest -[32m[PASS][0m test_benchmark_editionStake_claimRewards() (gas: 65081) -[32m[PASS][0m test_benchmark_editionStake_stake() (gas: 185144) -[32m[PASS][0m test_benchmark_editionStake_withdraw() (gas: 46364) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 238.67ms - -Running 3 tests for src/test/benchmark/TokenStakeBenchmark.t.sol:TokenStakeBenchmarkTest -[32m[PASS][0m test_benchmark_tokenStake_claimRewards() (gas: 67554) -[32m[PASS][0m test_benchmark_tokenStake_stake() (gas: 177180) -[32m[PASS][0m test_benchmark_tokenStake_withdraw() (gas: 47396) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 241.12ms - -Running 4 tests for src/test/benchmark/TokenERC1155Benchmark.t.sol:TokenERC1155BenchmarkTest -[32m[PASS][0m test_benchmark_tokenERC1155_burn() (gas: 5728) -[32m[PASS][0m test_benchmark_tokenERC1155_mintTo() (gas: 122286) -[32m[PASS][0m test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 267175) -[32m[PASS][0m test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 296172) -Test result: [32mok[0m. [32m4[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 240.92ms - -Running 1 test for src/test/benchmark/AirdropERC1155Benchmark.t.sol:AirdropERC1155BenchmarkTest -[32m[PASS][0m test_benchmark_airdropERC1155_airdrop() (gas: 38083572) -Test result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 269.27ms - -Running 1 test for src/test/benchmark/AirdropERC20Benchmark.t.sol:AirdropERC20BenchmarkTest -[32m[PASS][0m test_benchmark_airdropERC20_airdrop() (gas: 32068413) -Test result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 270.94ms - -Running 1 test for src/test/smart-wallet/utils/AABenchmarkPrepare.sol:AABenchmarkPrepare -[32m[PASS][0m test_prepareBenchmarkFile() (gas: 2926370) -Test result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 272.43ms - -Running 1 test for src/test/benchmark/AirdropERC721Benchmark.t.sol:AirdropERC721BenchmarkTest -[32m[PASS][0m test_benchmark_airdropERC721_airdrop() (gas: 41912536) -Test result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 297.69ms - -Running 4 tests for src/test/benchmark/TokenERC721Benchmark.t.sol:TokenERC721BenchmarkTest -[32m[PASS][0m test_benchmark_tokenERC721_burn() (gas: 8954) -[32m[PASS][0m test_benchmark_tokenERC721_mintTo() (gas: 151552) -[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 262344) -[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 286914) -Test result: [32mok[0m. [32m4[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 242.17ms - -Running 3 tests for src/test/benchmark/NFTStakeBenchmark.t.sol:NFTStakeBenchmarkTest -[32m[PASS][0m test_benchmark_nftStake_claimRewards() (gas: 68287) -[32m[PASS][0m test_benchmark_nftStake_stake_five_tokens() (gas: 539145) -[32m[PASS][0m test_benchmark_nftStake_withdraw() (gas: 38076) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 279.71ms - -Running 5 tests for src/test/benchmark/SignatureDropBenchmark.t.sol:SignatureDropBenchmarkTest -[32m[PASS][0m test_benchmark_signatureDrop_claim_five_tokens() (gas: 140517) -[32m[PASS][0m test_benchmark_signatureDrop_lazyMint() (gas: 124311) -[32m[PASS][0m test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 225891) -[32m[PASS][0m test_benchmark_signatureDrop_reveal() (gas: 10647) -[32m[PASS][0m test_benchmark_signatureDrop_setClaimConditions() (gas: 73699) -Test result: [32mok[0m. [32m5[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 251.39ms - -Running 3 tests for src/test/benchmark/TokenERC20Benchmark.t.sol:TokenERC20BenchmarkTest -[32m[PASS][0m test_benchmark_tokenERC20_mintTo() (gas: 118586) -[32m[PASS][0m test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 183032) -[32m[PASS][0m test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 207694) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 287.73ms - -Running 14 tests for src/test/benchmark/AccountBenchmark.t.sol:AccountBenchmarkTest -[32m[PASS][0m test_state_accountReceivesNativeTokens() (gas: 11037) -[32m[PASS][0m test_state_addAndWithdrawDeposit() (gas: 83332) -[32m[PASS][0m test_state_contractMetadata() (gas: 56507) -[32m[PASS][0m test_state_createAccount_viaEntrypoint() (gas: 432040) -[32m[PASS][0m test_state_createAccount_viaFactory() (gas: 334122) -[32m[PASS][0m test_state_executeBatchTransaction() (gas: 39874) -[32m[PASS][0m test_state_executeBatchTransaction_viaAccountSigner() (gas: 392782) -[32m[PASS][0m test_state_executeBatchTransaction_viaEntrypoint() (gas: 82915) -[32m[PASS][0m test_state_executeTransaction() (gas: 35735) -[32m[PASS][0m test_state_executeTransaction_viaAccountSigner() (gas: 378632) -[32m[PASS][0m test_state_executeTransaction_viaEntrypoint() (gas: 75593) -[32m[PASS][0m test_state_receiveERC1155NFT() (gas: 39343) -[32m[PASS][0m test_state_receiveERC721NFT() (gas: 78624) -[32m[PASS][0m test_state_transferOutsNativeTokens() (gas: 81713) -Test result: [32mok[0m. [32m14[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 364.96ms - -Running 3 tests for src/test/benchmark/PackBenchmark.t.sol:PackBenchmarkTest -[32m[PASS][0m test_benchmark_pack_addPackContents() (gas: 219188) -[32m[PASS][0m test_benchmark_pack_createPack() (gas: 1412868) -[32m[PASS][0m test_benchmark_pack_openPack() (gas: 141860) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 258.39ms - -Running 3 tests for src/test/benchmark/PackVRFDirectBenchmark.t.sol:PackVRFDirectBenchmarkTest -[32m[PASS][0m test_benchmark_packvrf_createPack() (gas: 1379604) -[32m[PASS][0m test_benchmark_packvrf_openPack() (gas: 119953) +Ran 3 tests for src/test/benchmark/PackBenchmark.t.sol:PackBenchmarkTest +[32m[PASS][0m test_benchmark_pack_addPackContents() (gas: 312595) +[32m[PASS][0m test_benchmark_pack_createPack() (gas: 1419379) +[32m[PASS][0m test_benchmark_pack_openPack() (gas: 306658) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 872.22ms (3.54ms CPU time) + +Ran 1 test for src/test/benchmark/AirdropERC1155Benchmark.t.sol:AirdropERC1155BenchmarkTest +[32m[PASS][0m test_benchmark_airdropERC1155_airdrop() (gas: 38536544) +Suite result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 886.25ms (24.92ms CPU time) + +Ran 4 tests for src/test/benchmark/TokenERC1155Benchmark.t.sol:TokenERC1155BenchmarkTest +[32m[PASS][0m test_benchmark_tokenERC1155_burn() (gas: 30352) +[32m[PASS][0m test_benchmark_tokenERC1155_mintTo() (gas: 144229) +[32m[PASS][0m test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 307291) +[32m[PASS][0m test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 318712) +Suite result: [32mok[0m. [32m4[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 892.58ms (1.57ms CPU time) + +Ran 1 test for src/test/smart-wallet/utils/AABenchmarkPrepare.sol:AABenchmarkPrepare +[32m[PASS][0m test_prepareBenchmarkFile() (gas: 2955770) +Suite result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 897.40ms (23.41ms CPU time) + +Ran 3 tests for src/test/benchmark/NFTStakeBenchmark.t.sol:NFTStakeBenchmarkTest +[32m[PASS][0m test_benchmark_nftStake_claimRewards() (gas: 99831) +[32m[PASS][0m test_benchmark_nftStake_stake_five_tokens() (gas: 553577) +[32m[PASS][0m test_benchmark_nftStake_withdraw() (gas: 96144) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 919.06ms (868.63µs CPU time) + +Ran 1 test for src/test/benchmark/AirdropERC721Benchmark.t.sol:AirdropERC721BenchmarkTest +[32m[PASS][0m test_benchmark_airdropERC721_airdrop() (gas: 42241588) +Suite result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 919.32ms (18.01ms CPU time) + +Ran 14 tests for src/test/benchmark/AccountBenchmark.t.sol:AccountBenchmarkTest +[32m[PASS][0m test_state_accountReceivesNativeTokens() (gas: 34537) +[32m[PASS][0m test_state_addAndWithdrawDeposit() (gas: 148780) +[32m[PASS][0m test_state_contractMetadata() (gas: 114307) +[32m[PASS][0m test_state_createAccount_viaEntrypoint() (gas: 458192) +[32m[PASS][0m test_state_createAccount_viaFactory() (gas: 355822) +[32m[PASS][0m test_state_executeBatchTransaction() (gas: 76066) +[32m[PASS][0m test_state_executeBatchTransaction_viaAccountSigner() (gas: 488470) +[32m[PASS][0m test_state_executeBatchTransaction_viaEntrypoint() (gas: 138443) +[32m[PASS][0m test_state_executeTransaction() (gas: 68891) +[32m[PASS][0m test_state_executeTransaction_viaAccountSigner() (gas: 471272) +[32m[PASS][0m test_state_executeTransaction_viaEntrypoint() (gas: 128073) +[32m[PASS][0m test_state_receiveERC1155NFT() (gas: 66043) +[32m[PASS][0m test_state_receiveERC721NFT() (gas: 100196) +[32m[PASS][0m test_state_transferOutsNativeTokens() (gas: 133673) +Suite result: [32mok[0m. [32m14[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 969.03ms (19.13ms CPU time) + +Ran 2 tests for src/test/benchmark/MultiwrapBenchmark.t.sol:MultiwrapBenchmarkTest +[32m[PASS][0m test_benchmark_multiwrap_unwrap() (gas: 152040) +[32m[PASS][0m test_benchmark_multiwrap_wrap() (gas: 480722) +Suite result: [32mok[0m. [32m2[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 1.01s (697.83µs CPU time) + +Ran 3 tests for src/test/benchmark/EditionStakeBenchmark.t.sol:EditionStakeBenchmarkTest +[32m[PASS][0m test_benchmark_editionStake_claimRewards() (gas: 98765) +[32m[PASS][0m test_benchmark_editionStake_stake() (gas: 203676) +[32m[PASS][0m test_benchmark_editionStake_withdraw() (gas: 94296) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 223.21ms (691.33µs CPU time) + +Ran 3 tests for src/test/benchmark/PackVRFDirectBenchmark.t.sol:PackVRFDirectBenchmarkTest +[32m[PASS][0m test_benchmark_packvrf_createPack() (gas: 1392387) +[32m[PASS][0m test_benchmark_packvrf_openPack() (gas: 150677) [32m[PASS][0m test_benchmark_packvrf_openPackAndClaimRewards() (gas: 3621) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 285.64ms - -Running 3 tests for src/test/benchmark/DropERC1155Benchmark.t.sol:DropERC1155BenchmarkTest -[32m[PASS][0m test_benchmark_dropERC1155_claim() (gas: 185032) -[32m[PASS][0m test_benchmark_dropERC1155_lazyMint() (gas: 123913) -[32m[PASS][0m test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 492121) -Test result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 735.56ms - -Running 5 tests for src/test/benchmark/DropERC721Benchmark.t.sol:DropERC721BenchmarkTest -[32m[PASS][0m test_benchmark_dropERC721_claim_five_tokens() (gas: 210967) -[32m[PASS][0m test_benchmark_dropERC721_lazyMint() (gas: 124540) -[32m[PASS][0m test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 226149) -[32m[PASS][0m test_benchmark_dropERC721_reveal() (gas: 13732) -[32m[PASS][0m test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 500494) -Test result: [32mok[0m. [32m5[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 742.03ms - -Running 2 tests for src/test/benchmark/DropERC20Benchmark.t.sol:DropERC20BenchmarkTest -[32m[PASS][0m test_benchmark_dropERC20_claim() (gas: 230505) -[32m[PASS][0m test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 500858) -Test result: [32mok[0m. [32m2[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 1.12s - - -Ran 18 test suites: [32m61[0m tests passed, [31m0[0m failed, [33m0[0m skipped (61 total tests) -test_state_accountReceivesNativeTokens() (gas: 0 (0.000%)) -test_state_addAndWithdrawDeposit() (gas: 0 (0.000%)) -test_state_contractMetadata() (gas: 0 (0.000%)) -test_state_createAccount_viaEntrypoint() (gas: 0 (0.000%)) -test_state_createAccount_viaFactory() (gas: 0 (0.000%)) -test_state_executeBatchTransaction() (gas: 0 (0.000%)) -test_state_executeBatchTransaction_viaAccountSigner() (gas: 0 (0.000%)) -test_state_executeBatchTransaction_viaEntrypoint() (gas: 0 (0.000%)) -test_state_executeTransaction() (gas: 0 (0.000%)) -test_state_executeTransaction_viaAccountSigner() (gas: 0 (0.000%)) -test_state_executeTransaction_viaEntrypoint() (gas: 0 (0.000%)) -test_state_receiveERC1155NFT() (gas: 0 (0.000%)) -test_state_receiveERC721NFT() (gas: 0 (0.000%)) -test_state_transferOutsNativeTokens() (gas: 0 (0.000%)) -test_benchmark_airdropERC1155_airdrop() (gas: 0 (0.000%)) -test_benchmark_airdropERC20_airdrop() (gas: 0 (0.000%)) -test_benchmark_airdropERC721_airdrop() (gas: 0 (0.000%)) -test_benchmark_dropERC1155_claim() (gas: 0 (0.000%)) -test_benchmark_dropERC1155_lazyMint() (gas: 0 (0.000%)) -test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 0 (0.000%)) -test_benchmark_dropERC20_claim() (gas: 0 (0.000%)) -test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 0 (0.000%)) -test_benchmark_dropERC721_claim_five_tokens() (gas: 0 (0.000%)) -test_benchmark_dropERC721_lazyMint() (gas: 0 (0.000%)) -test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 0 (0.000%)) -test_benchmark_dropERC721_reveal() (gas: 0 (0.000%)) -test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 0 (0.000%)) -test_benchmark_editionStake_claimRewards() (gas: 0 (0.000%)) -test_benchmark_editionStake_stake() (gas: 0 (0.000%)) -test_benchmark_editionStake_withdraw() (gas: 0 (0.000%)) -test_benchmark_multiwrap_unwrap() (gas: 0 (0.000%)) -test_benchmark_multiwrap_wrap() (gas: 0 (0.000%)) -test_benchmark_nftStake_claimRewards() (gas: 0 (0.000%)) -test_benchmark_nftStake_stake_five_tokens() (gas: 0 (0.000%)) -test_benchmark_nftStake_withdraw() (gas: 0 (0.000%)) -test_benchmark_pack_addPackContents() (gas: 0 (0.000%)) -test_benchmark_pack_createPack() (gas: 0 (0.000%)) -test_benchmark_pack_openPack() (gas: 0 (0.000%)) -test_benchmark_packvrf_createPack() (gas: 0 (0.000%)) -test_benchmark_packvrf_openPack() (gas: 0 (0.000%)) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 276.88ms (1.95ms CPU time) + +Ran 5 tests for src/test/benchmark/SignatureDropBenchmark.t.sol:SignatureDropBenchmarkTest +[32m[PASS][0m test_benchmark_signatureDrop_claim_five_tokens() (gas: 185688) +[32m[PASS][0m test_benchmark_signatureDrop_lazyMint() (gas: 147153) +[32m[PASS][0m test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 249057) +[32m[PASS][0m test_benchmark_signatureDrop_reveal() (gas: 49802) +[32m[PASS][0m test_benchmark_signatureDrop_setClaimConditions() (gas: 100719) +Suite result: [32mok[0m. [32m5[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 266.44ms (801.92µs CPU time) + +Ran 1 test for src/test/benchmark/AirdropERC20Benchmark.t.sol:AirdropERC20BenchmarkTest +[32m[PASS][0m test_benchmark_airdropERC20_airdrop() (gas: 32443785) +Suite result: [32mok[0m. [32m1[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 288.14ms (21.29ms CPU time) + +Ran 3 tests for src/test/benchmark/TokenERC20Benchmark.t.sol:TokenERC20BenchmarkTest +[32m[PASS][0m test_benchmark_tokenERC20_mintTo() (gas: 139513) +[32m[PASS][0m test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 221724) +[32m[PASS][0m test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 228786) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 317.00ms (3.05ms CPU time) + +Ran 3 tests for src/test/benchmark/TokenERC721AltBenchmark.t.sol:TokenERC721AltBenchmarkTest +[32m[PASS][0m test_benchmark_tokenERC721Alt_mintWithSignature_fiveTokensMulticall() (gas: 959657) +[32m[PASS][0m test_benchmark_tokenERC721Alt_mintWithSignature_oneToken() (gas: 211914) +[32m[PASS][0m test_benchmark_tokenERC721Alt_mintWithSignature_tenTokensMulticall() (gas: 1884555) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 299.42ms (10.26ms CPU time) + +Ran 7 tests for src/test/benchmark/TokenERC721Benchmark.t.sol:TokenERC721BenchmarkTest +[32m[PASS][0m test_benchmark_tokenERC721_burn() (gas: 40414) +[32m[PASS][0m test_benchmark_tokenERC721_mintTo() (gas: 172856) +[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_fiveTokensMulticall_zeroPrice() (gas: 1203653) +[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 301866) +[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 308836) +[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_tenTokensMulticall_zeroPrice() (gas: 2375791) +[32m[PASS][0m test_benchmark_tokenERC721_mintWithSignature_zeroPrice() (gas: 258961) +Suite result: [32mok[0m. [32m7[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 192.05ms (10.38ms CPU time) + +Ran 3 tests for src/test/benchmark/TokenStakeBenchmark.t.sol:TokenStakeBenchmarkTest +[32m[PASS][0m test_benchmark_tokenStake_claimRewards() (gas: 101098) +[32m[PASS][0m test_benchmark_tokenStake_stake() (gas: 195556) +[32m[PASS][0m test_benchmark_tokenStake_withdraw() (gas: 104792) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 191.77ms (761.08µs CPU time) + +Ran 5 tests for src/test/benchmark/DropERC721Benchmark.t.sol:DropERC721BenchmarkTest +[32m[PASS][0m test_benchmark_dropERC721_claim_five_tokens() (gas: 273303) +[32m[PASS][0m test_benchmark_dropERC721_lazyMint() (gas: 147052) +[32m[PASS][0m test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 248985) +[32m[PASS][0m test_benchmark_dropERC721_reveal() (gas: 49433) +[32m[PASS][0m test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 529470) +Suite result: [32mok[0m. [32m5[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 1.41s (808.03ms CPU time) + +Ran 2 tests for src/test/benchmark/DropERC20Benchmark.t.sol:DropERC20BenchmarkTest +[32m[PASS][0m test_benchmark_dropERC20_claim() (gas: 291508) +[32m[PASS][0m test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 530026) +Suite result: [32mok[0m. [32m2[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 1.47s (789.54ms CPU time) + +Ran 3 tests for src/test/benchmark/DropERC1155Benchmark.t.sol:DropERC1155BenchmarkTest +[32m[PASS][0m test_benchmark_dropERC1155_claim() (gas: 245552) +[32m[PASS][0m test_benchmark_dropERC1155_lazyMint() (gas: 146425) +[32m[PASS][0m test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 525725) +Suite result: [32mok[0m. [32m3[0m passed; [31m0[0m failed; [33m0[0m skipped; finished in 556.80ms (624.58ms CPU time) + + +Ran 19 test suites in 1.53s (12.84s CPU time): [32m67[0m tests passed, [31m0[0m failed, [33m0[0m skipped (67 total tests) test_benchmark_packvrf_openPackAndClaimRewards() (gas: 0 (0.000%)) -test_benchmark_signatureDrop_claim_five_tokens() (gas: 0 (0.000%)) -test_benchmark_signatureDrop_lazyMint() (gas: 0 (0.000%)) -test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 0 (0.000%)) -test_benchmark_signatureDrop_reveal() (gas: 0 (0.000%)) -test_benchmark_signatureDrop_setClaimConditions() (gas: 0 (0.000%)) -test_benchmark_tokenERC1155_burn() (gas: 0 (0.000%)) -test_benchmark_tokenERC1155_mintTo() (gas: 0 (0.000%)) -test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 0 (0.000%)) -test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 0 (0.000%)) -test_benchmark_tokenERC20_mintTo() (gas: 0 (0.000%)) -test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 0 (0.000%)) -test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 0 (0.000%)) -test_benchmark_tokenERC721_burn() (gas: 0 (0.000%)) -test_benchmark_tokenERC721_mintTo() (gas: 0 (0.000%)) -test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 0 (0.000%)) -test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 0 (0.000%)) -test_benchmark_tokenStake_claimRewards() (gas: 0 (0.000%)) -test_benchmark_tokenStake_stake() (gas: 0 (0.000%)) -test_benchmark_tokenStake_withdraw() (gas: 0 (0.000%)) test_prepareBenchmarkFile() (gas: 0 (0.000%)) -Overall gas change: 0 (0.000%) +test_benchmark_airdropERC721_airdrop() (gas: [31m329052[0m ([31m0.785%[0m)) +test_benchmark_pack_createPack() (gas: [31m12712[0m ([31m0.904%[0m)) +test_benchmark_packvrf_createPack() (gas: [31m12712[0m ([31m0.921%[0m)) +test_benchmark_airdropERC20_airdrop() (gas: [31m375372[0m ([31m1.171%[0m)) +test_benchmark_airdropERC1155_airdrop() (gas: [31m452972[0m ([31m1.189%[0m)) +test_benchmark_multiwrap_wrap() (gas: [31m7260[0m ([31m1.533%[0m)) +test_benchmark_nftStake_stake_five_tokens() (gas: [31m14432[0m ([31m2.677%[0m)) +test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: [31m28976[0m ([31m5.789%[0m)) +test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: [31m29168[0m ([31m5.824%[0m)) +test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: [31m33604[0m ([31m6.828%[0m)) +test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: [31m22540[0m ([31m7.610%[0m)) +test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: [31m21922[0m ([31m7.641%[0m)) +test_benchmark_editionStake_stake() (gas: [31m18532[0m ([31m10.010%[0m)) +test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: [31m22836[0m ([31m10.095%[0m)) +test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: [31m22836[0m ([31m10.098%[0m)) +test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: [31m21092[0m ([31m10.155%[0m)) +test_benchmark_tokenStake_stake() (gas: [31m18416[0m ([31m10.396%[0m)) +test_benchmark_tokenERC721_mintTo() (gas: [31m18930[0m ([31m12.298%[0m)) +test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: [31m40116[0m ([31m15.015%[0m)) +test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: [31m39522[0m ([31m15.065%[0m)) +test_benchmark_tokenERC20_mintTo() (gas: [31m18556[0m ([31m15.341%[0m)) +test_benchmark_tokenERC1155_mintTo() (gas: [31m19572[0m ([31m15.701%[0m)) +test_benchmark_signatureDrop_lazyMint() (gas: [31m22512[0m ([31m18.061%[0m)) +test_benchmark_dropERC721_lazyMint() (gas: [31m22512[0m ([31m18.076%[0m)) +test_benchmark_dropERC1155_lazyMint() (gas: [31m22512[0m ([31m18.168%[0m)) +test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: [31m38692[0m ([31m21.139%[0m)) +test_benchmark_packvrf_openPack() (gas: [31m30632[0m ([31m25.517%[0m)) +test_benchmark_dropERC20_claim() (gas: [31m61316[0m ([31m26.637%[0m)) +test_benchmark_dropERC721_claim_five_tokens() (gas: [31m62552[0m ([31m29.681%[0m)) +test_benchmark_signatureDrop_claim_five_tokens() (gas: [31m45172[0m ([31m32.147%[0m)) +test_benchmark_dropERC1155_claim() (gas: [31m60680[0m ([31m32.823%[0m)) +test_benchmark_signatureDrop_setClaimConditions() (gas: [31m27020[0m ([31m36.663%[0m)) +test_benchmark_pack_addPackContents() (gas: [31m93608[0m ([31m42.746%[0m)) +test_benchmark_nftStake_claimRewards() (gas: [31m31552[0m ([31m46.210%[0m)) +test_benchmark_tokenStake_claimRewards() (gas: [31m33552[0m ([31m49.673%[0m)) +test_benchmark_editionStake_claimRewards() (gas: [31m33692[0m ([31m51.776%[0m)) +test_benchmark_multiwrap_unwrap() (gas: [31m63090[0m ([31m70.927%[0m)) +test_benchmark_editionStake_withdraw() (gas: [31m47932[0m ([31m103.382%[0m)) +test_benchmark_pack_openPack() (gas: [31m164732[0m ([31m116.069%[0m)) +test_benchmark_tokenStake_withdraw() (gas: [31m57404[0m ([31m121.136%[0m)) +test_benchmark_nftStake_withdraw() (gas: [31m58068[0m ([31m152.506%[0m)) +test_benchmark_dropERC721_reveal() (gas: [31m35685[0m ([31m259.565%[0m)) +test_benchmark_tokenERC721_burn() (gas: [31m31460[0m ([31m351.351%[0m)) +test_benchmark_signatureDrop_reveal() (gas: [31m38891[0m ([31m356.438%[0m)) +test_benchmark_tokenERC1155_burn() (gas: [31m24633[0m ([31m430.722%[0m)) +Overall gas change: [31m2689029[0m ([31m2.148%[0m) diff --git a/src/test/benchmark/TokenERC721AltBenchmark.t.sol b/src/test/benchmark/TokenERC721AltBenchmark.t.sol new file mode 100644 index 000000000..b8e312c37 --- /dev/null +++ b/src/test/benchmark/TokenERC721AltBenchmark.t.sol @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: Apache-2.0 +pragma solidity ^0.8.0; + +import { TokenERC721Alt } from "contracts/prebuilts/token/TokenERC721Alt.sol"; +import { TWProxy } from "contracts/infra/TWProxy.sol"; + +// Test imports +import "../utils/BaseTest.sol"; +import "@openzeppelin/contracts-upgradeable/utils/StringsUpgradeable.sol"; + +contract TokenERC721AltBenchmarkTest is BaseTest { + using Strings for uint256; + + event TokensMinted(address indexed mintedTo, uint256 indexed tokenIdMinted, string uri); + event TokensMintedWithSignature( + address indexed signer, + address indexed mintedTo, + uint256 indexed tokenIdMinted, + TokenERC721Alt.MintRequest mintRequest + ); + event OwnerUpdated(address indexed prevOwner, address indexed newOwner); + event DefaultRoyalty(address indexed newRoyaltyRecipient, uint256 newRoyaltyBps); + event RoyaltyForToken(uint256 indexed tokenId, address indexed royaltyRecipient, uint256 royaltyBps); + + TokenERC721Alt public tokenContract; + bytes32 internal typehashMintRequest; + bytes32 internal nameHash; + bytes32 internal versionHash; + bytes32 internal typehashEip712; + bytes32 internal domainSeparator; + + bytes private emptyEncodedBytes = abi.encode("", ""); + + TokenERC721Alt.MintRequest _mintrequest; + bytes _signature; + + address internal deployerSigner; + address internal recipient; + + using stdStorage for StdStorage; + + function setUp() public override { + super.setUp(); + deployerSigner = signer; + recipient = address(0x123); + address _imp = address(new TokenERC721Alt()); + tokenContract = TokenERC721Alt( + address( + new TWProxy( + _imp, + abi.encodeCall( + TokenERC721Alt.initialize, + (deployerSigner, NAME, SYMBOL, CONTRACT_URI, forwarders(), royaltyRecipient, royaltyBps) + ) + ) + ) + ); + + typehashMintRequest = keccak256( + "MintRequest(address to,uint128 validityStartTimestamp,uint128 validityEndTimestamp,bytes32 uid)" + ); + nameHash = keccak256(bytes("TokenERC721")); + versionHash = keccak256(bytes("1")); + typehashEip712 = keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ); + domainSeparator = keccak256( + abi.encode(typehashEip712, nameHash, versionHash, block.chainid, address(tokenContract)) + ); + + // construct default mintrequest + _mintrequest.to = recipient; + _mintrequest.validityStartTimestamp = 1000; + _mintrequest.validityEndTimestamp = 2000; + _mintrequest.uid = bytes32(0); + + _signature = signMintRequest(_mintrequest, privateKey); + } + + function signMintRequest( + TokenERC721Alt.MintRequest memory _request, + uint256 _privateKey + ) internal view returns (bytes memory) { + bytes memory encodedRequest = abi.encode( + typehashMintRequest, + _request.to, + _request.validityStartTimestamp, + _request.validityEndTimestamp, + _request.uid + ); + bytes32 structHash = keccak256(encodedRequest); + bytes32 typedDataHash = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash)); + + (uint8 v, bytes32 r, bytes32 s) = vm.sign(_privateKey, typedDataHash); + bytes memory sig = abi.encodePacked(r, s, v); + + return sig; + } + + /*/////////////////////////////////////////////////////////////// + Benchmark: TokenERC721Alt + //////////////////////////////////////////////////////////////*/ + + function test_benchmark_tokenERC721Alt_mintWithSignature_oneToken() public { + vm.pauseGasMetering(); + vm.warp(1000); + + _signature = signMintRequest(_mintrequest, privateKey); + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.mintWithSignature(_mintrequest, _signature); + } + + function test_benchmark_tokenERC721Alt_mintWithSignature_fiveTokensMulticall() public { + vm.pauseGasMetering(); + vm.warp(1000); + + bytes[] memory calls = new bytes[](5); + for (uint256 i = 0; i < 5; i++) { + _mintrequest.uid = bytes32(i); + _signature = signMintRequest(_mintrequest, privateKey); + + calls[i] = abi.encodeWithSelector(TokenERC721Alt.mintWithSignature.selector, _mintrequest, _signature); + } + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.multicall(calls); + } + + function test_benchmark_tokenERC721Alt_mintWithSignature_tenTokensMulticall() public { + vm.pauseGasMetering(); + vm.warp(1000); + + bytes[] memory calls = new bytes[](10); + for (uint256 i = 0; i < 10; i++) { + _mintrequest.uid = bytes32(i); + _signature = signMintRequest(_mintrequest, privateKey); + + calls[i] = abi.encodeWithSelector(TokenERC721Alt.mintWithSignature.selector, _mintrequest, _signature); + } + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.multicall(calls); + } +} diff --git a/src/test/benchmark/TokenERC721Benchmark.t.sol b/src/test/benchmark/TokenERC721Benchmark.t.sol index 410709462..742f56837 100644 --- a/src/test/benchmark/TokenERC721Benchmark.t.sol +++ b/src/test/benchmark/TokenERC721Benchmark.t.sol @@ -109,6 +109,65 @@ contract TokenERC721BenchmarkTest is BaseTest { Benchmark: TokenERC721 //////////////////////////////////////////////////////////////*/ + function test_benchmark_tokenERC721_mintWithSignature_zeroPrice() public { + vm.pauseGasMetering(); + vm.warp(1000); + + // update mintrequest data + _mintrequest.price = 0; + _mintrequest.currency = address(erc20); + _signature = signMintRequest(_mintrequest, privateKey); + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.mintWithSignature(_mintrequest, _signature); + } + + function test_benchmark_tokenERC721_mintWithSignature_fiveTokensMulticall_zeroPrice() public { + vm.pauseGasMetering(); + vm.warp(1000); + + // update mintrequest data + _mintrequest.price = 0; + _mintrequest.currency = address(erc20); + + bytes[] memory calls = new bytes[](5); + for (uint256 i = 0; i < 5; i++) { + _mintrequest.uid = bytes32(i); + _signature = signMintRequest(_mintrequest, privateKey); + + calls[i] = abi.encodeWithSelector(TokenERC721.mintWithSignature.selector, _mintrequest, _signature); + } + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.multicall(calls); + } + + function test_benchmark_tokenERC721_mintWithSignature_tenTokensMulticall_zeroPrice() public { + vm.pauseGasMetering(); + vm.warp(1000); + + // update mintrequest data + _mintrequest.price = 0; + _mintrequest.currency = address(erc20); + + bytes[] memory calls = new bytes[](10); + for (uint256 i = 0; i < 10; i++) { + _mintrequest.uid = bytes32(i); + _signature = signMintRequest(_mintrequest, privateKey); + + calls[i] = abi.encodeWithSelector(TokenERC721.mintWithSignature.selector, _mintrequest, _signature); + } + + // mint with signature + vm.prank(recipient); + vm.resumeGasMetering(); + tokenContract.multicall(calls); + } + function test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() public { vm.pauseGasMetering(); vm.warp(1000);