Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename create functions #798

Merged
merged 2 commits into from
Jan 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 7 additions & 5 deletions script/Init.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -78,11 +78,13 @@ contract Init is BaseScript {
//////////////////////////////////////////////////////////////////////////*/

// Create the default lockupDynamic stream.
LockupDynamic.SegmentWithDelta[] memory segments = new LockupDynamic.SegmentWithDelta[](2);
segments[0] = LockupDynamic.SegmentWithDelta({ amount: 2500e18, exponent: ud2x18(3.14e18), delta: 1 hours });
segments[1] = LockupDynamic.SegmentWithDelta({ amount: 7500e18, exponent: ud2x18(0.5e18), delta: 1 weeks });
lockupDynamic.createWithDeltas(
LockupDynamic.CreateWithDeltas({
LockupDynamic.SegmentWithDuration[] memory segments = new LockupDynamic.SegmentWithDuration[](2);
segments[0] =
LockupDynamic.SegmentWithDuration({ amount: 2500e18, exponent: ud2x18(3.14e18), duration: 1 hours });
segments[1] =
LockupDynamic.SegmentWithDuration({ amount: 7500e18, exponent: ud2x18(0.5e18), duration: 1 weeks });
lockupDynamic.createWithDurations(
LockupDynamic.CreateWithDurations({
sender: sender,
recipient: recipient,
totalAmount: 10_000e18,
Expand Down
42 changes: 21 additions & 21 deletions src/SablierV2LockupDynamic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -267,18 +267,18 @@ contract SablierV2LockupDynamic is
//////////////////////////////////////////////////////////////////////////*/

/// @inheritdoc ISablierV2LockupDynamic
function createWithDeltas(LockupDynamic.CreateWithDeltas calldata params)
function createWithDurations(LockupDynamic.CreateWithDurations calldata params)
external
override
noDelegateCall
returns (uint256 streamId)
{
// Checks: check the deltas and generate the canonical segments.
LockupDynamic.Segment[] memory segments = Helpers.checkDeltasAndCalculateMilestones(params.segments);
// Checks: check the durations and generate the canonical segments.
LockupDynamic.Segment[] memory segments = Helpers.checkDurationsAndCalculateTimestamps(params.segments);

// Checks, Effects and Interactions: create the stream.
streamId = _createWithMilestones(
LockupDynamic.CreateWithMilestones({
streamId = _createWithTimestamps(
LockupDynamic.CreateWithTimestamps({
sender: params.sender,
recipient: params.recipient,
totalAmount: params.totalAmount,
Expand All @@ -293,14 +293,14 @@ contract SablierV2LockupDynamic is
}

/// @inheritdoc ISablierV2LockupDynamic
function createWithMilestones(LockupDynamic.CreateWithMilestones calldata params)
function createWithTimestamps(LockupDynamic.CreateWithTimestamps calldata params)
external
override
noDelegateCall
returns (uint256 streamId)
{
// Checks, Effects and Interactions: create the stream.
streamId = _createWithMilestones(params);
streamId = _createWithTimestamps(params);
}

/*//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -345,32 +345,32 @@ contract SablierV2LockupDynamic is

// Sum the amounts in all segments that precede the current time.
uint128 previousSegmentAmounts;
uint40 currentSegmentMilestone = stream.segments[0].milestone;
uint40 currentSegmentTimestamp = stream.segments[0].timestamp;
uint256 index = 0;
while (currentSegmentMilestone < currentTime) {
while (currentSegmentTimestamp < currentTime) {
previousSegmentAmounts += stream.segments[index].amount;
index += 1;
currentSegmentMilestone = stream.segments[index].milestone;
currentSegmentTimestamp = stream.segments[index].timestamp;
}

// After exiting the loop, the current segment is at `index`.
SD59x18 currentSegmentAmount = stream.segments[index].amount.intoSD59x18();
SD59x18 currentSegmentExponent = stream.segments[index].exponent.intoSD59x18();
currentSegmentMilestone = stream.segments[index].milestone;
currentSegmentTimestamp = stream.segments[index].timestamp;

uint40 previousMilestone;
uint40 previousTimestamp;
if (index > 0) {
// When the current segment's index is greater than or equal to 1, it implies that the segment is not
// the first. In this case, use the previous segment's milestone.
previousMilestone = stream.segments[index - 1].milestone;
// the first. In this case, use the previous segment's timestamp.
previousTimestamp = stream.segments[index - 1].timestamp;
} else {
// Otherwise, the current segment is the first, so use the start time as the previous milestone.
previousMilestone = stream.startTime;
// Otherwise, the current segment is the first, so use the start time as the previous timestamp.
previousTimestamp = stream.startTime;
}

// Calculate how much time has passed since the segment started, and the total time of the segment.
SD59x18 elapsedSegmentTime = (currentTime - previousMilestone).intoSD59x18();
SD59x18 totalSegmentTime = (currentSegmentMilestone - previousMilestone).intoSD59x18();
SD59x18 elapsedSegmentTime = (currentTime - previousTimestamp).intoSD59x18();
SD59x18 totalSegmentTime = (currentSegmentTimestamp - previousTimestamp).intoSD59x18();

// Divide the elapsed segment time by the total duration of the segment.
SD59x18 elapsedSegmentTimePercentage = elapsedSegmentTime.div(totalSegmentTime);
Expand Down Expand Up @@ -537,7 +537,7 @@ contract SablierV2LockupDynamic is
}

/// @dev See the documentation for the user-facing functions that call this internal function.
function _createWithMilestones(LockupDynamic.CreateWithMilestones memory params)
function _createWithTimestamps(LockupDynamic.CreateWithTimestamps memory params)
internal
returns (uint256 streamId)
{
Expand All @@ -550,7 +550,7 @@ contract SablierV2LockupDynamic is
Helpers.checkAndCalculateFees(params.totalAmount, protocolFee, params.broker.fee, MAX_FEE);

// Checks: validate the user-provided parameters.
Helpers.checkCreateWithMilestones(createAmounts.deposit, params.segments, MAX_SEGMENT_COUNT, params.startTime);
Helpers.checkCreateWithTimestamps(createAmounts.deposit, params.segments, MAX_SEGMENT_COUNT, params.startTime);

// Load the stream id in a variable.
streamId = nextStreamId;
Expand All @@ -567,7 +567,7 @@ contract SablierV2LockupDynamic is
unchecked {
// The segment count cannot be zero at this point.
uint256 segmentCount = params.segments.length;
stream.endTime = params.segments[segmentCount - 1].milestone;
stream.endTime = params.segments[segmentCount - 1].timestamp;
stream.startTime = params.startTime;

// Effects: store the segments. Since Solidity lacks a syntax for copying arrays directly from
Expand Down
17 changes: 10 additions & 7 deletions src/SablierV2LockupLinear.sol
Original file line number Diff line number Diff line change
Expand Up @@ -261,15 +261,15 @@ contract SablierV2LockupLinear is
range.start = uint40(block.timestamp);

// Calculate the cliff time and the end time. It is safe to use unchecked arithmetic because
// {_createWithRange} will nonetheless check that the end time is greater than the cliff time,
// {_createWithTimestamps} will nonetheless check that the end time is greater than the cliff time,
// and also that the cliff time is greater than or equal to the start time.
unchecked {
range.cliff = range.start + params.durations.cliff;
range.end = range.start + params.durations.total;
}
// Checks, Effects and Interactions: create the stream.
streamId = _createWithRange(
LockupLinear.CreateWithRange({
streamId = _createWithTimestamps(
LockupLinear.CreateWithTimestamps({
sender: params.sender,
recipient: params.recipient,
totalAmount: params.totalAmount,
Expand All @@ -283,14 +283,14 @@ contract SablierV2LockupLinear is
}

/// @inheritdoc ISablierV2LockupLinear
function createWithRange(LockupLinear.CreateWithRange calldata params)
function createWithTimestamps(LockupLinear.CreateWithTimestamps calldata params)
external
override
noDelegateCall
returns (uint256 streamId)
{
// Checks, Effects and Interactions: create the stream.
streamId = _createWithRange(params);
streamId = _createWithTimestamps(params);
}

/*//////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -452,7 +452,10 @@ contract SablierV2LockupLinear is
}

/// @dev See the documentation for the user-facing functions that call this internal function.
function _createWithRange(LockupLinear.CreateWithRange memory params) internal returns (uint256 streamId) {
function _createWithTimestamps(LockupLinear.CreateWithTimestamps memory params)
internal
returns (uint256 streamId)
{
// Safe Interactions: query the protocol fee. This is safe because it's a known Sablier contract that does
// not call other unknown contracts.
UD60x18 protocolFee = comptroller.protocolFees(params.asset);
Expand All @@ -462,7 +465,7 @@ contract SablierV2LockupLinear is
Helpers.checkAndCalculateFees(params.totalAmount, protocolFee, params.broker.fee, MAX_FEE);

// Checks: validate the user-provided parameters.
Helpers.checkCreateWithRange(createAmounts.deposit, params.range);
Helpers.checkCreateWithTimestamps(createAmounts.deposit, params.range);

// Load the stream id.
streamId = nextStreamId;
Expand Down
22 changes: 12 additions & 10 deletions src/interfaces/ISablierV2LockupDynamic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,42 +92,44 @@ interface ISablierV2LockupDynamic is ISablierV2Lockup {
//////////////////////////////////////////////////////////////////////////*/

/// @notice Creates a stream by setting the start time to `block.timestamp`, and the end time to the sum of
/// `block.timestamp` and all specified time deltas. The segment milestones are derived from these
/// deltas. The stream is funded by `msg.sender` and is wrapped in an ERC-721 NFT.
/// `block.timestamp` and all specified time durations. The segment timestamps are derived from these
/// durations. The stream is funded by `msg.sender` and is wrapped in an ERC-721 NFT.
///
/// @dev Emits a {Transfer} and {CreateLockupDynamicStream} event.
///
/// Requirements:
/// - All requirements in {createWithMilestones} must be met for the calculated parameters.
/// - All requirements in {createWithTimestamps} must be met for the calculated parameters.
///
/// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}.
/// @return streamId The id of the newly created stream.
function createWithDeltas(LockupDynamic.CreateWithDeltas calldata params) external returns (uint256 streamId);
function createWithDurations(LockupDynamic.CreateWithDurations calldata params)
external
returns (uint256 streamId);

/// @notice Creates a stream with the provided segment milestones, implying the end time from the last milestone.
/// @notice Creates a stream with the provided segment timestamps, implying the end time from the last timestamp.
/// The stream is funded by `msg.sender` and is wrapped in an ERC-721 NFT.
///
/// @dev Emits a {Transfer} and {CreateLockupDynamicStream} event.
///
/// Notes:
/// - As long as the segment milestones are arranged in ascending order, it is not an error for some
/// - As long as the segment timestamps are arranged in ascending order, it is not an error for some
/// of them to be in the past.
///
/// Requirements:
/// - Must not be delegate called.
/// - `params.totalAmount` must be greater than zero.
/// - If set, `params.broker.fee` must not be greater than `MAX_FEE`.
/// - `params.segments` must have at least one segment, but not more than `MAX_SEGMENT_COUNT`.
/// - `params.startTime` must be less than the first segment's milestone.
/// - The segment milestones must be arranged in ascending order.
/// - The last segment milestone (i.e. the stream's end time) must be in the future.
/// - `params.startTime` must be less than the first segment's timestamp.
/// - The segment timestamps must be arranged in ascending order.
/// - The last segment timestamp (i.e. the stream's end time) must be in the future.
/// - The sum of the segment amounts must equal the deposit amount.
/// - `params.recipient` must not be the zero address.
/// - `msg.sender` must have allowed this contract to spend at least `params.totalAmount` assets.
///
/// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}.
/// @return streamId The id of the newly created stream.
function createWithMilestones(LockupDynamic.CreateWithMilestones calldata params)
function createWithTimestamps(LockupDynamic.CreateWithTimestamps calldata params)
external
returns (uint256 streamId);
}
6 changes: 4 additions & 2 deletions src/interfaces/ISablierV2LockupLinear.sol
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ interface ISablierV2LockupLinear is ISablierV2Lockup {
/// @dev Emits a {Transfer} and {CreateLockupLinearStream} event.
///
/// Requirements:
/// - All requirements in {createWithRange} must be met for the calculated parameters.
/// - All requirements in {createWithTimestamps} must be met for the calculated parameters.
///
/// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}.
/// @return streamId The id of the newly created stream.
Expand Down Expand Up @@ -120,5 +120,7 @@ interface ISablierV2LockupLinear is ISablierV2Lockup {
///
/// @param params Struct encapsulating the function parameters, which are documented in {DataTypes}.
/// @return streamId The id of the newly created stream.
function createWithRange(LockupLinear.CreateWithRange calldata params) external returns (uint256 streamId);
function createWithTimestamps(LockupLinear.CreateWithTimestamps calldata params)
external
returns (uint256 streamId);
}
12 changes: 6 additions & 6 deletions src/libraries/Errors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ library Errors {
/// @notice Thrown when trying to create a stream with no segments.
error SablierV2LockupDynamic_SegmentCountZero();

/// @notice Thrown when trying to create a stream with unordered segment milestones.
error SablierV2LockupDynamic_SegmentMilestonesNotOrdered(
uint256 index, uint40 previousMilestone, uint40 currentMilestone
/// @notice Thrown when trying to create a stream with unordered segment timestampts.
error SablierV2LockupDynamic_SegmentTimestampsNotOrdered(
uint256 index, uint40 previousTimestamp, uint40 currentTimestamp
);

/// @notice Thrown when trying to create a stream with a start time not strictly less than the first
/// segment milestone.
error SablierV2LockupDynamic_StartTimeNotLessThanFirstSegmentMilestone(
uint40 startTime, uint40 firstSegmentMilestone
/// segment timestamp.
error SablierV2LockupDynamic_StartTimeNotLessThanFirstSegmentTimestamp(
uint40 startTime, uint40 firstSegmentTimestamp
);

/*//////////////////////////////////////////////////////////////////////////
Expand Down
Loading
Loading