forge test --mt test_WithdrawMaxAndTransfer_SameRecipient -vvvv
[⠒] Compiling...
No files changed, compilation skipped
Ran 1 test for test/integration/concrete/lockup-dynamic/LockupDynamic.t.sol:WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test
[PASS] test_WithdrawMaxAndTransfer_SameRecipient() (gas: 136108)
Traces:
[136108] WithdrawMaxAndTransfer_LockupDynamic_Integration_Concrete_Test::test_WithdrawMaxAndTransfer_SameRecipient()
├─ [273] Defaults::WARP_26_PERCENT() [staticcall]
│ └─ ← [Return] 1714693400 [1.714e9]
├─ [0] VM::warp(1714693400 [1.714e9])
│ └─ ← [Return]
├─ [30405] LockupDynamic::withdrawableAmountOf(1) [staticcall]
│ └─ ← [Return] 3366025403784438632500 [3.366e21]
├─ [0] VM::expectCall(DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 0xa9059cbb00000000000000000000000003e9b88f4b1406163ef9ec4875a52e1e55953ec10000000000000000000000000000000000000000000000b678fc7ec668425034)
│ └─ ← [Return]
├─ [0] VM::expectEmit(LockupDynamic: [0x49c3486EC9f488230dD85FAc098929AeA9a3A898])
│ └─ ← [Return]
├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 3366025403784438632500 [3.366e21])
├─ [0] VM::expectEmit(LockupDynamic: [0x49c3486EC9f488230dD85FAc098929AeA9a3A898])
│ └─ ← [Return]
├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
├─ [0] VM::expectEmit(LockupDynamic: [0x49c3486EC9f488230dD85FAc098929AeA9a3A898])
│ └─ ← [Return]
├─ emit MetadataUpdate(_tokenId: 1)
├─ [74946] LockupDynamic::withdrawMaxAndTransfer(1, Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1])
│ ├─ [12866] DAI::transfer(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], 3366025403784438632500 [3.366e21])
│ │ ├─ emit Transfer(from: LockupDynamic: [0x49c3486EC9f488230dD85FAc098929AeA9a3A898], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], value: 3366025403784438632500 [3.366e21])
│ │ └─ ← [Return] true
│ ├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 3366025403784438632500 [3.366e21])
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ ├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ └─ ← [Stop]
├─ [845] LockupDynamic::getWithdrawnAmount(1) [staticcall]
│ └─ ← [Return] 3366025403784438632500 [3.366e21]
├─ [0] VM::assertEq(3366025403784438632500 [3.366e21], 3366025403784438632500 [3.366e21], "withdrawnAmount") [staticcall]
│ └─ ← [Return]
├─ [665] LockupDynamic::getRecipient(1) [staticcall]
│ └─ ← [Return] Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1]
├─ [0] VM::assertEq(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], "recipient") [staticcall]
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 6.15ms (344.68µs CPU time)
Ran 1 test for test/integration/concrete/lockup-tranched/LockupTranched.t.sol:WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test
[PASS] test_WithdrawMaxAndTransfer_SameRecipient() (gas: 100436)
Traces:
[100436] WithdrawMaxAndTransfer_LockupTranched_Integration_Concrete_Test::test_WithdrawMaxAndTransfer_SameRecipient()
├─ [273] Defaults::WARP_26_PERCENT() [staticcall]
│ └─ ← [Return] 1714693400 [1.714e9]
├─ [0] VM::warp(1714693400 [1.714e9])
│ └─ ← [Return]
├─ [19862] LockupTranched::withdrawableAmountOf(1) [staticcall]
│ └─ ← [Return] 2600000000000000000000 [2.6e21]
├─ [0] VM::expectCall(DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 0xa9059cbb00000000000000000000000003e9b88f4b1406163ef9ec4875a52e1e55953ec100000000000000000000000000000000000000000000008cf23f909c0fa00000)
│ └─ ← [Return]
├─ [0] VM::expectEmit(LockupTranched: [0x923b5Ab3714FD343316aF5A5434582Fd16722523])
│ └─ ← [Return]
├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 2600000000000000000000 [2.6e21])
├─ [0] VM::expectEmit(LockupTranched: [0x923b5Ab3714FD343316aF5A5434582Fd16722523])
│ └─ ← [Return]
├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
├─ [0] VM::expectEmit(LockupTranched: [0x923b5Ab3714FD343316aF5A5434582Fd16722523])
│ └─ ← [Return]
├─ emit MetadataUpdate(_tokenId: 1)
├─ [49817] LockupTranched::withdrawMaxAndTransfer(1, Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1])
│ ├─ [12866] DAI::transfer(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], 2600000000000000000000 [2.6e21])
│ │ ├─ emit Transfer(from: LockupTranched: [0x923b5Ab3714FD343316aF5A5434582Fd16722523], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], value: 2600000000000000000000 [2.6e21])
│ │ └─ ← [Return] true
│ ├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 2600000000000000000000 [2.6e21])
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ ├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ └─ ← [Stop]
├─ [845] LockupTranched::getWithdrawnAmount(1) [staticcall]
│ └─ ← [Return] 2600000000000000000000 [2.6e21]
├─ [0] VM::assertEq(2600000000000000000000 [2.6e21], 2600000000000000000000 [2.6e21], "withdrawnAmount") [staticcall]
│ └─ ← [Return]
├─ [665] LockupTranched::getRecipient(1) [staticcall]
│ └─ ← [Return] Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1]
├─ [0] VM::assertEq(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], "recipient") [staticcall]
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 10.83ms (294.71µs CPU time)
Ran 1 test for test/integration/concrete/lockup-linear/LockupLinear.t.sol:WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test
[PASS] test_WithdrawMaxAndTransfer_SameRecipient() (gas: 92432)
Traces:
[92432] WithdrawMaxAndTransfer_LockupLinear_Integration_Concrete_Test::test_WithdrawMaxAndTransfer_SameRecipient()
├─ [273] Defaults::WARP_26_PERCENT() [staticcall]
│ └─ ← [Return] 1714693400 [1.714e9]
├─ [0] VM::warp(1714693400 [1.714e9])
│ └─ ← [Return]
├─ [13202] LockupLinear::withdrawableAmountOf(1) [staticcall]
│ └─ ← [Return] 2600000000000000000000 [2.6e21]
├─ [0] VM::expectCall(DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], 0xa9059cbb00000000000000000000000003e9b88f4b1406163ef9ec4875a52e1e55953ec100000000000000000000000000000000000000000000008cf23f909c0fa00000)
│ └─ ← [Return]
├─ [0] VM::expectEmit(LockupLinear: [0x4a6eD11Fa3612925cF0E72459893Ed6e33984E83])
│ └─ ← [Return]
├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 2600000000000000000000 [2.6e21])
├─ [0] VM::expectEmit(LockupLinear: [0x4a6eD11Fa3612925cF0E72459893Ed6e33984E83])
│ └─ ← [Return]
├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
├─ [0] VM::expectEmit(LockupLinear: [0x4a6eD11Fa3612925cF0E72459893Ed6e33984E83])
│ └─ ← [Return]
├─ emit MetadataUpdate(_tokenId: 1)
├─ [48479] LockupLinear::withdrawMaxAndTransfer(1, Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1])
│ ├─ [12866] DAI::transfer(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], 2600000000000000000000 [2.6e21])
│ │ ├─ emit Transfer(from: LockupLinear: [0x4a6eD11Fa3612925cF0E72459893Ed6e33984E83], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], value: 2600000000000000000000 [2.6e21])
│ │ └─ ← [Return] true
│ ├─ emit WithdrawFromLockupStream(streamId: 1, to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], asset: DAI: [0x1d1499e622D69689cdf9004d05Ec547d650Ff211], amount: 2600000000000000000000 [2.6e21])
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ ├─ emit Transfer(from: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], to: Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], tokenId: 1)
│ ├─ emit MetadataUpdate(_tokenId: 1)
│ └─ ← [Stop]
├─ [845] LockupLinear::getWithdrawnAmount(1) [staticcall]
│ └─ ← [Return] 2600000000000000000000 [2.6e21]
├─ [0] VM::assertEq(2600000000000000000000 [2.6e21], 2600000000000000000000 [2.6e21], "withdrawnAmount") [staticcall]
│ └─ ← [Return]
├─ [665] LockupLinear::getRecipient(1) [staticcall]
│ └─ ← [Return] Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1]
├─ [0] VM::assertEq(Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], Recipient: [0x03E9b88f4b1406163Ef9eC4875A52e1e55953eC1], "recipient") [staticcall]
│ └─ ← [Return]
└─ ← [Stop]
Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 8.92ms (183.22µs CPU time)
Ran 3 test suites in 1.43s (25.90ms CPU time): 3 tests passed, 0 failed, 0 skipped (3 total tests)
To prevent the self-transfer bug, implement a check in the withdrawMaxAndTransfer function to ensure that the newRecipient is different from the currentRecipient. If the newRecipient is the same as the currentRecipient, revert the transaction.