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

Multiple refactors (SegmentWithDelta, broker.account, range unpack, order of params) #334

Merged
merged 7 commits into from
Feb 15, 2023
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
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,4 @@
[rpc_endpoints]
ethereum = "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_API_KEY}"
goerli = "https://goerli.infura.io/v3/${INFURA_API_KEY}"
localhost = "http://localhost:8545"
localhost = "http://localhost:8545"
13 changes: 4 additions & 9 deletions script/bootstrap/BootstrapProtocol.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ contract BootstrapProtocol is BaseScript {
});
}

// Deplete the 1st stream.
linear.withdrawMax({ streamId: 1, to: recipient });

// Renounce the 5th stream.
linear.renounce({ streamId: 5 });

Expand All @@ -87,18 +84,16 @@ contract BootstrapProtocol is BaseScript {
//////////////////////////////////////////////////////////////////////////*/

// Create the default pro stream.
LockupPro.Segment[] memory segments = new LockupPro.Segment[](2);
segments[0] = LockupPro.Segment({ amount: 2_500e18, exponent: ud2x18(3.14e18), milestone: 0 });
segments[1] = LockupPro.Segment({ amount: 7_500e18, exponent: ud2x18(0.5e18), milestone: 0 });
uint40[] memory deltas = Solarray.uint40s(1 hours, 1 weeks);
LockupPro.SegmentWithDelta[] memory segments = new LockupPro.SegmentWithDelta[](2);
segments[0] = LockupPro.SegmentWithDelta({ amount: 2_500e18, exponent: ud2x18(3.14e18), delta: 1 hours });
segments[1] = LockupPro.SegmentWithDelta({ amount: 7_500e18, exponent: ud2x18(0.5e18), delta: 1 weeks });
pro.createWithDeltas({
sender: sender,
recipient: recipient,
totalAmount: 10_000e18,
segments: segments,
asset: asset,
cancelable: true,
deltas: deltas,
segments: segments,
broker: Broker(address(0), ud(0))
});
}
Expand Down
28 changes: 17 additions & 11 deletions src/SablierV2LockupLinear.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ contract SablierV2LockupLinear is

/// @inheritdoc ISablierV2LockupLinear
function getCliffTime(uint256 streamId) external view override returns (uint40 cliffTime) {
cliffTime = _streams[streamId].range.cliff;
cliffTime = _streams[streamId].cliffTime;
}

/// @inheritdoc ISablierV2Lockup
Expand All @@ -89,12 +89,16 @@ contract SablierV2LockupLinear is

/// @inheritdoc ISablierV2Lockup
function getEndTime(uint256 streamId) external view override returns (uint40 endTime) {
endTime = _streams[streamId].range.end;
endTime = _streams[streamId].endTime;
}

/// @inheritdoc ISablierV2LockupLinear
function getRange(uint256 streamId) external view override returns (LockupLinear.Range memory range) {
range = _streams[streamId].range;
range = LockupLinear.Range({
start: _streams[streamId].startTime,
cliff: _streams[streamId].cliffTime,
end: _streams[streamId].endTime
});
}

/// @inheritdoc ISablierV2Lockup
Expand All @@ -111,7 +115,7 @@ contract SablierV2LockupLinear is

/// @inheritdoc ISablierV2Lockup
function getStartTime(uint256 streamId) external view override returns (uint40 startTime) {
startTime = _streams[streamId].range.start;
startTime = _streams[streamId].startTime;
}

/// @inheritdoc ISablierV2Lockup
Expand Down Expand Up @@ -168,12 +172,12 @@ contract SablierV2LockupLinear is
// always greater than the start time, this also checks whether the start time is greater than
// the block timestamp.
uint256 currentTime = block.timestamp;
uint256 cliffTime = uint256(_streams[streamId].range.cliff);
uint256 cliffTime = uint256(_streams[streamId].cliffTime);
if (cliffTime > currentTime) {
return 0;
}

uint256 endTime = uint256(_streams[streamId].range.end);
uint256 endTime = uint256(_streams[streamId].endTime);

