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
-[PASS] test_benchmark_multiwrap_unwrap() (gas: 88950)
-[PASS] test_benchmark_multiwrap_wrap() (gas: 473462)
-Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 236.08ms
-
-Running 3 tests for src/test/benchmark/EditionStakeBenchmark.t.sol:EditionStakeBenchmarkTest
-[PASS] test_benchmark_editionStake_claimRewards() (gas: 65081)
-[PASS] test_benchmark_editionStake_stake() (gas: 185144)
-[PASS] test_benchmark_editionStake_withdraw() (gas: 46364)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 238.67ms
-
-Running 3 tests for src/test/benchmark/TokenStakeBenchmark.t.sol:TokenStakeBenchmarkTest
-[PASS] test_benchmark_tokenStake_claimRewards() (gas: 67554)
-[PASS] test_benchmark_tokenStake_stake() (gas: 177180)
-[PASS] test_benchmark_tokenStake_withdraw() (gas: 47396)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 241.12ms
-
-Running 4 tests for src/test/benchmark/TokenERC1155Benchmark.t.sol:TokenERC1155BenchmarkTest
-[PASS] test_benchmark_tokenERC1155_burn() (gas: 5728)
-[PASS] test_benchmark_tokenERC1155_mintTo() (gas: 122286)
-[PASS] test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 267175)
-[PASS] test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 296172)
-Test result: ok. 4 passed; 0 failed; 0 skipped; finished in 240.92ms
-
-Running 1 test for src/test/benchmark/AirdropERC1155Benchmark.t.sol:AirdropERC1155BenchmarkTest
-[PASS] test_benchmark_airdropERC1155_airdrop() (gas: 38083572)
-Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 269.27ms
-
-Running 1 test for src/test/benchmark/AirdropERC20Benchmark.t.sol:AirdropERC20BenchmarkTest
-[PASS] test_benchmark_airdropERC20_airdrop() (gas: 32068413)
-Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 270.94ms
-
-Running 1 test for src/test/smart-wallet/utils/AABenchmarkPrepare.sol:AABenchmarkPrepare
-[PASS] test_prepareBenchmarkFile() (gas: 2926370)
-Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 272.43ms
-
-Running 1 test for src/test/benchmark/AirdropERC721Benchmark.t.sol:AirdropERC721BenchmarkTest
-[PASS] test_benchmark_airdropERC721_airdrop() (gas: 41912536)
-Test result: ok. 1 passed; 0 failed; 0 skipped; finished in 297.69ms
-
-Running 4 tests for src/test/benchmark/TokenERC721Benchmark.t.sol:TokenERC721BenchmarkTest
-[PASS] test_benchmark_tokenERC721_burn() (gas: 8954)
-[PASS] test_benchmark_tokenERC721_mintTo() (gas: 151552)
-[PASS] test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 262344)
-[PASS] test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 286914)
-Test result: ok. 4 passed; 0 failed; 0 skipped; finished in 242.17ms
-
-Running 3 tests for src/test/benchmark/NFTStakeBenchmark.t.sol:NFTStakeBenchmarkTest
-[PASS] test_benchmark_nftStake_claimRewards() (gas: 68287)
-[PASS] test_benchmark_nftStake_stake_five_tokens() (gas: 539145)
-[PASS] test_benchmark_nftStake_withdraw() (gas: 38076)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 279.71ms
-
-Running 5 tests for src/test/benchmark/SignatureDropBenchmark.t.sol:SignatureDropBenchmarkTest
-[PASS] test_benchmark_signatureDrop_claim_five_tokens() (gas: 140517)
-[PASS] test_benchmark_signatureDrop_lazyMint() (gas: 124311)
-[PASS] test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 225891)
-[PASS] test_benchmark_signatureDrop_reveal() (gas: 10647)
-[PASS] test_benchmark_signatureDrop_setClaimConditions() (gas: 73699)
-Test result: ok. 5 passed; 0 failed; 0 skipped; finished in 251.39ms
-
-Running 3 tests for src/test/benchmark/TokenERC20Benchmark.t.sol:TokenERC20BenchmarkTest
-[PASS] test_benchmark_tokenERC20_mintTo() (gas: 118586)
-[PASS] test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 183032)
-[PASS] test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 207694)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 287.73ms
-
-Running 14 tests for src/test/benchmark/AccountBenchmark.t.sol:AccountBenchmarkTest
-[PASS] test_state_accountReceivesNativeTokens() (gas: 11037)
-[PASS] test_state_addAndWithdrawDeposit() (gas: 83332)
-[PASS] test_state_contractMetadata() (gas: 56507)
-[PASS] test_state_createAccount_viaEntrypoint() (gas: 432040)
-[PASS] test_state_createAccount_viaFactory() (gas: 334122)
-[PASS] test_state_executeBatchTransaction() (gas: 39874)
-[PASS] test_state_executeBatchTransaction_viaAccountSigner() (gas: 392782)
-[PASS] test_state_executeBatchTransaction_viaEntrypoint() (gas: 82915)
-[PASS] test_state_executeTransaction() (gas: 35735)
-[PASS] test_state_executeTransaction_viaAccountSigner() (gas: 378632)
-[PASS] test_state_executeTransaction_viaEntrypoint() (gas: 75593)
-[PASS] test_state_receiveERC1155NFT() (gas: 39343)
-[PASS] test_state_receiveERC721NFT() (gas: 78624)
-[PASS] test_state_transferOutsNativeTokens() (gas: 81713)
-Test result: ok. 14 passed; 0 failed; 0 skipped; finished in 364.96ms
-
-Running 3 tests for src/test/benchmark/PackBenchmark.t.sol:PackBenchmarkTest
-[PASS] test_benchmark_pack_addPackContents() (gas: 219188)
-[PASS] test_benchmark_pack_createPack() (gas: 1412868)
-[PASS] test_benchmark_pack_openPack() (gas: 141860)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 258.39ms
-
-Running 3 tests for src/test/benchmark/PackVRFDirectBenchmark.t.sol:PackVRFDirectBenchmarkTest
-[PASS] test_benchmark_packvrf_createPack() (gas: 1379604)
-[PASS] test_benchmark_packvrf_openPack() (gas: 119953)
+Ran 3 tests for src/test/benchmark/PackBenchmark.t.sol:PackBenchmarkTest
+[PASS] test_benchmark_pack_addPackContents() (gas: 312595)
+[PASS] test_benchmark_pack_createPack() (gas: 1419379)
+[PASS] test_benchmark_pack_openPack() (gas: 306658)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 872.22ms (3.54ms CPU time)
+
+Ran 1 test for src/test/benchmark/AirdropERC1155Benchmark.t.sol:AirdropERC1155BenchmarkTest
+[PASS] test_benchmark_airdropERC1155_airdrop() (gas: 38536544)
+Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 886.25ms (24.92ms CPU time)
+
+Ran 4 tests for src/test/benchmark/TokenERC1155Benchmark.t.sol:TokenERC1155BenchmarkTest
+[PASS] test_benchmark_tokenERC1155_burn() (gas: 30352)
+[PASS] test_benchmark_tokenERC1155_mintTo() (gas: 144229)
+[PASS] test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 307291)
+[PASS] test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 318712)
+Suite result: ok. 4 passed; 0 failed; 0 skipped; finished in 892.58ms (1.57ms CPU time)
+
+Ran 1 test for src/test/smart-wallet/utils/AABenchmarkPrepare.sol:AABenchmarkPrepare
+[PASS] test_prepareBenchmarkFile() (gas: 2955770)
+Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 897.40ms (23.41ms CPU time)
+
+Ran 3 tests for src/test/benchmark/NFTStakeBenchmark.t.sol:NFTStakeBenchmarkTest
+[PASS] test_benchmark_nftStake_claimRewards() (gas: 99831)
+[PASS] test_benchmark_nftStake_stake_five_tokens() (gas: 553577)
+[PASS] test_benchmark_nftStake_withdraw() (gas: 96144)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 919.06ms (868.63µs CPU time)
+
+Ran 1 test for src/test/benchmark/AirdropERC721Benchmark.t.sol:AirdropERC721BenchmarkTest
+[PASS] test_benchmark_airdropERC721_airdrop() (gas: 42241588)
+Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 919.32ms (18.01ms CPU time)
+
+Ran 14 tests for src/test/benchmark/AccountBenchmark.t.sol:AccountBenchmarkTest
+[PASS] test_state_accountReceivesNativeTokens() (gas: 34537)
+[PASS] test_state_addAndWithdrawDeposit() (gas: 148780)
+[PASS] test_state_contractMetadata() (gas: 114307)
+[PASS] test_state_createAccount_viaEntrypoint() (gas: 458192)
+[PASS] test_state_createAccount_viaFactory() (gas: 355822)
+[PASS] test_state_executeBatchTransaction() (gas: 76066)
+[PASS] test_state_executeBatchTransaction_viaAccountSigner() (gas: 488470)
+[PASS] test_state_executeBatchTransaction_viaEntrypoint() (gas: 138443)
+[PASS] test_state_executeTransaction() (gas: 68891)
+[PASS] test_state_executeTransaction_viaAccountSigner() (gas: 471272)
+[PASS] test_state_executeTransaction_viaEntrypoint() (gas: 128073)
+[PASS] test_state_receiveERC1155NFT() (gas: 66043)
+[PASS] test_state_receiveERC721NFT() (gas: 100196)
+[PASS] test_state_transferOutsNativeTokens() (gas: 133673)
+Suite result: ok. 14 passed; 0 failed; 0 skipped; finished in 969.03ms (19.13ms CPU time)
+
+Ran 2 tests for src/test/benchmark/MultiwrapBenchmark.t.sol:MultiwrapBenchmarkTest
+[PASS] test_benchmark_multiwrap_unwrap() (gas: 152040)
+[PASS] test_benchmark_multiwrap_wrap() (gas: 480722)
+Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.01s (697.83µs CPU time)
+
+Ran 3 tests for src/test/benchmark/EditionStakeBenchmark.t.sol:EditionStakeBenchmarkTest
+[PASS] test_benchmark_editionStake_claimRewards() (gas: 98765)
+[PASS] test_benchmark_editionStake_stake() (gas: 203676)
+[PASS] test_benchmark_editionStake_withdraw() (gas: 94296)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 223.21ms (691.33µs CPU time)
+
+Ran 3 tests for src/test/benchmark/PackVRFDirectBenchmark.t.sol:PackVRFDirectBenchmarkTest
+[PASS] test_benchmark_packvrf_createPack() (gas: 1392387)
+[PASS] test_benchmark_packvrf_openPack() (gas: 150677)
 [PASS] test_benchmark_packvrf_openPackAndClaimRewards() (gas: 3621)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 285.64ms
