diff --git a/src/modules/invoice-module/sablier-v2/StreamManager.sol b/src/modules/invoice-module/sablier-v2/StreamManager.sol index a890638..83d3541 100644 --- a/src/modules/invoice-module/sablier-v2/StreamManager.sol +++ b/src/modules/invoice-module/sablier-v2/StreamManager.sol @@ -16,7 +16,7 @@ import { Types } from "./../libraries/Types.sol"; /// @title StreamManager /// @dev See the documentation in {IStreamManager} -contract StreamManager is IStreamManager { +abstract contract StreamManager is IStreamManager { using SafeERC20 for IERC20; /*////////////////////////////////////////////////////////////////////////// @@ -40,6 +40,8 @@ contract StreamManager is IStreamManager { //////////////////////////////////////////////////////////////////////////*/ /// @dev Stores the initial address of the account that started the stream + /// By default, each stream will be created by this contract (the sender address of each stream will be address(this)) + /// therefore this mapping is used to allow only authorized senders to execute management-related actions i.e. cancellations mapping(uint256 streamId => address initialSender) private _initialStreamSender; /*////////////////////////////////////////////////////////////////////////// @@ -93,7 +95,7 @@ contract StreamManager is IStreamManager { // Create the Lockup Linear stream streamId = _createLinearStream(asset, totalAmount, startTime, endTime, recipient); - // Set `msg.sender` as the initial stream sender to allow secure stream management + // Set `msg.sender` as the initial stream sender to allow authenticated stream management _initialStreamSender[streamId] = msg.sender; } @@ -112,7 +114,7 @@ contract StreamManager is IStreamManager { // Create the Lockup Linear stream streamId = _createTranchedStream(asset, totalAmount, startTime, recipient, numberOfTranches, recurrence); - // Set `msg.sender` as the initial stream sender to allow secure stream management + // Set `msg.sender` as the initial stream sender to allow authenticated stream management _initialStreamSender[streamId] = msg.sender; } @@ -145,11 +147,13 @@ contract StreamManager is IStreamManager { /// @inheritdoc IStreamManager function cancelLinearStream(uint256 streamId) public { + // Checks, Effect, Interactions _cancelStream({ sablier: LOCKUP_LINEAR, streamId: streamId }); } /// @inheritdoc IStreamManager function cancelTranchedStream(uint256 streamId) public { + // Checks, Effect, Interactions _cancelStream({ sablier: LOCKUP_TRANCHED, streamId: streamId }); } @@ -257,7 +261,12 @@ contract StreamManager is IStreamManager { } /// @dev Cancels the `streamId` stream - function _cancelStream(ISablierV2Lockup sablier, uint256 streamId) internal onlyInitialStreamSender(streamId) { + function _cancelStream(ISablierV2Lockup sablier, uint256 streamId) internal { + // Checks: the `msg.sender` is the initial stream creator + address initialSender = _initialStreamSender[streamId]; + if (msg.sender != initialSender) revert Errors.OnlyInitialStreamSender(initialSender); + + // Cancel the stream sablier.cancel(streamId); } diff --git a/src/modules/invoice-module/sablier-v2/interfaces/IStreamManager.sol b/src/modules/invoice-module/sablier-v2/interfaces/IStreamManager.sol index 9202263..c39dece 100644 --- a/src/modules/invoice-module/sablier-v2/interfaces/IStreamManager.sol +++ b/src/modules/invoice-module/sablier-v2/interfaces/IStreamManager.sol @@ -100,8 +100,14 @@ interface IStreamManager { function withdrawTranchedStream(uint256 streamId, address to, uint128 amount) external; /// @notice See the documentation in {ISablierV2Lockup-cancel} + /// + /// Notes: + /// - Reverts with {OnlyInitialStreamSender} if `msg.sender` is not the initial stream creator function cancelLinearStream(uint256 streamId) external; /// @notice See the documentation in {ISablierV2Lockup-cancel} + /// + /// Notes: + /// - Reverts with {OnlyInitialStreamSender} if `msg.sender` is not the initial stream creator function cancelTranchedStream(uint256 streamId) external; }