Skip to content

Commit 68f2d7b

Browse files
smol-ninjaandreivladbrg
authored andcommitted
feat: function to calculate min fee in wei for a given stream ID
refactor: use the new function to calculate min fee in wei test: add integration test for calculateMinFeeWei
1 parent 83c9e7c commit 68f2d7b

File tree

6 files changed

+74
-7
lines changed

6 files changed

+74
-7
lines changed

bun.lock

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"dependencies": {
77
"@openzeppelin/contracts": "5.3.0",
88
"@prb/math": "4.1.0",
9-
"@sablier/evm-utils": "github:sablier-labs/evm-utils",
9+
"@sablier/evm-utils": "github:sablier-labs/evm-utils#31f94ff",
1010
},
1111
"devDependencies": {
1212
"@sablier/devkit": "github:sablier-labs/devkit",
@@ -172,7 +172,7 @@
172172

173173
"@sablier/devkit": ["@sablier/devkit@github:sablier-labs/devkit#3be93f7", {}, "sablier-labs-devkit-3be93f7"],
174174

175-
"@sablier/evm-utils": ["@sablier/evm-utils@github:sablier-labs/evm-utils#cc3a85c", { "dependencies": { "@chainlink/contracts": "1.3.0" } }, "sablier-labs-evm-utils-cc3a85c"],
175+
"@sablier/evm-utils": ["@sablier/evm-utils@github:sablier-labs/evm-utils#31f94ff", { "dependencies": { "@chainlink/contracts": "1.3.0" } }, "sablier-labs-evm-utils-31f94ff"],
176176

177177
"@scroll-tech/contracts": ["@scroll-tech/[email protected]", "", {}, "sha512-aBbDOc3WB/WveZdpJYcrfvMYMz7ZTEiW8M9XMJLba8p9FAR5KGYB/cV+8+EUsq3MKt7C1BfR+WnXoTVdvwIY6w=="],
178178

@@ -414,7 +414,7 @@
414414

415415
"got": ["[email protected]", "", { "dependencies": { "@sindresorhus/is": "^5.2.0", "@szmarczak/http-timer": "^5.0.1", "cacheable-lookup": "^7.0.0", "cacheable-request": "^10.2.8", "decompress-response": "^6.0.0", "form-data-encoder": "^2.1.2", "get-stream": "^6.0.1", "http2-wrapper": "^2.1.10", "lowercase-keys": "^3.0.0", "p-cancelable": "^3.0.0", "responselike": "^3.0.0" } }, "sha512-mThBblvlAF1d4O5oqyvN+ZxLAYwIJK7bpMxgYqPD9okW0C3qm5FFn7k811QrcuEBwaogR3ngOFoCfs6mRv7teQ=="],
416416

417-
"graceful-fs": ["[email protected].11", "", {}, "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="],
417+
"graceful-fs": ["[email protected].10", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
418418

419419
"has-flag": ["[email protected]", "", {}, "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ=="],
420420

@@ -810,8 +810,6 @@
810810

811811
"@openzeppelin/upgrades-core/minimatch": ["[email protected]", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
812812

813-
"@pnpm/network.ca-file/graceful-fs": ["[email protected]", "", {}, "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA=="],
814-
815813
"better-ajv-errors/chalk": ["[email protected]", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
816814

817815
"cli-truncate/slice-ansi": ["[email protected]", "", { "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" } }, "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ=="],

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
"dependencies": {
1414
"@openzeppelin/contracts": "5.3.0",
1515
"@prb/math": "4.1.0",
16-
"@sablier/evm-utils": "github:sablier-labs/evm-utils"
16+
"@sablier/evm-utils": "github:sablier-labs/evm-utils#31f94ff"
1717
},
1818
"devDependencies": {
1919
"@sablier/devkit": "github:sablier-labs/devkit",

src/SablierLockup.sol

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions
99
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
1010
import { Batch } from "@sablier/evm-utils/src/Batch.sol";
1111
import { Comptrollerable } from "@sablier/evm-utils/src/Comptrollerable.sol";
12+
import { ISablierComptroller } from "@sablier/evm-utils/src/interfaces/ISablierComptroller.sol";
1213

1314
import { SablierLockupDynamic } from "./abstracts/SablierLockupDynamic.sol";
1415
import { SablierLockupLinear } from "./abstracts/SablierLockupLinear.sol";
@@ -64,6 +65,21 @@ contract SablierLockup is
6465
USER-FACING READ-ONLY FUNCTIONS
6566
//////////////////////////////////////////////////////////////////////////*/
6667

68+
/// @inheritdoc ISablierLockup
69+
function calculateMinFeeWei(uint256 streamId)
70+
external
71+
view
72+
override
73+
notNull(streamId)
74+
returns (uint256 minFeeWei)
75+
{
76+
// Calculate the minimum fee in wei for the stream sender.
77+
minFeeWei = comptroller.calculateMinFeeWeiFor({
78+
protocol: ISablierComptroller.Protocol.Lockup,
79+
user: _streams[streamId].sender
80+
});
81+
}
82+
6783
/// @inheritdoc ISablierLockup
6884
function getRecipient(uint256 streamId) external view override returns (address recipient) {
6985
// Check the stream NFT exists and return the owner, which is the stream's recipient.
@@ -645,7 +661,12 @@ contract SablierLockup is
645661

646662
/// @dev See the documentation for the user-facing functions that call this private function.
647663
function _withdraw(uint256 streamId, address to, uint128 amount) private {
648-
uint256 minFeeWei = comptroller.calculateLockupMinFeeWeiFor(_streams[streamId].sender);
664+
// Calculate the minimum fee in wei for the stream sender.
665+
uint256 minFeeWei = comptroller.calculateMinFeeWeiFor({
666+
protocol: ISablierComptroller.Protocol.Lockup,
667+
user: _streams[streamId].sender
668+
});
669+
649670
uint256 feePaid = msg.value;
650671

651672
// Check: fee paid is at least the minimum fee.

src/interfaces/ISablierLockup.sol

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ interface ISablierLockup is
8787
USER-FACING READ-ONLY FUNCTIONS
8888
//////////////////////////////////////////////////////////////////////////*/
8989

90+
/// @notice Calculates the minimum fee in wei required to withdraw from the given stream ID.
91+
/// @dev Reverts if `streamId` references a null stream.
92+
/// @param streamId The stream ID for the query.
93+
function calculateMinFeeWei(uint256 streamId) external view returns (uint256 minFeeWei);
94+
9095
/// @notice Retrieves the stream's recipient.
9196
/// @dev Reverts if the NFT has been burned.
9297
/// @param streamId The stream ID for the query.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
// SPDX-License-Identifier: UNLICENSED
2+
pragma solidity >=0.8.22 <0.9.0;
3+
4+
import { ISablierComptroller } from "@sablier/evm-utils/src/interfaces/ISablierComptroller.sol";
5+
6+
import { Integration_Test } from "../../../Integration.t.sol";
7+
8+
contract CalculateMinFeeWeiFor_Integration_Concrete_Test is Integration_Test {
9+
function test_RevertGiven_Null() external {
10+
expectRevert_Null({ callData: abi.encodeCall(lockup.calculateMinFeeWei, ids.nullStream) });
11+
}
12+
13+
function test_GivenCustomFeeSet() external givenNotNull {
14+
setMsgSender(admin);
15+
16+
uint256 customFeeUSD = 100e8; // 100 USD.
17+
18+
// Set the custom fee.
19+
comptroller.setCustomFeeUSDFor({
20+
protocol: ISablierComptroller.Protocol.Lockup,
21+
user: users.sender,
22+
customFeeUSD: customFeeUSD
23+
});
24+
25+
uint256 expectedFeeWei = (1e18 * customFeeUSD) / 3000e8; // at $3000 per ETH
26+
27+
// It should return the custom fee in wei.
28+
assertEq(lockup.calculateMinFeeWei(ids.defaultStream), expectedFeeWei, "customFeeWei");
29+
}
30+
31+
function test_GivenCustomFeeNotSet() external view givenNotNull {
32+
// It should return the minimum fee in wei.
33+
assertEq(lockup.calculateMinFeeWei(ids.defaultStream), LOCKUP_MIN_FEE_WEI, "minFeeWei");
34+
}
35+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CalculateMinFeeWeiFor_Integration_Concrete_Test
2+
├── given null
3+
│ └── it should revert
4+
└── given not null
5+
├── given custom fee set
6+
│ └── it should return the custom fee in wei
7+
└── given custom fee not set
8+
└── it should return the minimum fee in wei

0 commit comments

Comments
 (0)