diff --git a/.forge-snapshots/lockdown.snap b/.forge-snapshots/lockdown.snap index a193479b..4ccb621d 100644 --- a/.forge-snapshots/lockdown.snap +++ b/.forge-snapshots/lockdown.snap @@ -1 +1 @@ -28435 \ No newline at end of file +28447 \ No newline at end of file diff --git a/.forge-snapshots/permitBatchCleanWrite.snap b/.forge-snapshots/permitBatchCleanWrite.snap index ff36c94f..92372b01 100644 --- a/.forge-snapshots/permitBatchCleanWrite.snap +++ b/.forge-snapshots/permitBatchCleanWrite.snap @@ -1 +1 @@ -91924 \ No newline at end of file +91826 \ No newline at end of file diff --git a/.forge-snapshots/permitBatchDirtyWrite.snap b/.forge-snapshots/permitBatchDirtyWrite.snap index 2020125e..ce14a661 100644 --- a/.forge-snapshots/permitBatchDirtyWrite.snap +++ b/.forge-snapshots/permitBatchDirtyWrite.snap @@ -1 +1 @@ -57724 \ No newline at end of file +57626 \ No newline at end of file diff --git a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap index bd650401..c71e74a3 100644 --- a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap +++ b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap @@ -1 +1 @@ -143387 \ No newline at end of file +143240 \ No newline at end of file diff --git a/.forge-snapshots/permitBatchTransferFromSingleToken.snap b/.forge-snapshots/permitBatchTransferFromSingleToken.snap index c1642c97..de1bdfcc 100644 --- a/.forge-snapshots/permitBatchTransferFromSingleToken.snap +++ b/.forge-snapshots/permitBatchTransferFromSingleToken.snap @@ -1 +1 @@ -88867 \ No newline at end of file +88818 \ No newline at end of file diff --git a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap index 3adcc82d..62d87846 100644 --- a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap +++ b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap @@ -1 +1 @@ -120325 \ No newline at end of file +120227 \ No newline at end of file diff --git a/.forge-snapshots/single recipient 2 tokens.snap b/.forge-snapshots/single recipient 2 tokens.snap index 37c51f05..2e7ed90e 100644 --- a/.forge-snapshots/single recipient 2 tokens.snap +++ b/.forge-snapshots/single recipient 2 tokens.snap @@ -1 +1 @@ -118525 \ No newline at end of file +118427 \ No newline at end of file diff --git a/.forge-snapshots/single recipient many tokens.snap b/.forge-snapshots/single recipient many tokens.snap index 770e7a83..76ad6a7a 100644 --- a/.forge-snapshots/single recipient many tokens.snap +++ b/.forge-snapshots/single recipient many tokens.snap @@ -1 +1 @@ -133544 \ No newline at end of file +133054 \ No newline at end of file diff --git a/.gas-snapshot b/.gas-snapshot index cf5cca81..65154378 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,26 +1,26 @@ -AllowanceTransferInvariants:invariant_balanceEqualsSpent() (runs: 256, calls: 3840, reverts: 886) -AllowanceTransferInvariants:invariant_permit2NeverHoldsBalance() (runs: 256, calls: 3840, reverts: 886) -AllowanceTransferInvariants:invariant_spendNeverExceedsPermit() (runs: 256, calls: 3840, reverts: 886) +AllowanceTransferInvariants:invariant_balanceEqualsSpent() (runs: 256, calls: 3840, reverts: 885) +AllowanceTransferInvariants:invariant_permit2NeverHoldsBalance() (runs: 256, calls: 3840, reverts: 885) +AllowanceTransferInvariants:invariant_spendNeverExceedsPermit() (runs: 256, calls: 3840, reverts: 885) AllowanceTransferTest:testApprove() (gas: 47561) AllowanceTransferTest:testBatchTransferFrom() (gas: 159268) AllowanceTransferTest:testBatchTransferFromDifferentOwners() (gas: 235508) -AllowanceTransferTest:testBatchTransferFromMultiToken() (gas: 231810) +AllowanceTransferTest:testBatchTransferFromMultiToken() (gas: 231712) AllowanceTransferTest:testBatchTransferFromWithGasSnapshot() (gas: 159818) AllowanceTransferTest:testExcessiveInvalidation() (gas: 64136) AllowanceTransferTest:testInvalidateMultipleNonces() (gas: 83139) AllowanceTransferTest:testInvalidateNonces() (gas: 62679) AllowanceTransferTest:testInvalidateNoncesInvalid() (gas: 16261) -AllowanceTransferTest:testLockdown() (gas: 145952) -AllowanceTransferTest:testLockdownEvent() (gas: 117758) +AllowanceTransferTest:testLockdown() (gas: 145866) +AllowanceTransferTest:testLockdownEvent() (gas: 117672) AllowanceTransferTest:testMaxAllowance() (gas: 134993) AllowanceTransferTest:testMaxAllowanceDirtyWrite() (gas: 117582) AllowanceTransferTest:testPartialAllowance() (gas: 105067) AllowanceTransferTest:testReuseOrderedNonceInvalid() (gas: 69095) AllowanceTransferTest:testSetAllowance() (gas: 89583) -AllowanceTransferTest:testSetAllowanceBatch() (gas: 133608) -AllowanceTransferTest:testSetAllowanceBatchDifferentNonces() (gas: 118583) -AllowanceTransferTest:testSetAllowanceBatchDirtyWrite() (gas: 99144) -AllowanceTransferTest:testSetAllowanceBatchEvent() (gas: 115892) +AllowanceTransferTest:testSetAllowanceBatch() (gas: 133510) +AllowanceTransferTest:testSetAllowanceBatchDifferentNonces() (gas: 118485) +AllowanceTransferTest:testSetAllowanceBatchDirtyWrite() (gas: 99046) +AllowanceTransferTest:testSetAllowanceBatchEvent() (gas: 115794) AllowanceTransferTest:testSetAllowanceCompactSig() (gas: 89543) AllowanceTransferTest:testSetAllowanceDeadlinePassed() (gas: 56500) AllowanceTransferTest:testSetAllowanceDirtyWrite() (gas: 72175) @@ -72,20 +72,20 @@ Permit2LibTest:testTransferFrom2Full() (gas: 53258) Permit2LibTest:testTransferFrom2InvalidAmount() (gas: 12710) Permit2LibTest:testTransferFrom2NonPermitToken() (gas: 53104) SignatureTransferTest:testCorrectWitnessTypehashes() (gas: 3075) -SignatureTransferTest:testGasMultiplePermitBatchTransferFrom() (gas: 270919) -SignatureTransferTest:testGasSinglePermitBatchTransferFrom() (gas: 186316) +SignatureTransferTest:testGasMultiplePermitBatchTransferFrom() (gas: 270772) +SignatureTransferTest:testGasSinglePermitBatchTransferFrom() (gas: 186267) SignatureTransferTest:testGasSinglePermitTransferFrom() (gas: 123850) SignatureTransferTest:testInvalidateUnorderedNonces() (gas: 41268) -SignatureTransferTest:testPermitBatchMultiPermitSingleTransfer() (gas: 133644) -SignatureTransferTest:testPermitBatchTransferFrom() (gas: 162010) -SignatureTransferTest:testPermitBatchTransferFromSingleRecipient() (gas: 190319) -SignatureTransferTest:testPermitBatchTransferFromTypedWitness() (gas: 239854) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidType() (gas: 84467) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeHash() (gas: 85864) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidWitness() (gas: 85688) -SignatureTransferTest:testPermitBatchTransferInvalidAmountsLengthMismatch() (gas: 43967) -SignatureTransferTest:testPermitBatchTransferMultiAddr() (gas: 160406) -SignatureTransferTest:testPermitBatchTransferSingleRecipientManyTokens() (gas: 211834) +SignatureTransferTest:testPermitBatchMultiPermitSingleTransfer() (gas: 133546) +SignatureTransferTest:testPermitBatchTransferFrom() (gas: 161912) +SignatureTransferTest:testPermitBatchTransferFromSingleRecipient() (gas: 190221) +SignatureTransferTest:testPermitBatchTransferFromTypedWitness() (gas: 239756) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidType() (gas: 84369) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeHash() (gas: 85766) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidWitness() (gas: 85590) +SignatureTransferTest:testPermitBatchTransferInvalidAmountsLengthMismatch() (gas: 43869) +SignatureTransferTest:testPermitBatchTransferMultiAddr() (gas: 160308) +SignatureTransferTest:testPermitBatchTransferSingleRecipientManyTokens() (gas: 211344) SignatureTransferTest:testPermitTransferFrom() (gas: 93012) SignatureTransferTest:testPermitTransferFromCompactSig() (gas: 123927) SignatureTransferTest:testPermitTransferFromIncorrectSigLength() (gas: 51327) @@ -96,14 +96,14 @@ SignatureTransferTest:testPermitTransferFromTypedWitness() (gas: 125271) SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidType() (gas: 55906) SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidTypehash() (gas: 56794) SignatureTransferTest:testPermitTransferSpendLessThanFull(uint256,uint128) (runs: 256, μ: 97989, ~: 99707) -TypehashGeneration:testPermitBatch() (gas: 40493) -TypehashGeneration:testPermitBatchTransferFrom() (gas: 49854) -TypehashGeneration:testPermitBatchTransferFromWithWitness() (gas: 56587) -TypehashGeneration:testPermitBatchTransferFromWithWitnessIncorrectPermitData() (gas: 56744) -TypehashGeneration:testPermitBatchTransferFromWithWitnessIncorrectTypehashStub() (gas: 57229) +TypehashGeneration:testPermitBatch() (gas: 40400) +TypehashGeneration:testPermitBatchTransferFrom() (gas: 49756) +TypehashGeneration:testPermitBatchTransferFromWithWitness() (gas: 56489) +TypehashGeneration:testPermitBatchTransferFromWithWitnessIncorrectPermitData() (gas: 56646) +TypehashGeneration:testPermitBatchTransferFromWithWitnessIncorrectTypehashStub() (gas: 57131) TypehashGeneration:testPermitSingle() (gas: 28117) TypehashGeneration:testPermitTransferFrom() (gas: 36520) TypehashGeneration:testPermitTransferFromWithWitness() (gas: 43369) TypehashGeneration:testPermitTransferFromWithWitnessIncorrectPermitData() (gas: 43430) TypehashGeneration:testPermitTransferFromWithWitnessIncorrectTypehashStub() (gas: 43833) -MockPermit2Lib:testPermit2Code(address):(bool) (runs: 256, μ: 3025, ~: 3016) +MockPermit2Lib:testPermit2Code(address):(bool) (runs: 256, μ: 3035, ~: 3016) diff --git a/src/AllowanceTransfer.sol b/src/AllowanceTransfer.sol index ddf3781e..c224504f 100644 --- a/src/AllowanceTransfer.sol +++ b/src/AllowanceTransfer.sol @@ -47,10 +47,12 @@ contract AllowanceTransfer is IAllowanceTransfer, EIP712 { signature.verify(_hashTypedData(permitBatch.hash()), owner); address spender = permitBatch.spender; - unchecked { - uint256 length = permitBatch.details.length; - for (uint256 i = 0; i < length; ++i) { - _updateApproval(permitBatch.details[i], owner, spender); + + uint256 length = permitBatch.details.length; + for (uint256 i = 0; i < length;) { + _updateApproval(permitBatch.details[i], owner, spender); + unchecked { + ++i; } } } @@ -62,11 +64,12 @@ contract AllowanceTransfer is IAllowanceTransfer, EIP712 { /// @inheritdoc IAllowanceTransfer function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external { - unchecked { - uint256 length = transferDetails.length; - for (uint256 i = 0; i < length; ++i) { - AllowanceTransferDetails memory transferDetail = transferDetails[i]; - _transfer(transferDetail.from, transferDetail.to, transferDetail.amount, transferDetail.token); + uint256 length = transferDetails.length; + for (uint256 i = 0; i < length;) { + AllowanceTransferDetails memory transferDetail = transferDetails[i]; + _transfer(transferDetail.from, transferDetail.to, transferDetail.amount, transferDetail.token); + unchecked { + ++i; } } } @@ -97,14 +100,16 @@ contract AllowanceTransfer is IAllowanceTransfer, EIP712 { function lockdown(TokenSpenderPair[] calldata approvals) external { address owner = msg.sender; // Revoke allowances for each pair of spenders and tokens. - unchecked { - uint256 length = approvals.length; - for (uint256 i = 0; i < length; ++i) { - address token = approvals[i].token; - address spender = approvals[i].spender; - allowance[owner][token][spender].amount = 0; - emit Lockdown(owner, token, spender); + uint256 length = approvals.length; + for (uint256 i = 0; i < length;) { + address token = approvals[i].token; + address spender = approvals[i].spender; + + allowance[owner][token][spender].amount = 0; + emit Lockdown(owner, token, spender); + unchecked { + ++i; } } } diff --git a/src/SignatureTransfer.sol b/src/SignatureTransfer.sol index c026553a..31e977dd 100644 --- a/src/SignatureTransfer.sol +++ b/src/SignatureTransfer.sol @@ -111,17 +111,19 @@ contract SignatureTransfer is ISignatureTransfer, EIP712 { _useUnorderedNonce(owner, permit.nonce); signature.verify(_hashTypedData(dataHash), owner); - unchecked { - for (uint256 i = 0; i < numPermitted; ++i) { - TokenPermissions memory permitted = permit.permitted[i]; - uint256 requestedAmount = transferDetails[i].requestedAmount; + for (uint256 i = 0; i < numPermitted;) { + TokenPermissions memory permitted = permit.permitted[i]; + uint256 requestedAmount = transferDetails[i].requestedAmount; - if (requestedAmount > permitted.amount) revert InvalidAmount(permitted.amount); + if (requestedAmount > permitted.amount) revert InvalidAmount(permitted.amount); - if (requestedAmount != 0) { - // allow spender to specify which of the permitted tokens should be transferred - ERC20(permitted.token).safeTransferFrom(owner, transferDetails[i].to, requestedAmount); - } + if (requestedAmount != 0) { + // allow spender to specify which of the permitted tokens should be transferred + ERC20(permitted.token).safeTransferFrom(owner, transferDetails[i].to, requestedAmount); + } + + unchecked { + ++i; } } } diff --git a/src/libraries/Allowance.sol b/src/libraries/Allowance.sol index 671c9724..1bd38091 100644 --- a/src/libraries/Allowance.sol +++ b/src/libraries/Allowance.sol @@ -37,7 +37,7 @@ library Allowance { uint48 expiration ) internal { // If the inputted expiration is 0, the allowance only lasts the duration of the block. - allowed.expiration = expiration == 0 ? uint48(block.timestamp) : expiration; + allowed.expiration = expiration == BLOCK_TIMESTAMP_EXPIRATION ? uint48(block.timestamp) : expiration; allowed.amount = amount; } diff --git a/src/libraries/PermitHash.sol b/src/libraries/PermitHash.sol index 32d4a83f..50c87f0c 100644 --- a/src/libraries/PermitHash.sol +++ b/src/libraries/PermitHash.sol @@ -43,8 +43,11 @@ library PermitHash { function hash(IAllowanceTransfer.PermitBatch memory permitBatch) internal pure returns (bytes32) { uint256 numPermits = permitBatch.details.length; bytes32[] memory permitHashes = new bytes32[](numPermits); - for (uint256 i = 0; i < numPermits; ++i) { + for (uint256 i = 0; i < numPermits;) { permitHashes[i] = _hashPermitDetails(permitBatch.details[i]); + unchecked { + ++i; + } } return keccak256( abi.encode( @@ -67,8 +70,11 @@ library PermitHash { uint256 numPermitted = permit.permitted.length; bytes32[] memory tokenPermissionHashes = new bytes32[](numPermitted); - for (uint256 i = 0; i < numPermitted; ++i) { + for (uint256 i = 0; i < numPermitted;) { tokenPermissionHashes[i] = _hashTokenPermissions(permit.permitted[i]); + unchecked { + ++i; + } } return keccak256( @@ -104,8 +110,11 @@ library PermitHash { uint256 numPermitted = permit.permitted.length; bytes32[] memory tokenPermissionHashes = new bytes32[](numPermitted); - for (uint256 i = 0; i < numPermitted; ++i) { + for (uint256 i = 0; i < numPermitted;) { tokenPermissionHashes[i] = _hashTokenPermissions(permit.permitted[i]); + unchecked { + ++i; + } } return keccak256(