-
-Running 3 tests for src/test/benchmark/DropERC1155Benchmark.t.sol:DropERC1155BenchmarkTest
-[PASS] test_benchmark_dropERC1155_claim() (gas: 185032)
-[PASS] test_benchmark_dropERC1155_lazyMint() (gas: 123913)
-[PASS] test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 492121)
-Test result: ok. 3 passed; 0 failed; 0 skipped; finished in 735.56ms
-
-Running 5 tests for src/test/benchmark/DropERC721Benchmark.t.sol:DropERC721BenchmarkTest
-[PASS] test_benchmark_dropERC721_claim_five_tokens() (gas: 210967)
-[PASS] test_benchmark_dropERC721_lazyMint() (gas: 124540)
-[PASS] test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 226149)
-[PASS] test_benchmark_dropERC721_reveal() (gas: 13732)
-[PASS] test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 500494)
-Test result: ok. 5 passed; 0 failed; 0 skipped; finished in 742.03ms
-
-Running 2 tests for src/test/benchmark/DropERC20Benchmark.t.sol:DropERC20BenchmarkTest
-[PASS] test_benchmark_dropERC20_claim() (gas: 230505)
-[PASS] test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 500858)
-Test result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.12s
-
- 
-Ran 18 test suites: 61 tests passed, 0 failed, 0 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: ok. 3 passed; 0 failed; 0 skipped; finished in 276.88ms (1.95ms CPU time)
+
+Ran 5 tests for src/test/benchmark/SignatureDropBenchmark.t.sol:SignatureDropBenchmarkTest
+[PASS] test_benchmark_signatureDrop_claim_five_tokens() (gas: 185688)
+[PASS] test_benchmark_signatureDrop_lazyMint() (gas: 147153)
+[PASS] test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 249057)
+[PASS] test_benchmark_signatureDrop_reveal() (gas: 49802)
+[PASS] test_benchmark_signatureDrop_setClaimConditions() (gas: 100719)
+Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 266.44ms (801.92µs CPU time)
+
+Ran 1 test for src/test/benchmark/AirdropERC20Benchmark.t.sol:AirdropERC20BenchmarkTest
+[PASS] test_benchmark_airdropERC20_airdrop() (gas: 32443785)
+Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 288.14ms (21.29ms CPU time)
+
+Ran 3 tests for src/test/benchmark/TokenERC20Benchmark.t.sol:TokenERC20BenchmarkTest
+[PASS] test_benchmark_tokenERC20_mintTo() (gas: 139513)
+[PASS] test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 221724)
+[PASS] test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 228786)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 317.00ms (3.05ms CPU time)
+
+Ran 3 tests for src/test/benchmark/TokenERC721AltBenchmark.t.sol:TokenERC721AltBenchmarkTest
+[PASS] test_benchmark_tokenERC721Alt_mintWithSignature_fiveTokensMulticall() (gas: 959657)
+[PASS] test_benchmark_tokenERC721Alt_mintWithSignature_oneToken() (gas: 211914)
+[PASS] test_benchmark_tokenERC721Alt_mintWithSignature_tenTokensMulticall() (gas: 1884555)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 299.42ms (10.26ms CPU time)
+
+Ran 7 tests for src/test/benchmark/TokenERC721Benchmark.t.sol:TokenERC721BenchmarkTest
+[PASS] test_benchmark_tokenERC721_burn() (gas: 40414)
+[PASS] test_benchmark_tokenERC721_mintTo() (gas: 172856)
+[PASS] test_benchmark_tokenERC721_mintWithSignature_fiveTokensMulticall_zeroPrice() (gas: 1203653)
+[PASS] test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 301866)
+[PASS] test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 308836)
+[PASS] test_benchmark_tokenERC721_mintWithSignature_tenTokensMulticall_zeroPrice() (gas: 2375791)
+[PASS] test_benchmark_tokenERC721_mintWithSignature_zeroPrice() (gas: 258961)
+Suite result: ok. 7 passed; 0 failed; 0 skipped; finished in 192.05ms (10.38ms CPU time)
+
+Ran 3 tests for src/test/benchmark/TokenStakeBenchmark.t.sol:TokenStakeBenchmarkTest
+[PASS] test_benchmark_tokenStake_claimRewards() (gas: 101098)
+[PASS] test_benchmark_tokenStake_stake() (gas: 195556)
+[PASS] test_benchmark_tokenStake_withdraw() (gas: 104792)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 191.77ms (761.08µs CPU time)
+
+Ran 5 tests for src/test/benchmark/DropERC721Benchmark.t.sol:DropERC721BenchmarkTest
+[PASS] test_benchmark_dropERC721_claim_five_tokens() (gas: 273303)
+[PASS] test_benchmark_dropERC721_lazyMint() (gas: 147052)
+[PASS] test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 248985)
+[PASS] test_benchmark_dropERC721_reveal() (gas: 49433)
+[PASS] test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 529470)
+Suite result: ok. 5 passed; 0 failed; 0 skipped; finished in 1.41s (808.03ms CPU time)
+
+Ran 2 tests for src/test/benchmark/DropERC20Benchmark.t.sol:DropERC20BenchmarkTest
+[PASS] test_benchmark_dropERC20_claim() (gas: 291508)
+[PASS] test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 530026)
+Suite result: ok. 2 passed; 0 failed; 0 skipped; finished in 1.47s (789.54ms CPU time)
+
+Ran 3 tests for src/test/benchmark/DropERC1155Benchmark.t.sol:DropERC1155BenchmarkTest
+[PASS] test_benchmark_dropERC1155_claim() (gas: 245552)
+[PASS] test_benchmark_dropERC1155_lazyMint() (gas: 146425)
+[PASS] test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 525725)
+Suite result: ok. 3 passed; 0 failed; 0 skipped; finished in 556.80ms (624.58ms CPU time)
+
+
+Ran 19 test suites in 1.53s (12.84s CPU time): 67 tests passed, 0 failed, 0 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: 329052 (0.785%)) 
+test_benchmark_pack_createPack() (gas: 12712 (0.904%)) 
+test_benchmark_packvrf_createPack() (gas: 12712 (0.921%)) 
+test_benchmark_airdropERC20_airdrop() (gas: 375372 (1.171%)) 
+test_benchmark_airdropERC1155_airdrop() (gas: 452972 (1.189%)) 
+test_benchmark_multiwrap_wrap() (gas: 7260 (1.533%)) 
+test_benchmark_nftStake_stake_five_tokens() (gas: 14432 (2.677%)) 
+test_benchmark_dropERC721_setClaimConditions_five_conditions() (gas: 28976 (5.789%)) 
+test_benchmark_dropERC20_setClaimConditions_five_conditions() (gas: 29168 (5.824%)) 
+test_benchmark_dropERC1155_setClaimConditions_five_conditions() (gas: 33604 (6.828%)) 
+test_benchmark_tokenERC1155_mintWithSignature_pay_with_native_token() (gas: 22540 (7.610%)) 
+test_benchmark_tokenERC721_mintWithSignature_pay_with_native_token() (gas: 21922 (7.641%)) 
+test_benchmark_editionStake_stake() (gas: 18532 (10.010%)) 
+test_benchmark_signatureDrop_lazyMint_for_delayed_reveal() (gas: 22836 (10.095%)) 
+test_benchmark_dropERC721_lazyMint_for_delayed_reveal() (gas: 22836 (10.098%)) 
+test_benchmark_tokenERC20_mintWithSignature_pay_with_native_token() (gas: 21092 (10.155%)) 
+test_benchmark_tokenStake_stake() (gas: 18416 (10.396%)) 
+test_benchmark_tokenERC721_mintTo() (gas: 18930 (12.298%)) 
+test_benchmark_tokenERC1155_mintWithSignature_pay_with_ERC20() (gas: 40116 (15.015%)) 
+test_benchmark_tokenERC721_mintWithSignature_pay_with_ERC20() (gas: 39522 (15.065%)) 
+test_benchmark_tokenERC20_mintTo() (gas: 18556 (15.341%)) 
+test_benchmark_tokenERC1155_mintTo() (gas: 19572 (15.701%)) 
+test_benchmark_signatureDrop_lazyMint() (gas: 22512 (18.061%)) 
+test_benchmark_dropERC721_lazyMint() (gas: 22512 (18.076%)) 
+test_benchmark_dropERC1155_lazyMint() (gas: 22512 (18.168%)) 
+test_benchmark_tokenERC20_mintWithSignature_pay_with_ERC20() (gas: 38692 (21.139%)) 
+test_benchmark_packvrf_openPack() (gas: 30632 (25.517%)) 
+test_benchmark_dropERC20_claim() (gas: 61316 (26.637%)) 
+test_benchmark_dropERC721_claim_five_tokens() (gas: 62552 (29.681%)) 
+test_benchmark_signatureDrop_claim_five_tokens() (gas: 45172 (32.147%)) 
+test_benchmark_dropERC1155_claim() (gas: 60680 (32.823%)) 
+test_benchmark_signatureDrop_setClaimConditions() (gas: 27020 (36.663%)) 
+test_benchmark_pack_addPackContents() (gas: 93608 (42.746%)) 
+test_benchmark_nftStake_claimRewards() (gas: 31552 (46.210%)) 
+test_benchmark_tokenStake_claimRewards() (gas: 33552 (49.673%)) 
+test_benchmark_editionStake_claimRewards() (gas: 33692 (51.776%)) 
+test_benchmark_multiwrap_unwrap() (gas: 63090 (70.927%)) 
+test_benchmark_editionStake_withdraw() (gas: 47932 (103.382%)) 
+test_benchmark_pack_openPack() (gas: 164732 (116.069%)) 
+test_benchmark_tokenStake_withdraw() (gas: 57404 (121.136%)) 
+test_benchmark_nftStake_withdraw() (gas: 58068 (152.506%)) 
+test_benchmark_dropERC721_reveal() (gas: 35685 (259.565%)) 
+test_benchmark_tokenERC721_burn() (gas: 31460 (351.351%)) 
+test_benchmark_signatureDrop_reveal() (gas: 38891 (356.438%)) 
+test_benchmark_tokenERC1155_burn() (gas: 24633 (430.722%)) 
+Overall gas change: 2689029 (2.148%)
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);