Skip to content

Commit

Permalink
Optimize ERC721
Browse files Browse the repository at this point in the history
  • Loading branch information
Vectorized committed Jan 22, 2024
1 parent b302888 commit 18adf11
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 70 deletions.
104 changes: 52 additions & 52 deletions .gas-snapshot
Original file line number Diff line number Diff line change
Expand Up @@ -227,25 +227,25 @@ ERC4337FactoryTest:test__codesize() (gas: 13520)
ERC4337Test:testCdFallback() (gas: 443989)
ERC4337Test:testCdFallback2() (gas: 1140699)
ERC4337Test:testDelegateExecute() (gas: 369570)
ERC4337Test:testDelegateExecute(uint256) (runs: 256, μ: 356131, ~: 344555)
ERC4337Test:testDelegateExecute(uint256) (runs: 256, μ: 352832, ~: 344555)
ERC4337Test:testDelegateExecuteRevertsIfOwnerSlotValueChanged() (gas: 319282)
ERC4337Test:testDepositFunctions() (gas: 502955)
ERC4337Test:testDirectStorage() (gas: 70413)
ERC4337Test:testDisableInitializerForImplementation() (gas: 1177324)
ERC4337Test:testETHReceived() (gas: 16584)
ERC4337Test:testExecute() (gas: 382786)
ERC4337Test:testExecuteBatch() (gas: 692605)
ERC4337Test:testExecuteBatch(uint256) (runs: 256, μ: 534983, ~: 368321)
ERC4337Test:testExecuteBatch(uint256) (runs: 256, μ: 519572, ~: 368320)
ERC4337Test:testInitializer() (gas: 285192)
ERC4337Test:testIsValidSignature() (gas: 111663)
ERC4337Test:testIsValidSignaturePersonalSign() (gas: 96270)
ERC4337Test:testIsValidSignatureWrapped() (gas: 406706)
ERC4337Test:testOnERC1155BatchReceived() (gas: 1393788)
ERC4337Test:testOnERC1155Received() (gas: 1391111)
ERC4337Test:testOnERC721Received() (gas: 1371823)
ERC4337Test:testOnERC721Received() (gas: 1366600)
ERC4337Test:testOwnerRecovery() (gas: 486105)
ERC4337Test:testValidateUserOp() (gas: 491555)
ERC4337Test:test__codesize() (gas: 54804)
ERC4337Test:test__codesize() (gas: 54778)
ERC4626Test:testDepositWithNoApprovalReverts() (gas: 16371)
ERC4626Test:testDepositWithNotEnoughApprovalReverts() (gas: 89884)
ERC4626Test:testDifferentialFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 3325, ~: 3185)
Expand All @@ -266,21 +266,21 @@ ERC4626Test:testWithdrawWithNotEnoughUnderlyingAmountReverts() (gas: 144074)
ERC4626Test:testWithdrawZero() (gas: 52807)
ERC4626Test:test__codesize() (gas: 41067)
ERC6551Test:testCdFallback() (gas: 894585)
ERC6551Test:testDeployERC6551(uint256) (runs: 256, μ: 171121, ~: 168747)
ERC6551Test:testDeployERC6551(uint256) (runs: 256, μ: 171288, ~: 168767)
ERC6551Test:testDeployERC6551Proxy() (gas: 80751)
ERC6551Test:testExecute() (gas: 507949)
ERC6551Test:testExecuteBatch() (gas: 817049)
ERC6551Test:testExecuteBatch(uint256) (runs: 256, μ: 619335, ~: 483214)
ERC6551Test:testExecuteBatch(uint256) (runs: 256, μ: 630199, ~: 483214)
ERC6551Test:testInitializeERC6551ProxyImplementation() (gas: 189807)
ERC6551Test:testIsValidSignature() (gas: 187662)
ERC6551Test:testIsValidSignature() (gas: 187653)
ERC6551Test:testOnERC1155BatchReceived() (gas: 1526548)
ERC6551Test:testOnERC1155Received() (gas: 1523904)
ERC6551Test:testOnERC721Received() (gas: 1508551)
ERC6551Test:testOnERC721ReceivedCycles() (gas: 1714607)
ERC6551Test:testOnERC721ReceivedCyclesWithDifferentChainIds(uint256) (runs: 256, μ: 449108, ~: 454591)
ERC6551Test:testOnERC721Received() (gas: 1503328)
ERC6551Test:testOnERC721ReceivedCycles() (gas: 1714290)
ERC6551Test:testOnERC721ReceivedCyclesWithDifferentChainIds(uint256) (runs: 256, μ: 449044, ~: 454558)
ERC6551Test:testSupportsInterface() (gas: 169393)
ERC6551Test:testUpgrade() (gas: 1154917)
ERC6551Test:test__codesize() (gas: 48064)
ERC6551Test:test__codesize() (gas: 48038)
ERC6909Test:testApprove() (gas: 36771)
ERC6909Test:testApprove(address,uint256,uint256) (runs: 256, μ: 36480, ~: 37413)
ERC6909Test:testBurn() (gas: 40676)
Expand Down Expand Up @@ -317,57 +317,57 @@ ERC6909Test:testTransferInsufficientBalanceReverts(address,uint256,uint256,uint2
ERC6909Test:testTransferOverMaxUintReverts() (gas: 63438)
ERC6909Test:testTransferOverMaxUintReverts(address,uint256,uint256,uint256) (runs: 256, μ: 63957, ~: 63967)
ERC6909Test:test__codesize() (gas: 26802)
ERC721HooksTest:testERC721Hooks() (gas: 2944418)
ERC721HooksTest:test__codesize() (gas: 10028)
ERC721Test:testApprove(uint256) (runs: 256, μ: 108113, ~: 108135)
ERC721Test:testApproveAll(uint256) (runs: 256, μ: 47583, ~: 40316)
ERC721Test:testApproveBurn(uint256) (runs: 256, μ: 86779, ~: 86847)
ERC721Test:testApproveNonExistentReverts(uint256,address) (runs: 256, μ: 33641, ~: 33571)
ERC721Test:testApproveUnauthorizedReverts(uint256) (runs: 256, μ: 83295, ~: 82491)
ERC721HooksTest:testERC721Hooks() (gas: 2938642)
ERC721HooksTest:test__codesize() (gas: 10002)
ERC721Test:testApprove(uint256) (runs: 256, μ: 108112, ~: 108130)
ERC721Test:testApproveAll(uint256) (runs: 256, μ: 47968, ~: 40334)
ERC721Test:testApproveBurn(uint256) (runs: 256, μ: 86804, ~: 86849)
ERC721Test:testApproveNonExistentReverts(uint256,address) (runs: 256, μ: 33638, ~: 33571)
ERC721Test:testApproveUnauthorizedReverts(uint256) (runs: 256, μ: 83347, ~: 82532)
ERC721Test:testAuthorizedEquivalence(address,bool,bool) (runs: 256, μ: 748, ~: 743)
ERC721Test:testAux(uint256) (runs: 256, μ: 191858, ~: 193040)
ERC721Test:testBurn(uint256) (runs: 256, μ: 83032, ~: 94017)
ERC721Test:testAux(uint256) (runs: 256, μ: 191930, ~: 193054)
ERC721Test:testBurn(uint256) (runs: 256, μ: 82819, ~: 93918)
ERC721Test:testBurnNonExistentReverts(uint256) (runs: 256, μ: 10783, ~: 10783)
ERC721Test:testCannotExceedMaxBalance() (gas: 169072)
ERC721Test:testDoubleBurnReverts(uint256) (runs: 256, μ: 63580, ~: 63525)
ERC721Test:testDoubleMintReverts(uint256) (runs: 256, μ: 79140, ~: 79170)
ERC721Test:testEverything(uint256) (runs: 256, μ: 311073, ~: 302034)
ERC721Test:testExtraData(uint256) (runs: 256, μ: 99095, ~: 99188)
ERC721Test:testCannotExceedMaxBalance() (gas: 169055)
ERC721Test:testDoubleBurnReverts(uint256) (runs: 256, μ: 63584, ~: 63583)
ERC721Test:testDoubleMintReverts(uint256) (runs: 256, μ: 79139, ~: 79170)
ERC721Test:testEverything(uint256) (runs: 256, μ: 314405, ~: 302356)
ERC721Test:testExtraData(uint256) (runs: 256, μ: 99112, ~: 99144)
ERC721Test:testExtraData2(uint256,uint256) (runs: 256, μ: 54285, ~: 53934)
ERC721Test:testIsApprovedOrOwner(uint256) (runs: 256, μ: 135170, ~: 135191)
ERC721Test:testMint(uint256) (runs: 256, μ: 82827, ~: 82864)
ERC721Test:testMintAndSetExtraDataUnchecked(uint256) (runs: 256, μ: 84346, ~: 84383)
ERC721Test:testMintAndSetExtraDataUncheckedWithOverwrite(uint256,uint96) (runs: 256, μ: 83609, ~: 83515)
ERC721Test:testMintToZeroReverts(uint256) (runs: 256, μ: 39209, ~: 39209)
ERC721Test:testOwnerOfNonExistent(uint256) (runs: 256, μ: 33391, ~: 33338)
ERC721Test:testSafeMintToEOA(uint256) (runs: 256, μ: 83353, ~: 83399)
ERC721Test:testSafeMintToERC721Recipient(uint256) (runs: 256, μ: 409317, ~: 410424)
ERC721Test:testSafeMintToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 470667, ~: 459930)
ERC721Test:testIsApprovedOrOwner(uint256) (runs: 256, μ: 135176, ~: 135199)
ERC721Test:testMint(uint256) (runs: 256, μ: 82829, ~: 82879)
ERC721Test:testMintAndSetExtraDataUnchecked(uint256) (runs: 256, μ: 84345, ~: 84385)
ERC721Test:testMintAndSetExtraDataUncheckedWithOverwrite(uint256,uint96) (runs: 256, μ: 83613, ~: 83670)
ERC721Test:testMintToZeroReverts(uint256) (runs: 256, μ: 39197, ~: 39197)
ERC721Test:testOwnerOfNonExistent(uint256) (runs: 256, μ: 33394, ~: 33338)
ERC721Test:testSafeMintToEOA(uint256) (runs: 256, μ: 83328, ~: 83369)
ERC721Test:testSafeMintToERC721Recipient(uint256) (runs: 256, μ: 409309, ~: 410424)
ERC721Test:testSafeMintToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 470745, ~: 460016)
ERC721Test:testSafeMintToERC721RecipientWithWrongReturnData(uint256) (runs: 256, μ: 169926, ~: 169926)
ERC721Test:testSafeMintToERC721RecipientWithWrongReturnDataWithData(uint256,bytes) (runs: 256, μ: 171141, ~: 171088)
ERC721Test:testSafeMintToNonERC721RecipientReverts(uint256) (runs: 256, μ: 100388, ~: 100388)
ERC721Test:testSafeMintToNonERC721RecipientWithDataReverts(uint256,bytes) (runs: 256, μ: 101635, ~: 101582)
ERC721Test:testSafeMintToRevertingERC721RecipientReverts(uint256) (runs: 256, μ: 203045, ~: 203045)
ERC721Test:testSafeMintToRevertingERC721RecipientWithDataReverts(uint256,bytes) (runs: 256, μ: 204281, ~: 204228)
ERC721Test:testSafeTransferFromToEOA(uint256) (runs: 256, μ: 121890, ~: 122012)
ERC721Test:testSafeTransferFromToERC721Recipient(uint256) (runs: 256, μ: 470911, ~: 472038)
ERC721Test:testSafeTransferFromToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 532336, ~: 521643)
ERC721Test:testSafeTransferFromToERC721RecipientWithWrongReturnDataReverts(uint256) (runs: 256, μ: 200879, ~: 200936)
ERC721Test:testSafeTransferFromToERC721RecipientWithWrongReturnDataWithDataReverts(uint256,bytes) (runs: 256, μ: 202120, ~: 202134)
ERC721Test:testSafeTransferFromToNonERC721RecipientReverts(uint256) (runs: 256, μ: 131286, ~: 131226)
ERC721Test:testSafeTransferFromToEOA(uint256) (runs: 256, μ: 121907, ~: 121998)
ERC721Test:testSafeTransferFromToERC721Recipient(uint256) (runs: 256, μ: 470909, ~: 472029)
ERC721Test:testSafeTransferFromToERC721RecipientWithData(uint256,bytes) (runs: 256, μ: 532319, ~: 521665)
ERC721Test:testSafeTransferFromToERC721RecipientWithWrongReturnDataReverts(uint256) (runs: 256, μ: 200869, ~: 200919)
ERC721Test:testSafeTransferFromToERC721RecipientWithWrongReturnDataWithDataReverts(uint256,bytes) (runs: 256, μ: 202108, ~: 202123)
ERC721Test:testSafeTransferFromToNonERC721RecipientReverts(uint256) (runs: 256, μ: 131276, ~: 131217)
ERC721Test:testSafeTransferFromToNonERC721RecipientWithDataReverts(uint256,bytes) (runs: 256, μ: 132589, ~: 132600)
ERC721Test:testSafeTransferFromToRevertingERC721RecipientReverts(uint256) (runs: 256, μ: 233956, ~: 234005)
ERC721Test:testSafeTransferFromToRevertingERC721RecipientWithDataReverts(uint256,bytes) (runs: 256, μ: 235254, ~: 235265)
ERC721Test:testSafeTransferFromToRevertingERC721RecipientReverts(uint256) (runs: 256, μ: 233944, ~: 233996)
ERC721Test:testSafeTransferFromToRevertingERC721RecipientWithDataReverts(uint256,bytes) (runs: 256, μ: 235253, ~: 235264)
ERC721Test:testSafetyOfCustomStorage(uint256,uint256) (runs: 256, μ: 1063, ~: 713)
ERC721Test:testTransferFrom() (gas: 85772)
ERC721Test:testTransferFrom(uint256) (runs: 256, μ: 113859, ~: 112464)
ERC721Test:testTransferFromApproveAll(uint256) (runs: 256, μ: 119319, ~: 119293)
ERC721Test:testTransferFromNotExistentReverts(address,address,uint256) (runs: 256, μ: 34037, ~: 34014)
ERC721Test:testTransferFromNotOwner(uint256) (runs: 256, μ: 84751, ~: 84719)
ERC721Test:testTransferFromSelf(uint256) (runs: 256, μ: 92708, ~: 92697)
ERC721Test:testTransferFromToZeroReverts(uint256) (runs: 256, μ: 79080, ~: 79051)
ERC721Test:testTransferFromWrongFromReverts(address,uint256) (runs: 256, μ: 80444, ~: 80446)
ERC721Test:test__codesize() (gas: 43715)
ERC721Test:testTransferFrom() (gas: 85763)
ERC721Test:testTransferFrom(uint256) (runs: 256, μ: 113797, ~: 112450)
ERC721Test:testTransferFromApproveAll(uint256) (runs: 256, μ: 119282, ~: 119257)
ERC721Test:testTransferFromNotExistentReverts(address,address,uint256) (runs: 256, μ: 34047, ~: 34014)
ERC721Test:testTransferFromNotOwner(uint256) (runs: 256, μ: 84732, ~: 84702)
ERC721Test:testTransferFromSelf(uint256) (runs: 256, μ: 92705, ~: 92688)
ERC721Test:testTransferFromToZeroReverts(uint256) (runs: 256, μ: 62792, ~: 62791)
ERC721Test:testTransferFromWrongFromReverts(address,uint256) (runs: 256, μ: 80442, ~: 80450)
ERC721Test:test__codesize() (gas: 43689)
FixedPointMathLibTest:testAbs() (gas: 578)
FixedPointMathLibTest:testAbs(int256) (runs: 256, μ: 516, ~: 485)
FixedPointMathLibTest:testAbsEdgeCases() (gas: 410)
Expand Down Expand Up @@ -918,7 +918,7 @@ OwnableTest:test__codesize() (gas: 12253)
ReceiverTest:testETHReceived() (gas: 9621)
ReceiverTest:testOnERC1155BatchReceived() (gas: 48975)
ReceiverTest:testOnERC1155Received() (gas: 46717)
ReceiverTest:testOnERC721Received() (gas: 64136)
ReceiverTest:testOnERC721Received() (gas: 64127)
ReceiverTest:test__codesize() (gas: 3310)
RedBlackTreeLibTest:testRedBlackTreeBenchUint160() (gas: 3433600)
RedBlackTreeLibTest:testRedBlackTreeBenchUint256() (gas: 5847065)
Expand Down
30 changes: 12 additions & 18 deletions src/tokens/ERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,6 @@ abstract contract ERC721 {
mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
revert(0x1c, 0x04)
}
// Revert if `to` is the zero address.
if iszero(to) {
mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
revert(0x1c, 0x04)
}
// Load, check, and update the token approval.
{
mstore(0x00, from)
Expand All @@ -303,8 +298,10 @@ abstract contract ERC721 {
mstore(0x00, to)
let toBalanceSlot := keccak256(0x0c, 0x1c)
let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
// Revert if `to` is the zero address, or if the account balance overflows.
if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
// `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
mstore(shl(2, iszero(to)), 0xea553b3401336cea)
revert(0x1c, 0x04)
}
sstore(toBalanceSlot, toBalanceSlotPacked)
Expand Down Expand Up @@ -476,8 +473,8 @@ abstract contract ERC721 {
// Revert if `to` is the zero address, or if the account balance overflows.
if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
// `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
mstore(0x00, 0xea553b3401336cea)
revert(xor(0x1c, shl(2, iszero(to))), 0x04)
mstore(shl(2, iszero(to)), 0xea553b3401336cea)
revert(0x1c, 0x04)
}
sstore(balanceSlot, balanceSlotPacked)
}
Expand Down Expand Up @@ -513,8 +510,8 @@ abstract contract ERC721 {
// Revert if `to` is the zero address, or if the account balance overflows.
if iszero(mul(to, and(balanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
// `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
mstore(0x00, 0xea553b3401336cea)
revert(xor(0x1c, shl(2, iszero(to))), 0x04)
mstore(shl(2, iszero(to)), 0xea553b3401336cea)
revert(0x1c, 0x04)
}
sstore(balanceSlot, balanceSlotPacked)
}
Expand Down Expand Up @@ -771,11 +768,6 @@ abstract contract ERC721 {
mstore(0x00, 0xa1148100) // `TransferFromIncorrectOwner()`.
revert(0x1c, 0x04)
}
// Revert if `to` is the zero address.
if iszero(to) {
mstore(0x00, 0xea553b34) // `TransferToZeroAddress()`.
revert(0x1c, 0x04)
}
// Load, check, and update the token approval.
{
mstore(0x00, from)
Expand Down Expand Up @@ -803,8 +795,10 @@ abstract contract ERC721 {
mstore(0x00, to)
let toBalanceSlot := keccak256(0x0c, 0x1c)
let toBalanceSlotPacked := add(sload(toBalanceSlot), 1)
if iszero(and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE)) {
mstore(0x00, 0x01336cea) // `AccountBalanceOverflow()`.
// Revert if `to` is the zero address, or if the account balance overflows.
if iszero(mul(to, and(toBalanceSlotPacked, _MAX_ACCOUNT_BALANCE))) {
// `TransferToZeroAddress()`, `AccountBalanceOverflow()`.
mstore(shl(2, iszero(to)), 0xea553b3401336cea)
revert(0x1c, 0x04)
}
sstore(toBalanceSlot, toBalanceSlotPacked)
Expand Down

0 comments on commit 18adf11

Please sign in to comment.