Skip to content

Commit

Permalink
test: createAndDepositMultiple function
Browse files Browse the repository at this point in the history
  • Loading branch information
andreivladbrg committed Apr 24, 2024
1 parent 0d0576a commit 6cca0e6
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 11 deletions.
2 changes: 1 addition & 1 deletion src/SablierV2OpenEnded.sol
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ contract SablierV2OpenEnded is ISablierV2OpenEnded, NoDelegateCall, SablierV2Ope
uint256 sendersCount = senders.length;
uint256 ratesPerSecondCount = ratesPerSecond.length;

// Check: count of `senders`, `recipients`, `ratesPerSecond` matches.
// Check: count of `senders`, `recipients` and `ratesPerSecond` matches.
if (recipientsCount != sendersCount || recipientsCount != ratesPerSecondCount) {
revert Errors.SablierV2OpenEnded_CreateMultipleArrayCountsNotEqual(
recipientsCount, sendersCount, ratesPerSecondCount
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.22;

import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol";
import { Errors } from "src/libraries/Errors.sol";
import { OpenEnded } from "src/types/DataTypes.sol";

import { Integration_Test } from "../Integration.t.sol";

contract CreateMultiple_Integration_Test is Integration_Test {
address[] internal defaultRecipients;
address[] internal defaultSenders;
uint128[] internal defaultRatesPerSecond;
uint128[] internal defaultDepositAmounts;

function setUp() public override {
Integration_Test.setUp();

defaultRecipients.push(users.recipient);
defaultRecipients.push(users.recipient);
defaultSenders.push(users.sender);
defaultSenders.push(users.sender);
defaultRatesPerSecond.push(RATE_PER_SECOND);
defaultRatesPerSecond.push(RATE_PER_SECOND);
defaultDepositAmounts.push(DEPOSIT_AMOUNT);
defaultDepositAmounts.push(DEPOSIT_AMOUNT);
}

function test_RevertWhen_DelegateCall() external {
bytes memory callData = abi.encodeCall(
ISablierV2OpenEnded.createAndDepositMultiple,
(defaultRecipients, defaultSenders, defaultRatesPerSecond, dai, defaultDepositAmounts)
);
_test_RevertWhen_DelegateCall(callData);
}

function test_RevertWhen_DepositAmountsArrayIsNotEqual() external whenNotDelegateCalled whenArrayCountsNotEqual {
uint128[] memory depositAmounts = new uint128[](0);

vm.expectRevert(
abi.encodeWithSelector(
Errors.SablierV2OpenEnded_DepositArrayCountsNotEqual.selector,
defaultRecipients.length,
depositAmounts.length
)
);
openEnded.createAndDepositMultiple(
defaultRecipients, defaultSenders, defaultRatesPerSecond, dai, depositAmounts
);
}

function test_CreateAndDepositMultiple() external whenNotDelegateCalled whenArrayCountsEqual {
uint256 beforeNextStreamId = openEnded.nextStreamId();

vm.expectEmit({ emitter: address(openEnded) });
emit CreateOpenEndedStream({
streamId: beforeNextStreamId,
sender: users.sender,
recipient: users.recipient,
ratePerSecond: RATE_PER_SECOND,
asset: dai,
lastTimeUpdate: uint40(block.timestamp)
});
vm.expectEmit({ emitter: address(openEnded) });
emit CreateOpenEndedStream({
streamId: beforeNextStreamId + 1,
sender: users.sender,
recipient: users.recipient,
ratePerSecond: RATE_PER_SECOND,
asset: dai,
lastTimeUpdate: uint40(block.timestamp)
});

vm.expectEmit({ emitter: address(openEnded) });
emit DepositOpenEndedStream({
streamId: beforeNextStreamId,
funder: users.sender,
asset: dai,
depositAmount: DEPOSIT_AMOUNT
});

vm.expectEmit({ emitter: address(openEnded) });
emit DepositOpenEndedStream({
streamId: beforeNextStreamId + 1,
funder: users.sender,
asset: dai,
depositAmount: DEPOSIT_AMOUNT
});

expectCallToTransferFrom({ asset: dai, from: users.sender, to: address(openEnded), amount: DEPOSIT_AMOUNT });
expectCallToTransferFrom({ asset: dai, from: users.sender, to: address(openEnded), amount: DEPOSIT_AMOUNT });

uint256[] memory streamIds = openEnded.createAndDepositMultiple(
defaultRecipients, defaultSenders, defaultRatesPerSecond, dai, defaultDepositAmounts
);

uint256 afterNextStreamId = openEnded.nextStreamId();

assertEq(streamIds[0], beforeNextStreamId, "streamIds[0] != beforeNextStreamId");
assertEq(streamIds[1], beforeNextStreamId + 1, "streamIds[1] != beforeNextStreamId + 1");

assertEq(streamIds.length, defaultRecipients.length, "streamIds.length != defaultRecipients.length");
assertEq(
beforeNextStreamId + defaultRecipients.length,
afterNextStreamId,
"afterNextStreamId != beforeNextStreamId + defaultRecipients.length"
);

OpenEnded.Stream memory expectedStream = OpenEnded.Stream({
ratePerSecond: RATE_PER_SECOND,
asset: dai,
assetDecimals: 18,
balance: DEPOSIT_AMOUNT,
lastTimeUpdate: uint40(block.timestamp),
isCanceled: false,
isStream: true,
recipient: users.recipient,
sender: users.sender
});

OpenEnded.Stream memory actualStream = openEnded.getStream(streamIds[0]);
assertEq(actualStream, expectedStream);

actualStream = openEnded.getStream(streamIds[1]);
assertEq(actualStream, expectedStream);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
createMultiple.t.sol
β”œβ”€β”€ when delegate called
β”‚ └── it should revert
└── when not delegate called
β”œβ”€β”€ when array counts are not equal
β”‚ └── when the deposit amounts array is not equal
β”‚ └── it should revert
└── when array counts are equal
β”œβ”€β”€ it should create multiple streams
β”œβ”€β”€ it should update the stream balance
β”œβ”€β”€ it should perform the ERC-20 transfer
β”œβ”€β”€ it should bump the next stream id multiple times
└── it should emit multiple {CreateOpenEndedStream}, {Transfer} and {DepositOpenEndedStream} events
8 changes: 0 additions & 8 deletions test/integration/create-multiple/createMultiple.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,6 @@ contract CreateMultiple_Integration_Test is Integration_Test {
_test_RevertWhen_DelegateCall(callData);
}

modifier whenArrayCountsNotEqual() {
_;
}

function test_RevertWhen_RecipientsCountNotEqual() external whenNotDelegateCalled whenArrayCountsNotEqual {
address[] memory recipients = new address[](1);

Expand Down Expand Up @@ -76,10 +72,6 @@ contract CreateMultiple_Integration_Test is Integration_Test {
openEnded.createMultiple(defaultRecipients, defaultSenders, ratesPerSecond, dai);
}

modifier whenArrayCountsEqual() {
_;
}

function test_CreateMultiple() external whenNotDelegateCalled whenArrayCountsEqual {
uint256 beforeNextStreamId = openEnded.nextStreamId();

Expand Down
4 changes: 2 additions & 2 deletions test/integration/create-multiple/createMultiple.tree
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@ createMultiple.t.sol
β”œβ”€β”€ when delegate called
β”‚ └── it should revert
└── when not delegate called
β”œβ”€β”€ when arrays counts are not equal
β”œβ”€β”€ when array counts are not equal
β”‚ β”œβ”€β”€ when the recipients array is not equal
β”‚ β”‚ └── it should revert
β”‚ β”œβ”€β”€ when the senders array is not equal
β”‚ β”‚ └── it should revert
β”‚ └── when the rates per second array is not equal
β”‚ └── it should revert
└── when arrays counts are equal
└── when array counts are equal
β”œβ”€β”€ it should create multiple streams
β”œβ”€β”€ it should bump the next stream id multiple times
└── it should emit multiple {CreateOpenEndedStream} events
12 changes: 12 additions & 0 deletions test/utils/Modifiers.sol
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,18 @@ abstract contract Modifiers {
_;
}

/*//////////////////////////////////////////////////////////////////////////
CREATE-MULTIPLE
//////////////////////////////////////////////////////////////////////////*/

modifier whenArrayCountsNotEqual() {
_;
}

modifier whenArrayCountsEqual() {
_;
}

/*//////////////////////////////////////////////////////////////////////////
DEPOSIT
//////////////////////////////////////////////////////////////////////////*/
Expand Down

0 comments on commit 6cca0e6

Please sign in to comment.