diff --git a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap index 27ca5b34..85a1adbe 100644 --- a/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap +++ b/.forge-snapshots/permitBatchTransferFromMultipleTokens.snap @@ -1 +1 @@ -143500 \ No newline at end of file +143701 \ No newline at end of file diff --git a/.forge-snapshots/permitBatchTransferFromSingleToken.snap b/.forge-snapshots/permitBatchTransferFromSingleToken.snap index 6977b61a..40cd7da8 100644 --- a/.forge-snapshots/permitBatchTransferFromSingleToken.snap +++ b/.forge-snapshots/permitBatchTransferFromSingleToken.snap @@ -1 +1 @@ -88950 \ No newline at end of file +89017 \ No newline at end of file diff --git a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap index 33581732..91e8f6d4 100644 --- a/.forge-snapshots/permitTransferFromBatchTypedWitness.snap +++ b/.forge-snapshots/permitTransferFromBatchTypedWitness.snap @@ -1 +1 @@ -121317 \ No newline at end of file +121451 \ 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 effa30f9..e6558df0 100644 --- a/.forge-snapshots/single recipient 2 tokens.snap +++ b/.forge-snapshots/single recipient 2 tokens.snap @@ -1 +1 @@ -118623 \ No newline at end of file +118757 \ 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 9493e70d..497b063b 100644 --- a/.forge-snapshots/single recipient many tokens.snap +++ b/.forge-snapshots/single recipient many tokens.snap @@ -1 +1 @@ -133765 \ No newline at end of file +134435 \ No newline at end of file diff --git a/.gas-snapshot b/.gas-snapshot index 02a741cf..32bba8d2 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -50,28 +50,29 @@ Permit2LibTest:testTransferFrom2() (gas: 38404) Permit2LibTest:testTransferFrom2Full() (gas: 53437) Permit2LibTest:testTransferFrom2InvalidAmount() (gas: 12519) Permit2LibTest:testTransferFrom2NonPermitToken() (gas: 53305) -SignatureTransferTest:testGasMultiplePermitBatchTransferFrom() (gas: 270959) -SignatureTransferTest:testGasSinglePermitBatchTransferFrom() (gas: 186309) -SignatureTransferTest:testGasSinglePermitTransferFrom() (gas: 124095) -SignatureTransferTest:testInvalidateUnorderedNonces() (gas: 56540) -SignatureTransferTest:testPermitBatchTransferFrom() (gas: 162076) -SignatureTransferTest:testPermitBatchTransferFromSingleRecipient() (gas: 190355) -SignatureTransferTest:testPermitBatchTransferFromTypedWitness() (gas: 242493) +SignatureTransferTest:testGasMultiplePermitBatchTransferFrom() (gas: 271182) +SignatureTransferTest:testGasSinglePermitBatchTransferFrom() (gas: 186398) +SignatureTransferTest:testGasSinglePermitTransferFrom() (gas: 124117) +SignatureTransferTest:testInvalidateUnorderedNonces() (gas: 56562) +SignatureTransferTest:testPermitBatchMultiPermitSingleTransfer() (gas: 133761) +SignatureTransferTest:testPermitBatchTransferFrom() (gas: 162210) +SignatureTransferTest:testPermitBatchTransferFromSingleRecipient() (gas: 190511) +SignatureTransferTest:testPermitBatchTransferFromTypedWitness() (gas: 242649) SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidType() (gas: 87340) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeHash() (gas: 86803) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeName() (gas: 88276) -SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidWitness() (gas: 88321) -SignatureTransferTest:testPermitBatchTransferInvalidAmountsLengthMismatch() (gas: 43738) -SignatureTransferTest:testPermitBatchTransferMultiAddr() (gas: 160450) -SignatureTransferTest:testPermitBatchTransferSingleRecipientManyTokens() (gas: 211974) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeHash() (gas: 86825) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidTypeName() (gas: 88298) +SignatureTransferTest:testPermitBatchTransferFromTypedWitnessInvalidWitness() (gas: 88343) +SignatureTransferTest:testPermitBatchTransferInvalidAmountsLengthMismatch() (gas: 43760) +SignatureTransferTest:testPermitBatchTransferMultiAddr() (gas: 160606) +SignatureTransferTest:testPermitBatchTransferSingleRecipientManyTokens() (gas: 212666) SignatureTransferTest:testPermitTransferFrom() (gas: 93208) -SignatureTransferTest:testPermitTransferFromCompactSig() (gas: 124159) +SignatureTransferTest:testPermitTransferFromCompactSig() (gas: 124181) SignatureTransferTest:testPermitTransferFromIncorrectSigLength() (gas: 51430) -SignatureTransferTest:testPermitTransferFromInvalidNonce() (gas: 93215) -SignatureTransferTest:testPermitTransferFromRandomNonceAndAmount(uint256,uint128) (runs: 256, μ: 95842, ~: 96818) -SignatureTransferTest:testPermitTransferFromToSpender() (gas: 93494) +SignatureTransferTest:testPermitTransferFromInvalidNonce() (gas: 93237) +SignatureTransferTest:testPermitTransferFromRandomNonceAndAmount(uint256,uint128) (runs: 256, μ: 95864, ~: 96840) +SignatureTransferTest:testPermitTransferFromToSpender() (gas: 93516) SignatureTransferTest:testPermitTransferFromTypedWitness() (gas: 127964) -SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidType() (gas: 58668) -SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidTypeName() (gas: 59722) -SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidTypehash() (gas: 57658) -SignatureTransferTest:testPermitTransferSpendLessThanFull(uint256,uint128) (runs: 256, μ: 98177, ~: 99895) +SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidType() (gas: 58690) +SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidTypeName() (gas: 59744) +SignatureTransferTest:testPermitTransferFromTypedWitnessInvalidTypehash() (gas: 57680) +SignatureTransferTest:testPermitTransferSpendLessThanFull(uint256,uint128) (runs: 256, μ: 98199, ~: 99917) diff --git a/src/SignatureTransfer.sol b/src/SignatureTransfer.sol index c58529e6..ae5940db 100644 --- a/src/SignatureTransfer.sol +++ b/src/SignatureTransfer.sol @@ -123,7 +123,10 @@ contract SignatureTransfer is ISignatureTransfer, EIP712 { if (requestedAmount > permitted.amount) revert InvalidAmount(); - 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); + } } } } diff --git a/test/SignatureTransfer.t.sol b/test/SignatureTransfer.t.sol index 731f1bfb..9692511b 100644 --- a/test/SignatureTransfer.t.sol +++ b/test/SignatureTransfer.t.sol @@ -186,7 +186,6 @@ contract SignatureTransferTest is Test, PermitSignature, TokenProvider, GasSnaps ISignatureTransfer.PermitBatchTransferFrom memory permit = defaultERC20PermitMultiple(tokens, nonce); bytes memory sig = getPermitBatchTransferSignature(permit, fromPrivateKey, DOMAIN_SEPARATOR); - // address(0) gets sent to spender address[] memory to = AddressBuilder.fill(1, address(address2)).push(address(address0)); ISignatureTransfer.SignatureTransferDetails[] memory toAmountPairs = StructBuilder.fillSigTransferDetails(defaultAmount, to); @@ -204,6 +203,34 @@ contract SignatureTransferTest is Test, PermitSignature, TokenProvider, GasSnaps assertEq(token1.balanceOf(address0), startBalanceTo1 + defaultAmount); } + function testPermitBatchMultiPermitSingleTransfer() public { + uint256 nonce = 0; + address[] memory tokens = AddressBuilder.fill(1, address(token0)).push(address(token1)); + ISignatureTransfer.PermitBatchTransferFrom memory permit = defaultERC20PermitMultiple(tokens, nonce); + + bytes memory sig = getPermitBatchTransferSignature(permit, fromPrivateKey, DOMAIN_SEPARATOR); + + // must fill address to even though token0 wont get sent. + // transfer details must be lenght of permit + address[] memory to = AddressBuilder.fill(1, address(address0)).push(address(address0)); + ISignatureTransfer.SignatureTransferDetails[] memory toAmountPairs = + StructBuilder.fillSigTransferDetails(defaultAmount, to); + // spender doesnt need token0 even though user permitted it + toAmountPairs[0].requestedAmount = 0; + + uint256 startBalanceFrom0 = token0.balanceOf(from); + uint256 startBalanceFrom1 = token1.balanceOf(from); + uint256 startBalanceTo0 = token0.balanceOf(address2); + uint256 startBalanceTo1 = token1.balanceOf(address0); + + permit2.permitTransferFrom(permit, from, toAmountPairs, sig); + + assertEq(token0.balanceOf(from), startBalanceFrom0); + assertEq(token1.balanceOf(from), startBalanceFrom1 - defaultAmount); + assertEq(token0.balanceOf(address2), startBalanceTo0); + assertEq(token1.balanceOf(address0), startBalanceTo1 + defaultAmount); + } + function testPermitBatchTransferFromSingleRecipient() public { uint256 nonce = 0; address[] memory tokens = AddressBuilder.fill(1, address(token0)).push(address(token1));