// If the current time is greater than or equal to the end time, we simply return the deposit minus
// the withdrawn amount.
Expand All @@ -184,7 +188,7 @@ contract SablierV2LockupLinear is
unchecked {
// In all other cases, calculate how much has been streamed so far.
// First, calculate how much time has elapsed since the stream started, and the total time of the stream.
uint256 startTime = uint256(_streams[streamId].range.start);
uint256 startTime = uint256(_streams[streamId].startTime);
UD60x18 elapsedTime = ud(currentTime - startTime);
UD60x18 totalTime = ud(endTime - startTime);

Expand Down Expand Up @@ -257,7 +261,7 @@ contract SablierV2LockupLinear is
streamId = _createWithRange(
CreateWithRangeParams({
amounts: amounts,
broker: broker.addr,
broker: broker.account,
cancelable: cancelable,
recipient: recipient,
sender: sender,
Expand Down Expand Up @@ -293,7 +297,7 @@ contract SablierV2LockupLinear is
streamId = _createWithRange(
CreateWithRangeParams({
amounts: amounts,
broker: broker.addr,
broker: broker.account,
cancelable: cancelable,
recipient: recipient,
sender: sender,
Expand Down Expand Up @@ -418,11 +422,13 @@ contract SablierV2LockupLinear is
// Effects: create the stream.
_streams[streamId] = LockupLinear.Stream({
amounts: Lockup.Amounts({ deposit: params.amounts.deposit, withdrawn: 0 }),
asset: params.asset,
cliffTime: params.range.cliff,
endTime: params.range.end,
isCancelable: params.cancelable,
sender: params.sender,
status: Lockup.Status.ACTIVE,
range: params.range,
asset: params.asset
startTime: params.range.start
});

// Effects: bump the next stream id and record the protocol fee.
Expand Down
41 changes: 19 additions & 22 deletions src/SablierV2LockupPro.sol
Original file line number Diff line number Diff line change
Expand Up @@ -99,12 +99,12 @@ contract SablierV2LockupPro is

/// @inheritdoc ISablierV2Lockup
function getEndTime(uint256 streamId) external view override returns (uint40 endTime) {
endTime = _streams[streamId].range.end;
endTime = _streams[streamId].endTime;
}

/// @inheritdoc ISablierV2LockupPro
function getRange(uint256 streamId) external view override returns (LockupPro.Range memory range) {
range = _streams[streamId].range;
range = LockupPro.Range({ start: _streams[streamId].startTime, end: _streams[streamId].endTime });
}

/// @inheritdoc ISablierV2Lockup
Expand All @@ -126,7 +126,7 @@ contract SablierV2LockupPro is

/// @inheritdoc ISablierV2Lockup
function getStartTime(uint256 streamId) external view override returns (uint40 startTime) {
startTime = _streams[streamId].range.start;
startTime = _streams[streamId].startTime;
}

/// @inheritdoc ISablierV2Lockup
Expand Down Expand Up @@ -181,12 +181,12 @@ contract SablierV2LockupPro is

// If the start time is greater than or equal to the block timestamp, return zero.
uint40 currentTime = uint40(block.timestamp);
if (_streams[streamId].range.start >= currentTime) {
if (_streams[streamId].startTime >= currentTime) {
return 0;
}

uint256 segmentCount = _streams[streamId].segments.length;
uint40 endTime = _streams[streamId].range.end;
uint40 endTime = _streams[streamId].endTime;

// If the current time is greater than or equal to the end time, we simply return the deposit minus
// the withdrawn amount.
Expand Down Expand Up @@ -227,14 +227,13 @@ contract SablierV2LockupPro is
address sender,
address recipient,
uint128 totalAmount,
LockupPro.Segment[] memory segments,
IERC20 asset,
bool cancelable,
uint40[] calldata deltas,
LockupPro.SegmentWithDelta[] memory segments,
Broker calldata broker
) external override returns (uint256 streamId) {
// Checks: check the deltas and adjust the segments accordingly.
Helpers.checkDeltasAndCalculateMilestones(segments, deltas);
// Checks: check the deltas and generate the canonical segments.
LockupPro.Segment[] memory segmentsWithMilestones = Helpers.checkDeltasAndCalculateMilestones(segments);

// Safe Interactions: query the protocol fee. This is safe because it's a known Sablier contract.
UD60x18 protocolFee = comptroller.getProtocolFee(asset);
Expand All @@ -251,10 +250,10 @@ contract SablierV2LockupPro is
streamId = _createWithMilestones(
CreateWithMilestonesParams({
amounts: amounts,
broker: broker.addr,
broker: broker.account,
cancelable: cancelable,
recipient: recipient,
segments: segments,
segments: segmentsWithMilestones,
sender: sender,
asset: asset,
startTime: uint40(block.timestamp)
Expand All @@ -267,9 +266,9 @@ contract SablierV2LockupPro is
address sender,
address recipient,
uint128 totalAmount,
LockupPro.Segment[] calldata segments,
IERC20 asset,
bool cancelable,
LockupPro.Segment[] calldata segments,
uint40 startTime,
Broker calldata broker
) external override returns (uint256 streamId) {
Expand All @@ -288,7 +287,7 @@ contract SablierV2LockupPro is
streamId = _createWithMilestones(
CreateWithMilestonesParams({
amounts: amounts,
broker: broker.addr,
broker: broker.account,
cancelable: cancelable,
recipient: recipient,
segments: segments,
Expand Down Expand Up @@ -335,7 +334,7 @@ contract SablierV2LockupPro is
previousMilestone = _streams[streamId].segments[index - 2].milestone;
} else {
// Otherwise, the current segment is the first, so use the start time as the previous milestone.
previousMilestone = _streams[streamId].range.start;
previousMilestone = _streams[streamId].startTime;
}

// Calculate how much time has elapsed since the segment started, and the total time of the segment.
Expand Down Expand Up @@ -364,8 +363,8 @@ contract SablierV2LockupPro is
SD59x18 exponent = _streams[streamId].segments[0].exponent.intoSD59x18();

// Calculate how much time has elapsed since the stream started, and the total time of the stream.
SD59x18 elapsedTime = (uint40(block.timestamp) - _streams[streamId].range.start).intoSD59x18();
SD59x18 totalTime = (_streams[streamId].range.end - _streams[streamId].range.start).intoSD59x18();
SD59x18 elapsedTime = (uint40(block.timestamp) - _streams[streamId].startTime).intoSD59x18();
SD59x18 totalTime = (_streams[streamId].endTime - _streams[streamId].startTime).intoSD59x18();

// Calculate the streamed amount.
SD59x18 elapsedTimePercentage = elapsedTime.div(totalTime);
Expand Down Expand Up @@ -502,10 +501,8 @@ contract SablierV2LockupPro is

unchecked {
// The segment count cannot be zero at this point.
stream.range = LockupPro.Range({
start: params.startTime,
end: params.segments[segmentCount - 1].milestone
});
stream.endTime = params.segments[segmentCount - 1].milestone;
stream.startTime = params.startTime;

// Effects: store the segments. Copying an array from memory to storage is not currently supported in
// Solidity, so it has to be done manually. See https://github.com/ethereum/solidity/issues/12783
Expand Down Expand Up @@ -544,10 +541,10 @@ contract SablierV2LockupPro is
sender: params.sender,
recipient: params.recipient,
amounts: params.amounts,
segments: params.segments,
asset: params.asset,
cancelable: params.cancelable,
range: stream.range,
segments: params.segments,
range: LockupPro.Range({ start: stream.startTime, end: stream.endTime }),
broker: params.broker
});
}
Expand Down
4 changes: 2 additions & 2 deletions src/abstracts/SablierV2Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -81,10 +81,10 @@ abstract contract SablierV2Config is
_protocolRevenues[asset] = 0;

// Interactions: perform the ERC-20 transfer to pay the protocol revenues.
asset.safeTransfer(msg.sender, protocolRevenues);
asset.safeTransfer({ to: msg.sender, value: protocolRevenues });

// Log the claim of the protocol revenues.
emit Events.ClaimProtocolRevenues(msg.sender, asset, protocolRevenues);
emit Events.ClaimProtocolRevenues({ admin: msg.sender, asset: asset, protocolRevenues: protocolRevenues });
}

/// @inheritdoc ISablierV2Config
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/ISablierV2Config.sol
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ interface ISablierV2Config is ISablierV2Adminable {
/// @dev Emits a {SetComptroller} event.
///
/// Notes:
/// - It is not an error to set the same comptroller.
/// - Does not revert if the comptroller is the same.
///
/// Requirements:
/// - The caller must be the contract admin.
Expand Down
6 changes: 3 additions & 3 deletions src/interfaces/ISablierV2Lockup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,8 @@ interface ISablierV2Lockup is
/// @dev Emits multiple {CancelLockupStream} events.
///
/// Notes:
/// - It is not an error if one of the stream ids points to a stream that is not active or is active but
/// is not cancelable.
/// - Does not revert if one of the stream ids points to a stream that is not active or is active but is
/// not cancelable.
/// - This function will attempt to call a hook on either the sender or the recipient of each stream.
///
/// Requirements:
Expand Down Expand Up @@ -187,7 +187,7 @@ interface ISablierV2Lockup is
/// @dev Emits multiple {WithdrawFromLockupStream} and {Transfer} events.
///
/// Notes:
/// - It is not an error if one of the stream ids points to a stream that is not active.
/// - Does not revert if one of the stream ids points to a stream that is not active.
/// - This function will attempt to call a hook on the recipient of each stream.
///
/// Requirements:
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/ISablierV2LockupLinear.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ interface ISablierV2LockupLinear is ISablierV2Lockup {
/// @dev Emits a {CreateLockupLinearStream} and a {Transfer} event.
///
/// Notes:
/// - As long as they are ordered, it is not an error to set a range in the past.
/// - As long as they are ordered, it is not an error to set a range that is in the past.
///
/// Requirements:
/// - `recipient` must not be the zero address.
Expand Down
23 changes: 10 additions & 13 deletions src/interfaces/ISablierV2LockupPro.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,11 @@ interface ISablierV2LockupPro is ISablierV2Lockup {
//////////////////////////////////////////////////////////////////////////*/

/// @notice Create a stream by setting the start time to `block.timestamp` and the end time to the sum of
/// `block.timestamp` and all `deltas`. The stream is funded by `msg.sender` and is wrapped in an ERC-721 NFT.
/// `block.timestamp` and all segment deltas. The stream is funded by `msg.sender` and is wrapped in an
/// ERC-721 NFT.
///
/// @dev Emits a {CreateLockupProStream} and a {Transfer} event.
///
/// Notes:
/// - The segment milestones should be empty, as they will be overridden.
///
/// Requirements:
/// - All from {createWithMilestones}.
///
Expand All @@ -63,32 +61,31 @@ interface ISablierV2LockupPro is ISablierV2Lockup {
/// @param recipient The address toward which to stream the assets.
/// @param totalAmount The total amount of ERC-20 assets to be paid, which includes the stream deposit and any
/// potential fees. This is represented in units of the asset's decimals.
/// @param segments The segments the protocol uses to compose the custom streaming curve.
/// @param asset The contract address of the ERC-20 asset to use for streaming.
/// @param cancelable Boolean that indicates whether the stream is cancelable or not.
/// @param deltas The differences between the Unix timestamp milestones used to compose the custom streaming
/// curve.
/// @param segments The segments with deltas the protocol will use to compose the custom streaming curve.
/// The milestones will be be calculated by adding each delta to `block.timestamp`.
/// @param broker An optional struct that encapsulates (i) the address of the broker that has helped create the
/// stream and (ii) the percentage fee that the broker is paid from `totalAmount`, as an UD60x18 number.
/// @return streamId The id of the newly created stream.
function createWithDeltas(
address sender,
address recipient,
uint128 totalAmount,
LockupPro.Segment[] memory segments,
IERC20 asset,
bool cancelable,
uint40[] memory deltas,
LockupPro.SegmentWithDelta[] memory segments,
Broker calldata broker
) external returns (uint256 streamId);

/// @notice Create a stream by using the provided milestones, implying the end time from the last segment's.
/// @notice Create a stream by using the provided milestones, implying the end time from the last segment's
/// milestone. The stream is funded by `msg.sender` and is wrapped in an ERC-721 NFT.
///
/// @dev Emits a {CreateLockupProStream} and a {Transfer} event.
///
/// Notes:
/// - As long as they are ordered, it is not an error to set the `startTime` and the milestones to a past range.
/// - As long as they are ordered, it is not an error to set the `startTime` and the milestones to a range that
/// is in the past
///
/// Requirements:
/// - `recipient` must not be the zero address.
Expand All @@ -105,9 +102,9 @@ interface ISablierV2LockupPro is ISablierV2Lockup {
/// @param recipient The address toward which to stream the assets.
/// @param totalAmount The total amount of ERC-20 assets to be paid, which includes the stream deposit and any
/// potential fees. This is represented in units of the asset's decimals.
/// @param segments The segments the protocol uses to compose the custom streaming curve.
/// @param asset The contract address of the ERC-20 asset to use for streaming.
/// @param cancelable Boolean that indicates whether the stream will be cancelable or not.
/// @param segments The segments the protocol uses to compose the custom streaming curve.
/// @param startTime The Unix timestamp for when the stream will start.
/// @param broker An optional struct that encapsulates (i) the address of the broker that has helped create the
/// stream and (ii) the percentage fee that the broker is paid from `totalAmount`, as an UD60x18 number.
Expand All @@ -116,9 +113,9 @@ interface ISablierV2LockupPro is ISablierV2Lockup {
address sender,
address recipient,
uint128 totalAmount,
LockupPro.Segment[] memory segments,
IERC20 asset,
bool cancelable,
LockupPro.Segment[] memory segments,
uint40 startTime,
Broker calldata broker
) external returns (uint256 streamId);
Expand Down
Loading