Skip to content

Commit

Permalink
feat: implement sablier fee in withdraw
Browse files Browse the repository at this point in the history
test: update test accordingly

feat: implement withdraw fee function

refactor: correct the function name
test: setSablierFee function
test: withdrawFees function
test: implement expectRevert_CallerNotAdmin helper function
test: move ContractWithoutReceiveEth and ContractWithReceiveEth in Base_Test

feat: add feeAmount in withdraw event

build: decrease the optimizer runs to not exceed the size limit

docs: improve wording in natpsec

feat: add zero address check in withdrawFees

feat: make all functions payable in SablierLockup

refactor: remove sablierFee variable
refactor: remove setSablierFee
refactor: remove the fee amount from the withdraw event
test: add mirror functions in Integration_Test to avoid passing the value in lockup
test: dry-fy contract balance test
  • Loading branch information
andreivladbrg committed Nov 20, 2024
1 parent abdf8b3 commit 4794c03
Show file tree
Hide file tree
Showing 78 changed files with 697 additions and 341 deletions.
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
]
gas_limit = 9223372036854775807
optimizer = true
optimizer_runs = 1000
optimizer_runs = 800
out = "out"
script = "script"
sender = "0x1804c8AB1F12E6bbf3894d4083f33e07309d1f38"
Expand Down
12 changes: 6 additions & 6 deletions src/core/SablierBatchLockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
streamIds = new uint256[](batchSize);
for (i = 0; i < batchSize; ++i) {
// Create the stream.
streamIds[i] = lockup.createWithDurationsLD(
streamIds[i] = lockup.createWithDurationsLD{ value: 0 }(
Lockup.CreateWithDurations({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down Expand Up @@ -106,7 +106,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
}

// Create the stream.
streamIds[i] = lockup.createWithTimestampsLD(
streamIds[i] = lockup.createWithTimestampsLD{ value: 0 }(
Lockup.CreateWithTimestamps({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down Expand Up @@ -159,7 +159,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
streamIds = new uint256[](batchSize);
for (i = 0; i < batchSize; ++i) {
// Create the stream.
streamIds[i] = lockup.createWithDurationsLL(
streamIds[i] = lockup.createWithDurationsLL{ value: 0 }(
Lockup.CreateWithDurations({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down Expand Up @@ -208,7 +208,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
streamIds = new uint256[](batchSize);
for (i = 0; i < batchSize; ++i) {
// Create the stream.
streamIds[i] = lockup.createWithTimestampsLL(
streamIds[i] = lockup.createWithTimestampsLL{ value: 0 }(
Lockup.CreateWithTimestamps({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down Expand Up @@ -262,7 +262,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
streamIds = new uint256[](batchSize);
for (i = 0; i < batchSize; ++i) {
// Create the stream.
streamIds[i] = lockup.createWithDurationsLT(
streamIds[i] = lockup.createWithDurationsLT{ value: 0 }(
Lockup.CreateWithDurations({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down Expand Up @@ -317,7 +317,7 @@ contract SablierBatchLockup is ISablierBatchLockup {
}

// Create the stream.
streamIds[i] = lockup.createWithTimestampsLT(
streamIds[i] = lockup.createWithTimestampsLT{ value: 0 }(
Lockup.CreateWithTimestamps({
sender: batch[i].sender,
recipient: batch[i].recipient,
Expand Down
6 changes: 6 additions & 0 deletions src/core/SablierLockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
LockupDynamic.SegmentWithDuration[] calldata segmentsWithDuration
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand Down Expand Up @@ -170,6 +171,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
LockupLinear.Durations calldata durations
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand Down Expand Up @@ -212,6 +214,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
LockupTranched.TrancheWithDuration[] calldata tranchesWithDuration
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand Down Expand Up @@ -245,6 +248,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
LockupDynamic.Segment[] calldata segments
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand All @@ -260,6 +264,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
uint40 cliffTime
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand All @@ -274,6 +279,7 @@ contract SablierLockup is ISablierLockup, SablierLockupBase {
LockupTranched.Tranche[] calldata tranches
)
external
payable
override
noDelegateCall
returns (uint256 streamId)
Expand Down
2 changes: 1 addition & 1 deletion src/core/abstracts/Batch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ abstract contract Batch is IBatch {
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc IBatch
function batch(bytes[] calldata calls) external override {
function batch(bytes[] calldata calls) external payable override {
uint256 count = calls.length;

for (uint256 i = 0; i < count; ++i) {
Expand Down
49 changes: 41 additions & 8 deletions src/core/abstracts/SablierLockupBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Batch } from "./Batch.sol";
import { NoDelegateCall } from "./NoDelegateCall.sol";

/// @title SablierLockupBase
/// @notice See the documentation in {SablierLockupBase}.
/// @notice See the documentation in {ISablierLockupBase}.
abstract contract SablierLockupBase is
Batch, // 1 inherited components
NoDelegateCall, // 0 inherited components
Expand Down Expand Up @@ -271,7 +271,7 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function burn(uint256 streamId) external override noDelegateCall notNull(streamId) {
function burn(uint256 streamId) external payable override noDelegateCall notNull(streamId) {
// Check: only depleted streams can be burned.
if (!_streams[streamId].isDepleted) {
revert Errors.SablierLockupBase_StreamNotDepleted(streamId);
Expand All @@ -292,7 +292,7 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function cancel(uint256 streamId) public override noDelegateCall notNull(streamId) {
function cancel(uint256 streamId) public payable override noDelegateCall notNull(streamId) {
// Check: the stream is neither depleted nor canceled.
if (_streams[streamId].isDepleted) {
revert Errors.SablierLockupBase_StreamDepleted(streamId);
Expand All @@ -310,7 +310,7 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function cancelMultiple(uint256[] calldata streamIds) external override noDelegateCall {
function cancelMultiple(uint256[] calldata streamIds) external payable override noDelegateCall {
// Iterate over the provided array of stream IDs and cancel each stream.
uint256 count = streamIds.length;
for (uint256 i = 0; i < count; ++i) {
Expand All @@ -320,7 +320,7 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function renounce(uint256 streamId) public override noDelegateCall notNull(streamId) {
function renounce(uint256 streamId) public payable override noDelegateCall notNull(streamId) {
// Check: the stream is not cold.
Lockup.Status status = _statusOf(streamId);
if (status == Lockup.Status.DEPLETED) {
Expand All @@ -347,7 +347,7 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function renounceMultiple(uint256[] calldata streamIds) external override noDelegateCall {
function renounceMultiple(uint256[] calldata streamIds) external payable override noDelegateCall {
// Iterate over the provided array of stream IDs and renounce each stream.
uint256 count = streamIds.length;
for (uint256 i = 0; i < count; ++i) {
Expand All @@ -374,7 +374,17 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function withdraw(uint256 streamId, address to, uint128 amount) public override noDelegateCall notNull(streamId) {
function withdraw(
uint256 streamId,
address to,
uint128 amount
)
public
payable
override
noDelegateCall
notNull(streamId)
{
// Check: the stream is not depleted.
if (_streams[streamId].isDepleted) {
revert Errors.SablierLockupBase_StreamDepleted(streamId);
Expand Down Expand Up @@ -428,7 +438,28 @@ abstract contract SablierLockupBase is
}

/// @inheritdoc ISablierLockupBase
function withdrawMax(uint256 streamId, address to) external override returns (uint128 withdrawnAmount) {
function withdrawFees(address payable to) external override onlyAdmin {
// Check: the withdrawal address is not zero.
if (to == address(0)) {
revert Errors.SablierLockupBase_WithdrawFeesToZero();
}

uint256 feeAmount = address(this).balance;

// Effect: transfer the fees to the provided address.
(bool success,) = to.call{ value: feeAmount }("");

// Revert if the call failed.
if (!success) {
revert Errors.SablierLockupBase_FeeWithdrawFailed(to, feeAmount);
}

// Log the fee withdrawal.
emit ISablierLockupBase.WithdrawSablierFees({ admin: admin, to: to, feeAmount: feeAmount });
}

/// @inheritdoc ISablierLockupBase
function withdrawMax(uint256 streamId, address to) external payable override returns (uint128 withdrawnAmount) {
withdrawnAmount = _withdrawableAmountOf(streamId);
withdraw({ streamId: streamId, to: to, amount: withdrawnAmount });
}
Expand All @@ -439,6 +470,7 @@ abstract contract SablierLockupBase is
address newRecipient
)
external
payable
override
noDelegateCall
notNull(streamId)
Expand Down Expand Up @@ -468,6 +500,7 @@ abstract contract SablierLockupBase is
uint128[] calldata amounts
)
external
payable
override
noDelegateCall
{
Expand Down
2 changes: 1 addition & 1 deletion src/core/interfaces/IBatch.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ pragma solidity >=0.8.22;
interface IBatch {
/// @notice Allows batched call to self, `this` contract.
/// @param calls An array of inputs for each call.
function batch(bytes[] calldata calls) external;
function batch(bytes[] calldata calls) external payable;
}
6 changes: 6 additions & 0 deletions src/core/interfaces/ISablierLockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ interface ISablierLockup is ISablierLockupBase {
LockupDynamic.SegmentWithDuration[] calldata segmentsWithDuration
)
external
payable
returns (uint256 streamId);

/// @notice Creates a stream by setting the start time to `block.timestamp`, and the end time to
Expand All @@ -118,6 +119,7 @@ interface ISablierLockup is ISablierLockupBase {
LockupLinear.Durations calldata durations
)
external
payable
returns (uint256 streamId);

/// @notice Creates a stream by setting the start time to `block.timestamp`, and the end time to the sum of
Expand All @@ -138,6 +140,7 @@ interface ISablierLockup is ISablierLockupBase {
LockupTranched.TrancheWithDuration[] calldata tranchesWithDuration
)
external
payable
returns (uint256 streamId);

/// @notice Creates a stream with the provided segment timestamps, implying the end time from the last timestamp.
Expand Down Expand Up @@ -170,6 +173,7 @@ interface ISablierLockup is ISablierLockupBase {
LockupDynamic.Segment[] calldata segments
)
external
payable
returns (uint256 streamId);

/// @notice Creates a stream with the provided start time and end time. The stream is funded by `msg.sender` and is
Expand Down Expand Up @@ -206,6 +210,7 @@ interface ISablierLockup is ISablierLockupBase {
uint40 cliffTime
)
external
payable
returns (uint256 streamId);

/// @notice Creates a stream with the provided tranche timestamps, implying the end time from the last timestamp.
Expand Down Expand Up @@ -238,5 +243,6 @@ interface ISablierLockup is ISablierLockupBase {
LockupTranched.Tranche[] calldata tranches
)
external
payable
returns (uint256 streamId);
}
Loading

0 comments on commit 4794c03

Please sign in to comment.