From eea0b64ffb42962837a56ec6bca964a1f4c46bc6 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Fri, 20 Oct 2023 02:32:42 +0000 Subject: [PATCH 1/6] Copy docs template --- .gas-snapshot | 90 ++-- docs/.nojekyll | 0 docs/assets/css/prism-theme.css | 149 ++++++ docs/assets/fontello/LICENSE.txt | 21 + docs/assets/fontello/README.txt | 75 +++ docs/assets/fontello/css/fontello.css | 61 +++ docs/assets/fontello/font/fontello.eot | Bin 0 -> 7404 bytes docs/assets/fontello/font/fontello.svg | 20 + docs/assets/fontello/font/fontello.ttf | Bin 0 -> 7236 bytes docs/assets/fontello/font/fontello.woff | Bin 0 -> 4316 bytes docs/assets/fontello/font/fontello.woff2 | Bin 0 -> 3576 bytes docs/assets/img/favicon.png | Bin 0 -> 1833 bytes docs/assets/img/preview.png | Bin 0 -> 11624 bytes docs/design.md | 85 +++ docs/erc4907a.md | 77 +++ docs/erc721a-burnable.md | 25 + docs/erc721a-queryable.md | 89 ++++ docs/erc721a.md | 629 +++++++++++++++++++++++ docs/index.html | 333 ++++++++++++ docs/interfaces.md | 58 +++ docs/migration.md | 87 ++++ docs/overview.md | 35 ++ docs/sidebar.md | 33 ++ docs/tips.md | 90 ++++ docs/upgradeable.md | 209 ++++++++ 25 files changed, 2121 insertions(+), 45 deletions(-) create mode 100644 docs/.nojekyll create mode 100644 docs/assets/css/prism-theme.css create mode 100755 docs/assets/fontello/LICENSE.txt create mode 100755 docs/assets/fontello/README.txt create mode 100755 docs/assets/fontello/css/fontello.css create mode 100755 docs/assets/fontello/font/fontello.eot create mode 100755 docs/assets/fontello/font/fontello.svg create mode 100755 docs/assets/fontello/font/fontello.ttf create mode 100755 docs/assets/fontello/font/fontello.woff create mode 100755 docs/assets/fontello/font/fontello.woff2 create mode 100644 docs/assets/img/favicon.png create mode 100644 docs/assets/img/preview.png create mode 100644 docs/design.md create mode 100644 docs/erc4907a.md create mode 100644 docs/erc721a-burnable.md create mode 100644 docs/erc721a-queryable.md create mode 100644 docs/erc721a.md create mode 100644 docs/index.html create mode 100644 docs/interfaces.md create mode 100644 docs/migration.md create mode 100644 docs/overview.md create mode 100644 docs/sidebar.md create mode 100644 docs/tips.md create mode 100644 docs/upgradeable.md diff --git a/.gas-snapshot b/.gas-snapshot index 64f9ac7e4..8b083c30f 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -136,7 +136,7 @@ ERC1155Test:testBatchBurn(uint256) (runs: 256, μ: 173689, ~: 159422) ERC1155Test:testBatchBurnInsufficientBalanceReverts(uint256) (runs: 256, μ: 167264, ~: 173551) ERC1155Test:testBatchBurnWithArrayLengthMismatchReverts(uint256) (runs: 256, μ: 43100, ~: 42515) ERC1155Test:testBatchMintToEOA(uint256) (runs: 256, μ: 122095, ~: 100127) -ERC1155Test:testBatchMintToERC1155Recipient(uint256) (runs: 256, μ: 781590, ~: 778552) +ERC1155Test:testBatchMintToERC1155Recipient(uint256) (runs: 256, μ: 781517, ~: 778869) ERC1155Test:testBatchMintToNonERC1155RecipientReverts(uint256) (runs: 256, μ: 172187, ~: 185725) ERC1155Test:testBatchMintToRevertingERC1155RecipientReverts(uint256) (runs: 256, μ: 326907, ~: 315897) ERC1155Test:testBatchMintToWrongReturnDataERC1155RecipientReverts(uint256) (runs: 256, μ: 298286, ~: 318698) @@ -173,10 +173,10 @@ ERC1155Test:test__codesize() (gas: 43475) ERC1967FactoryTest:testChangeAdmin() (gas: 266356) ERC1967FactoryTest:testChangeAdminUnauthorized() (gas: 257236) ERC1967FactoryTest:testDeploy() (gas: 257363) -ERC1967FactoryTest:testDeployAndCall(uint256) (runs: 256, μ: 339480, ~: 340789) +ERC1967FactoryTest:testDeployAndCall(uint256) (runs: 256, μ: 339133, ~: 340775) ERC1967FactoryTest:testDeployAndCallWithRevert() (gas: 211881) -ERC1967FactoryTest:testDeployBrutalized(uint256) (runs: 256, μ: 116831, ~: 44136) -ERC1967FactoryTest:testDeployDeterministicAndCall(uint256) (runs: 256, μ: 311706, ~: 350118) +ERC1967FactoryTest:testDeployBrutalized(uint256) (runs: 256, μ: 117632, ~: 44127) +ERC1967FactoryTest:testDeployDeterministicAndCall(uint256) (runs: 256, μ: 315490, ~: 350119) ERC1967FactoryTest:testFactoryDeployment() (gas: 995063) ERC1967FactoryTest:testProxyFails() (gas: 259019) ERC1967FactoryTest:testProxySucceeds() (gas: 255707) @@ -186,7 +186,7 @@ ERC1967FactoryTest:testUpgradeAndCallWithRevert() (gas: 265645) ERC1967FactoryTest:testUpgradeUnauthorized() (gas: 270260) ERC1967FactoryTest:testUpgradeWithCorruptedProxy() (gas: 263163) ERC1967FactoryTest:test__codesize() (gas: 33963) -ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2422) +ERC20Invariants:invariantBalanceSum() (runs: 256, calls: 3840, reverts: 2409) ERC20Invariants:test__codesize() (gas: 7967) ERC20Test:testApprove() (gas: 35730) ERC20Test:testApprove(address,uint256) (runs: 256, μ: 30325, ~: 31181) @@ -221,20 +221,20 @@ ERC2981Test:testRoyaltyOverflowCheckDifferential(uint256,uint256) (runs: 256, μ ERC2981Test:testSetAndGetRoyaltyInfo(uint256) (runs: 256, μ: 107629, ~: 104801) ERC2981Test:test__codesize() (gas: 8419) ERC4337FactoryTest:testDeploy() (gas: 112614) -ERC4337FactoryTest:testDeploy(uint256) (runs: 256, μ: 135779, ~: 135788) -ERC4337FactoryTest:testDeployDeterministic(uint256) (runs: 256, μ: 131456, ~: 137158) +ERC4337FactoryTest:testDeploy(uint256) (runs: 256, μ: 135787, ~: 135788) +ERC4337FactoryTest:testDeployDeterministic(uint256) (runs: 256, μ: 132199, ~: 137159) ERC4337FactoryTest:testDeployDeterministicRevertWithDeploymentFailed() (gas: 96883638) ERC4337FactoryTest:test__codesize() (gas: 11125) ERC4337Test:testCdFallback() (gas: 1178533) ERC4337Test:testDelegateExecute() (gas: 370255) -ERC4337Test:testDelegateExecute(uint256) (runs: 256, μ: 358386, ~: 343833) +ERC4337Test:testDelegateExecute(uint256) (runs: 256, μ: 357716, ~: 343833) ERC4337Test:testDelegateExecuteRevertsIfOwnerSlotValueChanged() (gas: 318630) ERC4337Test:testDepositFunctions() (gas: 502817) ERC4337Test:testDirectStorage() (gas: 70481) ERC4337Test:testETHReceived() (gas: 16606) ERC4337Test:testExecute() (gas: 382275) ERC4337Test:testExecuteBatch() (gas: 691377) -ERC4337Test:testExecuteBatch(uint256) (runs: 256, μ: 518275, ~: 367593) +ERC4337Test:testExecuteBatch(uint256) (runs: 256, μ: 528699, ~: 377702) ERC4337Test:testInitializer() (gas: 285354) ERC4337Test:testIsValidSignature() (gas: 66112) ERC4337Test:testIsValidSignatureWrapped() (gas: 388468) @@ -245,14 +245,14 @@ ERC4337Test:testValidateUserOp() (gas: 491274) ERC4337Test:test__codesize() (gas: 46432) ERC4626Test:testDepositWithNoApprovalReverts() (gas: 16371) ERC4626Test:testDepositWithNotEnoughApprovalReverts() (gas: 89884) -ERC4626Test:testDifferentialFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 3337, ~: 3201) +ERC4626Test:testDifferentialFullMulDiv(uint256,uint256,uint256) (runs: 256, μ: 3336, ~: 3201) ERC4626Test:testMetadata() (gas: 15439) ERC4626Test:testMintWithNoApprovalReverts() (gas: 16345) ERC4626Test:testMintZero() (gas: 54317) ERC4626Test:testMultipleMintDepositRedeemWithdraw() (gas: 425667) ERC4626Test:testRedeemWithNoShareAmountReverts() (gas: 10918) ERC4626Test:testRedeemWithNotEnoughShareAmountReverts() (gas: 142915) -ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 202684, ~: 202694) +ERC4626Test:testSingleDepositWithdraw(uint128) (runs: 256, μ: 202683, ~: 202694) ERC4626Test:testSingleMintRedeem(uint128) (runs: 256, μ: 201604, ~: 201615) ERC4626Test:testTryGetAssetDecimals() (gas: 30483816) ERC4626Test:testUseVirtualShares() (gas: 2441768) @@ -263,12 +263,12 @@ ERC4626Test:testWithdrawWithNotEnoughUnderlyingAmountReverts() (gas: 144082) ERC4626Test:testWithdrawZero() (gas: 52807) ERC4626Test:test__codesize() (gas: 41069) ERC6551Test:testCdFallback() (gas: 914683) -ERC6551Test:testDeployERC6551(uint256) (runs: 256, μ: 192573, ~: 190183) +ERC6551Test:testDeployERC6551(uint256) (runs: 256, μ: 192907, ~: 190191) ERC6551Test:testDeployERC6551Proxy() (gas: 90053) ERC6551Test:testERC6551ProxyDefaultAddressTrick(uint256,uint256) (runs: 256, μ: 475, ~: 475) ERC6551Test:testExecute() (gas: 529002) ERC6551Test:testExecuteBatch() (gas: 837345) -ERC6551Test:testExecuteBatch(uint256) (runs: 256, μ: 622076, ~: 503770) +ERC6551Test:testExecuteBatch(uint256) (runs: 256, μ: 632714, ~: 503844) ERC6551Test:testIsValidSignature() (gas: 207329) ERC6551Test:testOnERC1155BatchReceived() (gas: 1547958) ERC6551Test:testOnERC1155Received() (gas: 1545111) @@ -508,7 +508,7 @@ LibBitTest:test__codesize() (gas: 6036) LibBitmapTest:testBitmapClaimWithGetSet() (gas: 27089) LibBitmapTest:testBitmapClaimWithToggle() (gas: 17479) LibBitmapTest:testBitmapFindLastSet() (gas: 1308941) -LibBitmapTest:testBitmapFindLastSet(uint256,uint256) (runs: 256, μ: 75849, ~: 76061) +LibBitmapTest:testBitmapFindLastSet(uint256,uint256) (runs: 256, μ: 76021, ~: 76084) LibBitmapTest:testBitmapGet() (gas: 2565) LibBitmapTest:testBitmapGet(uint256) (runs: 256, μ: 2593, ~: 2593) LibBitmapTest:testBitmapPopCount() (gas: 750426) @@ -673,7 +673,7 @@ LibStringTest:testFromAddressToHexString() (gas: 3774) LibStringTest:testFromAddressToHexStringChecksummed() (gas: 40448) LibStringTest:testFromAddressToHexStringChecksummedDifferential(uint256) (runs: 256, μ: 799933, ~: 629103) LibStringTest:testFromAddressToHexStringWithLeadingZeros() (gas: 3795) -LibStringTest:testHexStringNoPrefixVariants(uint256,uint256) (runs: 256, μ: 739125, ~: 639621) +LibStringTest:testHexStringNoPrefixVariants(uint256,uint256) (runs: 256, μ: 739141, ~: 639621) LibStringTest:testStringConcat() (gas: 7385) LibStringTest:testStringConcat(string,string) (runs: 256, μ: 760619, ~: 620958) LibStringTest:testStringConcatOriginal() (gas: 8045) @@ -726,7 +726,7 @@ LibStringTest:testToHexStringFixedLengthInsufficientLength() (gas: 3344) LibStringTest:testToHexStringFixedLengthPositiveNumberLong() (gas: 4454) LibStringTest:testToHexStringFixedLengthPositiveNumberShort() (gas: 1459) LibStringTest:testToHexStringFixedLengthUint256Max() (gas: 4478) -LibStringTest:testToHexStringFixedLengthZeroRightPadded(uint256,uint256) (runs: 256, μ: 8217, ~: 4985) +LibStringTest:testToHexStringFixedLengthZeroRightPadded(uint256,uint256) (runs: 256, μ: 8213, ~: 4985) LibStringTest:testToHexStringPositiveNumber() (gas: 1407) LibStringTest:testToHexStringUint256Max() (gas: 4219) LibStringTest:testToHexStringZero() (gas: 1302) @@ -822,7 +822,7 @@ OwnableRolesTest:testHasAnyRole(address,uint256,uint256) (runs: 256, μ: 32399, OwnableRolesTest:testInitializeOwnerDirect() (gas: 16724) OwnableRolesTest:testOnlyOwnerModifier(address,bool) (runs: 256, μ: 17702, ~: 11530) OwnableRolesTest:testOnlyOwnerOrRolesModifier() (gas: 36582) -OwnableRolesTest:testOnlyOwnerOrRolesModifier(address,bool,uint256,uint256) (runs: 256, μ: 54772, ~: 58495) +OwnableRolesTest:testOnlyOwnerOrRolesModifier(address,bool,uint256,uint256) (runs: 256, μ: 54687, ~: 58495) OwnableRolesTest:testOnlyRolesModifier(address,uint256,uint256) (runs: 256, μ: 52985, ~: 57912) OwnableRolesTest:testOnlyRolesOrOwnerModifier(address,bool,uint256,uint256) (runs: 256, μ: 55470, ~: 58382) OwnableRolesTest:testOrdinalsFromRoles() (gas: 3610415) @@ -908,16 +908,16 @@ SafeCastLibTest:testSafeCastToUint(uint256) (runs: 256, μ: 4134, ~: 3351) SafeCastLibTest:testSafeCastToUint256(int256) (runs: 256, μ: 1308, ~: 432) SafeCastLibTest:testSafeCastToUintBench() (gas: 326306) SafeCastLibTest:test__codesize() (gas: 16001) -SafeTransferLibTest:testApproveWithGarbageReverts(address,uint256) (runs: 256, μ: 108492, ~: 123373) +SafeTransferLibTest:testApproveWithGarbageReverts(address,uint256) (runs: 256, μ: 107976, ~: 123373) SafeTransferLibTest:testApproveWithMissingReturn() (gas: 31945) SafeTransferLibTest:testApproveWithMissingReturn(address,uint256) (runs: 256, μ: 31248, ~: 32104) SafeTransferLibTest:testApproveWithNonContract() (gas: 2989) -SafeTransferLibTest:testApproveWithNonContract(address,address,uint256) (runs: 256, μ: 3511, ~: 3536) -SafeTransferLibTest:testApproveWithNonGarbage(address,uint256) (runs: 256, μ: 79482, ~: 70402) +SafeTransferLibTest:testApproveWithNonContract(address,address,uint256) (runs: 256, μ: 3523, ~: 3536) +SafeTransferLibTest:testApproveWithNonGarbage(address,uint256) (runs: 256, μ: 78318, ~: 59187) SafeTransferLibTest:testApproveWithRetry() (gas: 768379) SafeTransferLibTest:testApproveWithRetry(address,uint256,uint256) (runs: 256, μ: 766824, ~: 768523) SafeTransferLibTest:testApproveWithRetryWithNonContract() (gas: 2990) -SafeTransferLibTest:testApproveWithRetryWithNonContract(address,address,uint256) (runs: 256, μ: 3508, ~: 3533) +SafeTransferLibTest:testApproveWithRetryWithNonContract(address,address,uint256) (runs: 256, μ: 3520, ~: 3533) SafeTransferLibTest:testApproveWithReturnsFalseReverts() (gas: 9515) SafeTransferLibTest:testApproveWithReturnsFalseReverts(address,uint256) (runs: 256, μ: 9652, ~: 9652) SafeTransferLibTest:testApproveWithReturnsTooLittleReverts() (gas: 9419) @@ -932,60 +932,60 @@ SafeTransferLibTest:testApproveWithStandardERC20(address,uint256) (runs: 256, μ SafeTransferLibTest:testBalanceOfStandardERC20() (gas: 7830) SafeTransferLibTest:testBalanceOfStandardERC20(address,uint256) (runs: 256, μ: 39521, ~: 40437) SafeTransferLibTest:testForceTransferETHToGriever() (gas: 1511304) -SafeTransferLibTest:testForceTransferETHToGriever(uint256,uint256) (runs: 256, μ: 533463, ~: 570828) +SafeTransferLibTest:testForceTransferETHToGriever(uint256,uint256) (runs: 256, μ: 531936, ~: 570828) SafeTransferLibTest:testTransferAllETH() (gas: 34598) SafeTransferLibTest:testTransferAllETH(address) (runs: 256, μ: 34883, ~: 35018) SafeTransferLibTest:testTransferAllETHToContractWithoutFallbackReverts() (gas: 10788) SafeTransferLibTest:testTransferAllETHToContractWithoutFallbackReverts(uint256) (runs: 256, μ: 10898, ~: 10898) SafeTransferLibTest:testTransferAllFromWithStandardERC20() (gas: 33092) -SafeTransferLibTest:testTransferAllFromWithStandardERC20(address,address,uint256) (runs: 256, μ: 56508, ~: 56508) +SafeTransferLibTest:testTransferAllFromWithStandardERC20(address,address,uint256) (runs: 256, μ: 56506, ~: 56508) SafeTransferLibTest:testTransferAllWithStandardERC20() (gas: 30735) SafeTransferLibTest:testTransferAllWithStandardERC20(address,uint256) (runs: 256, μ: 42114, ~: 42114) SafeTransferLibTest:testTransferETH() (gas: 34600) -SafeTransferLibTest:testTransferETH(address,uint256) (runs: 256, μ: 33823, ~: 35250) +SafeTransferLibTest:testTransferETH(address,uint256) (runs: 256, μ: 33948, ~: 35250) SafeTransferLibTest:testTransferETHToContractWithoutFallbackReverts() (gas: 10846) SafeTransferLibTest:testTransferETHToContractWithoutFallbackReverts(uint256) (runs: 256, μ: 10545, ~: 10928) -SafeTransferLibTest:testTransferFromWithGarbageReverts(address,address,uint256) (runs: 256, μ: 883364, ~: 783183) +SafeTransferLibTest:testTransferFromWithGarbageReverts(address,address,uint256) (runs: 256, μ: 832038, ~: 782175) SafeTransferLibTest:testTransferFromWithMissingReturn() (gas: 669607) -SafeTransferLibTest:testTransferFromWithMissingReturn(address,address,uint256) (runs: 256, μ: 758369, ~: 669056) +SafeTransferLibTest:testTransferFromWithMissingReturn(address,address,uint256) (runs: 256, μ: 763920, ~: 669110) SafeTransferLibTest:testTransferFromWithNonContract() (gas: 3022) SafeTransferLibTest:testTransferFromWithNonContract(address,address,address,uint256) (runs: 256, μ: 3658, ~: 3694) -SafeTransferLibTest:testTransferFromWithNonGarbage(address,address,uint256) (runs: 256, μ: 822858, ~: 718150) +SafeTransferLibTest:testTransferFromWithNonGarbage(address,address,uint256) (runs: 256, μ: 823288, ~: 719115) SafeTransferLibTest:testTransferFromWithReturnsFalseReverts() (gas: 634463) -SafeTransferLibTest:testTransferFromWithReturnsFalseReverts(address,address,uint256) (runs: 256, μ: 753021, ~: 634883) +SafeTransferLibTest:testTransferFromWithReturnsFalseReverts(address,address,uint256) (runs: 256, μ: 761487, ~: 634883) SafeTransferLibTest:testTransferFromWithReturnsTooLittleReverts() (gas: 634672) -SafeTransferLibTest:testTransferFromWithReturnsTooLittleReverts(address,address,uint256) (runs: 256, μ: 767198, ~: 634825) +SafeTransferLibTest:testTransferFromWithReturnsTooLittleReverts(address,address,uint256) (runs: 256, μ: 762070, ~: 634783) SafeTransferLibTest:testTransferFromWithReturnsTooMuch() (gas: 669442) -SafeTransferLibTest:testTransferFromWithReturnsTooMuch(address,address,uint256) (runs: 256, μ: 757060, ~: 669946) -SafeTransferLibTest:testTransferFromWithReturnsTwoReverts(address,address,uint256) (runs: 256, μ: 737951, ~: 634821) +SafeTransferLibTest:testTransferFromWithReturnsTooMuch(address,address,uint256) (runs: 256, μ: 748839, ~: 669956) +SafeTransferLibTest:testTransferFromWithReturnsTwoReverts(address,address,uint256) (runs: 256, μ: 757324, ~: 634809) SafeTransferLibTest:testTransferFromWithRevertingReverts() (gas: 628282) -SafeTransferLibTest:testTransferFromWithRevertingReverts(address,address,uint256) (runs: 256, μ: 741687, ~: 628268) +SafeTransferLibTest:testTransferFromWithRevertingReverts(address,address,uint256) (runs: 256, μ: 741315, ~: 628256) SafeTransferLibTest:testTransferFromWithStandardERC20() (gas: 667145) -SafeTransferLibTest:testTransferFromWithStandardERC20(address,address,uint256) (runs: 256, μ: 766228, ~: 666815) -SafeTransferLibTest:testTransferWithGarbageReverts(address,uint256) (runs: 256, μ: 806596, ~: 747147) +SafeTransferLibTest:testTransferFromWithStandardERC20(address,address,uint256) (runs: 256, μ: 733265, ~: 666841) +SafeTransferLibTest:testTransferWithGarbageReverts(address,uint256) (runs: 256, μ: 821926, ~: 746972) SafeTransferLibTest:testTransferWithMissingReturn() (gas: 655022) -SafeTransferLibTest:testTransferWithMissingReturn(address,uint256) (runs: 256, μ: 738122, ~: 655637) +SafeTransferLibTest:testTransferWithMissingReturn(address,uint256) (runs: 256, μ: 740730, ~: 655637) SafeTransferLibTest:testTransferWithNonContract() (gas: 2988) -SafeTransferLibTest:testTransferWithNonContract(address,address,uint256) (runs: 256, μ: 3532, ~: 3557) -SafeTransferLibTest:testTransferWithNonGarbage(address,uint256) (runs: 256, μ: 778913, ~: 683114) +SafeTransferLibTest:testTransferWithNonContract(address,address,uint256) (runs: 256, μ: 3544, ~: 3557) +SafeTransferLibTest:testTransferWithNonGarbage(address,uint256) (runs: 256, μ: 800535, ~: 701918) SafeTransferLibTest:testTransferWithReturnsFalseReverts() (gas: 631527) -SafeTransferLibTest:testTransferWithReturnsFalseReverts(address,uint256) (runs: 256, μ: 812981, ~: 632024) +SafeTransferLibTest:testTransferWithReturnsFalseReverts(address,uint256) (runs: 256, μ: 789424, ~: 632024) SafeTransferLibTest:testTransferWithReturnsTooLittleReverts() (gas: 632163) -SafeTransferLibTest:testTransferWithReturnsTooLittleReverts(address,uint256) (runs: 256, μ: 754644, ~: 631923) +SafeTransferLibTest:testTransferWithReturnsTooLittleReverts(address,uint256) (runs: 256, μ: 750545, ~: 631923) SafeTransferLibTest:testTransferWithReturnsTooMuch() (gas: 655448) -SafeTransferLibTest:testTransferWithReturnsTooMuch(address,uint256) (runs: 256, μ: 797020, ~: 655984) -SafeTransferLibTest:testTransferWithReturnsTwoReverts(address,uint256) (runs: 256, μ: 729115, ~: 631933) +SafeTransferLibTest:testTransferWithReturnsTooMuch(address,uint256) (runs: 256, μ: 794409, ~: 656050) +SafeTransferLibTest:testTransferWithReturnsTwoReverts(address,uint256) (runs: 256, μ: 759370, ~: 631933) SafeTransferLibTest:testTransferWithRevertingReverts() (gas: 631462) -SafeTransferLibTest:testTransferWithRevertingReverts(address,uint256) (runs: 256, μ: 735788, ~: 631957) +SafeTransferLibTest:testTransferWithRevertingReverts(address,uint256) (runs: 256, μ: 730332, ~: 631957) SafeTransferLibTest:testTransferWithStandardERC20() (gas: 656029) -SafeTransferLibTest:testTransferWithStandardERC20(address,uint256) (runs: 256, μ: 719429, ~: 655769) +SafeTransferLibTest:testTransferWithStandardERC20(address,uint256) (runs: 256, μ: 730018, ~: 655790) SafeTransferLibTest:testTryTransferAllETH() (gas: 148698) SafeTransferLibTest:testTryTransferETH() (gas: 148745) SafeTransferLibTest:testTryTransferETHWithNoGrief() (gas: 537083) SafeTransferLibTest:testTryTransferETHWithNoStorageWrites() (gas: 192518) SafeTransferLibTest:test__codesize() (gas: 37503) SignatureCheckerLibTest:testEmptyCalldataHelpers() (gas: 3919) -SignatureCheckerLibTest:testSignatureChecker(bytes32) (runs: 256, μ: 55288, ~: 46921) +SignatureCheckerLibTest:testSignatureChecker(bytes32) (runs: 256, μ: 54924, ~: 46848) SignatureCheckerLibTest:testSignatureCheckerOnEOAWithInvalidSignature() (gas: 21179) SignatureCheckerLibTest:testSignatureCheckerOnEOAWithInvalidSigner() (gas: 30679) SignatureCheckerLibTest:testSignatureCheckerOnEOAWithMatchingSignerAndSignature() (gas: 17621) @@ -1009,7 +1009,7 @@ UUPSUpgradeableTest:testUpgradeToAndCallRevertWithUpgradeFailed() (gas: 18272) UUPSUpgradeableTest:testUpgradeToRevertWithUnauthorized() (gas: 15651) UUPSUpgradeableTest:testUpgradeToRevertWithUpgradeFailed() (gas: 17947) UUPSUpgradeableTest:test__codesize() (gas: 6149) -WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 256, calls: 3840, reverts: 1809) +WETHInvariants:invariantTotalSupplyEqualsBalance() (runs: 256, calls: 3840, reverts: 1813) WETHInvariants:test__codesize() (gas: 6007) WETHTest:testDeposit() (gas: 68090) WETHTest:testDeposit(uint256) (runs: 256, μ: 65720, ~: 68384) diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/docs/assets/css/prism-theme.css b/docs/assets/css/prism-theme.css new file mode 100644 index 000000000..eec36df19 --- /dev/null +++ b/docs/assets/css/prism-theme.css @@ -0,0 +1,149 @@ +/* Generated with http://k88hudson.github.io/syntax-highlighting-theme-generator/www */ +/* http://k88hudson.github.io/react-markdocs */ +/** + * @author k88hudson + * + * Based on prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +/********************************************************* +* General +*/ +pre[class*="language-"], +code[class*="language-"] { + color: #555; + font-size: 13px; + text-shadow: none; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} +pre[class*="language-"]::selection, +code[class*="language-"]::selection, +pre[class*="language-"]::mozselection, +code[class*="language-"]::mozselection { + text-shadow: none; + background: #bbb; +} +@media print { + pre[class*="language-"], + code[class*="language-"] { + text-shadow: none; + } +} +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; + background: #f2f2f2; +} +:not(pre) > code[class*="language-"] { + padding: .1em .3em; + border-radius: .3em; + color: #db4c69; + background: #f9f2f4; +} +/********************************************************* +* Tokens +*/ +.namespace { + opacity: .7; +} +.token.keyword, +.token.comment { + font-style: italic; +} +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #888; + color: rgba(0,0,0,0.45); +} +.token.punctuation { + color: #666; +} +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #598; +} +.token.selector, +.token.attr-name, +.token.builtin, +.token.inserted { + color: #853; +} +.token.char, +.token.string { + color: #763; +} +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #788; + background: #f2f2f2; +} +.token.atrule, +.token.attr-value, +.token.keyword { + color: #369; +} +.token.function { + color: #345; +} +.token.regex, +.token.important, +.token.variable { + color: #598; +} +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} +.token.entity { + cursor: help; +} +/********************************************************* +* Line highlighting +*/ +pre[data-line] { + position: relative; +} +pre[class*="language-"] > code[class*="language-"] { + position: relative; + z-index: 1; +} +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; + background: #f7ebc6; + box-shadow: inset 5px 0 0 #f7d87c; + z-index: 0; + pointer-events: none; + line-height: inherit; + white-space: pre; +} diff --git a/docs/assets/fontello/LICENSE.txt b/docs/assets/fontello/LICENSE.txt new file mode 100755 index 000000000..042245e12 --- /dev/null +++ b/docs/assets/fontello/LICENSE.txt @@ -0,0 +1,21 @@ +Font license info + + +## Meteocons + + Copyright (C) 2012 by Alessio Atzeni + + Author: Alessio Atzeni + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.alessioatzeni.com + + +## Font Awesome + + Copyright (C) 2016 by Dave Gandy + + Author: Dave Gandy + License: SIL () + Homepage: http://fortawesome.github.com/Font-Awesome/ + + diff --git a/docs/assets/fontello/README.txt b/docs/assets/fontello/README.txt new file mode 100755 index 000000000..d870892e3 --- /dev/null +++ b/docs/assets/fontello/README.txt @@ -0,0 +1,75 @@ +This webfont is generated by https://fontello.com open source project. + + +================================================================================ +Please, note, that you should obey original font licenses, used to make this +webfont pack. Details available in LICENSE.txt file. + +- Usually, it's enough to publish content of LICENSE.txt file somewhere on your + site in "About" section. + +- If your project is open-source, usually, it will be ok to make LICENSE.txt + file publicly available in your repository. + +- Fonts, used in Fontello, don't require a clickable link on your site. + But any kind of additional authors crediting is welcome. +================================================================================ + + +Comments on archive content +--------------------------- + +- /font/* - fonts in different formats + +- /css/* - different kinds of css, for all situations. Should be ok with + twitter bootstrap. Also, you can skip style and assign icon classes + directly to text elements, if you don't mind about IE7. + +- demo.html - demo file, to show your webfont content + +- LICENSE.txt - license info about source fonts, used to build your one. + +- config.json - keeps your settings. You can import it back into fontello + anytime, to continue your work + + +Why so many CSS files ? +----------------------- + +Because we like to fit all your needs :) + +- basic file, .css - is usually enough, it contains @font-face + and character code definitions + +- *-ie7.css - if you need IE7 support, but still don't wish to put char codes + directly into html + +- *-codes.css and *-ie7-codes.css - if you like to use your own @font-face + rules, but still wish to benefit from css generation. That can be very + convenient for automated asset build systems. When you need to update font - + no need to manually edit files, just override old version with archive + content. See fontello source code for examples. + +- *-embedded.css - basic css file, but with embedded WOFF font, to avoid + CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. + We strongly recommend to resolve this issue by `Access-Control-Allow-Origin` + server headers. But if you ok with dirty hack - this file is for you. Note, + that data url moved to separate @font-face to avoid problems with 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 + + +Copyright (C) 2023 by original authors @ fontello.com + + + + + + + + + + + + + + + + diff --git a/docs/assets/fontello/font/fontello.ttf b/docs/assets/fontello/font/fontello.ttf new file mode 100755 index 0000000000000000000000000000000000000000..ebdf162eb0bcaf33027e9876938c4245c4fe509c GIT binary patch literal 7236 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 literal 0 HcmV?d00001 diff --git a/docs/assets/fontello/font/fontello.woff2 b/docs/assets/fontello/font/fontello.woff2 new file mode 100755 index 0000000000000000000000000000000000000000..004098955b4533f3f3ed40dde7946753ef595b21 GIT binary patch literal 3576 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 literal 0 HcmV?d00001 diff --git a/docs/assets/img/favicon.png b/docs/assets/img/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..5ce0402cd78627280f4bb87ffebad02e66a086e6 GIT binary patch literal 1833 zcmV+^2iEwBP)i00004XF*Lt006O% z3;baP00001b5ch_0Itp)=>Px#El^BUMMrQ<`T6<(|NsC0|NsC0larJG|NsC0{{R30 zDJd!4-Q81DQ@gvnczAf3nVFc0wEqAA00(qZPE!Euph+3VZ32jV>Hq)+herQY39s>-#TzOCY09=ufWwj?lR*{M) zP5CN`8#O`?s;{One+&k{x&hE}gM{i|V$9KE?W@p~a%`&ErJ3l_T>(vOuzx(93 zpP6<1Kmsg)zq3Hz{|#C%2cbGs4~@CwaUiI0Jf?F-75}gt-`Tg zHBB;ATUCPY(N_P-Bdj0EeZ&t@&uuI~cX6Oo9w(URo-IH<BpGqHw9=LXQ&v^aRJ)GfqDe; z=k$9hKZSTI;G9H13bZMK4pE?phw2jO3)JC9JaZy}wyOf2N}vG!4=z8PzfP#2eF>D8 zf?xRQT;CQ(BcJn`{Flpfa9bGVkgD{*{U9x&Lj+xt-x9w*5dXWHr0x_M_K+TmUoXP6 zf0^>q@Mxe*@+bX*{@|}Z*T#qjx7nD|2%K|p^hltQV7Jb#<0T2S zE=X_ML1{A`i{AuR%vM4Ior;4L^lhLsnw<*r!_2DLV=TD80xlcSIhZD#;KPvBQd1TOsX5VpYR00mr zX5V-s#bLN0N7F~3bsk8Py-N>D+{xm7zeTiM~mMwI2XVeMm?oByDr-<>#`e=M*hUc9JQWVqz0L z`{@xtBbD4h3mA1&j>b&!_;~dW;H_;uXi$E&eTmmLkN^bp47-a-q=mQLH3+#+nVNXr0#b9%uz4T zooiIM=EzMyLndWuvEsl@zY#P@O$WB`tfVtk*-*)!GAI2EpOkh=Z<|~LG&NO88czBd zJ}J%RQ|P3hVQR*z6Y!lMQW&OYT=Jo*i+*M&zXff;*hN3HSB`p{zy{oR(a-Faqe&@f zO;GeRd*vv}KN-qlpy^U+%vv^#H7#_6p`TgF@9HOOhM=EW%Z3NKyMYQ|w{4Fdvcm&WfD8obhw;dN~3a2&$4RnYH^$q!gE`?s; zK|@mx7Mb%Q1=O>CFqk>C5J*4#E&7C;Jceeh2^uuxMlU?DecdTQw=CoXi}O=A{a`18 zZ~H}LN-|~8T{HPHLbpQnKZ9CEB5U0-bke^MHMi95nbN>T|5K<9=ftiR)N=*Ac>`(~ z${bRuVfwTw#$%|pY3kDSnc*X>7~71QRHP-P39X<$*e>Qy=-=6_e-CPG3*0rbRpA<_ z`0hh3cp;+hxM?X(Z$Qn00jA$(YA#LhfNhO^L=#KX=pB5x0ds8q+#s7(3q1K?t7ya# zU7-ti4Y{!mLsRP%(-b-|NXczO`)%{Wjd^8OGtimds8KiqUwv<#EzN6bzOJ%Od}F;0 z?Q3bhU(Y3hwOnUd&&7+iToI|{GRxPW=i1F$E(opXD${x{UESn**jL-1_aa+WSML4? X+`DcOw9~e*00000NkvXXu0mjfVrFsw literal 0 HcmV?d00001 diff --git a/docs/assets/img/preview.png b/docs/assets/img/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..1c213343a4791d19df6a76219ab9deb6ef205d2c GIT binary patch literal 11624 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 literal 0 HcmV?d00001 diff --git a/docs/design.md b/docs/design.md new file mode 100644 index 000000000..b8e809bf2 --- /dev/null +++ b/docs/design.md @@ -0,0 +1,85 @@ +# Design + +ERC721A enables a near constant gas cost for batch minting via a lazy-initialization mechanism. + +Token IDs are minted in sequential order (e.g. 0, 1, 2, 3, ...). + +Regardless of the quantity minted, the `_mint` function only performs 3 `SSTORE` operations: + +- Initialize the ownership slot at the starting token ID with the address. +- Update the address' balance. +- Update the next token ID. + +> A `Transfer` event will still be emitted for each NFT minted. + However, emitting an event is an order of magnitude cheaper than a `SSTORE` operation. + +## Lower Fees + +ERC721A defers the initialization of token ownership slots from minting to transferring. + +This allows users to batch mint with low, near-constant transaction fees, and pick a good time to transfer when the network's BASEFEE is lower. + +Although this has a higher total gas cost (minting + transfers), **it gives significantly lower overall transaction fees in practice**. + +> Transaction Fee = (BASEFEE + Max Priority Per Gas) * Gas Used + +Gas savings during high BASEFEE periods matter **more**. + +As such, ERC721A prioritizes gas savings for the minting phase. + +### Benchmark + +To illustrate, we compare OpenZeppelin's ERC721 with ERC721A. + +| | ERC721 | ERC721A | +| -------------------------- | ------------ | -------------- | +| Batch Mint 5 Tokens | 155949 gas | 63748 gas | +| Transfer 5 Tokens | 226655 gas | 334450 gas | +| Mint BASEFEE | 200 gwei | 200 gwei | +| Transfer BASEFEE | 40 gwei | 40 gwei | +| Total Transaction Fees | 0.0403 ether | 0.0261 ether | + +Even for conservatively small batch sizes (e.g. 5), we can observe decent savings over the barebones implementation. + +In practice, the Mint BASEFEE for ERC721 can be much higher. + +When consecutive blocks hit the block gas limit, [the BASEFEE increases exponentially](https://ethereum.org/en/developers/docs/gas/#base-fee). + +#### First Transfer vs Subsequent Transfers + +The main overhead of transferring a token **only occurs during its very first transfer** for an uninitialized slot. + +| | ERC721 | ERC721A | +| -------------------------- | ------------ | -------------- | +| First transfer | 45331 gas | 92822 gas | +| Subsequent transfers | 45331 gas | 44499 gas | + +Here, we bulk mint 10 tokens, and compare the transfer costs of the 5th token in the batch. + +To keep the cost of the `SSTORE` writing to the balance mapping constant, we ensure that the destination addresses have non-zero balances during all transfers. + +The first transfer with ERC721A will incur the storage overheads: + +- 2 extra `SSTORE`s (initialize current slot and next slot, both of which are empty). +- 5 extra `SLOAD`s (read previous slots and next slot). + +## Balance Mapping + +ERC721A maintains an internal mapping of address balances. This is an important and deliberate design decision: + +- The `balanceOf` function is required by the ERC721 standard. + + We understand that it is tempting to remove the mapping -- it can save a `SSTORE` during mints, and 2 `SSTORE`s during transfers. + + However, this degrades the `balanceOf` function to become O(n) in complexity -- it must bruteforce through the entire mapping of ownerships. This hampers on-chain interoperability and scalability. + +- While it is possible to emulate the `balanceOf` function by listening to emitted events, this requires users to use centralized indexing services. + + In the case of service disruption, the data can get out-of-sync and hard to reconstruct. + +- In the context of saving gas, we are able to allow whitelist minting achieve the same amount of `SSTORE`s when compared to implementations without the mapping. See `ERC721A._getAux` and `ERC721A._setAux`. + + The address balance mapping is also used to store the mint and burn counts per address with negligible overhead, which can be very useful for tokenomics. + +In all, the address balance mapping gives a good balance of features and gas savings, which makes it desirable to keep. + diff --git a/docs/erc4907a.md b/docs/erc4907a.md new file mode 100644 index 000000000..f004f75a3 --- /dev/null +++ b/docs/erc4907a.md @@ -0,0 +1,77 @@ +# ERC4907A + +[`erc721a/contracts/extensions/ERC4907A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC4907A.sol) + +[ERC4907](https://eips.ethereum.org/EIPS/eip-4907) compliant extension of ERC721A, which allows owners and authorized addresses to add a time-limited role with restricted permissions to ERC721 tokens. + +This implementation does **not** reset the user information upon token transfer. +The new owner must call [`setUser`](#setUser) to change or reset the user. + +To reset or alter the user information after each transfer, you will need to override either +[`_beforeTokenTransfers`](erc721a.md#_beforeTokenTransfers) or +[`_afterTokenTransfers`](erc721a.md#_afterTokenTransfers) in ERC721A. + +Inherits: + +- [ERC721A](erc721a.md) +- [IERC4907A](interfaces.md#ierc4907a) + + +## Functions + +### setUser + +```solidity +function setUser(uint256 tokenId, address user, uint64 expires) public virtual +``` + +Sets the `user` and `expires` for `tokenId`. + +The zero address indicates there is no user. + +Requirements: + +- The caller must own `tokenId` or be an approved operator. + + +### userOf + +```solidity +function userOf(uint256 tokenId) public view virtual returns (address) +``` + +Returns the user address for `tokenId`. + +The zero address indicates that there is no user or if the user is expired. + +### userExpires + +```solidity +function userExpires(uint256 tokenId) public view virtual returns (uint256) +``` + +Returns the user's expires of `tokenId`. + +### \_explicitUserOf + +```solidity +function _explicitUserOf(uint256 tokenId) internal view virtual returns (address) +``` + +Returns the user address for `tokenId`, ignoring the expiry status. + + +## Events + +### UpdateUser + +`IERC4907-UpdateUser` + +```solidity +event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires) +``` + +Emitted when the `user` of an NFT or the `expires` of the `user` is changed. + +The zero address for user indicates that there is no user address. + diff --git a/docs/erc721a-burnable.md b/docs/erc721a-burnable.md new file mode 100644 index 000000000..54ca5ea29 --- /dev/null +++ b/docs/erc721a-burnable.md @@ -0,0 +1,25 @@ +# ERC721ABurnable + +[`erc721a/contracts/extensions/ERC721ABurnable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC721ABurnable.sol) + +ERC721A Token that can be irreversibly burned (destroyed). + +Inherits: + +- [ERC721A](erc721a.md) +- [IERC721ABurnable](interfaces.md#ierc721aburnable) + +## Functions + +### burn + +```solidity +function burn(uint256 tokenId) public virtual +``` + +Burns `tokenId`. See [`ERC721A._burn`](erc721a.md#_burn). + +Requirements: + +- The caller must own `tokenId` or be an approved operator. + diff --git a/docs/erc721a-queryable.md b/docs/erc721a-queryable.md new file mode 100644 index 000000000..78657ea9c --- /dev/null +++ b/docs/erc721a-queryable.md @@ -0,0 +1,89 @@ +# ERC721AQueryable + +[`erc721a/contracts/extensions/ERC721AQueryable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC721AQueryable.sol) + +ERC721A subclass with convenience query functions. + +Inherits: + +- [ERC721A](erc721a.md) +- [IERC721AQueryable](interfaces.md#ierc721aqueryable) + +## Functions + +### \_domainNameAndVersionMayChange + +```solidity +function explicitOwnershipOf(uint256 tokenId) public view returns (TokenOwnership memory) +``` + +Returns the [`TokenOwnership`](erc721a.md#tokenownership) struct at `tokenId` without reverting. + +This is useful for on-chain and off-chain querying of ownership data for tokenomics. + +The returned struct will contain the following values: + +- If the `tokenId` is out of bounds: + - `addr` = `address(0)` + - `startTimestamp` = `0` + - `burned` = `false` + +- If the `tokenId` is burned: + - `addr` = `

` + - `startTimestamp` = `` + - `burned` = `true` + +- Otherwise: + - `addr` = `
` + - `startTimestamp` = `` + - `burned` = `false` + +### explicitOwnershipsOf + +```solidity +function explicitOwnershipsOf( + uint256[] memory tokenIds +) external view returns (TokenOwnership[] memory) +``` + +Returns an array of `TokenOwnership` structs at `tokenIds` in order. + +See [`explicitOwnershipOf`](#explicitOwnershipOf). + +### tokensOfOwner + +```solidity +function tokensOfOwner(address owner) external view returns (uint256[] memory) +``` + +Returns an array of token IDs owned by `owner`. + +This function scans the ownership mapping and is O(totalSupply) in complexity. +It is meant to be called off-chain. + +See [`tokensOfOwnerIn`](#tokensOfOwnerIn) for splitting the scan into +multiple smaller scans if the collection is large enough to +cause an out-of-gas error. + +This function should work fine for 10k PFP collections. + +### tokensOfOwnerIn + +```solidity +function tokensOfOwnerIn( + address owner, + uint256 start, + uint256 stop +) external view returns (uint256[] memory) +``` + +Returns an array of token IDs owned by `owner`, +in the range \[`start`, `stop`) +(i.e. `start` ≤ `tokenId` < `stop`). + +This function allows for tokens to be queried if the collection +grows too big for a single call of [`tokensOfOwner`](#tokensOfOwner). + +Requirements: + +- `start` < `stop`. \ No newline at end of file diff --git a/docs/erc721a.md b/docs/erc721a.md new file mode 100644 index 000000000..9c8604541 --- /dev/null +++ b/docs/erc721a.md @@ -0,0 +1,629 @@ +# ERC721A + +[`erc721a/contracts/ERC721A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/ERC721A.sol) + +Implementation of [ERC721](https://eips.ethereum.org/EIPS/eip-721) Non-Fungible Token Standard, including the Metadata extension. Built to optimize for lower gas during batch mints. + +Token IDs are minted sequentially (e.g. 0, 1, 2, 3...) starting from `_startTokenId()`. + +An owner cannot have more than `2**64 - 1` (max value of `uint64`) tokens. + +Inherits: + +- [IERC721A](interfaces.md#ierc721a) + +## Structs + +### TokenOwnership + +```solidity +struct TokenOwnership { + // The address of the owner. + address addr; + // Keeps track of the start time of ownership with minimal overhead for tokenomics. + uint64 startTimestamp; + // Whether the token has been burned. + bool burned; +} +``` + +Holds ownership data for each token. + +`startTimestamp` is the timestamp when the token is minted to, transferred to, or burned by `addr`. + + +## Functions + +### constructor + +```solidity +constructor(string memory name_, string memory symbol_) +``` + +Initializes the contract by setting a `name` and a `symbol` to the token collection. + +### supportsInterface + +`IERC165-supportsInterface` + +```solidity +function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) +``` + +Returns `true` if this contract implements the interface defined by `interfaceId`. + +See the corresponding [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) to learn more about how these ids are created. + +See [migration](migration.md#supportsInterface) for `supportsInterface`. + +### totalSupply + +`IERC721Enumerable-totalSupply` + +```solidity +function totalSupply() public view returns (uint256) +``` + +Returns the total number of tokens in existence. + +Burned tokens will reduce the count. + +To get the total number of tokens minted, please see [`_totalMinted`](#_totalMinted). + +### balanceOf + +`IERC721-balanceOf` + +```solidity +function balanceOf(address owner) public view override returns (uint256) +``` + +Returns the number of tokens in `owner`'s account. + +### ownerOf + +`IERC721-ownerOf` + +```solidity +function ownerOf(uint256 tokenId) public view override returns (address) +``` + +Returns the owner of the `tokenId` token. + +Requirements: + +- `tokenId` must exist. + +### name + +`IERC721Metadata-name` + +```solidity +function name() public view virtual override returns (string memory) +``` + +Returns the token collection name. + +### symbol + +`IERC721Metadata-symbol` + +```solidity +function symbol() public view virtual override returns (string memory) +``` + +Returns the token collection symbol. + +### tokenURI + +`IERC721Metadata-tokenURI` + +```solidity +function tokenURI(uint256 tokenId) public view virtual override returns (string memory) +``` + +Returns the Uniform Resource Identifier (URI) for `tokenId` token. + +See [`_baseURI`](#_baseURI) and [`_toString`](#_toString). + + +### approve + +`IERC721-approve` + +```solidity +function approve(address to, uint256 tokenId) public override +``` + +Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred. + +Only a single account can be approved at a time, so approving the zero address clears previous approvals. + +Requirements: + +- The caller must own the token or be an approved operator. +- `tokenId` must exist. + +Emits an `Approval` event. + +### getApproved + +```solidity +function getApproved(uint256 tokenId) public view override returns (address) +``` + +`IERC721-getApproved` + +Returns the account approved for `tokenId` token. + +Requirements: + +- `tokenId` must exist. + +### setApprovalForAll + +`IERC721-setApprovalForAll` + +```solidity +function setApprovalForAll( + address operator, + bool approved +) public virtual override +``` + +Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller. + +Requirements: + +- The `operator` cannot be the caller. + +Emits an `ApprovalForAll` event. + +### isApprovedForAll + +`IERC721-isApprovedForAll` + +```solidity +function isApprovedForAll( + address owner, + address operator +) public view virtual override returns (bool) +``` + +Returns if the `operator` is allowed to manage all of the assets of owner. + +See [`setApprovalForAll`](#setApprovalForAll). + +### transferFrom + +`IERC721-transferFrom` + +```solidity +function transferFrom( + address from, + address to, + uint256 tokenId +) public virtual override +``` + +Transfers `tokenId` token from `from` to `to`. + +Requirements: + +- `from` cannot be the zero address. +- `to` cannot be the zero address. +- `tokenId` token must be owned by `from`. +- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`. + +Emits a `Transfer` event. + +### safeTransferFrom + +`IERC721-safeTransferFrom` + +```solidity +function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes memory _data +) public virtual override +``` + +Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. + +The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`). + +Requirements: + +- `from` cannot be the zero address. +- `to` cannot be the zero address. +- `tokenId` token must be owned by `from`. +- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`. +- If `to` refers to a smart contract, it must implement `IERC721Receiver.onERC721Received`, which is called upon a safe transfer. + +Emits a `Transfer` event. + + +### \_startTokenId + +```solidity +function _startTokenId() internal view virtual returns (uint256) +``` + +Returns the starting token ID (default: `0`). + +To change the starting token ID, override this function to return a different constant. + + +### \_nextTokenId + +```solidity +function _nextTokenId() internal view virtual returns (uint256) +``` + +Returns the next token ID to be minted. + + +### \_totalMinted + +```solidity +function _totalMinted() internal view returns (uint256) +``` + +Returns the total amount of tokens minted. + +### \_numberMinted + +```solidity +function _numberMinted(address owner) internal view returns (uint256) +``` + +Returns the number of tokens minted by or on behalf of `owner`. + +### \_totalBurned + +```solidity +function _totalBurned() internal view returns (uint256) +``` + +Returns the total amount of tokens burned. + + +### \_numberBurned + +```solidity +function _numberBurned(address owner) internal view returns (uint256) +``` + +Returns the number of tokens burned by or on behalf of `owner`. + +### \_getAux + +```solidity +function _getAux(address owner) internal view returns (uint64) +``` + +Returns the auxiliary data for `owner` (e.g. number of whitelist mint slots used). + +### \_setAux + +```solidity +function _setAux(address owner, uint64 aux) internal +``` + +Sets the auxiliary data for `owner` (e.g. number of whitelist mint slots used). + +If there are multiple variables, please pack them into a `uint64`. + + +### \_ownershipOf + +```solidity +function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) +``` + +Returns the token ownership data for `tokenId`. See [`TokenOwnership`](#TokenOwnership). + +The gas spent here starts off proportional to the maximum mint batch size. + +It gradually moves to O(1) as tokens get transferred around in the collection over time. + + +### \_ownershipAt + +```solidity +function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) +``` + +Returns the token ownership data at the `index` slot. See [`TokenOwnership`](#TokenOwnership). + +The token ownership data may or may not be initialized. + + +### \_initializeOwnershipAt + +```solidity +function _initializeOwnershipAt(uint256 index) internal +``` + +Initializes the token ownership data at the `index` slot, if it has not been initialized. + +If the batch minted is very large, this function can be used to initialize some tokens to +reduce the first-time transfer costs. + + +### \_exists + +```solidity +function _exists(uint256 tokenId) internal view returns (bool) +``` + +Returns whether `tokenId` exists. + +Tokens can be managed by their owner or approved accounts via `approve` or `setApprovalForAll`. + +Tokens start existing when they are minted via `_mint`. + +### \_safeMint + +```solidity +function _safeMint( + address to, + uint256 quantity, + bytes memory _data +) internal +``` + +The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`). + +**Safe minting is reentrancy safe since V3.** + +See [`_mint`](#_mint). + +### \_mint + +```solidity +function _mint( + address to, + uint256 quantity +) internal +``` + +Mints `quantity` tokens and transfers them to `to`. + +> To prevent excessive first-time token transfer costs, please limit the `quantity` to a reasonable number (e.g. 30). +> +> Extremely large `quantity` amounts (e.g. > 5000) may result in some marketplaces and indexers to drop some `Transfer` events, +> and cause some mints to not appear. + +Requirements: + +- `to` cannot be the zero address. +- `quantity` must be greater than `0`. + +Emits a `Transfer` event. + +### \_mintERC2309 + +```solidity +function _mintERC2309( + address to, + uint256 quantity +) internal +``` + +Mints `quantity` tokens and transfers them to `to`. + +This function is intended for efficient minting **only** during contract creation. + +It emits only one `ConsecutiveTransfer` as defined in [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), +instead of a sequence of `Transfer` event(s). + +Calling this function outside of contract creation **will** make your contract non-compliant with the ERC721 standard. + +For full ERC721 compliance, substituting ERC721 `Transfer` event(s) with the ERC2309 +`ConsecutiveTransfer` event is only permissible during contract creation. + +> To prevent overflows, the function limits `quantity` to a maximum of 5000. + +Requirements: + +- `to` cannot be the zero address. +- `quantity` must be greater than `0`. + +Emits a `ConsecutiveTransfer` event. + +### \_burn + +```solidity +function _burn(uint256 tokenId, bool approvalCheck) internal virtual +``` + +Destroys `tokenId`. + +The approval is cleared when the token is burned. + +Requirements: + +- `tokenId` must exist. +- If `approvalCheck` is `true`, the caller must own `tokenId` or be an approved operator. + +Emits a `Transfer` event. + + +### \_baseURI + +```solidity +function _baseURI() internal view virtual returns (string memory) +``` + +Base URI for computing `tokenURI`. + +If set, the resulting URI for each token will be the concatenation of the `baseURI` and the `tokenId`. + +Empty by default, it can be overridden in child contracts. + + +### \_beforeTokenTransfers + +```solidity +function _beforeTokenTransfers( + address from, + address to, + uint256 startTokenId, + uint256 quantity +) internal virtual +``` + +Hook that is called before a set of serially-ordered token IDs are about to be transferred. This includes minting. + +Also called before burning one token. + +`startTokenId` - the first token ID to be transferred. +`quantity` - the amount to be transferred. + +Calling conditions: + +- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. +- When `from` is zero, `tokenId` will be minted for `to`. +- When `to` is zero, `tokenId` will be burned by `from`. +- `from` and `to` are never both zero. + + +### \_afterTokenTransfers + +```solidity +function _afterTokenTransfers( + address from, + address to, + uint256 startTokenId, + uint256 quantity +) internal virtual +``` + +Hook that is called after a set of serially-ordered token IDs are about to be transferred. This includes minting. + +Also called after burning one token. + +`startTokenId` - the first token ID to be transferred. +`quantity` - the amount to be transferred. + +Calling conditions: + +- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. +- When `from` is zero, `tokenId` will be minted for `to`. +- When `to` is zero, `tokenId` will be burned by `from`. +- `from` and `to` are never both zero. + + +### \_toString + +```solidity +function _toString(uint256 value) internal pure returns (string memory) +``` + +Converts a `uint256` to its ASCII `string` decimal representation. + +This function is provided as a drop-in replacement for OpenZeppelin's `Strings.toString(uint256 value)`. + + +### \_msgSenderERC721A + +```solidity +function _msgSenderERC721A() internal view virtual returns (address) +``` + +Returns the message sender (defaults to `msg.sender`). + +If you are writing [GSN compatible contracts](https://docs.openzeppelin.com/contracts/2.x/gsn), +you need to override this function +(to return `_msgSender()` if using with OpenZeppelin). + +### \_extraData + +```solidity +function _extraData( + address from, + address to, + uint24 previousExtraData +) internal view virtual returns (uint24) +``` + +Called during each token transfer to set the 24bit `extraData` field. + +This is an advanced storage hitchhiking feature for storing token related data. + +Intended to be overridden by the deriving contract to return the value to be stored after transfer. + +`previousExtraData` - the value of `extraData` before transfer. + +Calling conditions: + +- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. +- When `from` is zero, `tokenId` will be minted for `to`. +- When `to` is zero, `tokenId` will be burned by `from`. +- `from` and `to` are never both zero. + +### \_setExtraDataAt + +```solidity +function _setExtraDataAt(uint256 index, uint24 extraData) internal +``` + +Directly sets the `extraData` for the ownership data at `index`. + +This is an advanced storage hitchhiking feature for storing token related data. + +Requirements: + +- The token at `index` must be initialized. + For bulk mints, `index` is the value of [`_nextTokenId`](#_nextTokenId) before bulk minting. + + +## Events + +### Transfer + +`IERC721-Transfer` + +```solidity +event Transfer(address from, address to, uint256 tokenId) +``` + +Emitted when `tokenId` token is transferred from `from` to `to`. + +### Approval + +`IERC721-Approval` + +```solidity +event Approval(address owner, address approved, uint256 tokenId) +``` + +Emitted when `owner` enables `approved` to manage the `tokenId` token. + +### ApprovalForAll + +`IERC721-ApprovalForAll` + +```solidity +event ApprovalForAll(address owner, address operator, bool approved) +``` + +Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. + +### ConsecutiveTransfer + +`IERC2309-ConsecutiveTransfer` + +```solidity +event ConsecutiveTransfer( + uint256 indexed fromTokenId, + uint256 toTokenId, + address indexed from, + address indexed to +) +``` + +Emitted when tokens from `fromTokenId` to `toTokenId` (inclusive) are transferred from `from` to `to`, during contract creation. diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..eb18fb672 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,333 @@ + + + +Solady Documentation + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/docs/interfaces.md b/docs/interfaces.md new file mode 100644 index 000000000..1a2db9505 --- /dev/null +++ b/docs/interfaces.md @@ -0,0 +1,58 @@ +# Interfaces + +These interfaces are available as `.sol` files. These are useful to interact with third-party contracts that implement them. +Please refer to the API for any details. + +- [IERC721A](erc721a.md) +- [IERC721ABurnable](erc721a-burnable.md) +- [IERC721AQueryable](erc721a-queryable.md) + +## List of interfaces + +### IERC721A + +[`erc721a/contracts/IERC721A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/IERC721A.sol) + +```solidity +import 'erc721a/contracts/interfaces/IERC721A.sol'; + +``` + +### IERC721ABurnable + +[`erc721a/contracts/extensions/IERC721ABurnable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC721ABurnable.sol) + +Inherits: + +- [IERC721A](#ierc721a) + +```solidity +import 'erc721a/contracts/interfaces/IERC721ABurnable.sol'; + +``` + +### IERC721AQueryable + +[`erc721a/contracts/extensions/IERC721AQueryable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC721AQueryable.sol) + +Inherits: + +- [IERC721A](#ierc721a) + +```solidity +import 'erc721a/contracts/interfaces/IERC721AQueryable.sol'; + +``` + +### IERC4907A + +[`erc721a/contracts/extensions/IERC4907A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC4907A.sol) + +Inherits: + +- [IERC721A](#ierc721a) + +```solidity +import 'erc721a/contracts/interfaces/IERC4907A.sol'; + +``` diff --git a/docs/migration.md b/docs/migration.md new file mode 100644 index 000000000..bfa7567ad --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,87 @@ +# Migration to 4.x + +In version 4.x, we have made the following breaking changes: + +- Removed OpenZeppelin +- Made some variables private +- Updated Upgradeable to use Diamond storage + +## API Changes + +### \_currentIndex + +The `_currentIndex` variable has been made private. + +Please use [`_nextTokenId`](erc721a.md#_nextTokenId) instead. + +If you need a `tokensOfOwner` function, please use [`ERC721AQueryable.tokensOfOwner`](erc721a-queryable.md#tokensOfOwner). + +### \_burnCounter + +The `_burnCounter` variable has been made private. + +Please use [`_totalBurned`](erc721a.md#_totalBurned) instead. + +### \_ownerships + +The `_ownerships` mapping has been made private. + +Please use the following instead: +- [`_ownershipOf`](erc721a.md#_ownershipOf) +- [`ERC721AQueryable.explicitOwnershipOf`](erc721a-queryable.md#explicitOwnershipOf) (non-reverting) +- [`ERC721AQueryable.tokensOfOwner`](erc721a-queryable.md#tokensOfOwner) +- [`_ownershipAt`](erc721a.md#_ownershipAt) + +### \_msgSender + +The dependency on OpenZeppelin `_msgSender` has been removed. + +Please use [`_msgSenderERC721A`](erc721a.md#_msgSenderERC721A) instead. + +### Strings.toString + +Due to removal of OpenZeppelin, `Strings.toString` has been removed. + +Please use [`_toString`](erc721a.md#_toString) instead. + +### supportsInterface + +Due to removal of OpenZeppelin, using `super.supportsInterface` in the function override may not work. + +When using with OpenZeppelin's libraries (e.g. [ERC2981](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/common/ERC2981.sol)), you will have to do the following: + +```solidity +function supportsInterface( + bytes4 interfaceId +) public view virtual override(ERC721A, ERC2981) returns (bool) { + // Supports the following `interfaceId`s: + // - IERC165: 0x01ffc9a7 + // - IERC721: 0x80ac58cd + // - IERC721Metadata: 0x5b5e139f + // - IERC2981: 0x2a55205a + return + ERC721A.supportsInterface(interfaceId) || + ERC2981.supportsInterface(interfaceId); +} +``` + +### ERC721AOwnersExplicit + +The `ERC721AOwnersExplicit` extension has been removed. + +Please use [`_initializeOwnershipAt`](erc721a.md#_initializeOwnershipAt) instead. + +You can make your own public wrapper function to initialize the slots for any desired range in a loop. + +## Diamond Storage + +If your upgradeable contracts are deployed using version 3.x, +they will **NOT** be compatible with version 4.x. + +Using version 4.x to upgrade upgradeable contracts deployed with 3.x will lead to unintended consequences. + +You will need to either continue using 3.3.0 (the last compatible version), +or redeploy from scratch with 4.x (the redeployed contracts will not have the previous data). + +Version 4.x of ERC721A Upgradeable will be compatible with the non-diamond OpenZeppelin Upgradeable libraries. + diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 000000000..85e2ce199 --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,35 @@ +# Overview + +ERC721A is an improved implementation of the [ERC721](https://eips.ethereum.org/EIPS/eip-721) Non-Fungible Token Standard that supports minting multiple tokens for close to the cost of one. + +## Announcements + +> **📢 Version 4.x introduces several breaking changes. +> [Please refer to the migration guide for more details.](migration.md)** + +_We highly recommend reading the migration guide_, **especially** _the part on [`supportsInterface`](migration.md?id=supportsinterface) if you are using with OpenZeppelin extensions_ (e.g. ERC2981). + +## Installation + +``` +npm install --save-dev erc721a +``` + +## Usage + +Once installed, you can use the contracts in the library by importing them: + +```solidity +pragma solidity ^0.8.4; + +import "erc721a/contracts/ERC721A.sol"; + +contract Azuki is ERC721A { + constructor() ERC721A("Azuki", "AZUKI") {} + + function mint(uint256 quantity) external payable { + // `_mint`'s second argument now takes in a `quantity`, not a `tokenId`. + _mint(msg.sender, quantity); + } +} +``` diff --git a/docs/sidebar.md b/docs/sidebar.md new file mode 100644 index 000000000..23964cebc --- /dev/null +++ b/docs/sidebar.md @@ -0,0 +1,33 @@ +- [Overview](/) +- [Design](design.md) +- [Tips](tips.md) +- [Upgradeable](upgradeable.md) +- [Migration to 4.x](migration.md) +- auth + - [ERC721A](erc721a.md) + - [ERC721ABurnable](erc721a-burnable.md) + - [ERC721AQueryable](erc721a-queryable.md) + - [ERC4907A](erc4907a.md) + - [Interfaces](interfaces.md) +- utils + - [ERC721A](erc721a.md) + - [ERC721ABurnable](erc721a-burnable.md) + - [ERC721AQueryable](erc721a-queryable.md) + - [ERC4907A](erc4907a.md) + - [Interfaces](interfaces.md) +- **Theme** +
+
+
+
light
+
+
+
auto
+
+
+
dark
+
+- **Links** + - [
Github
](https://github.com/Vectorized/solady) + - [
X
](https://x.com/optimizoor) + diff --git a/docs/tips.md b/docs/tips.md new file mode 100644 index 000000000..e0a69a7d0 --- /dev/null +++ b/docs/tips.md @@ -0,0 +1,90 @@ +# Tips + +## Transfers + +For users, it is more gas optimal to transfer bulk minted tokens in ascending token ID order. + +For example, if you have bulk minted token IDs (33, 34, ..., 99), +you should transfer in the order (33, 34, ..., 99). + +This is due to how the lazy-initialization mechanism works internally: +it scans uninitialized slots in descending order until it finds an initialized slot. + +## Popularity + +The more popular your NFT collection, the larger the expected savings in transaction fees. + +See [Design: Lower Fees](design.md#lower-fees). + +## Aux + +Consider using [`ERC721A._getAux`](erc721a.md#_getAux) and +[`ERC721A._setAux`](erc721a.md#_setAux) to get / set per-address variables +(e.g. number of whitelist mints per address). + +This can help remove an extra cold `SLOAD` and `SSTORE` operation. + +## Minting + +For typical artwork collections, consider using `_mint` over `_safeMint` if you don't expect users to mint to contracts. + +## Batch Size + +During transfers, ERC721A scans through ownership storage slots until it finds an initialized slot. + +To prevent expensive first-time transfer fees for tokens minted in large batches, either: + +- Restrict the max batch size for public mints to a reasonable number. + +- Break up excessively large batches into mini batches internally when minting. + +- Use [`_initializeOwnershipAt`](erc721a.md#_initializeOwnershipAt) every couple tokens to reduce number of reads during a transfer. + +## Efficient Tokenomics + +ERC721A keeps track of additional variables in the internal mappings. + +- [`startTimestamp`](erc721a.md#_ownershipOf) (starting time of holding) per token. +- [`numberMinted`](erc721a.md#_numberMinted) per address. +- [`numberBurned`](erc721a.md#_numberBurned) per address. + +These variables hitchhike on the `SLOAD`s and `SSTORE`s at near zero additional gas cost (< 1%). + +You can use them to design tokenomics with very minimal gas overhead. + +> The [`startTimestamp`](erc721a.md#_ownershipOf), is available via the +> [`TokenOwnership`](erc721a.md#TokenOwnership) struct. +> +> You can get it from the +> [`_ownershipOf`](erc721a.md#_ownershipOf) function or the non-reverting +> [`ERC721AQueryable.explicitOwnershipOf`](erc721a-queryable.md#explicitOwnershipOf) function. + +## ERC721A vs ERC1155 + +| | ERC721A | ERC1155 | +| ---------------- | -------------- | ---------------------- | +| O(1) ownerOf | Yes | No ownerOf | +| O(1) balanceOf | For all tokens | Within fungible tokens | +| O(1)\* bulk mint | For all tokens | Within fungible tokens | +| # mint `SSTORE`s | 3 | 1 | + +\* Approximately O(1) for ERC721A. See [Design](design.md). + + For unique collections, ERC1155 needs a counter which needs 1 more `SSTORE`. + +ERC1155 requires centralized indexing services to emulate ERC721-like functionality off-chain. + +## Other Implementations + +ERC721A is not a one-size-fits-all solution. + +It is heavily optimized for generative artwork NFT collections. + +If your collection does not expect a busy mint phase (e.g. a pure utility NFT), +or does not require bulk minting, +these excellent implementations can be better for lowering overall transaction fees: + +- [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts) +- [Solmate](https://github.com/Rari-Capital/solmate) + +Use the right tool for the job. diff --git a/docs/upgradeable.md b/docs/upgradeable.md new file mode 100644 index 000000000..ea2ee1215 --- /dev/null +++ b/docs/upgradeable.md @@ -0,0 +1,209 @@ +# Using with Upgrades + +If you are deploying upgradeable contracts, +such as using [OpenZeppelin Upgrade Plugins](https://docs.openzeppelin.com/upgrades-plugins/1.x/), +you will need to use the upgradeable variant of ERC721A. + +For more information, please refer to +[OpenZeppelin's documentation](https://docs.openzeppelin.com/contracts/4.x/upgradeable). + +Since v4, the upgradeable variant uses the Diamond storage pattern as defined in [EIP-2535](https://eips.ethereum.org/EIPS/eip-2535). + +## Installation + +``` +npm install --save-dev erc721a-upgradeable +``` + +## Usage + +The package shares the same directory layout as the main ERC721A package, but every file and contract has the suffix `Upgradeable`. + +Constructors are replaced by internal initializer functions following the naming convention `__{ContractName}__init`. + +These functions are internal, and you must define your own public initializer function that calls the parent class' initializer. + +```solidity +pragma solidity ^0.8.4; + +import 'erc721a-upgradeable/contracts/ERC721AUpgradeable.sol'; +import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; + +contract Something is ERC721AUpgradeable, OwnableUpgradeable { + // Take note of the initializer modifiers. + // - `initializerERC721A` for `ERC721AUpgradeable`. + // - `initializer` for OpenZeppelin's `OwnableUpgradeable`. + function initialize() initializerERC721A initializer public { + __ERC721A_init('Something', 'SMTH'); + __Ownable_init(); + } + + function mint(uint256 quantity) external payable { + // `_mint`'s second argument now takes in a `quantity`, not a `tokenId`. + _mint(msg.sender, quantity); + } + + function adminMint(uint256 quantity) external payable onlyOwner { + _mint(msg.sender, quantity); + } +} +``` + +If using with another upgradeable library, please do use their respective initializer modifier on the `initialize()` function, in addition to the `initializerERC721A` modifier. + +## Deployment + +If you are using hardhat, you can deploy it using +[OpenZeppelin Upgrade Plugins](https://docs.openzeppelin.com/upgrades-plugins/1.x/). + +``` +npm install --save-dev @openzeppelin/hardhat-upgrades +``` + +**Deploy Script** + +```javascript +// scripts/deploy.js +const { ethers, upgrades } = require('hardhat'); +const fs = require('fs'); + +async function main () { + const Something = await ethers.getContractFactory('Something'); + console.log('Deploying...'); + const something = await upgrades.deployProxy( + Something, + [], + { initializer: 'initialize' } + ); + await something.deployed(); + const addresses = { + proxy: something.address, + admin: await upgrades.erc1967.getAdminAddress(something.address), + implementation: await upgrades.erc1967.getImplementationAddress( + something.address) + }; + console.log('Addresses:', addresses); + + try { + await run('verify', { address: addresses.implementation }); + } catch (e) {} + + fs.writeFileSync('deployment-addresses.json', JSON.stringify(addresses)); +} + +main(); +``` + +**Upgrade Script** + +```javascript +// scripts/upgrade.js +const { ethers, upgrades } = require('hardhat'); +const fs = require('fs'); + +async function main () { + const Something = await ethers.getContractFactory('Something'); + console.log('Upgrading...'); + let addresses = JSON.parse(fs.readFileSync('deployment-addresses.json')); + await upgrades.upgradeProxy(addresses.proxy, Something); + console.log('Upgraded'); + + addresses = { + proxy: addresses.proxy, + admin: await upgrades.erc1967.getAdminAddress(addresses.proxy), + implementation: await upgrades.erc1967.getImplementationAddress( + addresses.proxy) + }; + console.log('Addresses:', addresses); + + try { + await run('verify', { address: addresses.implementation }); + } catch (e) {} + + fs.writeFileSync('deployment-addresses.json', JSON.stringify(addresses)); +} + +main(); +``` + +### Local + +Add the following to your `hardhat.config.js`: + +```javascript +// hardhat.config.js +require("@nomiclabs/hardhat-waffle"); +require('@openzeppelin/hardhat-upgrades'); + +module.exports = { + solidity: "0.8.11" +}; +``` + +**Deploy** + +``` +npx hardhat run --network localhost scripts/deploy.js +``` + +**Upgrade** + +``` +npx hardhat run --network localhost scripts/upgrade.js +``` + +### Testnet / Mainnet + +We will use the Goerli testnet as an example. + +Install the following packages if they are not already installed: + +``` +npm install --save-dev @nomiclabs/hardhat-etherscan +npm install --save-dev dotenv +``` + +Add the following to your environment file `.env`: + +``` +ETHERSCAN_KEY="Your Etherscan API Key" +PRIVATE_KEY="Your Wallet Private Key" +RPC_URL_GOERLI="https://Infura Or Alchemy URL With API Key" +``` + +Add the following to your `hardhat.config.js`: + +```javascript +// hardhat.config.js +require("@nomiclabs/hardhat-waffle"); +require('dotenv').config(); +require('@openzeppelin/hardhat-upgrades'); +require("@nomiclabs/hardhat-etherscan"); + +module.exports = { + solidity: "0.8.11", + networks: { + goerli: { + url: process.env.RPC_URL_GOERLI, + accounts: [process.env.PRIVATE_KEY] + } + }, + etherscan: { + // Your API key for Etherscan + // Obtain one at https://etherscan.io/ + apiKey: process.env.ETHERSCAN_KEY + } +}; +``` + +**Deploy** + +``` +npx hardhat run --network goerli scripts/deploy.js +``` + +**Upgrade** + +``` +npx hardhat run --network goerli scripts/upgrade.js +``` From ad4e06db96232ac7e927481d17c801ba0b4377d0 Mon Sep 17 00:00:00 2001 From: 0xlgtm Date: Fri, 20 Oct 2023 13:18:05 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=F0=9F=93=9D=20Documentation=20sidebar=20w/?= =?UTF-8?q?=20placeholders=20(#660)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * updated sidebar w/ placeholders * fixed broken link for libPRNG --- docs/accounts/erc4337.md | 3 + docs/accounts/erc4337factory.md | 3 + docs/accounts/erc6551.md | 3 + docs/accounts/erc6551proxy.md | 3 + docs/accounts/receiver.md | 3 + docs/auth/ownable.md | 3 + docs/auth/ownableroles.md | 3 + docs/erc4907a.md | 77 ---- docs/erc721a-burnable.md | 25 - docs/erc721a-queryable.md | 89 ---- docs/erc721a.md | 629 -------------------------- docs/interfaces.md | 58 --- docs/migration.md | 87 ---- docs/sidebar.md | 58 ++- docs/tokens/erc1155.md | 3 + docs/tokens/erc20.md | 3 + docs/tokens/erc2981.md | 3 + docs/tokens/erc4626.md | 3 + docs/tokens/erc6909.md | 3 + docs/tokens/erc721.md | 3 + docs/tokens/weth.md | 3 + docs/upgradeable.md | 209 --------- docs/utils/base64.md | 3 + docs/utils/clone.md | 3 + docs/utils/create3.md | 3 + docs/utils/datetimelib.md | 3 + docs/utils/dynamicbufferlib.md | 3 + docs/utils/ecdsa.md | 3 + docs/utils/eip712.md | 3 + docs/utils/erc1967factory.md | 3 + docs/utils/erc1967factoryconstants.md | 3 + docs/utils/fixedpointmathlib.md | 3 + docs/utils/jsonparserlib.md | 3 + docs/utils/libbit.md | 3 + docs/utils/libbitmap.md | 3 + docs/utils/libclone.md | 3 + docs/utils/libmap.md | 3 + docs/utils/libprng.md | 3 + docs/utils/librlp.md | 3 + docs/utils/libsort.md | 3 + docs/utils/libstring.md | 3 + docs/utils/libzip.md | 3 + docs/utils/merkleprooflib.md | 3 + docs/utils/metadatareaderlib.md | 3 + docs/utils/minheaplib.md | 3 + docs/utils/multicallable.md | 3 + docs/utils/redblacktreelib.md | 3 + docs/utils/safecastlib.md | 3 + docs/utils/safetransferlib.md | 3 + docs/utils/signaturecheckerlib.md | 3 + docs/utils/sstore2.md | 3 + docs/utils/uupsupgradeable.md | 3 + 52 files changed, 178 insertions(+), 1186 deletions(-) create mode 100644 docs/accounts/erc4337.md create mode 100644 docs/accounts/erc4337factory.md create mode 100644 docs/accounts/erc6551.md create mode 100644 docs/accounts/erc6551proxy.md create mode 100644 docs/accounts/receiver.md create mode 100644 docs/auth/ownable.md create mode 100644 docs/auth/ownableroles.md delete mode 100644 docs/erc4907a.md delete mode 100644 docs/erc721a-burnable.md delete mode 100644 docs/erc721a-queryable.md delete mode 100644 docs/erc721a.md delete mode 100644 docs/interfaces.md delete mode 100644 docs/migration.md create mode 100644 docs/tokens/erc1155.md create mode 100644 docs/tokens/erc20.md create mode 100644 docs/tokens/erc2981.md create mode 100644 docs/tokens/erc4626.md create mode 100644 docs/tokens/erc6909.md create mode 100644 docs/tokens/erc721.md create mode 100644 docs/tokens/weth.md delete mode 100644 docs/upgradeable.md create mode 100644 docs/utils/base64.md create mode 100644 docs/utils/clone.md create mode 100644 docs/utils/create3.md create mode 100644 docs/utils/datetimelib.md create mode 100644 docs/utils/dynamicbufferlib.md create mode 100644 docs/utils/ecdsa.md create mode 100644 docs/utils/eip712.md create mode 100644 docs/utils/erc1967factory.md create mode 100644 docs/utils/erc1967factoryconstants.md create mode 100644 docs/utils/fixedpointmathlib.md create mode 100644 docs/utils/jsonparserlib.md create mode 100644 docs/utils/libbit.md create mode 100644 docs/utils/libbitmap.md create mode 100644 docs/utils/libclone.md create mode 100644 docs/utils/libmap.md create mode 100644 docs/utils/libprng.md create mode 100644 docs/utils/librlp.md create mode 100644 docs/utils/libsort.md create mode 100644 docs/utils/libstring.md create mode 100644 docs/utils/libzip.md create mode 100644 docs/utils/merkleprooflib.md create mode 100644 docs/utils/metadatareaderlib.md create mode 100644 docs/utils/minheaplib.md create mode 100644 docs/utils/multicallable.md create mode 100644 docs/utils/redblacktreelib.md create mode 100644 docs/utils/safecastlib.md create mode 100644 docs/utils/safetransferlib.md create mode 100644 docs/utils/signaturecheckerlib.md create mode 100644 docs/utils/sstore2.md create mode 100644 docs/utils/uupsupgradeable.md diff --git a/docs/accounts/erc4337.md b/docs/accounts/erc4337.md new file mode 100644 index 000000000..ddc8ac120 --- /dev/null +++ b/docs/accounts/erc4337.md @@ -0,0 +1,3 @@ +# ERC4337 + +Under construction \ No newline at end of file diff --git a/docs/accounts/erc4337factory.md b/docs/accounts/erc4337factory.md new file mode 100644 index 000000000..78653c327 --- /dev/null +++ b/docs/accounts/erc4337factory.md @@ -0,0 +1,3 @@ +# ERC4337Factory + +Under construction \ No newline at end of file diff --git a/docs/accounts/erc6551.md b/docs/accounts/erc6551.md new file mode 100644 index 000000000..b290af464 --- /dev/null +++ b/docs/accounts/erc6551.md @@ -0,0 +1,3 @@ +# ERC6551 + +Under construction \ No newline at end of file diff --git a/docs/accounts/erc6551proxy.md b/docs/accounts/erc6551proxy.md new file mode 100644 index 000000000..5e2055147 --- /dev/null +++ b/docs/accounts/erc6551proxy.md @@ -0,0 +1,3 @@ +# ERC6551Proxy + +Under construction \ No newline at end of file diff --git a/docs/accounts/receiver.md b/docs/accounts/receiver.md new file mode 100644 index 000000000..9a8028d68 --- /dev/null +++ b/docs/accounts/receiver.md @@ -0,0 +1,3 @@ +# Receiver + +Under construction \ No newline at end of file diff --git a/docs/auth/ownable.md b/docs/auth/ownable.md new file mode 100644 index 000000000..83eba74dc --- /dev/null +++ b/docs/auth/ownable.md @@ -0,0 +1,3 @@ +# Ownable + +Under construction \ No newline at end of file diff --git a/docs/auth/ownableroles.md b/docs/auth/ownableroles.md new file mode 100644 index 000000000..5f812ff4b --- /dev/null +++ b/docs/auth/ownableroles.md @@ -0,0 +1,3 @@ +# OwnableRoles + +Under construction \ No newline at end of file diff --git a/docs/erc4907a.md b/docs/erc4907a.md deleted file mode 100644 index f004f75a3..000000000 --- a/docs/erc4907a.md +++ /dev/null @@ -1,77 +0,0 @@ -# ERC4907A - -[`erc721a/contracts/extensions/ERC4907A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC4907A.sol) - -[ERC4907](https://eips.ethereum.org/EIPS/eip-4907) compliant extension of ERC721A, which allows owners and authorized addresses to add a time-limited role with restricted permissions to ERC721 tokens. - -This implementation does **not** reset the user information upon token transfer. -The new owner must call [`setUser`](#setUser) to change or reset the user. - -To reset or alter the user information after each transfer, you will need to override either -[`_beforeTokenTransfers`](erc721a.md#_beforeTokenTransfers) or -[`_afterTokenTransfers`](erc721a.md#_afterTokenTransfers) in ERC721A. - -Inherits: - -- [ERC721A](erc721a.md) -- [IERC4907A](interfaces.md#ierc4907a) - - -## Functions - -### setUser - -```solidity -function setUser(uint256 tokenId, address user, uint64 expires) public virtual -``` - -Sets the `user` and `expires` for `tokenId`. - -The zero address indicates there is no user. - -Requirements: - -- The caller must own `tokenId` or be an approved operator. - - -### userOf - -```solidity -function userOf(uint256 tokenId) public view virtual returns (address) -``` - -Returns the user address for `tokenId`. - -The zero address indicates that there is no user or if the user is expired. - -### userExpires - -```solidity -function userExpires(uint256 tokenId) public view virtual returns (uint256) -``` - -Returns the user's expires of `tokenId`. - -### \_explicitUserOf - -```solidity -function _explicitUserOf(uint256 tokenId) internal view virtual returns (address) -``` - -Returns the user address for `tokenId`, ignoring the expiry status. - - -## Events - -### UpdateUser - -`IERC4907-UpdateUser` - -```solidity -event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires) -``` - -Emitted when the `user` of an NFT or the `expires` of the `user` is changed. - -The zero address for user indicates that there is no user address. - diff --git a/docs/erc721a-burnable.md b/docs/erc721a-burnable.md deleted file mode 100644 index 54ca5ea29..000000000 --- a/docs/erc721a-burnable.md +++ /dev/null @@ -1,25 +0,0 @@ -# ERC721ABurnable - -[`erc721a/contracts/extensions/ERC721ABurnable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC721ABurnable.sol) - -ERC721A Token that can be irreversibly burned (destroyed). - -Inherits: - -- [ERC721A](erc721a.md) -- [IERC721ABurnable](interfaces.md#ierc721aburnable) - -## Functions - -### burn - -```solidity -function burn(uint256 tokenId) public virtual -``` - -Burns `tokenId`. See [`ERC721A._burn`](erc721a.md#_burn). - -Requirements: - -- The caller must own `tokenId` or be an approved operator. - diff --git a/docs/erc721a-queryable.md b/docs/erc721a-queryable.md deleted file mode 100644 index 78657ea9c..000000000 --- a/docs/erc721a-queryable.md +++ /dev/null @@ -1,89 +0,0 @@ -# ERC721AQueryable - -[`erc721a/contracts/extensions/ERC721AQueryable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/ERC721AQueryable.sol) - -ERC721A subclass with convenience query functions. - -Inherits: - -- [ERC721A](erc721a.md) -- [IERC721AQueryable](interfaces.md#ierc721aqueryable) - -## Functions - -### \_domainNameAndVersionMayChange - -```solidity -function explicitOwnershipOf(uint256 tokenId) public view returns (TokenOwnership memory) -``` - -Returns the [`TokenOwnership`](erc721a.md#tokenownership) struct at `tokenId` without reverting. - -This is useful for on-chain and off-chain querying of ownership data for tokenomics. - -The returned struct will contain the following values: - -- If the `tokenId` is out of bounds: - - `addr` = `address(0)` - - `startTimestamp` = `0` - - `burned` = `false` - -- If the `tokenId` is burned: - - `addr` = `
` - - `startTimestamp` = `` - - `burned` = `true` - -- Otherwise: - - `addr` = `
` - - `startTimestamp` = `` - - `burned` = `false` - -### explicitOwnershipsOf - -```solidity -function explicitOwnershipsOf( - uint256[] memory tokenIds -) external view returns (TokenOwnership[] memory) -``` - -Returns an array of `TokenOwnership` structs at `tokenIds` in order. - -See [`explicitOwnershipOf`](#explicitOwnershipOf). - -### tokensOfOwner - -```solidity -function tokensOfOwner(address owner) external view returns (uint256[] memory) -``` - -Returns an array of token IDs owned by `owner`. - -This function scans the ownership mapping and is O(totalSupply) in complexity. -It is meant to be called off-chain. - -See [`tokensOfOwnerIn`](#tokensOfOwnerIn) for splitting the scan into -multiple smaller scans if the collection is large enough to -cause an out-of-gas error. - -This function should work fine for 10k PFP collections. - -### tokensOfOwnerIn - -```solidity -function tokensOfOwnerIn( - address owner, - uint256 start, - uint256 stop -) external view returns (uint256[] memory) -``` - -Returns an array of token IDs owned by `owner`, -in the range \[`start`, `stop`) -(i.e. `start` ≤ `tokenId` < `stop`). - -This function allows for tokens to be queried if the collection -grows too big for a single call of [`tokensOfOwner`](#tokensOfOwner). - -Requirements: - -- `start` < `stop`. \ No newline at end of file diff --git a/docs/erc721a.md b/docs/erc721a.md deleted file mode 100644 index 9c8604541..000000000 --- a/docs/erc721a.md +++ /dev/null @@ -1,629 +0,0 @@ -# ERC721A - -[`erc721a/contracts/ERC721A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/ERC721A.sol) - -Implementation of [ERC721](https://eips.ethereum.org/EIPS/eip-721) Non-Fungible Token Standard, including the Metadata extension. Built to optimize for lower gas during batch mints. - -Token IDs are minted sequentially (e.g. 0, 1, 2, 3...) starting from `_startTokenId()`. - -An owner cannot have more than `2**64 - 1` (max value of `uint64`) tokens. - -Inherits: - -- [IERC721A](interfaces.md#ierc721a) - -## Structs - -### TokenOwnership - -```solidity -struct TokenOwnership { - // The address of the owner. - address addr; - // Keeps track of the start time of ownership with minimal overhead for tokenomics. - uint64 startTimestamp; - // Whether the token has been burned. - bool burned; -} -``` - -Holds ownership data for each token. - -`startTimestamp` is the timestamp when the token is minted to, transferred to, or burned by `addr`. - - -## Functions - -### constructor - -```solidity -constructor(string memory name_, string memory symbol_) -``` - -Initializes the contract by setting a `name` and a `symbol` to the token collection. - -### supportsInterface - -`IERC165-supportsInterface` - -```solidity -function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) -``` - -Returns `true` if this contract implements the interface defined by `interfaceId`. - -See the corresponding [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) to learn more about how these ids are created. - -See [migration](migration.md#supportsInterface) for `supportsInterface`. - -### totalSupply - -`IERC721Enumerable-totalSupply` - -```solidity -function totalSupply() public view returns (uint256) -``` - -Returns the total number of tokens in existence. - -Burned tokens will reduce the count. - -To get the total number of tokens minted, please see [`_totalMinted`](#_totalMinted). - -### balanceOf - -`IERC721-balanceOf` - -```solidity -function balanceOf(address owner) public view override returns (uint256) -``` - -Returns the number of tokens in `owner`'s account. - -### ownerOf - -`IERC721-ownerOf` - -```solidity -function ownerOf(uint256 tokenId) public view override returns (address) -``` - -Returns the owner of the `tokenId` token. - -Requirements: - -- `tokenId` must exist. - -### name - -`IERC721Metadata-name` - -```solidity -function name() public view virtual override returns (string memory) -``` - -Returns the token collection name. - -### symbol - -`IERC721Metadata-symbol` - -```solidity -function symbol() public view virtual override returns (string memory) -``` - -Returns the token collection symbol. - -### tokenURI - -`IERC721Metadata-tokenURI` - -```solidity -function tokenURI(uint256 tokenId) public view virtual override returns (string memory) -``` - -Returns the Uniform Resource Identifier (URI) for `tokenId` token. - -See [`_baseURI`](#_baseURI) and [`_toString`](#_toString). - - -### approve - -`IERC721-approve` - -```solidity -function approve(address to, uint256 tokenId) public override -``` - -Gives permission to `to` to transfer `tokenId` token to another account. The approval is cleared when the token is transferred. - -Only a single account can be approved at a time, so approving the zero address clears previous approvals. - -Requirements: - -- The caller must own the token or be an approved operator. -- `tokenId` must exist. - -Emits an `Approval` event. - -### getApproved - -```solidity -function getApproved(uint256 tokenId) public view override returns (address) -``` - -`IERC721-getApproved` - -Returns the account approved for `tokenId` token. - -Requirements: - -- `tokenId` must exist. - -### setApprovalForAll - -`IERC721-setApprovalForAll` - -```solidity -function setApprovalForAll( - address operator, - bool approved -) public virtual override -``` - -Approve or remove `operator` as an operator for the caller. Operators can call `transferFrom` or `safeTransferFrom` for any token owned by the caller. - -Requirements: - -- The `operator` cannot be the caller. - -Emits an `ApprovalForAll` event. - -### isApprovedForAll - -`IERC721-isApprovedForAll` - -```solidity -function isApprovedForAll( - address owner, - address operator -) public view virtual override returns (bool) -``` - -Returns if the `operator` is allowed to manage all of the assets of owner. - -See [`setApprovalForAll`](#setApprovalForAll). - -### transferFrom - -`IERC721-transferFrom` - -```solidity -function transferFrom( - address from, - address to, - uint256 tokenId -) public virtual override -``` - -Transfers `tokenId` token from `from` to `to`. - -Requirements: - -- `from` cannot be the zero address. -- `to` cannot be the zero address. -- `tokenId` token must be owned by `from`. -- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`. - -Emits a `Transfer` event. - -### safeTransferFrom - -`IERC721-safeTransferFrom` - -```solidity -function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory _data -) public virtual override -``` - -Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients are aware of the ERC721 protocol to prevent tokens from being forever locked. - -The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`). - -Requirements: - -- `from` cannot be the zero address. -- `to` cannot be the zero address. -- `tokenId` token must be owned by `from`. -- If the caller is not `from`, it must be approved to move this token by either `approve` or `setApprovalForAll`. -- If `to` refers to a smart contract, it must implement `IERC721Receiver.onERC721Received`, which is called upon a safe transfer. - -Emits a `Transfer` event. - - -### \_startTokenId - -```solidity -function _startTokenId() internal view virtual returns (uint256) -``` - -Returns the starting token ID (default: `0`). - -To change the starting token ID, override this function to return a different constant. - - -### \_nextTokenId - -```solidity -function _nextTokenId() internal view virtual returns (uint256) -``` - -Returns the next token ID to be minted. - - -### \_totalMinted - -```solidity -function _totalMinted() internal view returns (uint256) -``` - -Returns the total amount of tokens minted. - -### \_numberMinted - -```solidity -function _numberMinted(address owner) internal view returns (uint256) -``` - -Returns the number of tokens minted by or on behalf of `owner`. - -### \_totalBurned - -```solidity -function _totalBurned() internal view returns (uint256) -``` - -Returns the total amount of tokens burned. - - -### \_numberBurned - -```solidity -function _numberBurned(address owner) internal view returns (uint256) -``` - -Returns the number of tokens burned by or on behalf of `owner`. - -### \_getAux - -```solidity -function _getAux(address owner) internal view returns (uint64) -``` - -Returns the auxiliary data for `owner` (e.g. number of whitelist mint slots used). - -### \_setAux - -```solidity -function _setAux(address owner, uint64 aux) internal -``` - -Sets the auxiliary data for `owner` (e.g. number of whitelist mint slots used). - -If there are multiple variables, please pack them into a `uint64`. - - -### \_ownershipOf - -```solidity -function _ownershipOf(uint256 tokenId) internal view returns (TokenOwnership memory) -``` - -Returns the token ownership data for `tokenId`. See [`TokenOwnership`](#TokenOwnership). - -The gas spent here starts off proportional to the maximum mint batch size. - -It gradually moves to O(1) as tokens get transferred around in the collection over time. - - -### \_ownershipAt - -```solidity -function _ownershipAt(uint256 index) internal view returns (TokenOwnership memory) -``` - -Returns the token ownership data at the `index` slot. See [`TokenOwnership`](#TokenOwnership). - -The token ownership data may or may not be initialized. - - -### \_initializeOwnershipAt - -```solidity -function _initializeOwnershipAt(uint256 index) internal -``` - -Initializes the token ownership data at the `index` slot, if it has not been initialized. - -If the batch minted is very large, this function can be used to initialize some tokens to -reduce the first-time transfer costs. - - -### \_exists - -```solidity -function _exists(uint256 tokenId) internal view returns (bool) -``` - -Returns whether `tokenId` exists. - -Tokens can be managed by their owner or approved accounts via `approve` or `setApprovalForAll`. - -Tokens start existing when they are minted via `_mint`. - -### \_safeMint - -```solidity -function _safeMint( - address to, - uint256 quantity, - bytes memory _data -) internal -``` - -The `data` parameter is forwarded in `IERC721Receiver.onERC721Received` to contract recipients (optional, default: `""`). - -**Safe minting is reentrancy safe since V3.** - -See [`_mint`](#_mint). - -### \_mint - -```solidity -function _mint( - address to, - uint256 quantity -) internal -``` - -Mints `quantity` tokens and transfers them to `to`. - -> To prevent excessive first-time token transfer costs, please limit the `quantity` to a reasonable number (e.g. 30). -> -> Extremely large `quantity` amounts (e.g. > 5000) may result in some marketplaces and indexers to drop some `Transfer` events, -> and cause some mints to not appear. - -Requirements: - -- `to` cannot be the zero address. -- `quantity` must be greater than `0`. - -Emits a `Transfer` event. - -### \_mintERC2309 - -```solidity -function _mintERC2309( - address to, - uint256 quantity -) internal -``` - -Mints `quantity` tokens and transfers them to `to`. - -This function is intended for efficient minting **only** during contract creation. - -It emits only one `ConsecutiveTransfer` as defined in [ERC2309](https://eips.ethereum.org/EIPS/eip-2309), -instead of a sequence of `Transfer` event(s). - -Calling this function outside of contract creation **will** make your contract non-compliant with the ERC721 standard. - -For full ERC721 compliance, substituting ERC721 `Transfer` event(s) with the ERC2309 -`ConsecutiveTransfer` event is only permissible during contract creation. - -> To prevent overflows, the function limits `quantity` to a maximum of 5000. - -Requirements: - -- `to` cannot be the zero address. -- `quantity` must be greater than `0`. - -Emits a `ConsecutiveTransfer` event. - -### \_burn - -```solidity -function _burn(uint256 tokenId, bool approvalCheck) internal virtual -``` - -Destroys `tokenId`. - -The approval is cleared when the token is burned. - -Requirements: - -- `tokenId` must exist. -- If `approvalCheck` is `true`, the caller must own `tokenId` or be an approved operator. - -Emits a `Transfer` event. - - -### \_baseURI - -```solidity -function _baseURI() internal view virtual returns (string memory) -``` - -Base URI for computing `tokenURI`. - -If set, the resulting URI for each token will be the concatenation of the `baseURI` and the `tokenId`. - -Empty by default, it can be overridden in child contracts. - - -### \_beforeTokenTransfers - -```solidity -function _beforeTokenTransfers( - address from, - address to, - uint256 startTokenId, - uint256 quantity -) internal virtual -``` - -Hook that is called before a set of serially-ordered token IDs are about to be transferred. This includes minting. - -Also called before burning one token. - -`startTokenId` - the first token ID to be transferred. -`quantity` - the amount to be transferred. - -Calling conditions: - -- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. -- When `from` is zero, `tokenId` will be minted for `to`. -- When `to` is zero, `tokenId` will be burned by `from`. -- `from` and `to` are never both zero. - - -### \_afterTokenTransfers - -```solidity -function _afterTokenTransfers( - address from, - address to, - uint256 startTokenId, - uint256 quantity -) internal virtual -``` - -Hook that is called after a set of serially-ordered token IDs are about to be transferred. This includes minting. - -Also called after burning one token. - -`startTokenId` - the first token ID to be transferred. -`quantity` - the amount to be transferred. - -Calling conditions: - -- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. -- When `from` is zero, `tokenId` will be minted for `to`. -- When `to` is zero, `tokenId` will be burned by `from`. -- `from` and `to` are never both zero. - - -### \_toString - -```solidity -function _toString(uint256 value) internal pure returns (string memory) -``` - -Converts a `uint256` to its ASCII `string` decimal representation. - -This function is provided as a drop-in replacement for OpenZeppelin's `Strings.toString(uint256 value)`. - - -### \_msgSenderERC721A - -```solidity -function _msgSenderERC721A() internal view virtual returns (address) -``` - -Returns the message sender (defaults to `msg.sender`). - -If you are writing [GSN compatible contracts](https://docs.openzeppelin.com/contracts/2.x/gsn), -you need to override this function -(to return `_msgSender()` if using with OpenZeppelin). - -### \_extraData - -```solidity -function _extraData( - address from, - address to, - uint24 previousExtraData -) internal view virtual returns (uint24) -``` - -Called during each token transfer to set the 24bit `extraData` field. - -This is an advanced storage hitchhiking feature for storing token related data. - -Intended to be overridden by the deriving contract to return the value to be stored after transfer. - -`previousExtraData` - the value of `extraData` before transfer. - -Calling conditions: - -- When `from` and `to` are both non-zero, `from`'s `tokenId` will be transferred to `to`. -- When `from` is zero, `tokenId` will be minted for `to`. -- When `to` is zero, `tokenId` will be burned by `from`. -- `from` and `to` are never both zero. - -### \_setExtraDataAt - -```solidity -function _setExtraDataAt(uint256 index, uint24 extraData) internal -``` - -Directly sets the `extraData` for the ownership data at `index`. - -This is an advanced storage hitchhiking feature for storing token related data. - -Requirements: - -- The token at `index` must be initialized. - For bulk mints, `index` is the value of [`_nextTokenId`](#_nextTokenId) before bulk minting. - - -## Events - -### Transfer - -`IERC721-Transfer` - -```solidity -event Transfer(address from, address to, uint256 tokenId) -``` - -Emitted when `tokenId` token is transferred from `from` to `to`. - -### Approval - -`IERC721-Approval` - -```solidity -event Approval(address owner, address approved, uint256 tokenId) -``` - -Emitted when `owner` enables `approved` to manage the `tokenId` token. - -### ApprovalForAll - -`IERC721-ApprovalForAll` - -```solidity -event ApprovalForAll(address owner, address operator, bool approved) -``` - -Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. - -### ConsecutiveTransfer - -`IERC2309-ConsecutiveTransfer` - -```solidity -event ConsecutiveTransfer( - uint256 indexed fromTokenId, - uint256 toTokenId, - address indexed from, - address indexed to -) -``` - -Emitted when tokens from `fromTokenId` to `toTokenId` (inclusive) are transferred from `from` to `to`, during contract creation. diff --git a/docs/interfaces.md b/docs/interfaces.md deleted file mode 100644 index 1a2db9505..000000000 --- a/docs/interfaces.md +++ /dev/null @@ -1,58 +0,0 @@ -# Interfaces - -These interfaces are available as `.sol` files. These are useful to interact with third-party contracts that implement them. -Please refer to the API for any details. - -- [IERC721A](erc721a.md) -- [IERC721ABurnable](erc721a-burnable.md) -- [IERC721AQueryable](erc721a-queryable.md) - -## List of interfaces - -### IERC721A - -[`erc721a/contracts/IERC721A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/IERC721A.sol) - -```solidity -import 'erc721a/contracts/interfaces/IERC721A.sol'; - -``` - -### IERC721ABurnable - -[`erc721a/contracts/extensions/IERC721ABurnable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC721ABurnable.sol) - -Inherits: - -- [IERC721A](#ierc721a) - -```solidity -import 'erc721a/contracts/interfaces/IERC721ABurnable.sol'; - -``` - -### IERC721AQueryable - -[`erc721a/contracts/extensions/IERC721AQueryable.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC721AQueryable.sol) - -Inherits: - -- [IERC721A](#ierc721a) - -```solidity -import 'erc721a/contracts/interfaces/IERC721AQueryable.sol'; - -``` - -### IERC4907A - -[`erc721a/contracts/extensions/IERC4907A.sol`](https://github.com/chiru-labs/ERC721A/blob/main/contracts/extensions/IERC4907A.sol) - -Inherits: - -- [IERC721A](#ierc721a) - -```solidity -import 'erc721a/contracts/interfaces/IERC4907A.sol'; - -``` diff --git a/docs/migration.md b/docs/migration.md deleted file mode 100644 index bfa7567ad..000000000 --- a/docs/migration.md +++ /dev/null @@ -1,87 +0,0 @@ -# Migration to 4.x - -In version 4.x, we have made the following breaking changes: - -- Removed OpenZeppelin -- Made some variables private -- Updated Upgradeable to use Diamond storage - -## API Changes - -### \_currentIndex - -The `_currentIndex` variable has been made private. - -Please use [`_nextTokenId`](erc721a.md#_nextTokenId) instead. - -If you need a `tokensOfOwner` function, please use [`ERC721AQueryable.tokensOfOwner`](erc721a-queryable.md#tokensOfOwner). - -### \_burnCounter - -The `_burnCounter` variable has been made private. - -Please use [`_totalBurned`](erc721a.md#_totalBurned) instead. - -### \_ownerships - -The `_ownerships` mapping has been made private. - -Please use the following instead: -- [`_ownershipOf`](erc721a.md#_ownershipOf) -- [`ERC721AQueryable.explicitOwnershipOf`](erc721a-queryable.md#explicitOwnershipOf) (non-reverting) -- [`ERC721AQueryable.tokensOfOwner`](erc721a-queryable.md#tokensOfOwner) -- [`_ownershipAt`](erc721a.md#_ownershipAt) - -### \_msgSender - -The dependency on OpenZeppelin `_msgSender` has been removed. - -Please use [`_msgSenderERC721A`](erc721a.md#_msgSenderERC721A) instead. - -### Strings.toString - -Due to removal of OpenZeppelin, `Strings.toString` has been removed. - -Please use [`_toString`](erc721a.md#_toString) instead. - -### supportsInterface - -Due to removal of OpenZeppelin, using `super.supportsInterface` in the function override may not work. - -When using with OpenZeppelin's libraries (e.g. [ERC2981](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/common/ERC2981.sol)), you will have to do the following: - -```solidity -function supportsInterface( - bytes4 interfaceId -) public view virtual override(ERC721A, ERC2981) returns (bool) { - // Supports the following `interfaceId`s: - // - IERC165: 0x01ffc9a7 - // - IERC721: 0x80ac58cd - // - IERC721Metadata: 0x5b5e139f - // - IERC2981: 0x2a55205a - return - ERC721A.supportsInterface(interfaceId) || - ERC2981.supportsInterface(interfaceId); -} -``` - -### ERC721AOwnersExplicit - -The `ERC721AOwnersExplicit` extension has been removed. - -Please use [`_initializeOwnershipAt`](erc721a.md#_initializeOwnershipAt) instead. - -You can make your own public wrapper function to initialize the slots for any desired range in a loop. - -## Diamond Storage - -If your upgradeable contracts are deployed using version 3.x, -they will **NOT** be compatible with version 4.x. - -Using version 4.x to upgrade upgradeable contracts deployed with 3.x will lead to unintended consequences. - -You will need to either continue using 3.3.0 (the last compatible version), -or redeploy from scratch with 4.x (the redeployed contracts will not have the previous data). - -Version 4.x of ERC721A Upgradeable will be compatible with the non-diamond OpenZeppelin Upgradeable libraries. - diff --git a/docs/sidebar.md b/docs/sidebar.md index 23964cebc..1dcbe5361 100644 --- a/docs/sidebar.md +++ b/docs/sidebar.md @@ -1,20 +1,54 @@ - [Overview](/) - [Design](design.md) - [Tips](tips.md) -- [Upgradeable](upgradeable.md) -- [Migration to 4.x](migration.md) +- accounts + - [Receiver](./accounts/receiver.md) + - [ERC4337](./accounts/erc4337.md) + - [ERC4337Factory](./accounts/erc4337factory.md) + - [ERC6551](./accounts/erc6551.md) + - [ERC6551Proxy](./accounts/erc6551proxy.md) - auth - - [ERC721A](erc721a.md) - - [ERC721ABurnable](erc721a-burnable.md) - - [ERC721AQueryable](erc721a-queryable.md) - - [ERC4907A](erc4907a.md) - - [Interfaces](interfaces.md) + - [Ownable](./auth/ownable.md) + - [OwnableRoles](./auth/ownableroles.md) +- tokens + - [WETH](./tokens/weth.md) + - [ERC20](./tokens/erc20.md) + - [ERC4626](./tokens/erc4626.md) + - [ERC721](./tokens/erc721.md) + - [ERC2981](./tokens/erc2981.md) + - [ERC1155](./tokens/erc1155.md) + - [ERC6909](./tokens/erc6909.md) - utils - - [ERC721A](erc721a.md) - - [ERC721ABurnable](erc721a-burnable.md) - - [ERC721AQueryable](erc721a-queryable.md) - - [ERC4907A](erc4907a.md) - - [Interfaces](interfaces.md) + - [MerkleProofLib](./utils/merkleprooflib.md) + - [SignatureCheckerLib](./utils/signaturecheckerlib.md) + - [ECDSA](./utils/ecdsa.md) + - [EIP712](./utils/eip712.md) + - [ERC1967Factory](./utils/erc1967factory.md) + - [ERC1967FactoryConstants](./utils/erc1967factoryconstants.md) + - [JSONParserLib](./utils/jsonparserlib.md) + - [LibSort](./utils/libsort.md) + - [LibPRNG](./utils/libprng.md) + - [Base64](./utils/base64.md) + - [SSTORE2](./utils/sstore2.md) + - [CREATE3](./utils/create3.md) + - [LibRLP](./utils/librlp.md) + - [LibBit](./utils/libbit.md) + - [LibZip](./utils/libzip.md) + - [Clone](./utils/clone.md) + - [LibClone](./utils/libclone.md) + - [UUPSUpgradeable](./utils/uupsupgradeable.md) + - [LibString](./utils/libstring.md) + - [LibBitmap](./utils/libbitmap.md) + - [LibMap](./utils/libmap.md) + - [MinHeapLib](./utils/minheaplib.md) + - [RedBlackTreeLib](./utils/redblacktreelib.md) + - [Multicallable](./utils/multicallable.md) + - [SafeTransferLib](./utils/safetransferlib.md) + - [DynamicBufferLib](./utils/dynamicbufferlib.md) + - [MetadataReaderLib](./utils/metadatareaderlib.md) + - [FixedPointMathLib](./utils/fixedpointmathlib.md) + - [SafeCastLib](./utils/safecastlib.md) + - [DateTimeLib](./utils/datetimelib.md) - **Theme**
diff --git a/docs/tokens/erc1155.md b/docs/tokens/erc1155.md new file mode 100644 index 000000000..8c8c15032 --- /dev/null +++ b/docs/tokens/erc1155.md @@ -0,0 +1,3 @@ +# ERC1155 + +Under construction \ No newline at end of file diff --git a/docs/tokens/erc20.md b/docs/tokens/erc20.md new file mode 100644 index 000000000..e6fc10f83 --- /dev/null +++ b/docs/tokens/erc20.md @@ -0,0 +1,3 @@ +# ERC20 + +Under construction \ No newline at end of file diff --git a/docs/tokens/erc2981.md b/docs/tokens/erc2981.md new file mode 100644 index 000000000..dc1de601d --- /dev/null +++ b/docs/tokens/erc2981.md @@ -0,0 +1,3 @@ +# ERC2981 + +Under construction \ No newline at end of file diff --git a/docs/tokens/erc4626.md b/docs/tokens/erc4626.md new file mode 100644 index 000000000..2ed6f6dea --- /dev/null +++ b/docs/tokens/erc4626.md @@ -0,0 +1,3 @@ +# ERC4626 + +Under construction \ No newline at end of file diff --git a/docs/tokens/erc6909.md b/docs/tokens/erc6909.md new file mode 100644 index 000000000..1e3f78d2a --- /dev/null +++ b/docs/tokens/erc6909.md @@ -0,0 +1,3 @@ +# ERC6909 + +Under construction \ No newline at end of file diff --git a/docs/tokens/erc721.md b/docs/tokens/erc721.md new file mode 100644 index 000000000..c3b8b30c2 --- /dev/null +++ b/docs/tokens/erc721.md @@ -0,0 +1,3 @@ +# ERC721 + +Under construction \ No newline at end of file diff --git a/docs/tokens/weth.md b/docs/tokens/weth.md new file mode 100644 index 000000000..d59712257 --- /dev/null +++ b/docs/tokens/weth.md @@ -0,0 +1,3 @@ +# WETH + +Under construction \ No newline at end of file diff --git a/docs/upgradeable.md b/docs/upgradeable.md deleted file mode 100644 index ea2ee1215..000000000 --- a/docs/upgradeable.md +++ /dev/null @@ -1,209 +0,0 @@ -# Using with Upgrades - -If you are deploying upgradeable contracts, -such as using [OpenZeppelin Upgrade Plugins](https://docs.openzeppelin.com/upgrades-plugins/1.x/), -you will need to use the upgradeable variant of ERC721A. - -For more information, please refer to -[OpenZeppelin's documentation](https://docs.openzeppelin.com/contracts/4.x/upgradeable). - -Since v4, the upgradeable variant uses the Diamond storage pattern as defined in [EIP-2535](https://eips.ethereum.org/EIPS/eip-2535). - -## Installation - -``` -npm install --save-dev erc721a-upgradeable -``` - -## Usage - -The package shares the same directory layout as the main ERC721A package, but every file and contract has the suffix `Upgradeable`. - -Constructors are replaced by internal initializer functions following the naming convention `__{ContractName}__init`. - -These functions are internal, and you must define your own public initializer function that calls the parent class' initializer. - -```solidity -pragma solidity ^0.8.4; - -import 'erc721a-upgradeable/contracts/ERC721AUpgradeable.sol'; -import '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; - -contract Something is ERC721AUpgradeable, OwnableUpgradeable { - // Take note of the initializer modifiers. - // - `initializerERC721A` for `ERC721AUpgradeable`. - // - `initializer` for OpenZeppelin's `OwnableUpgradeable`. - function initialize() initializerERC721A initializer public { - __ERC721A_init('Something', 'SMTH'); - __Ownable_init(); - } - - function mint(uint256 quantity) external payable { - // `_mint`'s second argument now takes in a `quantity`, not a `tokenId`. - _mint(msg.sender, quantity); - } - - function adminMint(uint256 quantity) external payable onlyOwner { - _mint(msg.sender, quantity); - } -} -``` - -If using with another upgradeable library, please do use their respective initializer modifier on the `initialize()` function, in addition to the `initializerERC721A` modifier. - -## Deployment - -If you are using hardhat, you can deploy it using -[OpenZeppelin Upgrade Plugins](https://docs.openzeppelin.com/upgrades-plugins/1.x/). - -``` -npm install --save-dev @openzeppelin/hardhat-upgrades -``` - -**Deploy Script** - -```javascript -// scripts/deploy.js -const { ethers, upgrades } = require('hardhat'); -const fs = require('fs'); - -async function main () { - const Something = await ethers.getContractFactory('Something'); - console.log('Deploying...'); - const something = await upgrades.deployProxy( - Something, - [], - { initializer: 'initialize' } - ); - await something.deployed(); - const addresses = { - proxy: something.address, - admin: await upgrades.erc1967.getAdminAddress(something.address), - implementation: await upgrades.erc1967.getImplementationAddress( - something.address) - }; - console.log('Addresses:', addresses); - - try { - await run('verify', { address: addresses.implementation }); - } catch (e) {} - - fs.writeFileSync('deployment-addresses.json', JSON.stringify(addresses)); -} - -main(); -``` - -**Upgrade Script** - -```javascript -// scripts/upgrade.js -const { ethers, upgrades } = require('hardhat'); -const fs = require('fs'); - -async function main () { - const Something = await ethers.getContractFactory('Something'); - console.log('Upgrading...'); - let addresses = JSON.parse(fs.readFileSync('deployment-addresses.json')); - await upgrades.upgradeProxy(addresses.proxy, Something); - console.log('Upgraded'); - - addresses = { - proxy: addresses.proxy, - admin: await upgrades.erc1967.getAdminAddress(addresses.proxy), - implementation: await upgrades.erc1967.getImplementationAddress( - addresses.proxy) - }; - console.log('Addresses:', addresses); - - try { - await run('verify', { address: addresses.implementation }); - } catch (e) {} - - fs.writeFileSync('deployment-addresses.json', JSON.stringify(addresses)); -} - -main(); -``` - -### Local - -Add the following to your `hardhat.config.js`: - -```javascript -// hardhat.config.js -require("@nomiclabs/hardhat-waffle"); -require('@openzeppelin/hardhat-upgrades'); - -module.exports = { - solidity: "0.8.11" -}; -``` - -**Deploy** - -``` -npx hardhat run --network localhost scripts/deploy.js -``` - -**Upgrade** - -``` -npx hardhat run --network localhost scripts/upgrade.js -``` - -### Testnet / Mainnet - -We will use the Goerli testnet as an example. - -Install the following packages if they are not already installed: - -``` -npm install --save-dev @nomiclabs/hardhat-etherscan -npm install --save-dev dotenv -``` - -Add the following to your environment file `.env`: - -``` -ETHERSCAN_KEY="Your Etherscan API Key" -PRIVATE_KEY="Your Wallet Private Key" -RPC_URL_GOERLI="https://Infura Or Alchemy URL With API Key" -``` - -Add the following to your `hardhat.config.js`: - -```javascript -// hardhat.config.js -require("@nomiclabs/hardhat-waffle"); -require('dotenv').config(); -require('@openzeppelin/hardhat-upgrades'); -require("@nomiclabs/hardhat-etherscan"); - -module.exports = { - solidity: "0.8.11", - networks: { - goerli: { - url: process.env.RPC_URL_GOERLI, - accounts: [process.env.PRIVATE_KEY] - } - }, - etherscan: { - // Your API key for Etherscan - // Obtain one at https://etherscan.io/ - apiKey: process.env.ETHERSCAN_KEY - } -}; -``` - -**Deploy** - -``` -npx hardhat run --network goerli scripts/deploy.js -``` - -**Upgrade** - -``` -npx hardhat run --network goerli scripts/upgrade.js -``` diff --git a/docs/utils/base64.md b/docs/utils/base64.md new file mode 100644 index 000000000..54dcf558b --- /dev/null +++ b/docs/utils/base64.md @@ -0,0 +1,3 @@ +# Base64 + +Under construction \ No newline at end of file diff --git a/docs/utils/clone.md b/docs/utils/clone.md new file mode 100644 index 000000000..0f294e570 --- /dev/null +++ b/docs/utils/clone.md @@ -0,0 +1,3 @@ +# Clone + +Under construction \ No newline at end of file diff --git a/docs/utils/create3.md b/docs/utils/create3.md new file mode 100644 index 000000000..62be642fb --- /dev/null +++ b/docs/utils/create3.md @@ -0,0 +1,3 @@ +# CREATE3 + +Under construction \ No newline at end of file diff --git a/docs/utils/datetimelib.md b/docs/utils/datetimelib.md new file mode 100644 index 000000000..3902e7639 --- /dev/null +++ b/docs/utils/datetimelib.md @@ -0,0 +1,3 @@ +# DateTimeLib + +Under construction \ No newline at end of file diff --git a/docs/utils/dynamicbufferlib.md b/docs/utils/dynamicbufferlib.md new file mode 100644 index 000000000..d21866539 --- /dev/null +++ b/docs/utils/dynamicbufferlib.md @@ -0,0 +1,3 @@ +# DynamicBufferLib + +Under construction \ No newline at end of file diff --git a/docs/utils/ecdsa.md b/docs/utils/ecdsa.md new file mode 100644 index 000000000..cb09e7802 --- /dev/null +++ b/docs/utils/ecdsa.md @@ -0,0 +1,3 @@ +# ECDSA + +Under construction \ No newline at end of file diff --git a/docs/utils/eip712.md b/docs/utils/eip712.md new file mode 100644 index 000000000..d361ea51c --- /dev/null +++ b/docs/utils/eip712.md @@ -0,0 +1,3 @@ +# EIP712 + +Under construction \ No newline at end of file diff --git a/docs/utils/erc1967factory.md b/docs/utils/erc1967factory.md new file mode 100644 index 000000000..6e409b857 --- /dev/null +++ b/docs/utils/erc1967factory.md @@ -0,0 +1,3 @@ +# ERC1967Factory + +Under construction \ No newline at end of file diff --git a/docs/utils/erc1967factoryconstants.md b/docs/utils/erc1967factoryconstants.md new file mode 100644 index 000000000..f507116e5 --- /dev/null +++ b/docs/utils/erc1967factoryconstants.md @@ -0,0 +1,3 @@ +# ERC1967FactoryConstants + +Under construction \ No newline at end of file diff --git a/docs/utils/fixedpointmathlib.md b/docs/utils/fixedpointmathlib.md new file mode 100644 index 000000000..8c5fa0b83 --- /dev/null +++ b/docs/utils/fixedpointmathlib.md @@ -0,0 +1,3 @@ +# FixedPointMathLib + +Under construction \ No newline at end of file diff --git a/docs/utils/jsonparserlib.md b/docs/utils/jsonparserlib.md new file mode 100644 index 000000000..635be092b --- /dev/null +++ b/docs/utils/jsonparserlib.md @@ -0,0 +1,3 @@ +# JSONParserLib + +Under construction \ No newline at end of file diff --git a/docs/utils/libbit.md b/docs/utils/libbit.md new file mode 100644 index 000000000..6f441d0cf --- /dev/null +++ b/docs/utils/libbit.md @@ -0,0 +1,3 @@ +# LibBit + +Under construction \ No newline at end of file diff --git a/docs/utils/libbitmap.md b/docs/utils/libbitmap.md new file mode 100644 index 000000000..94cc1acaa --- /dev/null +++ b/docs/utils/libbitmap.md @@ -0,0 +1,3 @@ +# LibBitMap + +Under construction \ No newline at end of file diff --git a/docs/utils/libclone.md b/docs/utils/libclone.md new file mode 100644 index 000000000..af03300f2 --- /dev/null +++ b/docs/utils/libclone.md @@ -0,0 +1,3 @@ +# LibClone + +Under construction \ No newline at end of file diff --git a/docs/utils/libmap.md b/docs/utils/libmap.md new file mode 100644 index 000000000..c5009f3f4 --- /dev/null +++ b/docs/utils/libmap.md @@ -0,0 +1,3 @@ +# LibMap + +Under construction \ No newline at end of file diff --git a/docs/utils/libprng.md b/docs/utils/libprng.md new file mode 100644 index 000000000..b85f04ce3 --- /dev/null +++ b/docs/utils/libprng.md @@ -0,0 +1,3 @@ +# LibPRNG + +Under construction \ No newline at end of file diff --git a/docs/utils/librlp.md b/docs/utils/librlp.md new file mode 100644 index 000000000..e85bfa4a4 --- /dev/null +++ b/docs/utils/librlp.md @@ -0,0 +1,3 @@ +# LibRLP + +Under construction \ No newline at end of file diff --git a/docs/utils/libsort.md b/docs/utils/libsort.md new file mode 100644 index 000000000..7384e3d89 --- /dev/null +++ b/docs/utils/libsort.md @@ -0,0 +1,3 @@ +# LibSort + +Under construction \ No newline at end of file diff --git a/docs/utils/libstring.md b/docs/utils/libstring.md new file mode 100644 index 000000000..09e5b3d8e --- /dev/null +++ b/docs/utils/libstring.md @@ -0,0 +1,3 @@ +# LibString + +Under construction \ No newline at end of file diff --git a/docs/utils/libzip.md b/docs/utils/libzip.md new file mode 100644 index 000000000..4ec4764d6 --- /dev/null +++ b/docs/utils/libzip.md @@ -0,0 +1,3 @@ +# LibZip + +Under construction \ No newline at end of file diff --git a/docs/utils/merkleprooflib.md b/docs/utils/merkleprooflib.md new file mode 100644 index 000000000..ff40c3d87 --- /dev/null +++ b/docs/utils/merkleprooflib.md @@ -0,0 +1,3 @@ +# MerkleProofLib + +Under construction \ No newline at end of file diff --git a/docs/utils/metadatareaderlib.md b/docs/utils/metadatareaderlib.md new file mode 100644 index 000000000..efff3b811 --- /dev/null +++ b/docs/utils/metadatareaderlib.md @@ -0,0 +1,3 @@ +# MetadataReaderLib + +Under construction \ No newline at end of file diff --git a/docs/utils/minheaplib.md b/docs/utils/minheaplib.md new file mode 100644 index 000000000..469dc81ce --- /dev/null +++ b/docs/utils/minheaplib.md @@ -0,0 +1,3 @@ +# MinHeapLib + +Under construction \ No newline at end of file diff --git a/docs/utils/multicallable.md b/docs/utils/multicallable.md new file mode 100644 index 000000000..5411923b9 --- /dev/null +++ b/docs/utils/multicallable.md @@ -0,0 +1,3 @@ +# Multicallable + +Under construction \ No newline at end of file diff --git a/docs/utils/redblacktreelib.md b/docs/utils/redblacktreelib.md new file mode 100644 index 000000000..f5f6fc3f6 --- /dev/null +++ b/docs/utils/redblacktreelib.md @@ -0,0 +1,3 @@ +# RedBlackTreeLib + +Under construction \ No newline at end of file diff --git a/docs/utils/safecastlib.md b/docs/utils/safecastlib.md new file mode 100644 index 000000000..050afcb5d --- /dev/null +++ b/docs/utils/safecastlib.md @@ -0,0 +1,3 @@ +# SafeCastLib + +Under construction \ No newline at end of file diff --git a/docs/utils/safetransferlib.md b/docs/utils/safetransferlib.md new file mode 100644 index 000000000..ad6676f40 --- /dev/null +++ b/docs/utils/safetransferlib.md @@ -0,0 +1,3 @@ +# SafeTransferLib + +Under construction \ No newline at end of file diff --git a/docs/utils/signaturecheckerlib.md b/docs/utils/signaturecheckerlib.md new file mode 100644 index 000000000..f14728ce8 --- /dev/null +++ b/docs/utils/signaturecheckerlib.md @@ -0,0 +1,3 @@ +# SignatureCheckerLib + +Under construction \ No newline at end of file diff --git a/docs/utils/sstore2.md b/docs/utils/sstore2.md new file mode 100644 index 000000000..87a12d1a3 --- /dev/null +++ b/docs/utils/sstore2.md @@ -0,0 +1,3 @@ +# SSTORE2 + +Under construction \ No newline at end of file diff --git a/docs/utils/uupsupgradeable.md b/docs/utils/uupsupgradeable.md new file mode 100644 index 000000000..eb7a4b1d2 --- /dev/null +++ b/docs/utils/uupsupgradeable.md @@ -0,0 +1,3 @@ +# UUPSUpgradable + +Under construction \ No newline at end of file From f649fbb0b85d4efc0dad23df35099f328c134158 Mon Sep 17 00:00:00 2001 From: 0xlgtm Date: Mon, 23 Oct 2023 17:37:04 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20docs=20paths=20(?= =?UTF-8?q?#671)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/sidebar.md | 88 ++++++++++++++++++++++++------------------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/docs/sidebar.md b/docs/sidebar.md index 1dcbe5361..a1199d40a 100644 --- a/docs/sidebar.md +++ b/docs/sidebar.md @@ -2,53 +2,53 @@ - [Design](design.md) - [Tips](tips.md) - accounts - - [Receiver](./accounts/receiver.md) - - [ERC4337](./accounts/erc4337.md) - - [ERC4337Factory](./accounts/erc4337factory.md) - - [ERC6551](./accounts/erc6551.md) - - [ERC6551Proxy](./accounts/erc6551proxy.md) + - [Receiver](accounts/receiver.md) + - [ERC4337](accounts/erc4337.md) + - [ERC4337Factory](accounts/erc4337factory.md) + - [ERC6551](accounts/erc6551.md) + - [ERC6551Proxy](accounts/erc6551proxy.md) - auth - - [Ownable](./auth/ownable.md) - - [OwnableRoles](./auth/ownableroles.md) + - [Ownable](auth/ownable.md) + - [OwnableRoles](auth/ownableroles.md) - tokens - - [WETH](./tokens/weth.md) - - [ERC20](./tokens/erc20.md) - - [ERC4626](./tokens/erc4626.md) - - [ERC721](./tokens/erc721.md) - - [ERC2981](./tokens/erc2981.md) - - [ERC1155](./tokens/erc1155.md) - - [ERC6909](./tokens/erc6909.md) + - [WETH](tokens/weth.md) + - [ERC20](tokens/erc20.md) + - [ERC4626](tokens/erc4626.md) + - [ERC721](tokens/erc721.md) + - [ERC2981](tokens/erc2981.md) + - [ERC1155](tokens/erc1155.md) + - [ERC6909](tokens/erc6909.md) - utils - - [MerkleProofLib](./utils/merkleprooflib.md) - - [SignatureCheckerLib](./utils/signaturecheckerlib.md) - - [ECDSA](./utils/ecdsa.md) - - [EIP712](./utils/eip712.md) - - [ERC1967Factory](./utils/erc1967factory.md) - - [ERC1967FactoryConstants](./utils/erc1967factoryconstants.md) - - [JSONParserLib](./utils/jsonparserlib.md) - - [LibSort](./utils/libsort.md) - - [LibPRNG](./utils/libprng.md) - - [Base64](./utils/base64.md) - - [SSTORE2](./utils/sstore2.md) - - [CREATE3](./utils/create3.md) - - [LibRLP](./utils/librlp.md) - - [LibBit](./utils/libbit.md) - - [LibZip](./utils/libzip.md) - - [Clone](./utils/clone.md) - - [LibClone](./utils/libclone.md) - - [UUPSUpgradeable](./utils/uupsupgradeable.md) - - [LibString](./utils/libstring.md) - - [LibBitmap](./utils/libbitmap.md) - - [LibMap](./utils/libmap.md) - - [MinHeapLib](./utils/minheaplib.md) - - [RedBlackTreeLib](./utils/redblacktreelib.md) - - [Multicallable](./utils/multicallable.md) - - [SafeTransferLib](./utils/safetransferlib.md) - - [DynamicBufferLib](./utils/dynamicbufferlib.md) - - [MetadataReaderLib](./utils/metadatareaderlib.md) - - [FixedPointMathLib](./utils/fixedpointmathlib.md) - - [SafeCastLib](./utils/safecastlib.md) - - [DateTimeLib](./utils/datetimelib.md) + - [MerkleProofLib](utils/merkleprooflib.md) + - [SignatureCheckerLib](utils/signaturecheckerlib.md) + - [ECDSA](utils/ecdsa.md) + - [EIP712](utils/eip712.md) + - [ERC1967Factory](utils/erc1967factory.md) + - [ERC1967FactoryConstants](utils/erc1967factoryconstants.md) + - [JSONParserLib](utils/jsonparserlib.md) + - [LibSort](utils/libsort.md) + - [LibPRNG](utils/libprng.md) + - [Base64](utils/base64.md) + - [SSTORE2](utils/sstore2.md) + - [CREATE3](utils/create3.md) + - [LibRLP](utils/librlp.md) + - [LibBit](utils/libbit.md) + - [LibZip](utils/libzip.md) + - [Clone](utils/clone.md) + - [LibClone](utils/libclone.md) + - [UUPSUpgradeable](utils/uupsupgradeable.md) + - [LibString](utils/libstring.md) + - [LibBitmap](utils/libbitmap.md) + - [LibMap](utils/libmap.md) + - [MinHeapLib](utils/minheaplib.md) + - [RedBlackTreeLib](utils/redblacktreelib.md) + - [Multicallable](utils/multicallable.md) + - [SafeTransferLib](utils/safetransferlib.md) + - [DynamicBufferLib](utils/dynamicbufferlib.md) + - [MetadataReaderLib](utils/metadatareaderlib.md) + - [FixedPointMathLib](utils/fixedpointmathlib.md) + - [SafeCastLib](utils/safecastlib.md) + - [DateTimeLib](utils/datetimelib.md) - **Theme**
From 02ffa0a15d121ac688337179b2202d29349d08c2 Mon Sep 17 00:00:00 2001 From: 0xlgtm Date: Mon, 23 Oct 2023 17:37:33 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20Fix=20docs=20repo=20li?= =?UTF-8?q?nk=20(#672)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.html b/docs/index.html index eb18fb672..105375e8b 100644 --- a/docs/index.html +++ b/docs/index.html @@ -164,7 +164,7 @@ var logo = ''; window.$docsify = { name: logo, - repo: 'https://github.com/chiru-labs/Solady', + repo: 'https://github.com/vectorized/Solady', coverpage: false, homepage: 'overview.md', loadSidebar: 'sidebar.md', From 7443a0112fe78c390b391e9634189bd030b81942 Mon Sep 17 00:00:00 2001 From: 0xlgtm Date: Mon, 6 Nov 2023 17:55:07 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=F0=9F=93=9D=20Completed=20ERC20=20docs=20(?= =?UTF-8?q?#703)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * added ERC20 draft * changed bullet point * added example usage section * added gas benchmarks and Api reference section * fixed formatting * added documentation up to totalSupply(), committing changes so I can see how it looks like * fixed grammar and standardized structure * added documentation for balanceOf and allowance * added documentation for the approve function * added documentation for transfer * added revert condition for transfer function * standardize * Added documentation on nonces * added documentation for permit * added documentation for DOMAIN_SEPERATOR * added section for events * fixed events table format * fixed small typo * added benchmarks for ERC20 --- docs/tokens/erc20.md | 394 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 393 insertions(+), 1 deletion(-) diff --git a/docs/tokens/erc20.md b/docs/tokens/erc20.md index e6fc10f83..deee5664d 100644 --- a/docs/tokens/erc20.md +++ b/docs/tokens/erc20.md @@ -1,3 +1,395 @@ # ERC20 -Under construction \ No newline at end of file +Source: [`tokens/ERC20.sol`](https://github.com/Vectorized/solady/blob/main/src/tokens/ERC20.sol) + +Solady's ERC20 token implementation is an opinionated and highly optimized implementation of the [ERC20 standard](https://eips.ethereum.org/EIPS/eip-20). It also inherits the [ERC2612 standard](https://eips.ethereum.org/EIPS/eip-2612) which enables permit-based approvals. + +## Things to note + +- The ERC20 standard does not impose any restriction on the addresses and amounts used. As such, this implementation **WILL NOT** revert for the following: + - mint to the zero address + - transfer to and from the zero address + - transfer zero tokens + - self approvals +- Every function can be overridden with the `override` keyword if a custom implementation is required. +- The `permit` function uses the ecrecover precompile (0x1). + +## Example usage + +### Foundry + +1. Create a new [foundry](https://github.com/foundry-rs/foundry) repository and navigate to the root folder. + +```bash +$ forge init +$ cd +``` + +2. Install the Solady library + +```bash +$ forge install vectorized/solady +``` + +3. Create a file called `MyToken.sol` in the `/src` folder. + +```bash +$ touch src/MyToken.sol +``` + +4. Copy the following implementation into the `MyToken.sol` file. + +```solidity +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.4; + +import {ERC20} from "solady/src/tokens/ERC20.sol"; + +contract MyToken is ERC20 { + function name() public view override returns (string memory) { + return "Mytoken"; + } + + function symbol() public view override returns (string memory) { + return "MYT"; + } +} +``` + +## Gas Benchmarks + +| Function name | [Solady](https://github.com/Vectorized/solady/blob/main/src/tokens/ERC20.sol) | [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Permit.sol) | +| ---------------- | ------ | ------------ | +| DOMAIN_SEPERATOR | 488 | 386 | +| allowance | 700 | 814 | +| approve | 24403 | 24762 | +| burn | 2141 | 2439 | +| decimals | 222 | 222 | +| mint | 24649 | 24978 | +| name | 494 | 3241 | +| nonces | 555 | 616 | +| permit | 50437 | 51478 | +| symbol | 542 | 3306 | +| transfer | 2235 | 2613 | +| transferFrom | 2577 | 3295 | + +## API Reference + +### Functions + +| Name | Description | +| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | +| [name](#name) | The name of the token. | +| [symbol](#symbol) | The symbol of the token. | +| [decimals](#decimals) | The number of decimals of the token. | +| [totalSupply](#totalsupply) | The amount of tokens in existence. | +| [balanceOf](#balanceof) | The amount of tokens owned by `owner`. | +| [allowance](#allowance) | The amount of tokens that `spender` can spend on behalf of `owner`. | +| [approve](#approve) | Sets `amount` as the allowance of `spender` over the caller's tokens. | +| [transfer](#transfer) | Transfer `amount` tokens from the caller to `to`. | +| [transferFrom](#transferfrom) | Transfers `amount` tokens from `from` to `to`. | +| [nonces](#nonces) | The current nonce for `owner`. | +| [permit](#permit) | Sets `value` as the allowance of `spender` over the tokens of `owner`, authorized by a signed approval by `owner`. | +| [DOMAIN_SEPARATOR](#domain_seperator) | The EIP-712 domain separator for the EIP-2612 permit. | + +--- + +#### name + +Returns the name of the token. + +```solidity +function name() public view virtual returns (string memory) +``` + +##### Parameter(s) + +- None + +##### Return Value(s) + +- The name of the token. + +##### Note(s) + +- Must override or the contract will not compile. + +--- + +#### symbol + +Returns the symbol of the token. + +```solidity +function symbol() public view virtual returns (string memory) +``` + +##### Parameter(s) + +- None + +##### Return Value(s) + +- The symbol of the token. + +##### Note(s) + +- Must override or the contract will not compile. + +--- + +#### decimals + +Returns the number of decimals of the token. + +```solidity +function decimals() public view virtual returns (uint8) +``` + +##### Parameter(s) + +- None + +##### Return Value(s) + +- The number of decimals of the token. + +##### Note(s) + +- None + +--- + +#### totalSupply + +Returns the amount of tokens in existence. + +```solidity +function totalSupply() public view virtual returns (uint256 result) +``` + +##### Parameter(s) + +- None + +##### Return Value(s) + +- `result`: The number of tokens in existence. + +##### Note(s) + +- None + +--- + +#### balanceOf + +Returns the amount of tokens owned by `owner`. + +```solidity +function balanceOf(address owner) public view virtual returns (uint256 result) +``` + +##### Parameter(s) + +- `owner`: The address to query the token balance of. + +##### Return Value(s) + +- `result`: The amount of tokens owned by `owner`. + +##### Note(s) + +- None + +--- + +#### allowance + +Returns the amount of tokens that `spender` can spend on behalf of `owner`. + +```solidity +function allowance(address owner, address spender) public view virtual returns (uint256 result) +``` + +##### Parameter(s) + +- `owner`: The owner of the tokens. +- `spender`: The spender of the tokens. + +##### Return Value(s) + +- `result`: The amount of tokens that `spender` can spend on behalf of `owner`. + +##### Note(s) + +- None + +--- + +#### approve + +Sets `amount` as the allowance of `spender` over the caller's tokens. + +```solidity +function approve(address spender, uint256 amount) public virtual returns (bool) +``` + +##### Parameter(s) + +- `spender`: The spender of the tokens. +- `amount`: The amount to set as spender's allowance. + +##### Return Value(s) + +- `true` if `spender`'s allowance is updated successfully. + +##### Note(s) + +- Emits the `Approval` event if `spender`'s allowance is updated successfully. + +--- + +#### transfer + +Transfer `amount` tokens from the caller to `to`. + +```solidity +function transfer(address to, uint256 amount) public virtual returns (bool) +``` + +##### Parameter(s) + +- `to`: The address to receive the tokens. +- `amount`: The amount of tokens to transfer from the caller. + +##### Return Value(s) + +- `true` if `amount` tokens are transferred from the caller to `to` successfully. + +##### Note(s) + +- Emits the `Transfer` event if `amount` of tokens are transferred from the caller to `to` successfully. +- Reverts with the `InsufficientBalance` error if caller does not have enough tokens. + +--- + +#### transferFrom + +Transfers `amount` tokens from `from` to `to`. + +```solidity +transferFrom(address from, address to, uint256 amount) public virtual returns (bool) +``` + +##### Parameter(s) + +- `from`: The address to transfer the tokens from. +- `to`: The address to transfer the tokens to. +- `amount`: The amount of tokens to be transferred. + +##### Return Value(s) + +- `true` if `amount` of tokens are transferred from `from` to `to`. + +##### Note(s) + +- Emits the `Transfer` event if `amount` of tokens are transferred from `from` to `to` successfully. +- Does not update caller's allowance if allowance is `type(uint256).max`. +- Reverts with `InsufficientAllowance` error if the caller does not have enough allowance. +- Reverts with `InsufficientBalance` error if `from` does not have enough tokens. + +--- + +#### nonces + +Returns the current nonce for `owner`. + +```solidity +function nonces(address owner) public view virtual returns (uint256 result) +``` + +##### Parameter(s) + +- `owner`: The address to query the nonce of. + +##### Return Value(s) + +- `result`: The current nonce of the `owner`. + +##### Note(s) + +- This value is used to compute the signature for [EIP-2612 permit](https://eips.ethereum.org/EIPS/eip-2612). + +--- + +#### permit + +Sets `value` as the allowance of `spender` over the tokens of `owner`, authorized by a signed approval by `owner`. + +```solidity +function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual +``` + +##### Parameter(s) + +- `owner`: The owner of the tokens. +- `spender`: The spender of the tokens. +- `value`: The amount to set as spender's allowance. +- `deadline`: The deadline of the signature. +- `v`: The v component of the signature. +- `r`: The r component of the signature. +- `s`: The s component of the signature. + +##### Return Value(s) + +- None + +##### Note(s) + +- Emits the `Approval` event if `spender`'s allowance is updated successfully. +- `owner`'s nonce will be incremented by 1 if `permit` is successful. +- Reverts with `PermitExpired` error if the current timestamp is greater than `deadline`. +- Reverts with `InvalidPermit` error if the address recovered does not match the `owner`. + +--- + +#### DOMAIN_SEPERATOR + +Returns the EIP-712 domain separator for the EIP-2612 permit. + +```solidity +function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) +``` + +##### Parameter(s) + +- None + +##### Return Value(s) + +- `result`: The EIP-712 domain separator for the EIP-2612 permit. + +##### Note(s) + +- None + +--- + +### Errors + +| Name | Description | Selector | +| ------------------- | -------------------------------------------- | ------------ | +| TotalSupplyOverflow | Thrown when the total supply has overflowed. | `0xe5cfe957` | +| AllowanceOverflow | Thrown when the allowance has overflowed. | `0xf9067066` | +| AllowanceUnderflow | Thrown when the allowance has underflowed. | `0x8301ab38` | +| InsufficientBalance | Thrown when there is insufficient balance. | `0xf4d678b8` | +| InvalidPermit | Thrown when the permit is invalid. | `0xddafbaef` | +| PermitExpired | Thrown when the permit has expired. | `0x1a15a3cc` | + +### Events + +| Name | Description | +| --------------------------------- | ------------------------------------ | +| Transfer(address,address,uint256) | Emitted when tokens are transferred. | +| Approval(address,address,uint256) | Emitted when allowances are updated. | From 9f6b5bbdcd6f857102bf398595d453ef94bcd470 Mon Sep 17 00:00:00 2001 From: 0xlgtm Date: Tue, 7 Nov 2023 03:31:07 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=F0=9F=93=9D=20Updates=20to=20ERC20=20docs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/tokens/erc20.md | 305 ++++++++++++++++++------------------------- 1 file changed, 125 insertions(+), 180 deletions(-) diff --git a/docs/tokens/erc20.md b/docs/tokens/erc20.md index deee5664d..224908443 100644 --- a/docs/tokens/erc20.md +++ b/docs/tokens/erc20.md @@ -12,89 +12,11 @@ Solady's ERC20 token implementation is an opinionated and highly optimized imple - transfer zero tokens - self approvals - Every function can be overridden with the `override` keyword if a custom implementation is required. -- The `permit` function uses the ecrecover precompile (0x1). - -## Example usage - -### Foundry - -1. Create a new [foundry](https://github.com/foundry-rs/foundry) repository and navigate to the root folder. - -```bash -$ forge init -$ cd -``` - -2. Install the Solady library - -```bash -$ forge install vectorized/solady -``` - -3. Create a file called `MyToken.sol` in the `/src` folder. - -```bash -$ touch src/MyToken.sol -``` - -4. Copy the following implementation into the `MyToken.sol` file. - -```solidity -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.4; - -import {ERC20} from "solady/src/tokens/ERC20.sol"; - -contract MyToken is ERC20 { - function name() public view override returns (string memory) { - return "Mytoken"; - } - - function symbol() public view override returns (string memory) { - return "MYT"; - } -} -``` - -## Gas Benchmarks - -| Function name | [Solady](https://github.com/Vectorized/solady/blob/main/src/tokens/ERC20.sol) | [OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/extensions/ERC20Permit.sol) | -| ---------------- | ------ | ------------ | -| DOMAIN_SEPERATOR | 488 | 386 | -| allowance | 700 | 814 | -| approve | 24403 | 24762 | -| burn | 2141 | 2439 | -| decimals | 222 | 222 | -| mint | 24649 | 24978 | -| name | 494 | 3241 | -| nonces | 555 | 616 | -| permit | 50437 | 51478 | -| symbol | 542 | 3306 | -| transfer | 2235 | 2613 | -| transferFrom | 2577 | 3295 | +- The `permit` function uses the ecrecover precompile (0x1). ## API Reference -### Functions - -| Name | Description | -| ------------------------------------- | ------------------------------------------------------------------------------------------------------------------ | -| [name](#name) | The name of the token. | -| [symbol](#symbol) | The symbol of the token. | -| [decimals](#decimals) | The number of decimals of the token. | -| [totalSupply](#totalsupply) | The amount of tokens in existence. | -| [balanceOf](#balanceof) | The amount of tokens owned by `owner`. | -| [allowance](#allowance) | The amount of tokens that `spender` can spend on behalf of `owner`. | -| [approve](#approve) | Sets `amount` as the allowance of `spender` over the caller's tokens. | -| [transfer](#transfer) | Transfer `amount` tokens from the caller to `to`. | -| [transferFrom](#transferfrom) | Transfers `amount` tokens from `from` to `to`. | -| [nonces](#nonces) | The current nonce for `owner`. | -| [permit](#permit) | Sets `value` as the allowance of `spender` over the tokens of `owner`, authorized by a signed approval by `owner`. | -| [DOMAIN_SEPARATOR](#domain_seperator) | The EIP-712 domain separator for the EIP-2612 permit. | - ---- - -#### name +### name Returns the name of the token. @@ -102,21 +24,21 @@ Returns the name of the token. function name() public view virtual returns (string memory) ``` -##### Parameter(s) +#### Parameter(s) - None -##### Return Value(s) +#### Return Value(s) -- The name of the token. +- string: The name of the token. -##### Note(s) +#### Note(s) - Must override or the contract will not compile. --- -#### symbol +### symbol Returns the symbol of the token. @@ -124,21 +46,21 @@ Returns the symbol of the token. function symbol() public view virtual returns (string memory) ``` -##### Parameter(s) +#### Parameter(s) - None -##### Return Value(s) +#### Return Value(s) -- The symbol of the token. +- string: The symbol of the token. -##### Note(s) +#### Note(s) - Must override or the contract will not compile. --- -#### decimals +### decimals Returns the number of decimals of the token. @@ -146,231 +68,231 @@ Returns the number of decimals of the token. function decimals() public view virtual returns (uint8) ``` -##### Parameter(s) +#### Parameter(s) - None -##### Return Value(s) +#### Return Value(s) -- The number of decimals of the token. +- uint8: The number of decimals of the token. -##### Note(s) +#### Note(s) - None --- -#### totalSupply +### totalSupply Returns the amount of tokens in existence. ```solidity -function totalSupply() public view virtual returns (uint256 result) +function totalSupply() public view virtual returns (uint256) ``` -##### Parameter(s) +#### Parameter(s) - None -##### Return Value(s) +#### Return Value(s) -- `result`: The number of tokens in existence. +- uint256: The number of tokens in existence. -##### Note(s) +#### Note(s) - None --- -#### balanceOf +### balanceOf -Returns the amount of tokens owned by `owner`. +Returns the amount of tokens owned by an address. ```solidity -function balanceOf(address owner) public view virtual returns (uint256 result) +function balanceOf(address) public view virtual returns (uint256) ``` -##### Parameter(s) +#### Parameter(s) -- `owner`: The address to query the token balance of. +- address: The address to query the token balance of. -##### Return Value(s) +#### Return Value(s) -- `result`: The amount of tokens owned by `owner`. +- uint256: The amount of tokens owned by the input address. -##### Note(s) +#### Note(s) - None --- -#### allowance +### allowance -Returns the amount of tokens that `spender` can spend on behalf of `owner`. +Returns the amount of tokens that a spender can spend on behalf of an owner. ```solidity -function allowance(address owner, address spender) public view virtual returns (uint256 result) +function allowance(address,address) public view virtual returns (uint256) ``` -##### Parameter(s) +#### Parameter(s) -- `owner`: The owner of the tokens. -- `spender`: The spender of the tokens. +- address: The owner of the tokens. +- address: The spender of the tokens. -##### Return Value(s) +#### Return Value(s) -- `result`: The amount of tokens that `spender` can spend on behalf of `owner`. +- uint256: The amount of tokens that the input spender can spend on behalf of the input owner. -##### Note(s) +#### Note(s) - None --- -#### approve +### approve -Sets `amount` as the allowance of `spender` over the caller's tokens. +Sets an amount of allowance for a spender over the caller's tokens. ```solidity -function approve(address spender, uint256 amount) public virtual returns (bool) +function approve(address,uint256) public virtual returns (bool) ``` -##### Parameter(s) +#### Parameter(s) -- `spender`: The spender of the tokens. -- `amount`: The amount to set as spender's allowance. +- address: The spender of the tokens. +- uint256: The amount to set as spender's allowance. -##### Return Value(s) +#### Return Value(s) -- `true` if `spender`'s allowance is updated successfully. +- bool: `true` -##### Note(s) +#### Note(s) -- Emits the `Approval` event if `spender`'s allowance is updated successfully. +- Emits the `Approval` event. --- -#### transfer +### transfer -Transfer `amount` tokens from the caller to `to`. +Transfer an amount of tokens from the caller to a recipient. ```solidity -function transfer(address to, uint256 amount) public virtual returns (bool) +function transfer(address,uint256) public virtual returns (bool) ``` -##### Parameter(s) +#### Parameter(s) -- `to`: The address to receive the tokens. -- `amount`: The amount of tokens to transfer from the caller. +- address: The recipient address to receive the tokens. +- uint256: The amount of tokens to transfer from the caller. -##### Return Value(s) +#### Return Value(s) -- `true` if `amount` tokens are transferred from the caller to `to` successfully. +- bool: `true` if it does not revert with `InsufficientBalance`. -##### Note(s) +#### Note(s) -- Emits the `Transfer` event if `amount` of tokens are transferred from the caller to `to` successfully. +- Emits the `Transfer` event. - Reverts with the `InsufficientBalance` error if caller does not have enough tokens. --- -#### transferFrom +### transferFrom -Transfers `amount` tokens from `from` to `to`. +Transfers an amount of tokens from an owner to a recipient. ```solidity -transferFrom(address from, address to, uint256 amount) public virtual returns (bool) +transferFrom(address,address,uint256) public virtual returns (bool) ``` -##### Parameter(s) +#### Parameter(s) -- `from`: The address to transfer the tokens from. -- `to`: The address to transfer the tokens to. -- `amount`: The amount of tokens to be transferred. +- address: The owner address to transfer the tokens from. +- address: The recipient address to receive the tokens. +- uint256: The amount of tokens to be transferred. -##### Return Value(s) +#### Return Value(s) -- `true` if `amount` of tokens are transferred from `from` to `to`. +- bool: `true` if it does not revert with `InsufficientAllowance` or `InsufficientBalance`. -##### Note(s) +#### Note(s) -- Emits the `Transfer` event if `amount` of tokens are transferred from `from` to `to` successfully. +- Emits the `Transfer` event. - Does not update caller's allowance if allowance is `type(uint256).max`. - Reverts with `InsufficientAllowance` error if the caller does not have enough allowance. -- Reverts with `InsufficientBalance` error if `from` does not have enough tokens. +- Reverts with `InsufficientBalance` error if the input owner does not have enough tokens. --- -#### nonces +### nonces -Returns the current nonce for `owner`. +Returns the current nonce of an address. ```solidity -function nonces(address owner) public view virtual returns (uint256 result) +function nonces(address) public view virtual returns (uint256) ``` -##### Parameter(s) +#### Parameter(s) -- `owner`: The address to query the nonce of. +- address: The address to query the nonce of. -##### Return Value(s) +#### Return Value(s) -- `result`: The current nonce of the `owner`. +- uint256: The current nonce of the input address. -##### Note(s) +#### Note(s) - This value is used to compute the signature for [EIP-2612 permit](https://eips.ethereum.org/EIPS/eip-2612). --- -#### permit +### permit -Sets `value` as the allowance of `spender` over the tokens of `owner`, authorized by a signed approval by `owner`. +Sets an amount of allowance for a spender over an owner's tokens, authorized by a signed approval by the owner. ```solidity -function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public virtual +function permit(address,address,uint256,uint256,uint8,bytes32,bytes32) public virtual ``` -##### Parameter(s) +#### Parameter(s) -- `owner`: The owner of the tokens. -- `spender`: The spender of the tokens. -- `value`: The amount to set as spender's allowance. -- `deadline`: The deadline of the signature. -- `v`: The v component of the signature. -- `r`: The r component of the signature. -- `s`: The s component of the signature. +- address: The owner of the tokens. +- address: The spender of the tokens. +- uint256: The amount to set as spender's allowance. +- uint256: The deadline of the signature. +- uint8: The v component of the signature. +- bytes32: The r component of the signature. +- bytes32: The s component of the signature. -##### Return Value(s) +#### Return Value(s) - None -##### Note(s) +#### Note(s) -- Emits the `Approval` event if `spender`'s allowance is updated successfully. -- `owner`'s nonce will be incremented by 1 if `permit` is successful. -- Reverts with `PermitExpired` error if the current timestamp is greater than `deadline`. -- Reverts with `InvalidPermit` error if the address recovered does not match the `owner`. +- Emits the `Approval` if it does not revert with `PermitExpired` or `InvalidPermit`. +- The input owner's nonce will be incremented by 1 if `permit` is successful. +- Reverts with `PermitExpired` error if the current timestamp is greater than the input deadline. +- Reverts with `InvalidPermit` error if the address recovered does not match the input owner. --- -#### DOMAIN_SEPERATOR +### DOMAIN_SEPERATOR Returns the EIP-712 domain separator for the EIP-2612 permit. ```solidity -function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) +function DOMAIN_SEPARATOR() public view virtual returns (bytes32) ``` -##### Parameter(s) +#### Parameter(s) - None -##### Return Value(s) +#### Return Value(s) -- `result`: The EIP-712 domain separator for the EIP-2612 permit. +- bytes32: The EIP-712 domain separator for the EIP-2612 permit. -##### Note(s) +#### Note(s) - None @@ -387,9 +309,32 @@ function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) | InvalidPermit | Thrown when the permit is invalid. | `0xddafbaef` | | PermitExpired | Thrown when the permit has expired. | `0x1a15a3cc` | +--- + ### Events | Name | Description | | --------------------------------- | ------------------------------------ | | Transfer(address,address,uint256) | Emitted when tokens are transferred. | | Approval(address,address,uint256) | Emitted when allowances are updated. | + +--- + + +### Constants + +| Name | Value | +| ---------------------------------------- | ------------------------------------------------------------------ | +| \_TRANSFER_EVENT_SIGNATURE | 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef | +| \_APPROVAL_EVENT_SIGNATURE | 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925 | +| \_TOTAL_SUPPLY_SLOT | 0x05345cdf77eb68f44c | +| \_BALANCE_SLOT_SEED | 0x87a211a2 | +| \_ALLOWANCE_SLOT_SEED | 0x7f5e9f20 | +| \_NONCES_SLOT_SEED | 0x38377508 | +| \_NONCES_SLOT_SEED_WITH_SIGNATURE_PREFIX | 0x383775081901 | +| \_DOMAIN_TYPEHASH | 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f | +| \_VERSION_HASH | 0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6 | +| \_PERMIT_TYPEHASH | 0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9 | + + +---