Skip to content

Commit

Permalink
Make max end hints a custom type (#346)
Browse files Browse the repository at this point in the history
  • Loading branch information
CodeSandwich committed Mar 4, 2024
1 parent 30be8e4 commit 02da8aa
Show file tree
Hide file tree
Showing 20 changed files with 436 additions and 239 deletions.
32 changes: 18 additions & 14 deletions src/AddressDriver.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.24;

import {AccountMetadata, Drips, StreamReceiver, IERC20, SplitsReceiver} from "./Drips.sol";
import {
AccountMetadata,
Drips,
MaxEndHints,
StreamReceiver,
IERC20,
SplitsReceiver
} from "./Drips.sol";
import {Managed} from "./Managed.sol";
import {DriverTransferUtils} from "./DriverTransferUtils.sol";

Expand Down Expand Up @@ -95,29 +102,29 @@ contract AddressDriver is DriverTransferUtils, Managed {
/// @param newReceivers The list of the streams receivers of the sender to be set.
/// Must be sorted by the account IDs and then by the stream configurations,
/// without identical elements and without 0 amtPerSecs.
/// @param maxEndHint1 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The first hint for finding the maximum end time when all streams stop due to funds
/// @param maxEndHints An optional parameter allowing gas optimization.
/// Pass a list of 8 zero value hints to ignore it, it's represented as an integer `0`.
/// The list of hints for finding the maximum end time when all streams stop due to funds
/// running out after the balance is updated and the new receivers list is applied.
/// Hints have no effect on the results of calling this function, except potentially saving gas.
/// Hints are Unix timestamps used as the starting points for binary search for the time
/// when funds run out in the range of timestamps from the current block's to `2^32`.
/// Hints lower than the current timestamp are ignored.
/// You can provide zero, one or two hints. The order of hints doesn't matter.
/// Hints lower than the current timestamp including the zero value hints are ignored.
/// If you provide fewer than 8 non-zero value hints make them the rightmost values to save gas.
/// It's the best approach to make the most risky and precise hints the rightmost ones.
/// Hints are the most effective when one of them is lower than or equal to
/// the last timestamp when funds are still streamed, and the other one is strictly larger
/// than that timestamp,the smaller the difference between such hints, the higher gas savings.
/// than that timestamp, the smaller the difference between such hints, the more gas is saved.
/// The savings are the highest possible when one of the hints is equal to
/// the last timestamp when funds are still streamed, and the other one is larger by 1.
/// It's worth noting that the exact timestamp of the block in which this function is executed
/// may affect correctness of the hints, especially if they're precise.
/// Hints don't provide any benefits when balance is not enough to cover
/// a single second of streaming or is enough to cover all streams until timestamp `2^32`.
/// Even inaccurate hints can be useful, and providing a single hint
/// or two hints that don't enclose the time when funds run out can still save some gas.
/// or hints that don't enclose the time when funds run out can still save some gas.
/// Providing poor hints that don't reduce the number of binary search steps
/// may cause slightly higher gas usage than not providing any hints.
/// @param maxEndHint2 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The second hint for finding the maximum end time, see `maxEndHint1` docs for more details.
/// @param transferTo The address to send funds to in case of decreasing balance
/// @return realBalanceDelta The actually applied streams balance change.
/// It's equal to the passed `balanceDelta`, unless it's negative
Expand All @@ -127,9 +134,7 @@ contract AddressDriver is DriverTransferUtils, Managed {
StreamReceiver[] calldata currReceivers,
int128 balanceDelta,
StreamReceiver[] calldata newReceivers,
// slither-disable-next-line similar-names
uint32 maxEndHint1,
uint32 maxEndHint2,
MaxEndHints maxEndHints,
address transferTo
) public onlyProxy returns (int128 realBalanceDelta) {
return _setStreamsAndTransfer(
Expand All @@ -139,8 +144,7 @@ contract AddressDriver is DriverTransferUtils, Managed {
currReceivers,
balanceDelta,
newReceivers,
maxEndHint1,
maxEndHint2,
maxEndHints,
transferTo
);
}
Expand Down
30 changes: 17 additions & 13 deletions src/Drips.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
pragma solidity ^0.8.24;

import {
Streams, StreamConfig, StreamsHistory, StreamConfigImpl, StreamReceiver
MaxEndHints,
MaxEndHintsImpl,
StreamConfig,
StreamConfigImpl,
Streams,
StreamsHistory,
StreamReceiver
} from "./Streams.sol";
import {Managed} from "./Managed.sol";
import {Splits, SplitsReceiver} from "./Splits.sol";
Expand Down Expand Up @@ -650,29 +656,29 @@ contract Drips is Managed, Streams, Splits {
/// @param newReceivers The list of the streams receivers of the account to be set.
/// Must be sorted by the account IDs and then by the stream configurations,
/// without identical elements and without 0 amtPerSecs.
/// @param maxEndHint1 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The first hint for finding the maximum end time when all streams stop due to funds
/// @param maxEndHints An optional parameter allowing gas optimization.
/// Pass a list of 8 zero value hints to ignore it, it's represented as an integer `0`.
/// The list of hints for finding the maximum end time when all streams stop due to funds
/// running out after the balance is updated and the new receivers list is applied.
/// Hints have no effect on the results of calling this function, except potentially saving gas.
/// Hints are Unix timestamps used as the starting points for binary search for the time
/// when funds run out in the range of timestamps from the current block's to `2^32`.
/// Hints lower than the current timestamp are ignored.
/// You can provide zero, one or two hints. The order of hints doesn't matter.
/// Hints lower than the current timestamp including the zero value hints are ignored.
/// If you provide fewer than 8 non-zero value hints make them the rightmost values to save gas.
/// It's the best approach to make the most risky and precise hints the rightmost ones.
/// Hints are the most effective when one of them is lower than or equal to
/// the last timestamp when funds are still streamed, and the other one is strictly larger
/// than that timestamp,the smaller the difference between such hints, the higher gas savings.
/// than that timestamp, the smaller the difference between such hints, the more gas is saved.
/// The savings are the highest possible when one of the hints is equal to
/// the last timestamp when funds are still streamed, and the other one is larger by 1.
/// It's worth noting that the exact timestamp of the block in which this function is executed
/// may affect correctness of the hints, especially if they're precise.
/// Hints don't provide any benefits when balance is not enough to cover
/// a single second of streaming or is enough to cover all streams until timestamp `2^32`.
/// Even inaccurate hints can be useful, and providing a single hint
/// or two hints that don't enclose the time when funds run out can still save some gas.
/// or hints that don't enclose the time when funds run out can still save some gas.
/// Providing poor hints that don't reduce the number of binary search steps
/// may cause slightly higher gas usage than not providing any hints.
/// @param maxEndHint2 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The second hint for finding the maximum end time, see `maxEndHint1` docs for more details.
/// @return realBalanceDelta The actually applied streams balance change.
/// It's equal to the passed `balanceDelta`, unless it's negative
/// and it gets capped at the current balance amount.
Expand All @@ -683,13 +689,11 @@ contract Drips is Managed, Streams, Splits {
StreamReceiver[] memory currReceivers,
int128 balanceDelta,
StreamReceiver[] memory newReceivers,
// slither-disable-next-line similar-names
uint32 maxEndHint1,
uint32 maxEndHint2
MaxEndHints maxEndHints
) public onlyProxy onlyDriver(accountId) returns (int128 realBalanceDelta) {
if (balanceDelta > 0) _increaseStreamsBalance(erc20, uint128(balanceDelta));
realBalanceDelta = Streams._setStreams(
accountId, erc20, currReceivers, balanceDelta, newReceivers, maxEndHint1, maxEndHint2
accountId, erc20, currReceivers, balanceDelta, newReceivers, maxEndHints
);
if (realBalanceDelta < 0) _decreaseStreamsBalance(erc20, uint128(-realBalanceDelta));
}
Expand Down
24 changes: 11 additions & 13 deletions src/DriverTransferUtils.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.24;

import {Drips, StreamReceiver, IERC20, SafeERC20} from "./Drips.sol";
import {Drips, MaxEndHints, StreamReceiver, IERC20, SafeERC20} from "./Drips.sol";
import {ERC2771Context} from "openzeppelin-contracts/metatx/ERC2771Context.sol";

/// @notice ERC-20 token transfer utilities for drivers.
Expand Down Expand Up @@ -77,29 +77,29 @@ abstract contract DriverTransferUtils is ERC2771Context {
/// @param newReceivers The list of the streams receivers of the sender to be set.
/// Must be sorted by the account IDs and then by the stream configurations,
/// without identical elements and without 0 amtPerSecs.
/// @param maxEndHint1 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The first hint for finding the maximum end time when all streams stop due to funds
/// @param maxEndHints An optional parameter allowing gas optimization.
/// Pass a list of 8 zero value hints to ignore it, it's represented as an integer `0`.
/// The list of hints for finding the maximum end time when all streams stop due to funds
/// running out after the balance is updated and the new receivers list is applied.
/// Hints have no effect on the results of calling this function, except potentially saving gas.
/// Hints are Unix timestamps used as the starting points for binary search for the time
/// when funds run out in the range of timestamps from the current block's to `2^32`.
/// Hints lower than the current timestamp are ignored.
/// You can provide zero, one or two hints. The order of hints doesn't matter.
/// Hints lower than the current timestamp including the zero value hints are ignored.
/// If you provide fewer than 8 non-zero value hints make them the rightmost values to save gas.
/// It's the best approach to make the most risky and precise hints the rightmost ones.
/// Hints are the most effective when one of them is lower than or equal to
/// the last timestamp when funds are still streamed, and the other one is strictly larger
/// than that timestamp,the smaller the difference between such hints, the higher gas savings.
/// than that timestamp, the smaller the difference between such hints, the more gas is saved.
/// The savings are the highest possible when one of the hints is equal to
/// the last timestamp when funds are still streamed, and the other one is larger by 1.
/// It's worth noting that the exact timestamp of the block in which this function is executed
/// may affect correctness of the hints, especially if they're precise.
/// Hints don't provide any benefits when balance is not enough to cover
/// a single second of streaming or is enough to cover all streams until timestamp `2^32`.
/// Even inaccurate hints can be useful, and providing a single hint
/// or two hints that don't enclose the time when funds run out can still save some gas.
/// or hints that don't enclose the time when funds run out can still save some gas.
/// Providing poor hints that don't reduce the number of binary search steps
/// may cause slightly higher gas usage than not providing any hints.
/// @param maxEndHint2 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The second hint for finding the maximum end time, see `maxEndHint1` docs for more details.
/// @param transferTo The address to send funds to in case of decreasing balance
/// @return realBalanceDelta The actually applied streams balance change.
/// It's equal to the passed `balanceDelta`, unless it's negative
Expand All @@ -111,14 +111,12 @@ abstract contract DriverTransferUtils is ERC2771Context {
StreamReceiver[] calldata currReceivers,
int128 balanceDelta,
StreamReceiver[] calldata newReceivers,
// slither-disable-next-line similar-names
uint32 maxEndHint1,
uint32 maxEndHint2,
MaxEndHints maxEndHints,
address transferTo
) internal returns (int128 realBalanceDelta) {
if (balanceDelta > 0) _transferFromCaller(drips, erc20, uint128(balanceDelta));
realBalanceDelta = drips.setStreams(
accountId, erc20, currReceivers, balanceDelta, newReceivers, maxEndHint1, maxEndHint2
accountId, erc20, currReceivers, balanceDelta, newReceivers, maxEndHints
);
if (realBalanceDelta < 0) drips.withdraw(erc20, transferTo, uint128(-realBalanceDelta));
}
Expand Down
31 changes: 17 additions & 14 deletions src/NFTDriver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,13 @@
pragma solidity ^0.8.24;

import {
AccountMetadata, Drips, StreamReceiver, IERC20, SafeERC20, SplitsReceiver
AccountMetadata,
Drips,
MaxEndHints,
StreamReceiver,
IERC20,
SafeERC20,
SplitsReceiver
} from "./Drips.sol";
import {DriverTransferUtils, ERC2771Context} from "./DriverTransferUtils.sol";
import {Managed} from "./Managed.sol";
Expand Down Expand Up @@ -262,29 +268,29 @@ contract NFTDriver is ERC721Burnable, DriverTransferUtils, Managed {
/// @param newReceivers The list of the streams receivers of the sender to be set.
/// Must be sorted by the account IDs and then by the stream configurations,
/// without identical elements and without 0 amtPerSecs.
/// @param maxEndHint1 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The first hint for finding the maximum end time when all streams stop due to funds
/// @param maxEndHints An optional parameter allowing gas optimization.
/// Pass a list of 8 zero value hints to ignore it, it's represented as an integer `0`.
/// The list of hints for finding the maximum end time when all streams stop due to funds
/// running out after the balance is updated and the new receivers list is applied.
/// Hints have no effect on the results of calling this function, except potentially saving gas.
/// Hints are Unix timestamps used as the starting points for binary search for the time
/// when funds run out in the range of timestamps from the current block's to `2^32`.
/// Hints lower than the current timestamp are ignored.
/// You can provide zero, one or two hints. The order of hints doesn't matter.
/// Hints lower than the current timestamp including the zero value hints are ignored.
/// If you provide fewer than 8 non-zero value hints make them the rightmost values to save gas.
/// It's the best approach to make the most risky and precise hints the rightmost ones.
/// Hints are the most effective when one of them is lower than or equal to
/// the last timestamp when funds are still streamed, and the other one is strictly larger
/// than that timestamp,the smaller the difference between such hints, the higher gas savings.
/// than that timestamp, the smaller the difference between such hints, the more gas is saved.
/// The savings are the highest possible when one of the hints is equal to
/// the last timestamp when funds are still streamed, and the other one is larger by 1.
/// It's worth noting that the exact timestamp of the block in which this function is executed
/// may affect correctness of the hints, especially if they're precise.
/// Hints don't provide any benefits when balance is not enough to cover
/// a single second of streaming or is enough to cover all streams until timestamp `2^32`.
/// Even inaccurate hints can be useful, and providing a single hint
/// or two hints that don't enclose the time when funds run out can still save some gas.
/// or hints that don't enclose the time when funds run out can still save some gas.
/// Providing poor hints that don't reduce the number of binary search steps
/// may cause slightly higher gas usage than not providing any hints.
/// @param maxEndHint2 An optional parameter allowing gas optimization, pass `0` to ignore it.
/// The second hint for finding the maximum end time, see `maxEndHint1` docs for more details.
/// @param transferTo The address to send funds to in case of decreasing balance
/// @return realBalanceDelta The actually applied streams balance change.
/// It's equal to the passed `balanceDelta`, unless it's negative
Expand All @@ -295,9 +301,7 @@ contract NFTDriver is ERC721Burnable, DriverTransferUtils, Managed {
StreamReceiver[] calldata currReceivers,
int128 balanceDelta,
StreamReceiver[] calldata newReceivers,
// slither-disable-next-line similar-names
uint32 maxEndHint1,
uint32 maxEndHint2,
MaxEndHints maxEndHints,
address transferTo
) public onlyProxy onlyApprovedOrOwner(tokenId) returns (int128 realBalanceDelta) {
return _setStreamsAndTransfer(
Expand All @@ -307,8 +311,7 @@ contract NFTDriver is ERC721Burnable, DriverTransferUtils, Managed {
currReceivers,
balanceDelta,
newReceivers,
maxEndHint1,
maxEndHint2,
maxEndHints,
transferTo
);
}
Expand Down
Loading

0 comments on commit 02da8aa

Please sign in to comment.