From 34d8da0443822857d0ed9dbf4ec905cd03fbb74a Mon Sep 17 00:00:00 2001 From: Sennett Lau Date: Thu, 20 Oct 2022 02:31:37 +0800 Subject: [PATCH 1/4] Add gas optimization by implementing unchecked index increment in for loops --- gas-snapshot | 26 +++++++++++++------------- src/PBTSimple.sol | 10 ++++++++-- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/gas-snapshot b/gas-snapshot index 03365c5..23861f7 100644 --- a/gas-snapshot +++ b/gas-snapshot @@ -1,21 +1,21 @@ ERC721ReadOnlyTest:testApprove() (gas: 10677) -ERC721ReadOnlyTest:testGetApproved() (gas: 16236) +ERC721ReadOnlyTest:testGetApproved() (gas: 16241) ERC721ReadOnlyTest:testIsApprovedForAll() (gas: 10051) ERC721ReadOnlyTest:testSetApprovalForAll() (gas: 10714) ERC721ReadOnlyTest:testTransferFunctions() (gas: 19077) -PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127965) -PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122516) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131807) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122355) -PBTSimpleTest:testIsChipSignatureForToken() (gas: 216733) -PBTSimpleTest:testMintTokenWithChip() (gas: 176613) -PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115251) -PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212298) +PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127811) +PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122357) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131653) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122191) +PBTSimpleTest:testIsChipSignatureForToken() (gas: 216594) +PBTSimpleTest:testMintTokenWithChip() (gas: 176454) +PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115137) +PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212184) PBTSimpleTest:testSeedChipToTokenMappingInvalidInput() (gas: 17175) PBTSimpleTest:testSupportsInterface() (gas: 7059) -PBTSimpleTest:testTokenIdFor() (gas: 117085) -PBTSimpleTest:testTokenIdMappedFor() (gas: 66779) -PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211915, ~: 211834) -PBTSimpleTest:testUpdateChips() (gas: 171055) +PBTSimpleTest:testTokenIdFor() (gas: 117028) +PBTSimpleTest:testTokenIdMappedFor() (gas: 66722) +PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211757, ~: 211675) +PBTSimpleTest:testUpdateChips() (gas: 170868) PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16433) PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23430) diff --git a/src/PBTSimple.sol b/src/PBTSimple.sol index 01fb588..325359b 100644 --- a/src/PBTSimple.sol +++ b/src/PBTSimple.sol @@ -48,13 +48,16 @@ contract PBTSimple is ERC721ReadOnly, IPBT { if (tokenIds.length != chipAddresses.length) { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < tokenIds.length; ++i) { + for (uint256 i = 0; i < tokenIds.length;) { address chipAddress = chipAddresses[i]; uint256 tokenId = tokenIds[i]; if (throwIfTokenAlreadyMinted && _exists(tokenId)) { revert SeedingChipDataForExistingToken(); } _tokenDatas[chipAddress] = TokenData(tokenId, chipAddress, true); + unchecked { + i++; + } } } @@ -66,7 +69,7 @@ contract PBTSimple is ERC721ReadOnly, IPBT { if (chipAddressesOld.length != chipAddressesNew.length) { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < chipAddressesOld.length; ++i) { + for (uint256 i = 0; i < chipAddressesOld.length;) { address oldChipAddress = chipAddressesOld[i]; TokenData memory oldTokenData = _tokenDatas[oldChipAddress]; if (!oldTokenData.set) { @@ -79,6 +82,9 @@ contract PBTSimple is ERC721ReadOnly, IPBT { emit PBTChipRemapping(tokenId, oldChipAddress, newChipAddress); } delete _tokenDatas[oldChipAddress]; + unchecked { + i++; + } } } From 6f0f31f0b2ecd13b40f67cdb5542896612e96554 Mon Sep 17 00:00:00 2001 From: Sennett Lau Date: Sat, 22 Oct 2022 10:02:54 +0800 Subject: [PATCH 2/4] update gas-snapshot after merge --- gas-snapshot | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gas-snapshot b/gas-snapshot index 3d4a93f..ab1d556 100644 --- a/gas-snapshot +++ b/gas-snapshot @@ -3,19 +3,19 @@ ERC721ReadOnlyTest:testGetApproved() (gas: 16241) ERC721ReadOnlyTest:testIsApprovedForAll() (gas: 10051) ERC721ReadOnlyTest:testSetApprovalForAll() (gas: 10714) ERC721ReadOnlyTest:testTransferFunctions() (gas: 19077) -PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127921) -PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122467) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131763) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122301) -PBTSimpleTest:testIsChipSignatureForToken() (gas: 216704) -PBTSimpleTest:testMintTokenWithChip() (gas: 176564) -PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115247) -PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212294) +PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127816) +PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122362) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131658) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122196) +PBTSimpleTest:testIsChipSignatureForToken() (gas: 216599) +PBTSimpleTest:testMintTokenWithChip() (gas: 176459) +PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115142) +PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212192) PBTSimpleTest:testSeedChipToTokenMappingInvalidInput() (gas: 17178) PBTSimpleTest:testSupportsInterface() (gas: 7059) -PBTSimpleTest:testTokenIdFor() (gas: 117084) -PBTSimpleTest:testTokenIdMappedFor() (gas: 66778) -PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211868, ~: 211785) -PBTSimpleTest:testUpdateChips() (gas: 171052) +PBTSimpleTest:testTokenIdFor() (gas: 117033) +PBTSimpleTest:testTokenIdMappedFor() (gas: 66727) +PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211762, ~: 211680) +PBTSimpleTest:testUpdateChips() (gas: 170872) PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16433) PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23430) From fa24a755fe236b7a30fc3f4b1c07171658435822 Mon Sep 17 00:00:00 2001 From: Sennett Lau Date: Sat, 22 Oct 2022 10:09:44 +0800 Subject: [PATCH 3/4] Add gas optimization by replacing for loop with do while loop with using chipAddressesOldLength to replace chipAddressesOld.length --- gas-snapshot | 28 ++++++++++++++-------------- src/PBTSimple.sol | 23 ++++++++++++++++++----- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/gas-snapshot b/gas-snapshot index ab1d556..0e77adb 100644 --- a/gas-snapshot +++ b/gas-snapshot @@ -3,19 +3,19 @@ ERC721ReadOnlyTest:testGetApproved() (gas: 16241) ERC721ReadOnlyTest:testIsApprovedForAll() (gas: 10051) ERC721ReadOnlyTest:testSetApprovalForAll() (gas: 10714) ERC721ReadOnlyTest:testTransferFunctions() (gas: 19077) -PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127816) -PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122362) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131658) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122196) -PBTSimpleTest:testIsChipSignatureForToken() (gas: 216599) -PBTSimpleTest:testMintTokenWithChip() (gas: 176459) -PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115142) -PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212192) +PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127775) +PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122321) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131617) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122155) +PBTSimpleTest:testIsChipSignatureForToken() (gas: 216558) +PBTSimpleTest:testMintTokenWithChip() (gas: 176418) +PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115101) +PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212146) PBTSimpleTest:testSeedChipToTokenMappingInvalidInput() (gas: 17178) PBTSimpleTest:testSupportsInterface() (gas: 7059) -PBTSimpleTest:testTokenIdFor() (gas: 117033) -PBTSimpleTest:testTokenIdMappedFor() (gas: 66727) -PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211762, ~: 211680) -PBTSimpleTest:testUpdateChips() (gas: 170872) -PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16433) -PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23430) +PBTSimpleTest:testTokenIdFor() (gas: 117009) +PBTSimpleTest:testTokenIdMappedFor() (gas: 66703) +PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211721, ~: 211639) +PBTSimpleTest:testUpdateChips() (gas: 170817) +PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16436) +PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23431) diff --git a/src/PBTSimple.sol b/src/PBTSimple.sol index e9815a6..5b90e3b 100644 --- a/src/PBTSimple.sol +++ b/src/PBTSimple.sol @@ -49,7 +49,13 @@ contract PBTSimple is ERC721ReadOnly, IPBT { if (tokenIdsLength != chipAddresses.length) { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < tokenIds.length;) { + + if (tokenIdsLength == 0) { + return; + } + + uint256 i = 0; + do { address chipAddress = chipAddresses[i]; uint256 tokenId = tokenIds[i]; if (throwIfTokenAlreadyMinted && _exists(tokenId)) { @@ -59,7 +65,7 @@ contract PBTSimple is ERC721ReadOnly, IPBT { unchecked { i++; } - } + } while (i < tokenIdsLength); } // Should only be called for tokenIds that have been minted @@ -67,10 +73,17 @@ contract PBTSimple is ERC721ReadOnly, IPBT { // Should only be used and called with care and rails to avoid a centralized entity swapping out valid chips. // TODO: consider preventing multiple chip addresses mapping to the same tokenId (store a tokenId->chip mapping) function _updateChips(address[] calldata chipAddressesOld, address[] calldata chipAddressesNew) internal { - if (chipAddressesOld.length != chipAddressesNew.length) { + uint256 chipAddressesOldLength = chipAddressesOld.length; + if (chipAddressesOldLength != chipAddressesNew.length) { revert ArrayLengthMismatch(); } - for (uint256 i = 0; i < chipAddressesOld.length;) { + + if (chipAddressesOldLength == 0) { + return; + } + + uint256 i = 0; + do { address oldChipAddress = chipAddressesOld[i]; TokenData memory oldTokenData = _tokenDatas[oldChipAddress]; if (!oldTokenData.set) { @@ -86,7 +99,7 @@ contract PBTSimple is ERC721ReadOnly, IPBT { unchecked { i++; } - } + } while (i < chipAddressesOldLength); } function tokenIdFor(address chipAddress) external view override returns (uint256) { From fc5e014a887c37e669c940b02bc659561b4e16e7 Mon Sep 17 00:00:00 2001 From: Sennett Lau Date: Fri, 28 Oct 2022 18:44:04 +0800 Subject: [PATCH 4/4] merge with v0.2.0 --- gas-snapshot | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/gas-snapshot b/gas-snapshot index 1be8ea8..69c3fe5 100644 --- a/gas-snapshot +++ b/gas-snapshot @@ -1,21 +1,21 @@ ERC721ReadOnlyTest:testApprove() (gas: 10677) -ERC721ReadOnlyTest:testGetApproved() (gas: 16236) +ERC721ReadOnlyTest:testGetApproved() (gas: 16241) ERC721ReadOnlyTest:testIsApprovedForAll() (gas: 10051) ERC721ReadOnlyTest:testSetApprovalForAll() (gas: 10714) ERC721ReadOnlyTest:testTransferFunctions() (gas: 19077) -PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127958) -PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122512) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131804) -PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122351) -PBTSimpleTest:testIsChipSignatureForToken() (gas: 217369) -PBTSimpleTest:testMintTokenWithChip() (gas: 176650) -PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115247) -PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212294) +PBTSimpleTest:testGetTokenDataForChipSignature() (gas: 127772) +PBTSimpleTest:testGetTokenDataForChipSignatureBlockNumTooOld() (gas: 122321) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalid() (gas: 131618) +PBTSimpleTest:testGetTokenDataForChipSignatureInvalidBlockNumber() (gas: 122155) +PBTSimpleTest:testIsChipSignatureForToken() (gas: 217173) +PBTSimpleTest:testMintTokenWithChip() (gas: 176459) +PBTSimpleTest:testSeedChipToTokenMapping() (gas: 115101) +PBTSimpleTest:testSeedChipToTokenMappingExistingToken() (gas: 212146) PBTSimpleTest:testSeedChipToTokenMappingInvalidInput() (gas: 17178) PBTSimpleTest:testSupportsInterface() (gas: 7059) -PBTSimpleTest:testTokenIdFor() (gas: 117084) -PBTSimpleTest:testTokenIdMappedFor() (gas: 66558) -PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211956, ~: 211875) -PBTSimpleTest:testUpdateChips() (gas: 171052) -PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16433) -PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23430) +PBTSimpleTest:testTokenIdFor() (gas: 117009) +PBTSimpleTest:testTokenIdMappedFor() (gas: 66483) +PBTSimpleTest:testTransferTokenWithChip(bool) (runs: 256, μ: 211765, ~: 211684) +PBTSimpleTest:testUpdateChips() (gas: 170817) +PBTSimpleTest:testUpdateChipsInvalidInput() (gas: 16436) +PBTSimpleTest:testUpdateChipsUnsetChip() (gas: 23431)