diff --git a/README.md b/README.md index 010e4643..15e13d2d 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ -## Sablier V2 Open-Ended +## Sablier Flow -This repository contains the smart contracts for the EOES (EVM open-ended streams) concept. By open-ended, we mean that -the streams have no fixed duration and no deposit amount at stream creation. This concept is primarily beneficial for -salaries and not for vesting or airdrops, where lockups are more appropriate. +This repository contains the smart contracts for "flow" streams. By flow, we mean that the streams have no fixed +duration and no deposit amount at stream creation. This concept is primarily beneficial for salaries and not for vesting +or airdrops, where lockups are more appropriate. ### Motivation @@ -36,14 +36,14 @@ As mentioned above, the creation and deposit operations are distinct. This means stream is created, and deposits are made afterward. However, a `createAndDeposit` function is implemented to maintain the same user experience. -Since the streams are open-ended, we don't have a start time nor an end time, instead we have a time reference +Since the streams are flow, we don't have a start time nor an end time, instead we have a time reference (`lastTimeUpdate`) which will be set to `block.timestamp` at the creation of the stream. There are several actions that will update this time reference: - when a withdrawal is made - `lastTimeUpdate` will be set to the given `time` parameter passed in the function, you can see why this parameter is - needed in the explantion from [this PR](https://github.com/sablier-labs/v2-open-ended/pull/4) + needed in the explantion from [this PR](https://github.com/sablier-labs/flow/pull/4) - when the rate per second is changed - `lastTimeUpdate` will be set to `block.timestamp`, this time update is required in the `_adjustRatePerSecond` @@ -120,7 +120,7 @@ time to get that 10 per day "streamed", using the 18 decimals format would delay $\ 0.000115740740740740 \times (oneDayInSeconds + 1 second) = 10.000115740740677000 \$ -Currently, I don't think it's possible to address this precision problem entirely, given the nature of open-endedness. +Currently, I don't think it's possible to address this precision problem entirely. ### Technical decisions @@ -155,7 +155,7 @@ _bal = sum of deposits - sum of withdrawals_ _sum of withdrawn amounts ≤ sum of deposits_ -_sum of stream balances normalized to asset decimals ≤ asset.balanceOf(SablierV2OpenEnded)_ +_sum of stream balances normalized to asset decimals ≤ asset.balanceOf(SablierFlow)_ _ltu ≤ now_ diff --git a/foundry.toml b/foundry.toml index 6145a01e..306f2673 100644 --- a/foundry.toml +++ b/foundry.toml @@ -44,7 +44,7 @@ [doc] ignore = ["**/*.t.sol"] out = "docs" - repository = "https://github.com/sablier-labs/v2-open-ended" + repository = "https://github.com/sablier-labs/v2-flow" [fmt] bracket_spacing = true diff --git a/package.json b/package.json index d383c576..3b46e65a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { - "name": "@sablier/v2-open-ended", - "description": "Open ended smart contracts of the Sablier V2 token streaming protocol", + "name": "@sablier/flow", + "description": "Flow smart contracts of the Sablier token distribution protocol", "license": "BUSL-1.1", "version": "1.0.0", "author": { @@ -8,7 +8,7 @@ "url": "https://sablier.com" }, "bugs": { - "url": "https://github.com/sablier-labs/v2-open-ended/issues" + "url": "https://github.com/sablier-labs/flow/issues" }, "dependencies": { "@openzeppelin/contracts": "5.0.2", diff --git a/precompiles/Precompiles.sol b/precompiles/Precompiles.sol index 386d8b29..7e4153a1 100644 --- a/precompiles/Precompiles.sol +++ b/precompiles/Precompiles.sol @@ -2,7 +2,7 @@ // solhint-disable max-line-length,no-inline-assembly,reason-string pragma solidity >=0.8.22; -import { ISablierV2OpenEnded } from "./../src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "./../src/interfaces/ISablierFlow.sol"; /// @notice This is useful for external integrations seeking to test against the exact deployed bytecode, as recompiling /// with via IR enabled would be time-consuming. @@ -10,14 +10,14 @@ import { ISablierV2OpenEnded } from "./../src/interfaces/ISablierV2OpenEnded.sol /// The BUSL-1.1 license permits non-production usage of this file. This prohibits running the code on mainnet, /// but allows for execution in test environments, such as a local development network or a testnet. contract Precompiles { - bytes public constant BYTECODE_OPEN_ENDED = + bytes public constant BYTECODE_FLOW = hex"60a080604052346100285730608052600160005561323c908161002e823960805181612b8c0152f35b600080fdfe6080604052600436101561001257600080fd5b60003560e01c80630444b8dd1461217a5780630adbd70814611f2e5780631400ecec14611ecd5780631e01043914611e725780631e99d56914611e54578063295d7fa414611dfe578063387930ed14611da657806339e3af9b14611d5257806340e58ee514611c29578063432b08c914611ba05780634869e12d14611b3f578063623717ab1461197a5780636d0cee751461191857806380448da3146118cc5780638518c082146117195780638659c27014611503578063894e9a0d1461135757806394ecac93146112f55780639e9e2e131461125c578063a8a482a614610fec578063af0759a514610fa7578063b8a3be6614610f70578063b971302a14610f0e578063c7e9492214610eac578063d074065014610e4a578063d32cc1a414610d21578063d5e4602f14610aee578063d8702fdb14610783578063d975dfed14610708578063ea5ead1914610477578063eac8f5b814610415578063f6de2360146103c35763fa0e3c941461018757600080fd5b346103be5760406003193601126103be576004356101a3612247565b906101ac612b75565b8060005260019060209082825260ff836040600020015460d01c1661038d578060005282825260ff836040600020015460c81c161561035c578060005282825273ffffffffffffffffffffffffffffffffffffffff9182600360406000200154163303610324578160005283815282600360406000200154169261023764ffffffffff421684612af2565b946fffffffffffffffffffffffffffffffff958688169687156102fa57811687116102a6575061028c85969785967f2bc0a2a296f3ca9cfd73a88d6ed9f60be91bb5ee2b5d77392a557ba279a99d0296612f78565b8460005282526002604060002001541694604051908152a4005b6040517f6a7885b2000000000000000000000000000000000000000000000000000000008152600481018690526fffffffffffffffffffffffffffffffff8981166024830152919091166044820152606490fd5b60046040517fa7025923000000000000000000000000000000000000000000000000000000008152fd5b6040517f70e0530f00000000000000000000000000000000000000000000000000000000815260048101839052336024820152604490fd5b602490604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b602490604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b600080fd5b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602060ff60026040600020015460a01c16604051908152f35b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602073ffffffffffffffffffffffffffffffffffffffff60026040600020015416604051908152f35b346103be5760406003193601126103be57600435610493612205565b9064ffffffffff908142166104a6612b75565b8160005260019060209180835260ff816040600020015460d01c166106d7578360005280835260ff816040600020015460c81c16156106a65773ffffffffffffffffffffffffffffffffffffffff9182871695861561067c578560005282855283836040600020015416808814159081610671575b506106345785600052828552826040600020015460a01c16808211156105fd5750846000528184526fffffffffffffffffffffffffffffffff968760406000205416156105cc57916105b1826105ab946105987f8979ea1e30f52867c984b014e2e83d8a8dbc8e439842a2efbcb8afc6f7cc567f9897958a612bde565b9586926105a5848c612e92565b8a612f17565b88612f78565b856000528352600260406000200154169560405191168152a4005b602486604051907f51c77d430000000000000000000000000000000000000000000000000000000082526004820152fd5b60449250604051917fe6e3e57a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60648688604051917f057638bc00000000000000000000000000000000000000000000000000000000835260048301523360248301526044820152fd5b90503314158961051b565b60046040517f95b899a3000000000000000000000000000000000000000000000000000000008152fd5b602484604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b602484604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5761076960209164ffffffffff421690612bde565b6fffffffffffffffffffffffffffffffff60405191168152f35b346103be5760406003193601126103be5767ffffffffffffffff6004358181116103be576107b590369060040161229d565b90916024359081116103be576107cf90369060040161229d565b6107d7612b75565b808303610ab75760005b8381106107ea57005b6107f58185876124a1565b356108018286886124a1565b35600052600160205273ffffffffffffffffffffffffffffffffffffffff600160406000200154166108348385876124a1565b359164ffffffffff831683036103be5761084c612b75565b80600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c57811561067c5780600052600160205273ffffffffffffffffffffffffffffffffffffffff60016040600020015416808314159081610aac575b50610a705780600052600160205264ffffffffff60016040600020015460a01c168064ffffffffff85161115610a32575064ffffffffff421664ffffffffff8416116109f4578060005260016020526fffffffffffffffffffffffffffffffff60406000205416156109c357908161094e61093d856001979695612bde565b936109488584612e92565b82612f17565b610959838383612f78565b80600052846020527f8979ea1e30f52867c984b014e2e83d8a8dbc8e439842a2efbcb8afc6f7cc567f602073ffffffffffffffffffffffffffffffffffffffff60026040600020015416946fffffffffffffffffffffffffffffffff60405191168152a4016107e1565b602490604051907f51c77d430000000000000000000000000000000000000000000000000000000082526004820152fd5b60448364ffffffffff604051917fa283f5be000000000000000000000000000000000000000000000000000000008352166004820152426024820152fd5b8360449164ffffffffff604051927fe6e3e57a0000000000000000000000000000000000000000000000000000000084521660048301526024820152fd5b606491604051917f057638bc00000000000000000000000000000000000000000000000000000000835260048301523360248301526044820152fd5b9050331415896108be565b82604491604051917fb90edbb900000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b346103be5760406003193601126103be57600435610b0a612247565b90610b13612b75565b8060005260019060209282845260ff836040600020015460c81c1615610cf0578160005282845273ffffffffffffffffffffffffffffffffffffffff80600360406000200154163303610cb8578260005283855260ff846040600020015460d01c1615610c87576fffffffffffffffffffffffffffffffff8216938415610c5d57807f6c4a61be11286a2f1055d4cf57ddc0f7ed6c5eee348deb8f9a96ef1c9fac7ba49385600052818852610c0960406000209182906fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b017fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff8154169055610c4164ffffffffff421685612f17565b83600052855260026040600020015416936040519384523393a4005b60046040517fad8c2697000000000000000000000000000000000000000000000000000000008152fd5b602483604051907f1f3ef9030000000000000000000000000000000000000000000000000000000082526004820152fd5b6040517f70e0530f00000000000000000000000000000000000000000000000000000000815260048101849052336024820152604490fd5b602482604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760a06003193601126103be5767ffffffffffffffff6004358181116103be57610d5390369060040161229d565b90916024358181116103be57610d6d90369060040161229d565b6044358381116103be57610d8590369060040161229d565b91610d8e612266565b936084359586116103be57610daa610dbc96369060040161229d565b979098610db682612452565b50612532565b91825191808303610e135760005b838110610de35760405180610ddf87826122ce565b0390f35b80610e0d610df36001938861251e565b51610e07610e028487896124a1565b612501565b90612976565b01610dca565b82604491604051917f4f7285de00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b346103be5760406003193601126103be57600435610e66612289565b9080600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5760209161076991612af2565b346103be5760406003193601126103be57600435610ec8612289565b9080600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5760209161076991612b26565b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602073ffffffffffffffffffffffffffffffffffffffff60036040600020015416604051908152f35b346103be5760206003193601126103be576004356000526001602052602060ff60016040600020015460c81c166040519015158152f35b346103be5760806003193601126103be576020610fe4610fc56121e2565b610fcd612205565b610fd5612228565b90610fde612266565b926125f9565b604051908152f35b346103be5760406003193601126103be57600435611008612247565b90611011612b75565b80600052600160209281845260ff826040600020015460d01c1661122b578260005281845260ff826040600020015460c81c16156111fa578260005281845273ffffffffffffffffffffffffffffffffffffffff806003604060002001541633036111c2576fffffffffffffffffffffffffffffffff92838316938415610c5d578560005281875260406000205460801c93848614611191579282606095926111448a6105a58b987f82382b5d2df37492128634f33f74e7df4804822c78be73b13b115f8ae9ddb1bd9b9864ffffffffff4216936110ef858d612bde565b9b6110fa8d82612e92565b600052526040600020906fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b85169485611170575b5087600052885260026040600020015416966040519384528301526040820152a3005b61118b9089600052828b52838360406000200154168a612f78565b8961114d565b602486604051907f1e3474d50000000000000000000000000000000000000000000000000000000082526004820152fd5b6040517f70e0530f00000000000000000000000000000000000000000000000000000000815260048101859052336024820152604490fd5b602483604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b602483604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760406003193601126103be57600435611278612247565b611280612b75565b81600052600160205260ff60016040600020015460d01c166112c45781600052600160205260ff60016040600020015460c81c1615610cf0576112c291612976565b005b602482604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760406003193601126103be57600435611311612289565b9080600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5760209161076991612bde565b346103be5760206003193601126103be57600435600061010060405161137c8161230a565b8281528260208201528260408201528260608201528260808201528260a08201528260c08201528260e0820152015280600052600160205260ff60016040600020015460c81c161561035c576000526001602052610120604060002073ffffffffffffffffffffffffffffffffffffffff6101006040516113fc8161230a565b8260038554956fffffffffffffffffffffffffffffffff871684528660801c602085015260ff6001820154848116604087015264ffffffffff8160a01c166060870152818160c81c161515608087015260d01c16151560a085015260ff600282015484811660c087015260a01c1660e0850152015416828201526fffffffffffffffffffffffffffffffff604051941684526fffffffffffffffffffffffffffffffff602082015116602085015282604082015116604085015264ffffffffff606082015116606085015260808101511515608085015260a0810151151560a08501528260c08201511660c085015260ff60e08201511660e0850152015116610100820152f35b346103be576020806003193601126103be5760043567ffffffffffffffff81116103be5761153590369060040161229d565b4264ffffffffff169060005b81811061154a57005b6115558183866124a1565b3561155e612b75565b80600052600180875260ff80826040600020015460d01c1661122b5782600052818852816040600020015460c81c1615610cf0578160005280875273ffffffffffffffffffffffffffffffffffffffff91600392808460406000200154163303610324577f7c8489a4add3095bad705c628240a59a782fad8c0d8f4297c92dfd0098ed886f8793836116f08c9460019998966000528386526040600020938180828701541698860154169661163261162b6fffffffffffffffffffffffffffffffff809854169b87612bde565b809b6123af565b956116466116408c89612952565b87612e92565b8560005282825260406000208381017a0100000000000000000000000000000000000000000000000000007fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff825416179055818154169055808716611709575b8a166116f9575b8460005252600260406000200154169660405193849384916040919493606084019584526fffffffffffffffffffffffffffffffff809216602085015216910152565b0390a401611541565b6117048a8a87612f78565b6116ad565b611714878a88612f78565b6116a6565b346103be5760606003193601126103be57600435611735612247565b9061173e612228565b90611747612b75565b8060005260019260209084825260ff856040600020015460c81c16156111fa578260005284825273ffffffffffffffffffffffffffffffffffffffff94856003604060002001541633036111c2578360005280835260ff816040600020015460d01c161561189b576fffffffffffffffffffffffffffffffff8216918215610c5d576112c2968286937f6c4a61be11286a2f1055d4cf57ddc0f7ed6c5eee348deb8f9a96ef1c9fac7ba4938560005281885261184460406000209182906fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b017fffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffff815416905561187c64ffffffffff421685612f17565b83600052855260026040600020015416936040519384523393a4612976565b602484604051907f1f3ef9030000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602060406000205460801c604051908152f35b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602073ffffffffffffffffffffffffffffffffffffffff60016040600020015416604051908152f35b346103be5760406003193601126103be5767ffffffffffffffff6004358181116103be57366023820112156103be578060040135906024926119bb83612397565b916119c96040519384612356565b83835260209385602085019160051b830101913683116103be5786869101915b838310611b2f575050505083359081116103be57611a0b90369060040161229d565b919093611a16612b75565b815193838503611af95760005b858110611a2c57005b611a36818561251e565b5180600052600180845260ff9182826040600020015460c81c1615611ac9576000528084526040600020015460d01c16611a8f5780611a89611a7a6001938761251e565b51610e07610e02848a8d6124a1565b01611a23565b611a9a91508361251e565b51604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b8590604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b6044858584604051927f4f7285de0000000000000000000000000000000000000000000000000000000084526004840152820152fd5b82358152918101918691016119e9565b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5761076960209164ffffffffff421690612b26565b346103be5760806003193601126103be5767ffffffffffffffff6004358181116103be57611bd290369060040161229d565b91906024358281116103be57611bec90369060040161229d565b936044359384116103be57610ddf94611c0c611c1d95369060040161229d565b939092611c17612266565b95612532565b604051918291826122ce565b346103be576020806003193601126103be57600435611c46612b75565b80600052600180835260ff816040600020015460d01c166112c4578160005280835260ff816040600020015460c81c1615610cf0578160005280835273ffffffffffffffffffffffffffffffffffffffff9182600360406000200154163303611d1957807f7c8489a4add3095bad705c628240a59a782fad8c0d8f4297c92dfd0098ed886f91600052828552604060002090611d148585840154169580600385015416956fffffffffffffffffffffffffffffffff809554169861163261162b64ffffffffff421687612bde565b0390a4005b6040517f70e0530f0000000000000000000000000000000000000000000000000000000081526004810191909152336024820152604490fd5b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602060ff60016040600020015460d01c166040519015158152f35b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c57610769602091612400565b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c576000526001602052602064ffffffffff60016040600020015460a01c16604051908152f35b346103be5760006003193601126103be576020600054604051908152f35b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460c81c161561035c57600052600160205260206fffffffffffffffffffffffffffffffff60406000205416604051908152f35b346103be5760206003193601126103be5760043580600052600160205260ff60016040600020015460d01c1661038d5780600052600160205260ff60016040600020015460c81c161561035c5761076960209164ffffffffff421690612af2565b346103be5760606003193601126103be57600435611f4a612205565b9064ffffffffff906044358281168082036103be57611f67612b75565b82600052600160209281845260ff826040600020015460d01c16612149578460005281845260ff826040600020015460c81c16156121185773ffffffffffffffffffffffffffffffffffffffff9283881696871561067c57866000528386528484604060002001541680891415908161210d575b506120d0578660005283865280846040600020015460a01c16808311156120995750421681116120625750846000528184526fffffffffffffffffffffffffffffffff968760406000205416156105cc57916105b1826105ab946105987f8979ea1e30f52867c984b014e2e83d8a8dbc8e439842a2efbcb8afc6f7cc567f9897958a612bde565b604490604051907fa283f5be0000000000000000000000000000000000000000000000000000000082526004820152426024820152fd5b82604491604051917fe6e3e57a00000000000000000000000000000000000000000000000000000000835260048301526024820152fd5b60648789604051917f057638bc00000000000000000000000000000000000000000000000000000000835260048301523360248301526044820152fd5b90503314158a611fdb565b602485604051907f6bc4151a0000000000000000000000000000000000000000000000000000000082526004820152fd5b602485604051907fe350190b0000000000000000000000000000000000000000000000000000000082526004820152fd5b346103be5760a06003193601126103be576121936121e2565b61219b612205565b906121a4612228565b916121ad612266565b91608435926fffffffffffffffffffffffffffffffff841684036103be57602094610fe4936121db936125f9565b9182612976565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036103be57565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036103be57565b604435906fffffffffffffffffffffffffffffffff821682036103be57565b602435906fffffffffffffffffffffffffffffffff821682036103be57565b6064359073ffffffffffffffffffffffffffffffffffffffff821682036103be57565b6024359064ffffffffff821682036103be57565b9181601f840112156103be5782359167ffffffffffffffff83116103be576020808501948460051b0101116103be57565b602090602060408183019282815285518094520193019160005b8281106122f6575050505090565b8351855293810193928101926001016122e8565b610120810190811067ffffffffffffffff82111761232757604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761232757604052565b67ffffffffffffffff81116123275760051b60200190565b6fffffffffffffffffffffffffffffffff91821690821603919082116123d157565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8060005260016020526fffffffffffffffffffffffffffffffff9061243582604060002054169164ffffffffff421690612b26565b91821681101561244b57612448916123af565b90565b5050600090565b9061245c82612397565b6124696040519182612356565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe06124978294612397565b0190602036910137565b91908110156124b15760051b0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b3573ffffffffffffffffffffffffffffffffffffffff811681036103be5790565b356fffffffffffffffffffffffffffffffff811681036103be5790565b80518210156124b15760209160051b010190565b929695939194908781148015906125ef575b6125b35761255181612452565b9760005b828110612566575050505050505050565b806125a28861258061257b600195878e6124a1565b6124e0565b61258e61257b85898d6124a1565b61259c610e02868b8d6124a1565b916125f9565b6125ac828d61251e565b5201612555565b60649188604051927fe29a514f000000000000000000000000000000000000000000000000000000008452600484015260248301526044820152fd5b5081811415612544565b92612602612b75565b73ffffffffffffffffffffffffffffffffffffffff8094169182156129285784169283156128fe576fffffffffffffffffffffffffffffffff809116918215610c5d57851660ff61265282612c83565b169182156128cd578460009182549864ffffffffff85814216978b8d6040519461267b8661230a565b89865260208601908d82526040870193845260608701988d8a5260808801926001845260a08901948d865260c08a0198895260e08a019788526101008a019c8d528d52818d60016020526040902099511689547fffffffffffffffffffffffffffffffff0000000000000000000000000000000016178955511661273b9088906fffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffff0000000000000000000000000000000083549260801b169116179055565b8760018801945116987fffffffffffffffffffffffff0000000000000000000000000000000000000000998a86541617855551166127be9084907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff78ffffffffff000000000000000000000000000000000000000083549260a01b169116179055565b5115159082549051151560d01b7aff0000000000000000000000000000000000000000000000000000169160c81b79ff0000000000000000000000000000000000000000000000000016907fffffffffff0000ffffffffffffffffffffffffffffffffffffffffffffffffff161717905583600284019251168254915160a01b74ff000000000000000000000000000000000000000016917fffffffffffffffffffffff0000000000000000000000000000000000000000001617179055600301925116908254161790556001870190556040519286845260208401526040830152606082015260807f94c6d4fd8f6d4dab69b3b48e0654c35e070dd2e06e95863ceee207268a1f5c8591a390565b602482604051907fb95c5c1d0000000000000000000000000000000000000000000000000000000082526004820152fd5b60046040517f6cc8cf6b000000000000000000000000000000000000000000000000000000008152fd5b60046040517fdfad875e000000000000000000000000000000000000000000000000000000008152fd5b9190916fffffffffffffffffffffffffffffffff808094169116019182116123d157565b6fffffffffffffffffffffffffffffffff90818316918215612ac857600082815260016020526040812080547fffffffffffffffffffffffffffffffff00000000000000000000000000000000846129d089828516612952565b1691161790558281526001602052612a0673ffffffffffffffffffffffffffffffffffffffff6002604084200154169584612d32565b91604051927f23b872dd0000000000000000000000000000000000000000000000000000000060208501523360248501523060448501521660648301526064825260a082019082821067ffffffffffffffff831117612a9b5750604052612a6d90846130e6565b6040519182527f24280ec27091ec3a806156c5f3fb6f9e10834dafd6bcee1164f2651c509fa38160203393a4565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526041600452fd5b60046040517f96520e64000000000000000000000000000000000000000000000000000000008152fd5b612b20612448928260005260016020526fffffffffffffffffffffffffffffffff6040600020541692612bde565b906123af565b600052600160205260406000209064ffffffffff80600184015460a01c16808284161115612b6c576fffffffffffffffffffffffffffffffff935460801c920316021690565b50505050600090565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003612bb457565b60046040517fa1c0d6e5000000000000000000000000000000000000000000000000000000008152fd5b908160005260016020526fffffffffffffffffffffffffffffffff908160406000205416928315612b6c578391612c1491612b26565b91821610612c20575090565b905090565b3d15612c7e573d9067ffffffffffffffff82116123275760405191612c7260207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160184612356565b82523d6000602084013e565b606090565b60405160208101907f313ce567000000000000000000000000000000000000000000000000000000008252600481526040810181811067ffffffffffffffff821117612327576040526000928392839251915afa612cdf612c25565b9080612d16575b15612d1257602081805181010312612d0e57602001519060ff82168203612d0b575090565b80fd5b5080fd5b5090565b506020815114612ce6565b60ff16604d81116123d157600a0a90565b6000908152600160205260ff600260408320015460a01c1660128114612e8d5760128111908115612e7c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffee0160ff8111612e4f57905b15612df157612da86fffffffffffffffffffffffffffffffff91612d21565b9216828102928184041490151715612dc4575061244890613091565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526011600452fd5b612dfd90929192612d21565b918215612e225750906fffffffffffffffffffffffffffffffff612448921604613091565b807f4e487b7100000000000000000000000000000000000000000000000000000000602492526012600452fd5b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b60120360ff8111612e4f5790612d89565b505090565b8060005260016020526fffffffffffffffffffffffffffffffff9182604060002054168093821611612ec357505050565b6040517ff0f27ae800000000000000000000000000000000000000000000000000000000815260048101929092526fffffffffffffffffffffffffffffffff92831660248301529091166044820152606490fd5b90612f769160005260016020526001604060002001907fffffffffffffff0000000000ffffffffffffffffffffffffffffffffffffffff78ffffffffff000000000000000000000000000000000000000083549260a01b169116179055565b565b600081815260016020526040812080549195946fffffffffffffffffffffffffffffffff92612fdc92907fffffffffffffffffffffffffffffffff0000000000000000000000000000000085612fd0858285166123af565b16911617905583612d32565b918552600160205273ffffffffffffffffffffffffffffffffffffffff918260026040882001541692604051947fa9059cbb000000000000000000000000000000000000000000000000000000006020870152166024850152166044830152604482526080820182811067ffffffffffffffff82111761306457612f769394506040526130e6565b6024857f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b6fffffffffffffffffffffffffffffffff908181116130ae571690565b604490604051907f6dfcc650000000000000000000000000000000000000000000000000000000008252608060048301526024820152fd5b73ffffffffffffffffffffffffffffffffffffffff169061311e600080836020829551910182875af1613117612c25565b908461318f565b908151918215159283613167575b5050506131365750565b602490604051907f5274afe70000000000000000000000000000000000000000000000000000000082526004820152fd5b819293509060209181010312612d0e576020015190811591821503612d0b575038808061312c565b906131ce57508051156131a457805190602001fd5b60046040517f1425ea42000000000000000000000000000000000000000000000000000000008152fd5b81511580613226575b6131df575090565b60249073ffffffffffffffffffffffffffffffffffffffff604051917f9996b315000000000000000000000000000000000000000000000000000000008352166004820152fd5b50803b156131d756fea164736f6c6343000817000a"; - function deployOpenEnded() public returns (ISablierV2OpenEnded openEnded) { - bytes memory bytecode = BYTECODE_OPEN_ENDED; + function deployFlow() public returns (ISablierFlow flow) { + bytes memory bytecode = BYTECODE_FLOW; assembly { - openEnded := create(0, add(bytecode, 0x20), mload(bytecode)) + flow := create(0, add(bytecode, 0x20), mload(bytecode)) } - require(address(openEnded) != address(0), "Sablier V2 Precompiles: deployment failed for OpenEnded contract"); + require(address(flow) != address(0), "Sablier Precompiles: deployment failed for Flow contract"); } } diff --git a/script/DeployDeterministicFlow.s.sol b/script/DeployDeterministicFlow.s.sol new file mode 100644 index 00000000..66fc3869 --- /dev/null +++ b/script/DeployDeterministicFlow.s.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22 <0.9.0; + +import { SablierFlow } from "src/SablierFlow.sol"; + +import { BaseScript } from "./Base.s.sol"; + +/// @notice Deploys {SablierFlow} at a deterministic address across chains. +/// @dev Reverts if the contract has already been deployed. +contract DeployDeterministicFlow is BaseScript { + function run() public broadcast returns (SablierFlow flow) { + flow = new SablierFlow{ salt: constructCreate2Salt() }(); + } +} diff --git a/script/DeployDeterministicOpenEnded.s.sol b/script/DeployDeterministicOpenEnded.s.sol deleted file mode 100644 index 329ec13f..00000000 --- a/script/DeployDeterministicOpenEnded.s.sol +++ /dev/null @@ -1,14 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierV2OpenEnded } from "src/SablierV2OpenEnded.sol"; - -import { BaseScript } from "./Base.s.sol"; - -/// @notice Deploys {SablierV2OpenEnded} at a deterministic address across chains. -/// @dev Reverts if the contract has already been deployed. -contract DeployDeterministicOpenEnded is BaseScript { - function run() public broadcast returns (SablierV2OpenEnded openEnded) { - openEnded = new SablierV2OpenEnded{ salt: constructCreate2Salt() }(); - } -} diff --git a/script/DeployFlow.s.sol b/script/DeployFlow.s.sol new file mode 100644 index 00000000..7eb9dcd5 --- /dev/null +++ b/script/DeployFlow.s.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier: GPL-3.0-or-later +pragma solidity >=0.8.22 <0.9.0; + +import { SablierFlow } from "src/SablierFlow.sol"; + +import { BaseScript } from "./Base.s.sol"; + +/// @notice Deploys {SablierFlow}. +contract DeployFlow is BaseScript { + function run() public broadcast returns (SablierFlow flow) { + flow = new SablierFlow(); + } +} diff --git a/script/DeployOpenEnded.s.sol b/script/DeployOpenEnded.s.sol deleted file mode 100644 index 73e785e4..00000000 --- a/script/DeployOpenEnded.s.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity >=0.8.22 <0.9.0; - -import { SablierV2OpenEnded } from "src/SablierV2OpenEnded.sol"; - -import { BaseScript } from "./Base.s.sol"; - -/// @notice Deploys {SablierV2OpenEnded}. -contract DeployOpenEnded is BaseScript { - function run() public broadcast returns (SablierV2OpenEnded openEnded) { - openEnded = new SablierV2OpenEnded(); - } -} diff --git a/shell/prepare-artifacts.sh b/shell/prepare-artifacts.sh index 6651ec4d..0a1a042e 100755 --- a/shell/prepare-artifacts.sh +++ b/shell/prepare-artifacts.sh @@ -22,11 +22,11 @@ mkdir $artifacts \ FOUNDRY_PROFILE=optimized forge build # Copy the production artifacts -cp out-optimized/SablierV2OpenEnded.sol/SablierV2OpenEnded.json $artifacts +cp out-optimized/SablierFlow.sol/SablierFlow.json $artifacts interfaces=./artifacts/interfaces -cp out-optimized/ISablierV2OpenEnded.sol/ISablierV2OpenEnded.json $interfaces -cp out-optimized/ISablierV2OpenEndedState.sol/ISablierV2OpenEndedState.json $interfaces +cp out-optimized/ISablierFlow.sol/ISablierFlow.json $interfaces +cp out-optimized/ISablierFlowState.sol/ISablierFlowState.json $interfaces erc20=./artifacts/interfaces/erc20 cp out-optimized/IERC20.sol/IERC20.json $erc20 diff --git a/shell/update-precompiles.sh b/shell/update-precompiles.sh index 44467515..aa3eb2e3 100755 --- a/shell/update-precompiles.sh +++ b/shell/update-precompiles.sh @@ -12,7 +12,7 @@ set -euo pipefail FOUNDRY_PROFILE=optimized forge build # Retrieve the raw bytecodes, removing the "0x" prefix -open_ended=$(cat out-optimized/SablierV2OpenEnded.sol/SablierV2OpenEnded.json | jq -r '.bytecode.object' | cut -c 3-) +flow=$(cat out-optimized/SablierFlow.sol/SablierFlow.json | jq -r '.bytecode.object' | cut -c 3-) precompiles_path="precompiles/Precompiles.sol" if [ ! -f $precompiles_path ]; then @@ -21,7 +21,7 @@ if [ ! -f $precompiles_path ]; then fi # Replace the current bytecodes -sd "(BYTECODE_OPEN_ENDED =)[^;]+;" "\$1 hex\"$open_ended\";" $precompiles_path +sd "(BYTECODE_FLOW =)[^;]+;" "\$1 hex\"$flow\";" $precompiles_path # Reformat the code with Forge forge fmt $precompiles_path \ No newline at end of file diff --git a/src/SablierV2OpenEnded.sol b/src/SablierFlow.sol similarity index 87% rename from src/SablierV2OpenEnded.sol rename to src/SablierFlow.sol index 7f592000..66331478 100644 --- a/src/SablierV2OpenEnded.sol +++ b/src/SablierFlow.sol @@ -9,17 +9,17 @@ import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import { ud } from "@prb/math/src/UD60x18.sol"; import { NoDelegateCall } from "./abstracts/NoDelegateCall.sol"; -import { SablierV2OpenEndedState } from "./abstracts/SablierV2OpenEndedState.sol"; -import { ISablierV2OpenEnded } from "./interfaces/ISablierV2OpenEnded.sol"; +import { SablierFlowState } from "./abstracts/SablierFlowState.sol"; +import { ISablierFlow } from "./interfaces/ISablierFlow.sol"; import { Errors } from "./libraries/Errors.sol"; -import { Broker, OpenEnded } from "./types/DataTypes.sol"; +import { Broker, Flow } from "./types/DataTypes.sol"; -/// @title SablierV2OpenEnded -/// @notice See the documentation in {ISablierV2OpenEnded}. -contract SablierV2OpenEnded is +/// @title SablierFlow +/// @notice See the documentation in {ISablierFlow}. +contract SablierFlow is NoDelegateCall, // 0 inherited components - ISablierV2OpenEnded, // 1 inherited components - SablierV2OpenEndedState // 7 inherited components + ISablierFlow, // 1 inherited components + SablierFlowState // 7 inherited components { using SafeCast for uint256; using SafeERC20 for IERC20; @@ -28,13 +28,13 @@ contract SablierV2OpenEnded is CONSTRUCTOR //////////////////////////////////////////////////////////////////////////*/ - constructor() ERC721("Sablier V2 Open Ended NFT", "SAB-V2-OPEN-EN") { } + constructor() ERC721("Sablier Flow NFT", "SAB-FLW") { } /*////////////////////////////////////////////////////////////////////////// CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function depletionTimeOf(uint256 streamId) external view @@ -66,7 +66,7 @@ contract SablierV2OpenEnded is } } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function refundableAmountOf(uint256 streamId) external view @@ -77,7 +77,7 @@ contract SablierV2OpenEnded is refundableAmount = _refundableAmountOf(streamId, uint40(block.timestamp)); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function refundableAmountOf( uint256 streamId, uint40 time @@ -91,7 +91,7 @@ contract SablierV2OpenEnded is refundableAmount = _refundableAmountOf(streamId, time); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function streamDebtOf(uint256 streamId) external view override notNull(streamId) returns (uint128 debt) { uint128 balance = _streams[streamId].balance; @@ -106,7 +106,7 @@ contract SablierV2OpenEnded is } } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function streamedAmountOf(uint256 streamId) external view @@ -118,7 +118,7 @@ contract SablierV2OpenEnded is streamedAmount = _streamedAmountOf(streamId, uint40(block.timestamp)); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function streamedAmountOf( uint256 streamId, uint40 time @@ -133,7 +133,7 @@ contract SablierV2OpenEnded is streamedAmount = _streamedAmountOf(streamId, time); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function withdrawableAmountOf(uint256 streamId) external view @@ -144,7 +144,7 @@ contract SablierV2OpenEnded is withdrawableAmount = _withdrawableAmountOf(streamId, uint40(block.timestamp)); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function withdrawableAmountOf( uint256 streamId, uint40 time @@ -162,7 +162,7 @@ contract SablierV2OpenEnded is USER-FACING NON-CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function adjustRatePerSecond( uint256 streamId, uint128 newRatePerSecond @@ -179,7 +179,7 @@ contract SablierV2OpenEnded is _adjustRatePerSecond(streamId, newRatePerSecond); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function create( address sender, address recipient, @@ -196,7 +196,7 @@ contract SablierV2OpenEnded is streamId = _create(sender, recipient, ratePerSecond, asset, isTransferable); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function createAndDeposit( address sender, address recipient, @@ -217,7 +217,7 @@ contract SablierV2OpenEnded is _deposit(streamId, amount); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function createAndDepositViaBroker( address sender, address recipient, @@ -239,7 +239,7 @@ contract SablierV2OpenEnded is _depositViaBroker(streamId, totalAmount, broker); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function deposit( uint256 streamId, uint128 amount @@ -269,7 +269,7 @@ contract SablierV2OpenEnded is _depositViaBroker(streamId, totalAmount, broker); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function pause(uint256 streamId) public override @@ -283,7 +283,7 @@ contract SablierV2OpenEnded is _pause(streamId); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function restartStream( uint256 streamId, uint128 ratePerSecond @@ -299,7 +299,7 @@ contract SablierV2OpenEnded is _restartStream(streamId, ratePerSecond); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function restartStreamAndDeposit( uint256 streamId, uint128 ratePerSecond, @@ -319,7 +319,7 @@ contract SablierV2OpenEnded is _deposit(streamId, amount); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function refundFromStream( uint256 streamId, uint128 amount @@ -334,7 +334,7 @@ contract SablierV2OpenEnded is _refundFromStream(streamId, amount); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function withdrawAt( uint256 streamId, address to, @@ -350,7 +350,7 @@ contract SablierV2OpenEnded is _withdrawAt(streamId, to, time); } - /// @inheritdoc ISablierV2OpenEnded + /// @inheritdoc ISablierFlow function withdrawMax( uint256 streamId, address to @@ -405,7 +405,7 @@ contract SablierV2OpenEnded is function _checkCalculatedAmount(uint256 streamId, uint128 amount) internal view { uint128 balance = _streams[streamId].balance; if (amount > balance) { - revert Errors.SablierV2OpenEnded_InvalidCalculation(streamId, balance, amount); + revert Errors.SablierFlow_InvalidCalculation(streamId, balance, amount); } } @@ -488,14 +488,14 @@ contract SablierV2OpenEnded is function _adjustRatePerSecond(uint256 streamId, uint128 newRatePerSecond) internal { // Check: the new rate per second is not zero. if (newRatePerSecond == 0) { - revert Errors.SablierV2OpenEnded_RatePerSecondZero(); + revert Errors.SablierFlow_RatePerSecondZero(); } uint128 oldRatePerSecond = _streams[streamId].ratePerSecond; // Check: the new rate per second is not equal to the actual rate per second. if (newRatePerSecond == oldRatePerSecond) { - revert Errors.SablierV2OpenEnded_RatePerSecondNotDifferent(newRatePerSecond); + revert Errors.SablierFlow_RatePerSecondNotDifferent(newRatePerSecond); } // Calculate the streamed amount since last update. @@ -511,7 +511,7 @@ contract SablierV2OpenEnded is _streams[streamId].ratePerSecond = newRatePerSecond; // Log the adjustment. - emit ISablierV2OpenEnded.AdjustOpenEndedStream(streamId, streamedAmount, oldRatePerSecond, newRatePerSecond); + emit ISablierFlow.AdjustFlowStream(streamId, streamedAmount, oldRatePerSecond, newRatePerSecond); } /// @dev See the documentation for the user-facing functions that call this internal function. @@ -527,26 +527,26 @@ contract SablierV2OpenEnded is { // Check: the sender is not the zero address. if (sender == address(0)) { - revert Errors.SablierV2OpenEnded_SenderZeroAddress(); + revert Errors.SablierFlow_SenderZeroAddress(); } // Check: the rate per second is not zero. if (ratePerSecond == 0) { - revert Errors.SablierV2OpenEnded_RatePerSecondZero(); + revert Errors.SablierFlow_RatePerSecondZero(); } uint8 assetDecimals = _safeAssetDecimals(address(asset)); // Check: the asset does not have decimals. if (assetDecimals == 0) { - revert Errors.SablierV2OpenEnded_InvalidAssetDecimals(asset); + revert Errors.SablierFlow_InvalidAssetDecimals(asset); } // Load the stream id. streamId = nextStreamId; // Effect: create the stream. - _streams[streamId] = OpenEnded.Stream({ + _streams[streamId] = Flow.Stream({ asset: asset, assetDecimals: assetDecimals, balance: 0, @@ -569,16 +569,14 @@ contract SablierV2OpenEnded is _mint({ to: recipient, tokenId: streamId }); // Log the newly created stream. - emit ISablierV2OpenEnded.CreateOpenEndedStream( - streamId, sender, recipient, ratePerSecond, asset, uint40(block.timestamp) - ); + emit ISablierFlow.CreateFlowStream(streamId, sender, recipient, ratePerSecond, asset, uint40(block.timestamp)); } /// @dev See the documentation for the user-facing functions that call this internal function. function _deposit(uint256 streamId, uint128 amount) internal { // Check: the deposit amount is not zero. if (amount == 0) { - revert Errors.SablierV2OpenEnded_DepositAmountZero(); + revert Errors.SablierFlow_DepositAmountZero(); } // Effect: update the stream balance. @@ -594,19 +592,19 @@ contract SablierV2OpenEnded is asset.safeTransferFrom(msg.sender, address(this), transferAmount); // Log the deposit. - emit ISablierV2OpenEnded.DepositOpenEndedStream(streamId, msg.sender, asset, amount); + emit ISablierFlow.DepositFlowStream(streamId, msg.sender, asset, amount); } /// @dev See the documentation for the user-facing functions that call this internal function. function _depositViaBroker(uint256 streamId, uint128 totalAmount, Broker memory broker) internal { // Check: the broker's fee is not greater than `MAX_BROKER_FEE`. if (broker.fee.gt(MAX_BROKER_FEE)) { - revert Errors.SablierV2OpenEnded_BrokerFeeTooHigh(streamId, broker.fee, MAX_BROKER_FEE); + revert Errors.SablierFlow_BrokerFeeTooHigh(streamId, broker.fee, MAX_BROKER_FEE); } // Check: the broker recipient is not the zero address. if (broker.account == address(0)) { - revert Errors.SablierV2OpenEnded_BrokerAddressZero(); + revert Errors.SablierFlow_BrokerAddressZero(); } // Calculate the broker's amount. @@ -646,7 +644,7 @@ contract SablierV2OpenEnded is _streams[streamId].isPaused = true; // Log the pause. - emit ISablierV2OpenEnded.PauseOpenEndedStream({ + emit ISablierFlow.PauseFlowStream({ streamId: streamId, sender: _streams[streamId].sender, recipient: _ownerOf(streamId), @@ -659,7 +657,7 @@ contract SablierV2OpenEnded is function _refundFromStream(uint256 streamId, uint128 amount) internal { // Check: the amount is not zero. if (amount == 0) { - revert Errors.SablierV2OpenEnded_RefundAmountZero(); + revert Errors.SablierFlow_RefundAmountZero(); } // Calculate the refundable amount. @@ -667,7 +665,7 @@ contract SablierV2OpenEnded is // Check: the refund amount is not greater than the refundable amount. if (amount > refundableAmount) { - revert Errors.SablierV2OpenEnded_Overrefund(streamId, amount, refundableAmount); + revert Errors.SablierFlow_Overrefund(streamId, amount, refundableAmount); } // Although the refund amount should never exceed the available amount in stream, this condition is checked to @@ -680,19 +678,19 @@ contract SablierV2OpenEnded is _extractFromStream(streamId, sender, amount); // Log the refund. - emit ISablierV2OpenEnded.RefundFromOpenEndedStream(streamId, sender, _streams[streamId].asset, amount); + emit ISablierFlow.RefundFromFlowStream(streamId, sender, _streams[streamId].asset, amount); } /// @dev See the documentation for the user-facing functions that call this internal function. function _restartStream(uint256 streamId, uint128 ratePerSecond) internal { // Check: the stream is paused. if (!_streams[streamId].isPaused) { - revert Errors.SablierV2OpenEnded_StreamNotPaused(streamId); + revert Errors.SablierFlow_StreamNotPaused(streamId); } // Check: the rate per second is not zero. if (ratePerSecond == 0) { - revert Errors.SablierV2OpenEnded_RatePerSecondZero(); + revert Errors.SablierFlow_RatePerSecondZero(); } // Effect: update the stream time. @@ -705,7 +703,7 @@ contract SablierV2OpenEnded is _streams[streamId].isPaused = false; // Log the restart. - emit ISablierV2OpenEnded.RestartOpenEndedStream(streamId, msg.sender, _streams[streamId].asset, ratePerSecond); + emit ISablierFlow.RestartFlowStream(streamId, msg.sender, _streams[streamId].asset, ratePerSecond); } /// @dev Sets the stream time to the current block timestamp. @@ -717,7 +715,7 @@ contract SablierV2OpenEnded is function _withdrawAt(uint256 streamId, address to, uint40 time) internal { // Check: the withdrawal address is not zero. if (to == address(0)) { - revert Errors.SablierV2OpenEnded_WithdrawToZeroAddress(); + revert Errors.SablierFlow_WithdrawToZeroAddress(); } // Retrieve the recipient from storage. @@ -726,7 +724,7 @@ contract SablierV2OpenEnded is // Check: if `msg.sender` is neither the stream's recipient nor an approved third party, the withdrawal address // must be the recipient. if (to != recipient && !_isCallerStreamRecipientOrApproved(streamId)) { - revert Errors.SablierV2OpenEnded_WithdrawalAddressNotRecipient(streamId, msg.sender, to); + revert Errors.SablierFlow_WithdrawalAddressNotRecipient(streamId, msg.sender, to); } // Retrieve the last time update from storage. @@ -734,12 +732,12 @@ contract SablierV2OpenEnded is // Check: the `lastTimeUpdate` is less than withdrawal time. if (time < lastTimeUpdate) { - revert Errors.SablierV2OpenEnded_LastUpdateNotLessThanWithdrawalTime(lastTimeUpdate, time); + revert Errors.SablierFlow_LastUpdateNotLessThanWithdrawalTime(lastTimeUpdate, time); } // Check: the withdrawal time is not in the future. if (time > uint40(block.timestamp)) { - revert Errors.SablierV2OpenEnded_WithdrawalTimeInTheFuture(time, block.timestamp); + revert Errors.SablierFlow_WithdrawalTimeInTheFuture(time, block.timestamp); } // Retrieve the remaining amount from storage. @@ -747,7 +745,7 @@ contract SablierV2OpenEnded is // Check: the stream balance and the remaining amount are not zero. if (_streams[streamId].balance == 0 && remainingAmount == 0) { - revert Errors.SablierV2OpenEnded_WithdrawNoFundsAvailable(streamId); + revert Errors.SablierFlow_WithdrawNoFundsAvailable(streamId); } // Calculate the withdrawable amount. @@ -773,6 +771,6 @@ contract SablierV2OpenEnded is _extractFromStream(streamId, to, withdrawableAmount); // Log the withdrawal. - emit ISablierV2OpenEnded.WithdrawFromOpenEndedStream(streamId, to, _streams[streamId].asset, withdrawableAmount); + emit ISablierFlow.WithdrawFromFlowStream(streamId, to, _streams[streamId].asset, withdrawableAmount); } } diff --git a/src/abstracts/SablierV2OpenEndedState.sol b/src/abstracts/SablierFlowState.sol similarity index 80% rename from src/abstracts/SablierV2OpenEndedState.sol rename to src/abstracts/SablierFlowState.sol index e405710e..8ca5cebe 100644 --- a/src/abstracts/SablierV2OpenEndedState.sol +++ b/src/abstracts/SablierFlowState.sol @@ -6,29 +6,29 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import { UD60x18 } from "@prb/math/src/UD60x18.sol"; -import { ISablierV2OpenEndedState } from "../interfaces/ISablierV2OpenEndedState.sol"; -import { OpenEnded } from "../types/DataTypes.sol"; +import { ISablierFlowState } from "../interfaces/ISablierFlowState.sol"; +import { Flow } from "../types/DataTypes.sol"; import { Errors } from "../libraries/Errors.sol"; -/// @title SablierV2OpenEndedState -/// @notice See the documentation in {ISablierV2OpenEndedState}. -abstract contract SablierV2OpenEndedState is +/// @title SablierFlowState +/// @notice See the documentation in {ISablierFlowState}. +abstract contract SablierFlowState is IERC4906, // 2 inherited components - ISablierV2OpenEndedState, // 3 inherited component + ISablierFlowState, // 3 inherited component ERC721 // 6 inherited components { /*////////////////////////////////////////////////////////////////////////// STATE VARIABLES //////////////////////////////////////////////////////////////////////////*/ - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState UD60x18 public constant override MAX_BROKER_FEE = UD60x18.wrap(0.1e18); - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState uint256 public override nextStreamId; - /// @dev Sablier V2 OpenEnded streams mapped by unsigned integers. - mapping(uint256 id => OpenEnded.Stream stream) internal _streams; + /// @dev Sablier Flow streams mapped by unsigned integers. + mapping(uint256 id => Flow.Stream stream) internal _streams; /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR @@ -45,7 +45,7 @@ abstract contract SablierV2OpenEndedState is /// @dev Checks that `streamId` does not reference a null stream. modifier notNull(uint256 streamId) { if (!_streams[streamId].isStream) { - revert Errors.SablierV2OpenEnded_Null(streamId); + revert Errors.SablierFlow_Null(streamId); } _; } @@ -53,7 +53,7 @@ abstract contract SablierV2OpenEndedState is /// @dev Checks that `streamId` does not reference a paused stream. modifier notPaused(uint256 streamId) { if (_streams[streamId].isPaused) { - revert Errors.SablierV2OpenEnded_StreamPaused(streamId); + revert Errors.SablierFlow_StreamPaused(streamId); } _; } @@ -61,7 +61,7 @@ abstract contract SablierV2OpenEndedState is /// @dev Checks the `msg.sender` is the stream's sender. modifier onlySender(uint256 streamId) { if (msg.sender != _streams[streamId].sender) { - revert Errors.SablierV2OpenEnded_Unauthorized(streamId, msg.sender); + revert Errors.SablierFlow_Unauthorized(streamId, msg.sender); } _; } @@ -76,12 +76,12 @@ abstract contract SablierV2OpenEndedState is CONSTANT FUNCTIONS //////////////////////////////////////////////////////////////////////////*/ - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getAsset(uint256 streamId) external view override notNull(streamId) returns (IERC20 asset) { asset = _streams[streamId].asset; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getAssetDecimals(uint256 streamId) external view @@ -92,12 +92,12 @@ abstract contract SablierV2OpenEndedState is assetDecimals = _streams[streamId].assetDecimals; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getBalance(uint256 streamId) external view override notNull(streamId) returns (uint128 balance) { balance = _streams[streamId].balance; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getLastTimeUpdate(uint256 streamId) external view @@ -108,7 +108,7 @@ abstract contract SablierV2OpenEndedState is lastTimeUpdate = _streams[streamId].lastTimeUpdate; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getRatePerSecond(uint256 streamId) external view @@ -119,12 +119,12 @@ abstract contract SablierV2OpenEndedState is ratePerSecond = _streams[streamId].ratePerSecond; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getRecipient(uint256 streamId) external view override notNull(streamId) returns (address recipient) { recipient = _ownerOf(streamId); } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getRemainingAmount(uint256 streamId) external view @@ -135,28 +135,22 @@ abstract contract SablierV2OpenEndedState is remainingAmount = _streams[streamId].remainingAmount; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function getSender(uint256 streamId) external view override notNull(streamId) returns (address sender) { sender = _streams[streamId].sender; } - /// @inheritdoc ISablierV2OpenEndedState - function getStream(uint256 streamId) - external - view - override - notNull(streamId) - returns (OpenEnded.Stream memory stream) - { + /// @inheritdoc ISablierFlowState + function getStream(uint256 streamId) external view override notNull(streamId) returns (Flow.Stream memory stream) { stream = _streams[streamId]; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function isPaused(uint256 streamId) public view override notNull(streamId) returns (bool result) { result = _streams[streamId].isPaused; } - /// @inheritdoc ISablierV2OpenEndedState + /// @inheritdoc ISablierFlowState function isStream(uint256 streamId) public view override returns (bool result) { result = _streams[streamId].isStream; } @@ -199,7 +193,7 @@ abstract contract SablierV2OpenEndedState is address from = _ownerOf(streamId); if (from != address(0) && !_streams[streamId].isTransferable) { - revert Errors.SablierV2OpenEndedState_NotTransferable(streamId); + revert Errors.SablierFlowState_NotTransferable(streamId); } return super._update(to, streamId, auth); diff --git a/src/interfaces/ISablierV2OpenEnded.sol b/src/interfaces/ISablierFlow.sol similarity index 87% rename from src/interfaces/ISablierV2OpenEnded.sol rename to src/interfaces/ISablierFlow.sol index 131b4be9..071d72dd 100644 --- a/src/interfaces/ISablierV2OpenEnded.sol +++ b/src/interfaces/ISablierFlow.sol @@ -3,13 +3,13 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEndedState } from "./ISablierV2OpenEndedState.sol"; +import { ISablierFlowState } from "./ISablierFlowState.sol"; import { Broker } from "../types/DataTypes.sol"; -/// @title ISablierV2OpenEnded -/// @notice Creates and manages Open Ended streams with linear streaming functions. -interface ISablierV2OpenEnded is - ISablierV2OpenEndedState // 3 inherited component +/// @title ISablierFlow +/// @notice Creates and manages Flow streams with linear streaming functions. +interface ISablierFlow is + ISablierFlowState // 3 inherited component { /*////////////////////////////////////////////////////////////////////////// EVENTS @@ -20,11 +20,11 @@ interface ISablierV2OpenEnded is /// @param recipientAmount The amount of assets that the recipient is able to withdraw, denoted in 18 decimals. /// @param oldRatePerSecond The rate per second to change. /// @param newRatePerSecond The newly changed rate per second. - event AdjustOpenEndedStream( + event AdjustFlowStream( uint256 indexed streamId, uint128 recipientAmount, uint128 oldRatePerSecond, uint128 newRatePerSecond ); - /// @notice Emitted when a open-ended stream is created. + /// @notice Emitted when a flow stream is created. /// @param streamId The ID of the newly created stream. /// @param sender The address from which to stream the assets, which has the ability to /// adjust and pause the stream. @@ -32,7 +32,7 @@ interface ISablierV2OpenEnded is /// @param ratePerSecond The amount of assets that is increasing by every second. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param lastTimeUpdate The Unix timestamp for the streamed amount calculation. - event CreateOpenEndedStream( + event CreateFlowStream( uint256 streamId, address indexed sender, address indexed recipient, @@ -41,22 +41,22 @@ interface ISablierV2OpenEnded is uint40 lastTimeUpdate ); - /// @notice Emitted when a open-ended stream is funded. - /// @param streamId The ID of the open-ended stream. + /// @notice Emitted when a flow stream is funded. + /// @param streamId The ID of the flow stream. /// @param funder The address which funded the stream. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param depositAmount The amount of assets deposited into the stream, denoted in 18 decimals. - event DepositOpenEndedStream( + event DepositFlowStream( uint256 indexed streamId, address indexed funder, IERC20 indexed asset, uint128 depositAmount ); - /// @notice Emitted when a open-ended stream is paused. + /// @notice Emitted when a flow stream is paused. /// @param streamId The ID of the stream. /// @param sender The address of the stream's sender. /// @param recipient The address of the stream's recipient. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param recipientAmount The amount of assets left for the stream's recipient to withdraw, denoted in 18 decimals. - event PauseOpenEndedStream( + event PauseFlowStream( uint256 streamId, address indexed sender, address indexed recipient, @@ -64,30 +64,30 @@ interface ISablierV2OpenEnded is uint128 recipientAmount ); - /// @notice Emitted when assets are refunded from a open-ended stream. - /// @param streamId The ID of the open-ended stream. + /// @notice Emitted when assets are refunded from a flow stream. + /// @param streamId The ID of the flow stream. /// @param sender The address of the stream's sender. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param refundAmount The amount of assets refunded to the sender, denoted in 18 decimals. - event RefundFromOpenEndedStream( + event RefundFromFlowStream( uint256 indexed streamId, address indexed sender, IERC20 indexed asset, uint128 refundAmount ); - /// @notice Emitted when a open-ended stream is re-started. - /// @param streamId The ID of the open-ended stream. + /// @notice Emitted when a flow stream is re-started. + /// @param streamId The ID of the flow stream. /// @param sender The address of the stream's sender. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param ratePerSecond The amount of assets that is increasing by every second, denoted in 18 decimals. - event RestartOpenEndedStream( + event RestartFlowStream( uint256 indexed streamId, address indexed sender, IERC20 indexed asset, uint128 ratePerSecond ); - /// @notice Emitted when assets are withdrawn from a open-ended stream. + /// @notice Emitted when assets are withdrawn from a flow stream. /// @param streamId The ID of the stream. /// @param to The address that has received the withdrawn assets. /// @param asset The contract address of the ERC-20 asset used for streaming. /// @param withdrawnAmount The amount of assets withdrawn, denoted in 18 decimals. - event WithdrawFromOpenEndedStream( + event WithdrawFromFlowStream( uint256 indexed streamId, address indexed to, IERC20 indexed asset, uint128 withdrawnAmount ); @@ -155,7 +155,7 @@ interface ISablierV2OpenEnded is /// @notice Changes the stream's rate per second. /// - /// @dev Emits a {Transfer} and {AdjustOpenEndedStream} event. + /// @dev Emits a {Transfer} and {AdjustFlowStream} event. /// /// Notes: /// - The streamed assets, until the adjustment moment, will be summed up to the remaining amount. @@ -168,13 +168,13 @@ interface ISablierV2OpenEnded is /// - `newRatePerSecond` must be greater than zero and not equal to the current rate per second. /// /// @param streamId The ID of the stream to adjust. - /// @param newRatePerSecond The new rate per second of the open-ended stream, denoted in 18 decimals. + /// @param newRatePerSecond The new rate per second of the flow stream, denoted in 18 decimals. function adjustRatePerSecond(uint256 streamId, uint128 newRatePerSecond) external; - /// @notice Creates a new open-ended stream with `block.timestamp` as `lastTimeUpdate` and set stream balance to 0. + /// @notice Creates a new flow stream with `block.timestamp` as `lastTimeUpdate` and set stream balance to 0. /// The stream is wrapped in an ERC-721 NFT. /// - /// @dev Emits a {CreateOpenEndedStream} event. + /// @dev Emits a {CreateFlowStream} event. /// /// Requiremenets: /// - Must not be delegate called. @@ -201,10 +201,10 @@ interface ISablierV2OpenEnded is external returns (uint256 streamId); - /// @notice Creates a new open-ended stream with `block.timestamp` as `lastTimeUpdate` and set the stream balance to + /// @notice Creates a new flow stream with `block.timestamp` as `lastTimeUpdate` and set the stream balance to /// `amount`. The stream is wrapped in an ERC-721 NFT. /// - /// @dev Emits a {CreateOpenEndedStream}, {Transfer} and {DepositOpenEndedStream} events. + /// @dev Emits a {CreateFlowStream}, {Transfer} and {DepositFlowStream} events. /// /// Requirements: /// - Refer to the requirements in {create} and {deposit}. @@ -227,11 +227,11 @@ interface ISablierV2OpenEnded is external returns (uint256 streamId); - /// @notice Creates a new open-ended stream with `block.timestamp` as `lastTimeUpdate` and set the stream balance to + /// @notice Creates a new flow stream with `block.timestamp` as `lastTimeUpdate` and set the stream balance to /// an amount calculated from the `totalAmount` after broker fee amount deduction. The stream is wrapped in an /// ERC-721 NFT. /// - /// @dev Emits a {CreateOpenEndedStream}, {Transfer} and {DepositOpenEndedStream} events. + /// @dev Emits a {CreateFlowStream}, {Transfer} and {DepositFlowStream} events. /// /// Requirements: /// - Refer to the requirements in {create} and {depositViaBroker}. @@ -259,7 +259,7 @@ interface ISablierV2OpenEnded is /// @notice Deposits assets in a stream. /// - /// @dev Emits a {Transfer} and {DepositOpenEndedStream} event. + /// @dev Emits a {Transfer} and {DepositFlowStream} event. /// /// Requirements: /// - Must not be delegate called. @@ -272,7 +272,7 @@ interface ISablierV2OpenEnded is /// @notice Deposits assets in a stream. /// - /// @dev Emits a {Transfer} and {DepositOpenEndedStream} event. + /// @dev Emits a {Transfer} and {DepositFlowStream} event. /// /// Requirements: /// - Must not be delegate called. @@ -289,7 +289,7 @@ interface ISablierV2OpenEnded is /// @notice Pauses the stream and refunds available assets to the sender. /// - /// @dev Emits a {Transfer} and {PauseOpenEndedStream} event. + /// @dev Emits a {Transfer} and {PauseFlowStream} event. /// /// Requirements: /// - Must not be delegate called. @@ -301,7 +301,7 @@ interface ISablierV2OpenEnded is /// @notice Refunds the provided amount of assets from the stream to the sender's address. /// - /// @dev Emits a {Transfer} and {RefundFromOpenEndedStream} event. + /// @dev Emits a {Transfer} and {RefundFromFlowStream} event. /// /// Requirements: /// - Must not be delegate called. @@ -315,7 +315,7 @@ interface ISablierV2OpenEnded is /// @notice Restarts the stream with the provided rate per second. /// - /// @dev Emits a {RestartOpenEndedStream} event. + /// @dev Emits a {RestartFlowStream} event. /// - This function updates stream's `lastTimeUpdate` to the current block timestamp. /// /// Requirements: @@ -332,7 +332,7 @@ interface ISablierV2OpenEnded is /// @notice Restarts the stream with the provided rate per second, and deposits `amount` in the stream /// balance. /// - /// @dev Emits a {RestartOpenEndedStream}, {Transfer} and {DepositOpenEndedStream} event. + /// @dev Emits a {RestartFlowStream}, {Transfer} and {DepositFlowStream} event. /// /// Requirements: /// - `amount` must be greater than zero. @@ -346,7 +346,7 @@ interface ISablierV2OpenEnded is /// @notice Withdraws the amount of assets calculated based on time reference and the remaining amount, from the /// stream to the provided `to` address. /// - /// @dev Emits a {Transfer} and {WithdrawFromOpenEndedStream} event. + /// @dev Emits a {Transfer} and {WithdrawFromFlowStream} event. /// /// Requirements: /// - Must not be delegate called. @@ -363,7 +363,7 @@ interface ISablierV2OpenEnded is /// @notice Withdraws the maximum withdrawable amount from the stream to the provided address `to`. /// - /// @dev Emits a {Transfer}, {WithdrawFromOpenEndedStream} event. + /// @dev Emits a {Transfer}, {WithdrawFromFlowStream} event. /// /// Requirements: /// - Refer to the requirements in {withdrawAt}. diff --git a/src/interfaces/ISablierV2OpenEndedState.sol b/src/interfaces/ISablierFlowState.sol similarity index 95% rename from src/interfaces/ISablierV2OpenEndedState.sol rename to src/interfaces/ISablierFlowState.sol index 90b8543a..6c9b8291 100644 --- a/src/interfaces/ISablierV2OpenEndedState.sol +++ b/src/interfaces/ISablierFlowState.sol @@ -5,12 +5,12 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC721Metadata } from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; import { UD60x18 } from "@prb/math/src/UD60x18.sol"; -import { OpenEnded } from "../types/DataTypes.sol"; +import { Flow } from "../types/DataTypes.sol"; -/// @title ISablierV2OpenEndedState -/// @notice State variables, storage and constants, for the {SablierV2OpenEnded} contract, and their respective getters. +/// @title ISablierFlowState +/// @notice State variables, storage and constants, for the {SablierFlow} contract, and their respective getters. /// @dev This contract also includes helpful modifiers and helper functions. -interface ISablierV2OpenEndedState is +interface ISablierFlowState is IERC721Metadata // 2 inherited components { /*////////////////////////////////////////////////////////////////////////// @@ -61,7 +61,7 @@ interface ISablierV2OpenEndedState is /// @notice Retrieves the stream entity. /// @dev Reverts if `streamId` references a null stream. /// @param streamId The stream ID for the query. - function getStream(uint256 streamId) external view returns (OpenEnded.Stream memory stream); + function getStream(uint256 streamId) external view returns (Flow.Stream memory stream); /// @notice Retrieves a flag indicating whether the stream is paused. /// @dev Reverts if `streamId` references a null stream. diff --git a/src/libraries/Errors.sol b/src/libraries/Errors.sol index 09efec64..5612fa73 100644 --- a/src/libraries/Errors.sol +++ b/src/libraries/Errors.sol @@ -5,7 +5,7 @@ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { UD60x18 } from "@prb/math/src/UD60x18.sol"; /// @title Errors -/// @notice Library with custom erros used across the OpenEnded contract. +/// @notice Library with custom erros used across the Flow contract. library Errors { /*////////////////////////////////////////////////////////////////////////// GENERICS @@ -15,67 +15,67 @@ library Errors { error DelegateCall(); /*////////////////////////////////////////////////////////////////////////// - SABLIER-V2-OpenEnded + SABLIER-FLOW //////////////////////////////////////////////////////////////////////////*/ /// @notice Thrown when trying to create a stream with a broker fee more than the allowed. - error SablierV2OpenEnded_BrokerFeeTooHigh(uint256 streamId, UD60x18 fee, UD60x18 maxFee); + error SablierFlow_BrokerFeeTooHigh(uint256 streamId, UD60x18 fee, UD60x18 maxFee); /// @notice Thrown when trying to create a stream with a broker recipient address as zero. - error SablierV2OpenEnded_BrokerAddressZero(); + error SablierFlow_BrokerAddressZero(); /// @notice Thrown when trying to create a stream with a zero deposit amount. - error SablierV2OpenEnded_DepositAmountZero(); + error SablierFlow_DepositAmountZero(); /// @notice Thrown when trying to create a stream with an asset with no decimals. - error SablierV2OpenEnded_InvalidAssetDecimals(IERC20 asset); + error SablierFlow_InvalidAssetDecimals(IERC20 asset); /// @notice Thrown when an unexpected error occurs during the calculation of an amount. - error SablierV2OpenEnded_InvalidCalculation(uint256 streamId, uint128 availableAmount, uint128 amount); + error SablierFlow_InvalidCalculation(uint256 streamId, uint128 availableAmount, uint128 amount); /// @notice Thrown when trying to withdraw assets with a withdrawal time not greater than or equal to /// `lastTimeUpdate`. - error SablierV2OpenEnded_LastUpdateNotLessThanWithdrawalTime(uint40 lastUpdate, uint40 time); + error SablierFlow_LastUpdateNotLessThanWithdrawalTime(uint40 lastUpdate, uint40 time); /// @notice Thrown when trying to transfer Stream NFT when transferability is disabled. - error SablierV2OpenEndedState_NotTransferable(uint256 streamId); + error SablierFlowState_NotTransferable(uint256 streamId); /// @notice Thrown when the ID references a null stream. - error SablierV2OpenEnded_Null(uint256 streamId); + error SablierFlow_Null(uint256 streamId); /// @notice Thrown when trying to refund an amount greater than the refundable amount. - error SablierV2OpenEnded_Overrefund(uint256 streamId, uint128 refundAmount, uint128 refundableAmount); + error SablierFlow_Overrefund(uint256 streamId, uint128 refundAmount, uint128 refundableAmount); /// @notice Thrown when trying to change the rate per second with the same rate per second. - error SablierV2OpenEnded_RatePerSecondNotDifferent(uint128 ratePerSecond); + error SablierFlow_RatePerSecondNotDifferent(uint128 ratePerSecond); /// @notice Thrown when trying to set the rate per second of a stream to zero. - error SablierV2OpenEnded_RatePerSecondZero(); + error SablierFlow_RatePerSecondZero(); /// @notice Thrown when trying to refund zero assets from a stream. - error SablierV2OpenEnded_RefundAmountZero(); + error SablierFlow_RefundAmountZero(); /// @notice Thrown when trying to create a stream with the sender as the zero address. - error SablierV2OpenEnded_SenderZeroAddress(); + error SablierFlow_SenderZeroAddress(); /// @notice Thrown when trying to perform an action with a paused stream. - error SablierV2OpenEnded_StreamPaused(uint256 streamId); + error SablierFlow_StreamPaused(uint256 streamId); /// @notice Thrown when trying to restart a stream that is not paused. - error SablierV2OpenEnded_StreamNotPaused(uint256 streamId); + error SablierFlow_StreamNotPaused(uint256 streamId); /// @notice Thrown when `msg.sender` lacks authorization to perform an action. - error SablierV2OpenEnded_Unauthorized(uint256 streamId, address caller); + error SablierFlow_Unauthorized(uint256 streamId, address caller); /// @notice Thrown when trying to withdraw to an address other than the recipient's. - error SablierV2OpenEnded_WithdrawalAddressNotRecipient(uint256 streamId, address caller, address to); + error SablierFlow_WithdrawalAddressNotRecipient(uint256 streamId, address caller, address to); /// @notice Thrown when trying to withdraw but the stream no funds available. - error SablierV2OpenEnded_WithdrawNoFundsAvailable(uint256 streamId); + error SablierFlow_WithdrawNoFundsAvailable(uint256 streamId); /// @notice Thrown when trying to withdraw assets with a withdrawal time in the future. - error SablierV2OpenEnded_WithdrawalTimeInTheFuture(uint40 time, uint256 currentTime); + error SablierFlow_WithdrawalTimeInTheFuture(uint40 time, uint256 currentTime); /// @notice Thrown when trying to withdraw to the zero address. - error SablierV2OpenEnded_WithdrawToZeroAddress(); + error SablierFlow_WithdrawToZeroAddress(); } diff --git a/src/types/DataTypes.sol b/src/types/DataTypes.sol index f7583e25..459a0c90 100644 --- a/src/types/DataTypes.sol +++ b/src/types/DataTypes.sol @@ -13,8 +13,8 @@ struct Broker { UD60x18 fee; } -library OpenEnded { - /// @notice OpenEnded stream. +library Flow { + /// @notice Flow stream. /// @dev The fields are arranged like this to save gas via tight variable packing. /// @param balance The amount of assets that is currently available in the stream, i.e. the sum of deposited amounts /// subtracted by the sum of withdrawn amounts, denoted in 18 decimals. diff --git a/test/Base.t.sol b/test/Base.t.sol index b78d439e..17a2fb90 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -5,7 +5,7 @@ import { Test } from "forge-std/src/Test.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; -import { SablierV2OpenEnded } from "src/SablierV2OpenEnded.sol"; +import { SablierFlow } from "src/SablierFlow.sol"; import { ERC20Mock } from "./mocks/ERC20Mock.sol"; import { ERC20MissingReturn } from "./mocks/ERC20MissingReturn.sol"; @@ -31,7 +31,7 @@ abstract contract Base_Test is Assertions, Constants, Events, Modifiers, Test, U ERC20Mock internal assetWithoutDecimals = new ERC20Mock("Asset without decimals", "AWD", 0); ERC20Mock internal dai = new ERC20Mock("Dai stablecoin", "DAI", 18); - SablierV2OpenEnded internal openEnded; + SablierFlow internal flow; ERC20Mock internal usdc = new ERC20Mock("USD Coin", "USDC", 6); ERC20MissingReturn internal usdt = new ERC20MissingReturn("USDT stablecoin", "USDT", 6); @@ -41,9 +41,9 @@ abstract contract Base_Test is Assertions, Constants, Events, Modifiers, Test, U function setUp() public virtual { if (!isTestOptimizedProfile()) { - openEnded = new SablierV2OpenEnded(); + flow = new SablierFlow(); } else { - openEnded = deployOptimizedOpenEnded(); + flow = deployOptimizedFlow(); } users.broker = createUser("broker"); @@ -70,19 +70,19 @@ abstract contract Base_Test is Assertions, Constants, Events, Modifiers, Test, U deal({ token: address(usdc), to: user, give: 1_000_000e6 }); deal({ token: address(usdt), to: user, give: 1_000_000e18 }); resetPrank(user); - dai.approve({ spender: address(openEnded), value: type(uint256).max }); - usdc.approve({ spender: address(openEnded), value: type(uint256).max }); - usdt.approve({ spender: address(openEnded), value: type(uint256).max }); + dai.approve({ spender: address(flow), value: type(uint256).max }); + usdc.approve({ spender: address(flow), value: type(uint256).max }); + usdt.approve({ spender: address(flow), value: type(uint256).max }); return user; } - /// @dev Deploys {SablierV2OpenEnded} from an optimized source compiled with `--via-ir`. - function deployOptimizedOpenEnded() internal returns (SablierV2OpenEnded) { - return SablierV2OpenEnded(deployCode("out-optimized/SablierV2OpenEnded.sol/SablierV2OpenEnded.json")); + /// @dev Deploys {SablierFlow} from an optimized source compiled with `--via-ir`. + function deployOptimizedFlow() internal returns (SablierFlow) { + return SablierFlow(deployCode("out-optimized/SablierFlow.sol/SablierFlow.json")); } function labelConctracts() internal { - vm.label(address(openEnded), "Open Ended"); + vm.label(address(flow), "Flow"); vm.label(address(dai), "DAI"); vm.label(address(usdt), "USDT"); } @@ -112,12 +112,12 @@ abstract contract Base_Test is Assertions, Constants, Events, Modifiers, Test, U /// @dev Normalizes `amount` to the decimal of `streamId` asset. function normalizeAmountWithStreamId(uint256 streamId, uint128 amount) internal view returns (uint256) { - return normalizeAmountToDecimal(amount, openEnded.getAssetDecimals(streamId)); + return normalizeAmountToDecimal(amount, flow.getAssetDecimals(streamId)); } /// @dev Normalizes stream balance to the decimal of `streamId` asset. function normalizeStreamBalance(uint256 streamId) internal view returns (uint256) { - return normalizeAmountToDecimal(openEnded.getBalance(streamId), openEnded.getAssetDecimals(streamId)); + return normalizeAmountToDecimal(flow.getBalance(streamId), flow.getAssetDecimals(streamId)); } /*////////////////////////////////////////////////////////////////////////// diff --git a/test/integration/Integration.t.sol b/test/integration/Integration.t.sol index d27f6723..2717777f 100644 --- a/test/integration/Integration.t.sol +++ b/test/integration/Integration.t.sol @@ -34,7 +34,7 @@ abstract contract Integration_Test is Base_Test { } function createDefaultStreamWithAsset(IERC20 asset_) internal returns (uint256) { - return openEnded.create({ + return flow.create({ sender: users.sender, recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -44,7 +44,7 @@ abstract contract Integration_Test is Base_Test { } function depositToDefaultStream() internal { - openEnded.deposit(defaultStreamId, DEPOSIT_AMOUNT); + flow.deposit(defaultStreamId, DEPOSIT_AMOUNT); } /*////////////////////////////////////////////////////////////////////////// @@ -52,17 +52,17 @@ abstract contract Integration_Test is Base_Test { //////////////////////////////////////////////////////////////////////////*/ function expectRevertDueToDelegateCall(bytes memory callData) internal { - (bool success, bytes memory returnData) = address(openEnded).delegatecall(callData); + (bool success, bytes memory returnData) = address(flow).delegatecall(callData); assertFalse(success, "delegatecall success"); assertEq(returnData, abi.encodeWithSelector(Errors.DelegateCall.selector), "delegatecall return data"); } function expectRevertNull() internal { - vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2OpenEnded_Null.selector, nullStreamId)); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_Null.selector, nullStreamId)); } function expectRevertPaused() internal { - openEnded.pause(defaultStreamId); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2OpenEnded_StreamPaused.selector, defaultStreamId)); + flow.pause(defaultStreamId); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_StreamPaused.selector, defaultStreamId)); } } diff --git a/test/integration/adjust-rate-per-second/adjustRatePerSecond.t.sol b/test/integration/adjust-rate-per-second/adjustRatePerSecond.t.sol index f47b3090..c706bf4f 100644 --- a/test/integration/adjust-rate-per-second/adjustRatePerSecond.t.sol +++ b/test/integration/adjust-rate-per-second/adjustRatePerSecond.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -12,19 +12,18 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = - abi.encodeCall(ISablierV2OpenEnded.adjustRatePerSecond, (defaultStreamId, RATE_PER_SECOND)); + bytes memory callData = abi.encodeCall(ISablierFlow.adjustRatePerSecond, (defaultStreamId, RATE_PER_SECOND)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.adjustRatePerSecond({ streamId: nullStreamId, newRatePerSecond: RATE_PER_SECOND }); + flow.adjustRatePerSecond({ streamId: nullStreamId, newRatePerSecond: RATE_PER_SECOND }); } function test_RevertGiven_Paused() external whenNotDelegateCalled givenNotNull { expectRevertPaused(); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_CallerUnauthorized_Recipient() @@ -36,9 +35,9 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { { resetPrank({ msgSender: users.recipient }); vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.recipient) + abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.recipient) ); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_CallerUnauthorized_MaliciousThirdParty() @@ -49,10 +48,8 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { whenCallerIsNotTheSender { resetPrank({ msgSender: users.eve }); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.eve) - ); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.eve)); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_RatePerSecondZero() @@ -62,8 +59,8 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { givenNotPaused whenCallerIsTheSender { - vm.expectRevert(Errors.SablierV2OpenEnded_RatePerSecondZero.selector); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: 0 }); + vm.expectRevert(Errors.SablierFlow_RatePerSecondZero.selector); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: 0 }); } function test_RevertWhen_RatePerSecondNotDifferent() @@ -74,10 +71,8 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { whenCallerIsTheSender whenRatePerSecondIsNotZero { - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_RatePerSecondNotDifferent.selector, RATE_PER_SECOND) - ); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_RatePerSecondNotDifferent.selector, RATE_PER_SECOND)); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: RATE_PER_SECOND }); } function test_AdjustRatePerSecond_WithdrawableAmountZero() @@ -91,37 +86,37 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { { vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); uint40 expectedLastTimeUpdate = uint40(block.timestamp - ONE_MONTH); assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); uint128 newRatePerSecond = RATE_PER_SECOND / 2; - vm.expectEmit({ emitter: address(openEnded) }); - emit AdjustOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit AdjustFlowStream({ streamId: defaultStreamId, recipientAmount: ONE_MONTH_STREAMED_AMOUNT, oldRatePerSecond: RATE_PER_SECOND, newRatePerSecond: newRatePerSecond }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: defaultStreamId }); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualRemainingAmount, 0, "remaining amount"); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: newRatePerSecond }); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: newRatePerSecond }); - actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - uint128 actualRatePerSecond = openEnded.getRatePerSecond(defaultStreamId); + uint128 actualRatePerSecond = flow.getRatePerSecond(defaultStreamId); uint128 expectedRatePerSecond = newRatePerSecond; assertEq(actualRatePerSecond, expectedRatePerSecond, "rate per second"); - actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); expectedLastTimeUpdate = uint40(block.timestamp); assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); } @@ -133,45 +128,45 @@ contract AdjustRatePerSecond_Integration_Test is Integration_Test { givenNotPaused whenCallerIsTheSender { - openEnded.deposit(defaultStreamId, DEPOSIT_AMOUNT); + flow.deposit(defaultStreamId, DEPOSIT_AMOUNT); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 actualRatePerSecond = openEnded.getRatePerSecond(defaultStreamId); + uint128 actualRatePerSecond = flow.getRatePerSecond(defaultStreamId); uint128 expectedRatePerSecond = RATE_PER_SECOND; assertEq(actualRatePerSecond, expectedRatePerSecond, "rate per second"); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); uint40 expectedLastTimeUpdate = uint40(block.timestamp - ONE_MONTH); assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = 0; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); uint128 newRatePerSecond = RATE_PER_SECOND / 2; - vm.expectEmit({ emitter: address(openEnded) }); - emit AdjustOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit AdjustFlowStream({ streamId: defaultStreamId, recipientAmount: ONE_MONTH_STREAMED_AMOUNT, oldRatePerSecond: RATE_PER_SECOND, newRatePerSecond: newRatePerSecond }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: defaultStreamId }); - openEnded.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: newRatePerSecond }); + flow.adjustRatePerSecond({ streamId: defaultStreamId, newRatePerSecond: newRatePerSecond }); - actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - actualRatePerSecond = openEnded.getRatePerSecond(defaultStreamId); + actualRatePerSecond = flow.getRatePerSecond(defaultStreamId); expectedRatePerSecond = newRatePerSecond; assertEq(actualRatePerSecond, expectedRatePerSecond, "rate per second"); - actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); expectedLastTimeUpdate = uint40(block.timestamp); assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); } diff --git a/test/integration/adjust-rate-per-second/adjustRatePerSecond.tree b/test/integration/adjust-rate-per-second/adjustRatePerSecond.tree index e131a76a..14b639de 100644 --- a/test/integration/adjust-rate-per-second/adjustRatePerSecond.tree +++ b/test/integration/adjust-rate-per-second/adjustRatePerSecond.tree @@ -24,11 +24,11 @@ adjustRatePerSecond.t.sol │ ├── it should update the stream remaining amount │ ├── it should update the rate per second │ ├── it should update the stream time - │ ├── it should emit a {AdjustOpenEndedStream} event + │ ├── it should emit a {AdjustFlowStream} event │ └── it should emit a {MetadataUpdate} event └── given the withdrawable amount is not zero ├── it should update the stream remaining amount ├── it should update the rate per second ├── it should update the stream time - ├── it should emit a {AdjustOpenEndedStream} event + ├── it should emit a {AdjustFlowStream} event └── it should emit a {MetadataUpdate} event \ No newline at end of file diff --git a/test/integration/constructor.t.sol b/test/integration/constructor.t.sol index 7a85a646..3b722413 100644 --- a/test/integration/constructor.t.sol +++ b/test/integration/constructor.t.sol @@ -2,22 +2,22 @@ pragma solidity >=0.8.22; import { UD60x18 } from "@prb/math/src/UD60x18.sol"; -import { SablierV2OpenEnded } from "src/SablierV2OpenEnded.sol"; +import { SablierFlow } from "src/SablierFlow.sol"; import { Integration_Test } from "./Integration.t.sol"; contract Constructor_Integration_Concrete_Test is Integration_Test { function test_Constructor() external { // Construct the contract. - SablierV2OpenEnded constructedOpenEnded = new SablierV2OpenEnded(); + SablierFlow constructedFlow = new SablierFlow(); - // {SablierV2OpenEndedState.MAX_BROKER_FEE} - UD60x18 actualMaxBrokerFee = constructedOpenEnded.MAX_BROKER_FEE(); + // {SablierFlowState.MAX_BROKER_FEE} + UD60x18 actualMaxBrokerFee = constructedFlow.MAX_BROKER_FEE(); UD60x18 expectedMaxBrokerFee = UD60x18.wrap(0.1e18); assertEq(actualMaxBrokerFee, expectedMaxBrokerFee, "MAX_BROKER_FEE"); - // {SablierV2OpenEndedState.nextStreamId} - uint256 actualStreamId = constructedOpenEnded.nextStreamId(); + // {SablierFlowState.nextStreamId} + uint256 actualStreamId = constructedFlow.nextStreamId(); uint256 expectedStreamId = 1; assertEq(actualStreamId, expectedStreamId, "nextStreamId"); } diff --git a/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.t.sol b/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.t.sol index a7c0601c..ae05623c 100644 --- a/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.t.sol +++ b/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.t.sol @@ -3,15 +3,15 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; -import { OpenEnded } from "src/types/DataTypes.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; +import { Flow } from "src/types/DataTypes.sol"; import { Integration_Test } from "../Integration.t.sol"; contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { function test_RevertWhen_DelegateCalled() external { bytes memory callData = abi.encodeCall( - ISablierV2OpenEnded.createAndDepositViaBroker, + ISablierFlow.createAndDepositViaBroker, ( users.sender, users.recipient, @@ -27,21 +27,21 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { } function test_WhenNotDelegateCalled() external { - uint256 expectedStreamId = openEnded.nextStreamId(); + uint256 expectedStreamId = flow.nextStreamId(); // it should create the stream // it should bump the next stream id // it should mint the NFT // it should update the stream balance // it should perform the ERC20 transfers - // it should emit events: 1 {MetadataUpdate}, 1 {CreateOpenEndedStream}, 2 {Transfer}, 1 - // {DepositOpenEndedStream} + // it should emit events: 1 {MetadataUpdate}, 1 {CreateFlowStream}, 2 {Transfer}, 1 + // {DepositFlowStream} - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: expectedStreamId }); - vm.expectEmit({ emitter: address(openEnded) }); - emit CreateOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit CreateFlowStream({ streamId: expectedStreamId, sender: users.sender, recipient: users.recipient, @@ -53,12 +53,12 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { vm.expectEmit({ emitter: address(dai) }); emit IERC20.Transfer({ from: users.sender, - to: address(openEnded), + to: address(flow), value: normalizeAmountToDecimal(DEPOSIT_AMOUNT, 18) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit DepositOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit DepositFlowStream({ streamId: expectedStreamId, funder: users.sender, asset: dai, @@ -75,7 +75,7 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { expectCallToTransferFrom({ asset: dai, from: users.sender, - to: address(openEnded), + to: address(flow), amount: normalizeAmountToDecimal(DEPOSIT_AMOUNT, 18) }); @@ -86,7 +86,7 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { amount: normalizeAmountToDecimal(BROKER_FEE_AMOUNT, 18) }); - uint256 actualStreamId = openEnded.createAndDepositViaBroker({ + uint256 actualStreamId = flow.createAndDepositViaBroker({ sender: users.sender, recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -96,8 +96,8 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { broker: defaultBroker }); - OpenEnded.Stream memory actualStream = openEnded.getStream(actualStreamId); - OpenEnded.Stream memory expectedStream = OpenEnded.Stream({ + Flow.Stream memory actualStream = flow.getStream(actualStreamId); + Flow.Stream memory expectedStream = Flow.Stream({ ratePerSecond: RATE_PER_SECOND, asset: dai, assetDecimals: 18, @@ -113,11 +113,11 @@ contract CreateAndDepositViaBroker_Integration_Test is Integration_Test { assertEq(actualStreamId, expectedStreamId, "stream id"); assertEq(actualStream, expectedStream); - address actualNFTOwner = openEnded.ownerOf({ tokenId: actualStreamId }); + address actualNFTOwner = flow.ownerOf({ tokenId: actualStreamId }); address expectedNFTOwner = users.recipient; assertEq(actualNFTOwner, expectedNFTOwner, "NFT owner"); - uint128 actualStreamBalance = openEnded.getBalance(expectedStreamId); + uint128 actualStreamBalance = flow.getBalance(expectedStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } diff --git a/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.tree b/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.tree index b71cdd9f..fc6a047d 100644 --- a/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.tree +++ b/test/integration/create-and-deposit-via-broker/createAndDepositViaBroker.tree @@ -7,4 +7,4 @@ CreateAndDepositViaBroker_Integration_Test ├── it should mint the NFT ├── it should update the stream balance ├── it should perform the ERC20 transfers - └── it should emit events: 1 {MetadataUpdate}, 1 {CreateOpenEndedStream}, 2 {Transfer}, 1 {DepositOpenEndedStream} \ No newline at end of file + └── it should emit events: 1 {MetadataUpdate}, 1 {CreateFlowStream}, 2 {Transfer}, 1 {DepositFlowStream} \ No newline at end of file diff --git a/test/integration/create/create.t.sol b/test/integration/create/create.t.sol index 1dc6c4f3..7eeca48d 100644 --- a/test/integration/create/create.t.sol +++ b/test/integration/create/create.t.sol @@ -4,9 +4,9 @@ pragma solidity >=0.8.22; import { IERC721Errors } from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; -import { OpenEnded } from "src/types/DataTypes.sol"; +import { Flow } from "src/types/DataTypes.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -16,15 +16,14 @@ contract Create_Integration_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall( - ISablierV2OpenEnded.create, (users.sender, users.recipient, RATE_PER_SECOND, dai, IS_TRANFERABLE) - ); + bytes memory callData = + abi.encodeCall(ISablierFlow.create, (users.sender, users.recipient, RATE_PER_SECOND, dai, IS_TRANFERABLE)); expectRevertDueToDelegateCall(callData); } function test_RevertWhen_SenderZeroAddress() external whenNotDelegateCalled { - vm.expectRevert(Errors.SablierV2OpenEnded_SenderZeroAddress.selector); - openEnded.create({ + vm.expectRevert(Errors.SablierFlow_SenderZeroAddress.selector); + flow.create({ sender: address(0), recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -35,7 +34,7 @@ contract Create_Integration_Test is Integration_Test { function test_RevertWhen_RecipientZeroAddress() external whenNotDelegateCalled whenSenderIsNotZeroAddress { vm.expectRevert(abi.encodeWithSelector(IERC721Errors.ERC721InvalidReceiver.selector, address(0))); - openEnded.create({ + flow.create({ sender: users.sender, recipient: address(0), ratePerSecond: RATE_PER_SECOND, @@ -50,8 +49,8 @@ contract Create_Integration_Test is Integration_Test { whenSenderIsNotZeroAddress whenRecipientIsNotZeroAddress { - vm.expectRevert(Errors.SablierV2OpenEnded_RatePerSecondZero.selector); - openEnded.create({ + vm.expectRevert(Errors.SablierFlow_RatePerSecondZero.selector); + flow.create({ sender: users.sender, recipient: users.recipient, ratePerSecond: 0, @@ -68,10 +67,8 @@ contract Create_Integration_Test is Integration_Test { whenRatePerSecondIsNotZero { address nonContract = address(8128); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_InvalidAssetDecimals.selector, IERC20(nonContract)) - ); - openEnded.create({ + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_InvalidAssetDecimals.selector, IERC20(nonContract))); + flow.create({ sender: users.sender, recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -88,12 +85,12 @@ contract Create_Integration_Test is Integration_Test { whenRatePerSecondIsNotZero whenAssetContract { - uint256 expectedStreamId = openEnded.nextStreamId(); + uint256 expectedStreamId = flow.nextStreamId(); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: expectedStreamId }); - vm.expectEmit({ emitter: address(openEnded) }); - emit CreateOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit CreateFlowStream({ streamId: expectedStreamId, sender: users.sender, recipient: users.recipient, @@ -102,7 +99,7 @@ contract Create_Integration_Test is Integration_Test { lastTimeUpdate: uint40(block.timestamp) }); - uint256 actualStreamId = openEnded.create({ + uint256 actualStreamId = flow.create({ sender: users.sender, recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -110,8 +107,8 @@ contract Create_Integration_Test is Integration_Test { isTransferable: IS_TRANFERABLE }); - OpenEnded.Stream memory actualStream = openEnded.getStream(actualStreamId); - OpenEnded.Stream memory expectedStream = OpenEnded.Stream({ + Flow.Stream memory actualStream = flow.getStream(actualStreamId); + Flow.Stream memory expectedStream = Flow.Stream({ ratePerSecond: RATE_PER_SECOND, asset: dai, assetDecimals: 18, @@ -127,7 +124,7 @@ contract Create_Integration_Test is Integration_Test { assertEq(actualStreamId, expectedStreamId, "stream id"); assertEq(actualStream, expectedStream); - address actualNFTOwner = openEnded.ownerOf({ tokenId: actualStreamId }); + address actualNFTOwner = flow.ownerOf({ tokenId: actualStreamId }); address expectedNFTOwner = users.recipient; assertEq(actualNFTOwner, expectedNFTOwner, "NFT owner"); } diff --git a/test/integration/create/create.tree b/test/integration/create/create.tree index b1db79bd..219b69d8 100644 --- a/test/integration/create/create.tree +++ b/test/integration/create/create.tree @@ -18,4 +18,4 @@ create.t.sol ├── it should bump the next stream id ├── it should mint the NFT ├── it should emit a {MetadataUpdate} event - └── it should emit a {CreateOpenEndedStream} event \ No newline at end of file + └── it should emit a {CreateFlowStream} event \ No newline at end of file diff --git a/test/integration/depletion-time-of/depletionTimeOf.t.sol b/test/integration/depletion-time-of/depletionTimeOf.t.sol index 8967ea22..01397ae4 100644 --- a/test/integration/depletion-time-of/depletionTimeOf.t.sol +++ b/test/integration/depletion-time-of/depletionTimeOf.t.sol @@ -7,18 +7,18 @@ contract DepletionTimeOf_Integration_Test is Integration_Test { function test_RevertGiven_Null() external { // it should revert expectRevertNull(); - openEnded.depletionTimeOf(nullStreamId); + flow.depletionTimeOf(nullStreamId); } function test_RevertGiven_Paused() external givenNotNull { // it should revert expectRevertPaused(); - openEnded.depletionTimeOf(defaultStreamId); + flow.depletionTimeOf(defaultStreamId); } function test_WhenBalanceIsZero() external view givenNotNull givenNotPaused { // it should return 0 - uint40 depletionTime = openEnded.depletionTimeOf(defaultStreamId); + uint40 depletionTime = flow.depletionTimeOf(defaultStreamId); assertEq(depletionTime, 0, "depletion time"); } @@ -30,13 +30,13 @@ contract DepletionTimeOf_Integration_Test is Integration_Test { function test_WhenStreamHasDebt() external givenNotNull givenNotPaused whenBalanceIsNotZero { vm.warp({ newTimestamp: block.timestamp + SOLVENCY_PERIOD }); // it should return 0 - uint40 depletionTime = openEnded.depletionTimeOf(defaultStreamId); + uint40 depletionTime = flow.depletionTimeOf(defaultStreamId); assertEq(depletionTime, 0, "depletion time"); } function test_WhenStreamHasNoDebt() external givenNotNull givenNotPaused whenBalanceIsNotZero { // it should return the time at which the stream depletes its balance - uint40 depletionTime = openEnded.depletionTimeOf(defaultStreamId); + uint40 depletionTime = flow.depletionTimeOf(defaultStreamId); assertEq(depletionTime, block.timestamp + SOLVENCY_PERIOD, "depletion time"); } } diff --git a/test/integration/deposit-via-broker/depositViaBroker.t.sol b/test/integration/deposit-via-broker/depositViaBroker.t.sol index 027388f3..6cfdc30b 100644 --- a/test/integration/deposit-via-broker/depositViaBroker.t.sol +++ b/test/integration/deposit-via-broker/depositViaBroker.t.sol @@ -4,7 +4,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { ud } from "@prb/math/src/UD60x18.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Broker } from "src/types/DataTypes.sol"; @@ -13,7 +13,7 @@ import { Integration_Test } from "../Integration.t.sol"; contract DepositViaBroker_Integration_Test is Integration_Test { function test_RevertWhen_DelegateCalled() external { bytes memory callData = abi.encodeCall( - ISablierV2OpenEnded.depositViaBroker, (defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker) + ISablierFlow.depositViaBroker, (defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker) ); // it should revert expectRevertDueToDelegateCall(callData); @@ -22,7 +22,7 @@ contract DepositViaBroker_Integration_Test is Integration_Test { function test_RevertGiven_Null() external whenNotDelegateCalled { // it should revert expectRevertNull(); - openEnded.depositViaBroker(nullStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); + flow.depositViaBroker(nullStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); } function test_RevertWhen_BrokerFeeGreaterThanMaxFee() external whenNotDelegateCalled givenNotNull { @@ -30,10 +30,10 @@ contract DepositViaBroker_Integration_Test is Integration_Test { // it should revert vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_BrokerFeeTooHigh.selector, defaultStreamId, defaultBroker.fee, MAX_BROKER_FEE + Errors.SablierFlow_BrokerFeeTooHigh.selector, defaultStreamId, defaultBroker.fee, MAX_BROKER_FEE ) ); - openEnded.depositViaBroker(defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); + flow.depositViaBroker(defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); } function test_RevertWhen_BrokeAddressIsZero() @@ -44,8 +44,8 @@ contract DepositViaBroker_Integration_Test is Integration_Test { { defaultBroker.account = address(0); // it should revert - vm.expectRevert(Errors.SablierV2OpenEnded_BrokerAddressZero.selector); - openEnded.depositViaBroker(defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); + vm.expectRevert(Errors.SablierFlow_BrokerAddressZero.selector); + flow.depositViaBroker(defaultStreamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, defaultBroker); } function test_RevertWhen_TotalAmountIsZero() @@ -56,8 +56,8 @@ contract DepositViaBroker_Integration_Test is Integration_Test { whenBrokerAddressIsNotZero { // it should revert - vm.expectRevert(Errors.SablierV2OpenEnded_DepositAmountZero.selector); - openEnded.depositViaBroker(defaultStreamId, 0, defaultBroker); + vm.expectRevert(Errors.SablierFlow_DepositAmountZero.selector); + flow.depositViaBroker(defaultStreamId, 0, defaultBroker); } function test_WhenAssetMissesERC20Return() @@ -84,7 +84,7 @@ contract DepositViaBroker_Integration_Test is Integration_Test { { // it should update the stream balance // it should perform the ERC20 transfer - // it should emit 2 {Transfer}, 1 {DepositOpenEndedStream}, 1 {MetadataUpdate} events + // it should emit 2 {Transfer}, 1 {DepositFlowStream}, 1 {MetadataUpdate} events uint256 streamId = createDefaultStreamWithAsset(IERC20(address(usdc))); _test_DepositViaBroker(streamId, IERC20(address(usdc)), defaultBroker); } @@ -100,7 +100,7 @@ contract DepositViaBroker_Integration_Test is Integration_Test { { // it should update the stream balance // it should perform the ERC20 transfer - // it should emit 2 {Transfer}, 1 {DepositOpenEndedStream}, 1 {MetadataUpdate} events + // it should emit 2 {Transfer}, 1 {DepositFlowStream}, 1 {MetadataUpdate} events uint256 streamId = createDefaultStreamWithAsset(IERC20(address(dai))); _test_DepositViaBroker(streamId, IERC20(address(dai)), defaultBroker); } @@ -109,17 +109,12 @@ contract DepositViaBroker_Integration_Test is Integration_Test { vm.expectEmit({ emitter: address(asset) }); emit IERC20.Transfer({ from: users.sender, - to: address(openEnded), + to: address(flow), value: normalizeAmountWithStreamId(streamId, DEPOSIT_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit DepositOpenEndedStream({ - streamId: streamId, - funder: users.sender, - asset: asset, - depositAmount: DEPOSIT_AMOUNT - }); + vm.expectEmit({ emitter: address(flow) }); + emit DepositFlowStream({ streamId: streamId, funder: users.sender, asset: asset, depositAmount: DEPOSIT_AMOUNT }); vm.expectEmit({ emitter: address(asset) }); emit IERC20.Transfer({ @@ -128,13 +123,13 @@ contract DepositViaBroker_Integration_Test is Integration_Test { value: normalizeAmountWithStreamId(streamId, BROKER_FEE_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: streamId }); expectCallToTransferFrom({ asset: asset, from: users.sender, - to: address(openEnded), + to: address(flow), amount: normalizeAmountWithStreamId(streamId, DEPOSIT_AMOUNT) }); @@ -145,9 +140,9 @@ contract DepositViaBroker_Integration_Test is Integration_Test { amount: normalizeAmountWithStreamId(streamId, BROKER_FEE_AMOUNT) }); - openEnded.depositViaBroker(streamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, broker); + flow.depositViaBroker(streamId, DEPOSIT_AMOUNT_WITH_BROKER_FEE, broker); - uint128 actualStreamBalance = openEnded.getBalance(streamId); + uint128 actualStreamBalance = flow.getBalance(streamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } diff --git a/test/integration/deposit-via-broker/depositViaBroker.tree b/test/integration/deposit-via-broker/depositViaBroker.tree index 229ae699..ed27e10b 100644 --- a/test/integration/deposit-via-broker/depositViaBroker.tree +++ b/test/integration/deposit-via-broker/depositViaBroker.tree @@ -20,8 +20,8 @@ DepositViaBroker_Integration_Test ├── given asset does not have 18 decimals │ ├── it should update the stream balance │ ├── it should perform the ERC20 transfer - │ └── it should emit 2 {Transfer}, 1 {DepositOpenEndedStream}, 1 {MetadataUpdate} events + │ └── it should emit 2 {Transfer}, 1 {DepositFlowStream}, 1 {MetadataUpdate} events └── given asset has 18 decimals ├── it should update the stream balance ├── it should perform the ERC20 transfer - └── it should emit 2 {Transfer}, 1 {DepositOpenEndedStream}, 1 {MetadataUpdate} events + └── it should emit 2 {Transfer}, 1 {DepositFlowStream}, 1 {MetadataUpdate} events diff --git a/test/integration/deposit/deposit.t.sol b/test/integration/deposit/deposit.t.sol index 5420a3f7..8feae766 100644 --- a/test/integration/deposit/deposit.t.sol +++ b/test/integration/deposit/deposit.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -14,24 +14,24 @@ contract Deposit_Integration_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall(ISablierV2OpenEnded.deposit, (defaultStreamId, DEPOSIT_AMOUNT)); + bytes memory callData = abi.encodeCall(ISablierFlow.deposit, (defaultStreamId, DEPOSIT_AMOUNT)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.deposit(nullStreamId, DEPOSIT_AMOUNT); + flow.deposit(nullStreamId, DEPOSIT_AMOUNT); } function test_RevertWhen_DepositAmountZero() external whenNotDelegateCalled givenNotNull givenNotPaused { - vm.expectRevert(Errors.SablierV2OpenEnded_DepositAmountZero.selector); - openEnded.deposit(defaultStreamId, 0); + vm.expectRevert(Errors.SablierFlow_DepositAmountZero.selector); + flow.deposit(defaultStreamId, 0); } function test_Deposit_Paused() external whenNotDelegateCalled givenNotNull { - openEnded.deposit(defaultStreamId, DEPOSIT_AMOUNT); + flow.deposit(defaultStreamId, DEPOSIT_AMOUNT); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } @@ -55,30 +55,25 @@ contract Deposit_Integration_Test is Integration_Test { vm.expectEmit({ emitter: address(asset) }); emit IERC20.Transfer({ from: users.sender, - to: address(openEnded), + to: address(flow), value: normalizeAmountWithStreamId(streamId, DEPOSIT_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit DepositOpenEndedStream({ - streamId: streamId, - funder: users.sender, - asset: asset, - depositAmount: DEPOSIT_AMOUNT - }); + vm.expectEmit({ emitter: address(flow) }); + emit DepositFlowStream({ streamId: streamId, funder: users.sender, asset: asset, depositAmount: DEPOSIT_AMOUNT }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: streamId }); expectCallToTransferFrom({ asset: asset, from: users.sender, - to: address(openEnded), + to: address(flow), amount: normalizeAmountWithStreamId(streamId, DEPOSIT_AMOUNT) }); - openEnded.deposit(streamId, DEPOSIT_AMOUNT); + flow.deposit(streamId, DEPOSIT_AMOUNT); - uint128 actualStreamBalance = openEnded.getBalance(streamId); + uint128 actualStreamBalance = flow.getBalance(streamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } diff --git a/test/integration/deposit/deposit.tree b/test/integration/deposit/deposit.tree index 09f0b8fd..fe50ab62 100644 --- a/test/integration/deposit/deposit.tree +++ b/test/integration/deposit/deposit.tree @@ -17,10 +17,10 @@ deposit.t.sol ├── given the asset does not have 18 decimals │ ├── it should update the stream balance │ ├── it should perform the ERC-20 transfer - │ ├── it should emit a {Transfer} and {DepositOpenEndedStream} event + │ ├── it should emit a {Transfer} and {DepositFlowStream} event │ └── it should emit a {MetadataUpdate} event └── given the asset has 18 decimals ├── it should update the stream balance ├── it should perform the ERC-20 transfer - ├── it should emit a {Transfer} and {DepositOpenEndedStream} event + ├── it should emit a {Transfer} and {DepositFlowStream} event └── it should emit a {MetadataUpdate} event \ No newline at end of file diff --git a/test/integration/pause/pause.t.sol b/test/integration/pause/pause.t.sol index ac7226d7..f29c05c4 100644 --- a/test/integration/pause/pause.t.sol +++ b/test/integration/pause/pause.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -14,18 +14,18 @@ contract Pause_Integration_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall(ISablierV2OpenEnded.pause, (defaultStreamId)); + bytes memory callData = abi.encodeCall(ISablierFlow.pause, (defaultStreamId)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.pause(nullStreamId); + flow.pause(nullStreamId); } function test_RevertGiven_Paused() external whenNotDelegateCalled givenNotNull { expectRevertPaused(); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); } function test_RevertWhen_CallerRecipient() @@ -37,9 +37,9 @@ contract Pause_Integration_Test is Integration_Test { { resetPrank({ msgSender: users.recipient }); vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.recipient) + abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.recipient) ); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); } function test_RevertWhen_CallerMaliciousThirdParty() @@ -50,10 +50,8 @@ contract Pause_Integration_Test is Integration_Test { whenCallerIsNotTheSender { resetPrank({ msgSender: users.eve }); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.eve) - ); - openEnded.pause(defaultStreamId); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.eve)); + flow.pause(defaultStreamId); } function test_Pause_StreamHasDebt() @@ -63,21 +61,21 @@ contract Pause_Integration_Test is Integration_Test { givenNotPaused whenCallerIsTheSender { - assertEq(openEnded.refundableAmountOf(defaultStreamId), 0, "refundable amount before pause"); - assertEq(openEnded.withdrawableAmountOf(defaultStreamId), 0, "withdrawable amount before pause"); + assertEq(flow.refundableAmountOf(defaultStreamId), 0, "refundable amount before pause"); + assertEq(flow.withdrawableAmountOf(defaultStreamId), 0, "withdrawable amount before pause"); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - assertTrue(openEnded.isPaused(defaultStreamId), "is paused"); + assertTrue(flow.isPaused(defaultStreamId), "is paused"); - uint128 actualRatePerSecond = openEnded.getRatePerSecond(defaultStreamId); + uint128 actualRatePerSecond = flow.getRatePerSecond(defaultStreamId); assertEq(actualRatePerSecond, 0, "rate per second"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); assertEq(actualStreamBalance, 0, "stream balance"); } @@ -91,10 +89,10 @@ contract Pause_Integration_Test is Integration_Test { { depositToDefaultStream(); - uint128 withdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); + uint128 withdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); - vm.expectEmit({ emitter: address(openEnded) }); - emit PauseOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit PauseFlowStream({ streamId: defaultStreamId, sender: users.sender, recipient: users.recipient, @@ -102,17 +100,17 @@ contract Pause_Integration_Test is Integration_Test { asset: dai }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: defaultStreamId }); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - assertTrue(openEnded.isPaused(defaultStreamId), "is paused"); + assertTrue(flow.isPaused(defaultStreamId), "is paused"); - uint256 actualRatePerSecond = openEnded.getRatePerSecond(defaultStreamId); + uint256 actualRatePerSecond = flow.getRatePerSecond(defaultStreamId); assertEq(actualRatePerSecond, 0, "rate per second"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualRemainingAmount, withdrawableAmount, "remaining amount"); } } diff --git a/test/integration/pause/pause.tree b/test/integration/pause/pause.tree index 6542567c..45de9d03 100644 --- a/test/integration/pause/pause.tree +++ b/test/integration/pause/pause.tree @@ -22,5 +22,5 @@ pause.t.sol ├── it should pause the stream ├── it should set the rate per second to zero ├── it should update the remaining amount - ├── it should emit a {PauseOpenEndedStream} event + ├── it should emit a {PauseFlowStream} event └── it should emit a {MetadataUpdate} event \ No newline at end of file diff --git a/test/integration/refund-from-stream/refundFromStream.t.sol b/test/integration/refund-from-stream/refundFromStream.t.sol index a2b8b78d..26bbbff8 100644 --- a/test/integration/refund-from-stream/refundFromStream.t.sol +++ b/test/integration/refund-from-stream/refundFromStream.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -18,13 +18,13 @@ contract RefundFromStream_Integration_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall(ISablierV2OpenEnded.refundFromStream, (defaultStreamId, REFUND_AMOUNT)); + bytes memory callData = abi.encodeCall(ISablierFlow.refundFromStream, (defaultStreamId, REFUND_AMOUNT)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.refundFromStream({ streamId: nullStreamId, amount: REFUND_AMOUNT }); + flow.refundFromStream({ streamId: nullStreamId, amount: REFUND_AMOUNT }); } function test_RevertWhen_CallerUnauthorized_Recipient() @@ -35,9 +35,9 @@ contract RefundFromStream_Integration_Test is Integration_Test { { resetPrank({ msgSender: users.recipient }); vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.recipient) + abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.recipient) ); - openEnded.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); + flow.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); } function test_RevertWhen_CallerUnauthorized_MaliciousThirdParty() @@ -47,15 +47,13 @@ contract RefundFromStream_Integration_Test is Integration_Test { whenCallerIsNotTheSender { resetPrank({ msgSender: users.eve }); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.eve) - ); - openEnded.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.eve)); + flow.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); } function test_RevertWhen_RefundAmountZero() external whenNotDelegateCalled givenNotNull whenCallerIsTheSender { - vm.expectRevert(Errors.SablierV2OpenEnded_RefundAmountZero.selector); - openEnded.refundFromStream({ streamId: defaultStreamId, amount: 0 }); + vm.expectRevert(Errors.SablierFlow_RefundAmountZero.selector); + flow.refundFromStream({ streamId: defaultStreamId, amount: 0 }); } function test_RevertWhen_Overrefund() @@ -67,22 +65,22 @@ contract RefundFromStream_Integration_Test is Integration_Test { { vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_Overrefund.selector, + Errors.SablierFlow_Overrefund.selector, defaultStreamId, DEPOSIT_AMOUNT, DEPOSIT_AMOUNT - ONE_MONTH_STREAMED_AMOUNT ) ); - openEnded.refundFromStream({ streamId: defaultStreamId, amount: DEPOSIT_AMOUNT }); + flow.refundFromStream({ streamId: defaultStreamId, amount: DEPOSIT_AMOUNT }); } function test_RefundFromStream_PausedStream() external whenNotDelegateCalled givenNotNull whenCallerIsTheSender { - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); expectCallToTransfer({ asset: dai, to: users.sender, amount: REFUND_AMOUNT }); - openEnded.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); + flow.refundFromStream({ streamId: defaultStreamId, amount: REFUND_AMOUNT }); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - REFUND_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } @@ -98,7 +96,7 @@ contract RefundFromStream_Integration_Test is Integration_Test { // Set the timestamp to 1 month ago to create the stream with the same `lastTimeUpdate` as `defaultStreamId`. vm.warp({ newTimestamp: WARP_ONE_MONTH - ONE_MONTH }); uint256 streamId = createDefaultStreamWithAsset(IERC20(address(usdt))); - openEnded.deposit(streamId, DEPOSIT_AMOUNT); + flow.deposit(streamId, DEPOSIT_AMOUNT); vm.warp({ newTimestamp: WARP_ONE_MONTH }); test_RefundFromStream(streamId, IERC20(address(usdt))); @@ -118,27 +116,22 @@ contract RefundFromStream_Integration_Test is Integration_Test { function test_RefundFromStream(uint256 streamId, IERC20 asset) internal { vm.expectEmit({ emitter: address(asset) }); emit IERC20.Transfer({ - from: address(openEnded), + from: address(flow), to: users.sender, value: normalizeAmountWithStreamId(streamId, REFUND_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit RefundFromOpenEndedStream({ - streamId: streamId, - sender: users.sender, - asset: asset, - refundAmount: REFUND_AMOUNT - }); + vm.expectEmit({ emitter: address(flow) }); + emit RefundFromFlowStream({ streamId: streamId, sender: users.sender, asset: asset, refundAmount: REFUND_AMOUNT }); expectCallToTransfer({ asset: asset, to: users.sender, amount: normalizeAmountWithStreamId(streamId, REFUND_AMOUNT) }); - openEnded.refundFromStream({ streamId: streamId, amount: REFUND_AMOUNT }); + flow.refundFromStream({ streamId: streamId, amount: REFUND_AMOUNT }); - uint128 actualStreamBalance = openEnded.getBalance(streamId); + uint128 actualStreamBalance = flow.getBalance(streamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - REFUND_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } diff --git a/test/integration/refund-from-stream/refundFromStream.tree b/test/integration/refund-from-stream/refundFromStream.tree index c64987ed..925de239 100644 --- a/test/integration/refund-from-stream/refundFromStream.tree +++ b/test/integration/refund-from-stream/refundFromStream.tree @@ -24,9 +24,9 @@ refundFromStream.t.sol │ ├── it should make the refund │ ├── it should update the stream balance │ ├── it should perform the ERC-20 transfer - │ └── it should emit a {Transfer} and {RefundFromOpenEndedStream} event + │ └── it should emit a {Transfer} and {RefundFromFlowStream} event └── given the asset has 18 decimals ├── it should make the refund ├── it should update the stream balance ├── it should perform the ERC-20 transfer - └── it should emit a {Transfer} and {RefundFromOpenEndedStream} event \ No newline at end of file + └── it should emit a {Transfer} and {RefundFromFlowStream} event \ No newline at end of file diff --git a/test/integration/refundable-amount-of/refundableAmountOf.t.sol b/test/integration/refundable-amount-of/refundableAmountOf.t.sol index 97845f10..82624727 100644 --- a/test/integration/refundable-amount-of/refundableAmountOf.t.sol +++ b/test/integration/refundable-amount-of/refundableAmountOf.t.sol @@ -10,31 +10,31 @@ contract RefundableAmountOf_Integration_Test is Integration_Test { function test_RevertGiven_Null() external { expectRevertNull(); - openEnded.refundableAmountOf(nullStreamId); + flow.refundableAmountOf(nullStreamId); } function test_RefundableAmountOf_BalanceZero() external view givenNotNull givenNotPaused { - uint128 refundableAmount = openEnded.refundableAmountOf(defaultStreamId); + uint128 refundableAmount = flow.refundableAmountOf(defaultStreamId); assertEq(refundableAmount, 0, "refundable amount"); } function test_RefundableAmountOf_Paused() external givenNotNull { depositToDefaultStream(); - openEnded.refundableAmountOf(defaultStreamId); + flow.refundableAmountOf(defaultStreamId); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - uint128 refundableAmount = openEnded.refundableAmountOf(defaultStreamId); + uint128 refundableAmount = flow.refundableAmountOf(defaultStreamId); assertEq(refundableAmount, ONE_MONTH_REFUNDABLE_AMOUNT, "refundable amount"); } function test_RefundableAmountOf_BalanceLessThanOrEqualStreamedAmount() external givenNotNull givenNotPaused { uint128 depositAmount = 1e18; - openEnded.deposit(defaultStreamId, depositAmount); + flow.deposit(defaultStreamId, depositAmount); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 refundableAmount = openEnded.refundableAmountOf(defaultStreamId); + uint128 refundableAmount = flow.refundableAmountOf(defaultStreamId); assertEq(refundableAmount, 0, "refundable amount"); } @@ -42,7 +42,7 @@ contract RefundableAmountOf_Integration_Test is Integration_Test { depositToDefaultStream(); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 refundableAmount = openEnded.refundableAmountOf(defaultStreamId); + uint128 refundableAmount = flow.refundableAmountOf(defaultStreamId); assertEq(refundableAmount, ONE_MONTH_REFUNDABLE_AMOUNT, "refundable amount"); } } diff --git a/test/integration/restart-stream/restartStream.t.sol b/test/integration/restart-stream/restartStream.t.sol index e9f4bffc..dd1a4c2c 100644 --- a/test/integration/restart-stream/restartStream.t.sol +++ b/test/integration/restart-stream/restartStream.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -10,23 +10,23 @@ contract RestartStream_Integration_Test is Integration_Test { function setUp() public override { Integration_Test.setUp(); - openEnded.pause({ streamId: defaultStreamId }); + flow.pause({ streamId: defaultStreamId }); } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall(ISablierV2OpenEnded.restartStream, (defaultStreamId, RATE_PER_SECOND)); + bytes memory callData = abi.encodeCall(ISablierFlow.restartStream, (defaultStreamId, RATE_PER_SECOND)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.restartStream({ streamId: nullStreamId, ratePerSecond: RATE_PER_SECOND }); + flow.restartStream({ streamId: nullStreamId, ratePerSecond: RATE_PER_SECOND }); } function test_RevertGiven_NotPaused() external whenNotDelegateCalled givenNotNull { uint256 streamId = createDefaultStream(); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2OpenEnded_StreamNotPaused.selector, streamId)); - openEnded.restartStream({ streamId: streamId, ratePerSecond: RATE_PER_SECOND }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_StreamNotPaused.selector, streamId)); + flow.restartStream({ streamId: streamId, ratePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_CallerUnauthorized_Recipient() @@ -38,9 +38,9 @@ contract RestartStream_Integration_Test is Integration_Test { { resetPrank({ msgSender: users.recipient }); vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.recipient) + abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.recipient) ); - openEnded.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); + flow.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_CallerUnauthorized_MaliciousThirdParty() @@ -51,10 +51,8 @@ contract RestartStream_Integration_Test is Integration_Test { whenCallerIsNotTheSender { resetPrank({ msgSender: users.eve }); - vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEnded_Unauthorized.selector, defaultStreamId, users.eve) - ); - openEnded.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_Unauthorized.selector, defaultStreamId, users.eve)); + flow.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); } function test_RevertWhen_RatePerSecondZero() @@ -64,8 +62,8 @@ contract RestartStream_Integration_Test is Integration_Test { givenPaused whenCallerIsTheSender { - vm.expectRevert(Errors.SablierV2OpenEnded_RatePerSecondZero.selector); - openEnded.restartStream({ streamId: defaultStreamId, ratePerSecond: 0 }); + vm.expectRevert(Errors.SablierFlow_RatePerSecondZero.selector); + flow.restartStream({ streamId: defaultStreamId, ratePerSecond: 0 }); } function test_RestartStream() @@ -76,25 +74,25 @@ contract RestartStream_Integration_Test is Integration_Test { whenCallerIsTheSender whenRatePerSecondIsNotZero { - vm.expectEmit({ emitter: address(openEnded) }); - emit RestartOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit RestartFlowStream({ streamId: defaultStreamId, sender: users.sender, asset: dai, ratePerSecond: RATE_PER_SECOND }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: defaultStreamId }); - openEnded.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); + flow.restartStream({ streamId: defaultStreamId, ratePerSecond: RATE_PER_SECOND }); - bool isPaused = openEnded.isPaused(defaultStreamId); + bool isPaused = flow.isPaused(defaultStreamId); assertFalse(isPaused); - uint128 actualratePerSecond = openEnded.getRatePerSecond(defaultStreamId); + uint128 actualratePerSecond = flow.getRatePerSecond(defaultStreamId); assertEq(actualratePerSecond, RATE_PER_SECOND, "ratePerSecond"); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); assertEq(actualLastTimeUpdate, block.timestamp, "lastTimeUpdate"); } } diff --git a/test/integration/restart-stream/restartStream.tree b/test/integration/restart-stream/restartStream.tree index d7d6cf23..97e89adb 100644 --- a/test/integration/restart-stream/restartStream.tree +++ b/test/integration/restart-stream/restartStream.tree @@ -23,5 +23,5 @@ restartStream.t.sol ├── it should restart the stream ├── it should update the rate per second ├── it should update the time - ├── it should emit a {RestartOpenEndedStream} event + ├── it should emit a {RestartFlowStream} event └── it should emit a {MetadataUpdate} event diff --git a/test/integration/stream-debt-of/streamDebtOf.t.sol b/test/integration/stream-debt-of/streamDebtOf.t.sol index d8e463b5..5c4dc446 100644 --- a/test/integration/stream-debt-of/streamDebtOf.t.sol +++ b/test/integration/stream-debt-of/streamDebtOf.t.sol @@ -10,28 +10,28 @@ contract StreamDebtOf_Integration_Test is Integration_Test { function test_RevertGiven_Null() external { expectRevertNull(); - openEnded.streamDebtOf(nullStreamId); + flow.streamDebtOf(nullStreamId); } function test_RevertGiven_BalanceNotLessThanRemainingAmount() external givenNotNull givenPaused { depositToDefaultStream(); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - uint128 actualDebt = openEnded.streamDebtOf(defaultStreamId); + uint128 actualDebt = flow.streamDebtOf(defaultStreamId); assertEq(actualDebt, 0, "stream debt"); } function test_RevertGiven_BalanceLessThanRemainingAmount() external givenNotNull givenPaused { uint128 depositAmount = ONE_MONTH_STREAMED_AMOUNT / 2; - openEnded.deposit(defaultStreamId, depositAmount); + flow.deposit(defaultStreamId, depositAmount); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - uint128 actualDebt = openEnded.streamDebtOf(defaultStreamId); + uint128 actualDebt = flow.streamDebtOf(defaultStreamId); uint128 expectedDebt = ONE_MONTH_STREAMED_AMOUNT - depositAmount; assertEq(actualDebt, expectedDebt, "stream debt"); } @@ -40,17 +40,17 @@ contract StreamDebtOf_Integration_Test is Integration_Test { depositToDefaultStream(); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 actualDebt = openEnded.streamDebtOf(defaultStreamId); + uint128 actualDebt = flow.streamDebtOf(defaultStreamId); assertEq(actualDebt, 0, "stream debt"); } function test_StreamDebtOf() external givenNotNull givenNotPaused { uint128 depositAmount = ONE_MONTH_STREAMED_AMOUNT / 2; - openEnded.deposit(defaultStreamId, depositAmount); + flow.deposit(defaultStreamId, depositAmount); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 actualDebt = openEnded.streamDebtOf(defaultStreamId); + uint128 actualDebt = flow.streamDebtOf(defaultStreamId); uint128 expectedDebt = ONE_MONTH_STREAMED_AMOUNT - depositAmount; assertEq(actualDebt, expectedDebt, "stream debt"); } diff --git a/test/integration/streamed-amount-of/streamedAmountOf.t.sol b/test/integration/streamed-amount-of/streamedAmountOf.t.sol index bc3b1bac..94cc5feb 100644 --- a/test/integration/streamed-amount-of/streamedAmountOf.t.sol +++ b/test/integration/streamed-amount-of/streamedAmountOf.t.sol @@ -10,22 +10,22 @@ contract StreamedAmountOf_Integration_Test is Integration_Test { function test_RevertGiven_Null() external { expectRevertNull(); - openEnded.streamedAmountOf(nullStreamId); + flow.streamedAmountOf(nullStreamId); } function test_RevertGiven_Paused() external givenNotNull { expectRevertPaused(); - openEnded.streamedAmountOf(defaultStreamId); + flow.streamedAmountOf(defaultStreamId); } function test_StreamedAmountOf_LastTimeUpdateInThePresent() external view givenNotNull givenNotPaused { - uint128 streamedAmount = openEnded.streamedAmountOf(defaultStreamId); + uint128 streamedAmount = flow.streamedAmountOf(defaultStreamId); assertEq(streamedAmount, 0, "streamed amount"); } function test_StreamedAmountOf() external givenNotNull givenNotPaused { vm.warp({ newTimestamp: WARP_ONE_MONTH }); - uint128 streamedAmount = openEnded.streamedAmountOf(defaultStreamId); + uint128 streamedAmount = flow.streamedAmountOf(defaultStreamId); assertEq(streamedAmount, ONE_MONTH_STREAMED_AMOUNT, "streamed amount"); } } diff --git a/test/integration/transfer-from/transferFrom.t.sol b/test/integration/transfer-from/transferFrom.t.sol index 39a12caf..31c11434 100644 --- a/test/integration/transfer-from/transferFrom.t.sol +++ b/test/integration/transfer-from/transferFrom.t.sol @@ -12,7 +12,7 @@ contract TransferFrom_Integration_Concrete_Test is Integration_Test { } function test_RevertGiven_StreamNotTransferable() external { - uint256 notTransferableStreamId = openEnded.create({ + uint256 notTransferableStreamId = flow.create({ sender: users.sender, recipient: users.recipient, ratePerSecond: RATE_PER_SECOND, @@ -20,9 +20,9 @@ contract TransferFrom_Integration_Concrete_Test is Integration_Test { isTransferable: false }); vm.expectRevert( - abi.encodeWithSelector(Errors.SablierV2OpenEndedState_NotTransferable.selector, notTransferableStreamId) + abi.encodeWithSelector(Errors.SablierFlowState_NotTransferable.selector, notTransferableStreamId) ); - openEnded.transferFrom({ from: users.recipient, to: users.eve, tokenId: notTransferableStreamId }); + flow.transferFrom({ from: users.recipient, to: users.eve, tokenId: notTransferableStreamId }); } modifier givenStreamTransferable() { @@ -34,16 +34,16 @@ contract TransferFrom_Integration_Concrete_Test is Integration_Test { uint256 streamId = createDefaultStream(); // Expect the relevant events to be emitted. - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit Transfer({ from: users.recipient, to: users.sender, tokenId: streamId }); - vm.expectEmit({ emitter: address(openEnded) }); + vm.expectEmit({ emitter: address(flow) }); emit MetadataUpdate({ _tokenId: streamId }); // Transfer the NFT. - openEnded.transferFrom({ from: users.recipient, to: users.sender, tokenId: streamId }); + flow.transferFrom({ from: users.recipient, to: users.sender, tokenId: streamId }); // Assert that Alice is the new stream recipient (and NFT owner). - address actualRecipient = openEnded.getRecipient(streamId); + address actualRecipient = flow.getRecipient(streamId); address expectedRecipient = users.sender; assertEq(actualRecipient, expectedRecipient, "recipient"); } diff --git a/test/integration/withdraw-at/withdrawAt.t.sol b/test/integration/withdraw-at/withdrawAt.t.sol index 48ff1061..bccf0ba6 100644 --- a/test/integration/withdraw-at/withdrawAt.t.sol +++ b/test/integration/withdraw-at/withdrawAt.t.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { Errors } from "src/libraries/Errors.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -19,13 +19,13 @@ contract WithdrawAt_Integration_Test is Integration_Test { function test_RevertWhen_DelegateCall() external { bytes memory callData = - abi.encodeCall(ISablierV2OpenEnded.withdrawAt, (defaultStreamId, users.recipient, WITHDRAW_TIME)); + abi.encodeCall(ISablierFlow.withdrawAt, (defaultStreamId, users.recipient, WITHDRAW_TIME)); expectRevertDueToDelegateCall(callData); } function test_RevertGiven_Null() external whenNotDelegateCalled { expectRevertNull(); - openEnded.withdrawAt({ streamId: nullStreamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: nullStreamId, to: users.recipient, time: WITHDRAW_TIME }); } function test_RevertWhen_CallerUnknown() @@ -40,14 +40,11 @@ contract WithdrawAt_Integration_Test is Integration_Test { vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_WithdrawalAddressNotRecipient.selector, - defaultStreamId, - unknownCaller, - unknownCaller + Errors.SablierFlow_WithdrawalAddressNotRecipient.selector, defaultStreamId, unknownCaller, unknownCaller ) ); - openEnded.withdrawAt({ streamId: defaultStreamId, to: unknownCaller, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: defaultStreamId, to: unknownCaller, time: WITHDRAW_TIME }); } function test_RevertWhen_CallerSender() @@ -61,14 +58,11 @@ contract WithdrawAt_Integration_Test is Integration_Test { vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_WithdrawalAddressNotRecipient.selector, - defaultStreamId, - users.sender, - users.sender + Errors.SablierFlow_WithdrawalAddressNotRecipient.selector, defaultStreamId, users.sender, users.sender ) ); - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.sender, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.sender, time: WITHDRAW_TIME }); } function test_RevertWhen_LastTimeNotLessThanWithdrawalTime() @@ -78,16 +72,14 @@ contract WithdrawAt_Integration_Test is Integration_Test { whenToNonZeroAddress whenWithdrawalAddressIsRecipient { - uint40 lastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 lastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_LastUpdateNotLessThanWithdrawalTime.selector, - lastTimeUpdate, - lastTimeUpdate - 1 + Errors.SablierFlow_LastUpdateNotLessThanWithdrawalTime.selector, lastTimeUpdate, lastTimeUpdate - 1 ) ); - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: lastTimeUpdate - 1 }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: lastTimeUpdate - 1 }); } function test_RevertWhen_WithdrawalTimeInTheFuture() @@ -102,10 +94,10 @@ contract WithdrawAt_Integration_Test is Integration_Test { vm.expectRevert( abi.encodeWithSelector( - Errors.SablierV2OpenEnded_WithdrawalTimeInTheFuture.selector, futureTime, uint40(block.timestamp) + Errors.SablierFlow_WithdrawalTimeInTheFuture.selector, futureTime, uint40(block.timestamp) ) ); - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: futureTime }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: futureTime }); } function test_RevertGiven_BalanceZero() @@ -122,8 +114,8 @@ contract WithdrawAt_Integration_Test is Integration_Test { uint256 streamId = createDefaultStream(); vm.warp({ newTimestamp: WARP_ONE_MONTH }); - vm.expectRevert(abi.encodeWithSelector(Errors.SablierV2OpenEnded_WithdrawNoFundsAvailable.selector, streamId)); - openEnded.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); + vm.expectRevert(abi.encodeWithSelector(Errors.SablierFlow_WithdrawNoFundsAvailable.selector, streamId)); + flow.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); } function test_WithdrawAt_BalanceZero() @@ -140,24 +132,24 @@ contract WithdrawAt_Integration_Test is Integration_Test { uint256 streamId = createDefaultStream(); vm.warp({ newTimestamp: WITHDRAW_TIME }); - openEnded.deposit(streamId, WITHDRAW_AMOUNT); - openEnded.adjustRatePerSecond(streamId, RATE_PER_SECOND - 1); + flow.deposit(streamId, WITHDRAW_AMOUNT); + flow.adjustRatePerSecond(streamId, RATE_PER_SECOND - 1); - uint128 actualStreamBalance = openEnded.getBalance(streamId); + uint128 actualStreamBalance = flow.getBalance(streamId); uint128 expectedStreamBalance = WITHDRAW_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(streamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(streamId); uint128 expectedRemainingAmount = WITHDRAW_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - openEnded.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); - actualRemainingAmount = openEnded.getRemainingAmount(streamId); + actualRemainingAmount = flow.getRemainingAmount(streamId); expectedRemainingAmount = 0; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - actualStreamBalance = openEnded.getBalance(streamId); + actualStreamBalance = flow.getBalance(streamId); expectedStreamBalance = 0; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } @@ -173,13 +165,13 @@ contract WithdrawAt_Integration_Test is Integration_Test { givenBalanceNotZero givenRemainingAmountZero { - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); uint40 expectedLastTimeUpdate = WITHDRAW_TIME; assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - WITHDRAW_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } @@ -198,13 +190,13 @@ contract WithdrawAt_Integration_Test is Integration_Test { address unknownCaller = address(0xCAFE); resetPrank({ msgSender: unknownCaller }); - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(defaultStreamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(defaultStreamId); uint40 expectedLastTimeUpdate = WITHDRAW_TIME; assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - WITHDRAW_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } @@ -221,17 +213,17 @@ contract WithdrawAt_Integration_Test is Integration_Test { givenRemainingAmountNotZero whenCallerRecipient { - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); vm.expectEmit({ emitter: address(dai) }); - emit IERC20.Transfer({ from: address(openEnded), to: users.recipient, value: ONE_MONTH_STREAMED_AMOUNT }); + emit IERC20.Transfer({ from: address(flow), to: users.recipient, value: ONE_MONTH_STREAMED_AMOUNT }); - vm.expectEmit({ emitter: address(openEnded) }); - emit WithdrawFromOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit WithdrawFromFlowStream({ streamId: defaultStreamId, to: users.recipient, asset: dai, @@ -240,9 +232,9 @@ contract WithdrawAt_Integration_Test is Integration_Test { expectCallToTransfer({ asset: dai, to: users.recipient, amount: ONE_MONTH_STREAMED_AMOUNT }); - openEnded.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: defaultStreamId, to: users.recipient, time: WITHDRAW_TIME }); - actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); expectedRemainingAmount = 0; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); } @@ -265,16 +257,16 @@ contract WithdrawAt_Integration_Test is Integration_Test { vm.warp({ newTimestamp: WARP_ONE_MONTH }); uint128 depositAmount = ONE_MONTH_STREAMED_AMOUNT / 2; - openEnded.deposit(streamId, depositAmount); - openEnded.adjustRatePerSecond(streamId, RATE_PER_SECOND - 1); + flow.deposit(streamId, depositAmount); + flow.adjustRatePerSecond(streamId, RATE_PER_SECOND - 1); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(streamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(streamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - openEnded.withdrawAt({ streamId: streamId, to: users.recipient, time: WARP_ONE_MONTH }); + flow.withdrawAt({ streamId: streamId, to: users.recipient, time: WARP_ONE_MONTH }); - actualRemainingAmount = openEnded.getRemainingAmount(streamId); + actualRemainingAmount = flow.getRemainingAmount(streamId); expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT - depositAmount; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); } @@ -298,7 +290,7 @@ contract WithdrawAt_Integration_Test is Integration_Test { // Set the timestamp to 1 month ago to create the stream with the same `lastTimeUpdate` as `defaultStreamId`. vm.warp({ newTimestamp: WARP_ONE_MONTH - ONE_MONTH }); uint256 streamId = createDefaultStreamWithAsset(IERC20(address(usdt))); - openEnded.deposit(streamId, DEPOSIT_AMOUNT); + flow.deposit(streamId, DEPOSIT_AMOUNT); vm.warp({ newTimestamp: WARP_ONE_MONTH }); _test_Withdraw(streamId, IERC20(address(usdt))); @@ -322,19 +314,19 @@ contract WithdrawAt_Integration_Test is Integration_Test { function _test_Withdraw(uint256 streamId, IERC20 asset) internal { resetPrank({ msgSender: users.recipient }); - uint40 actualLastTimeUpdate = openEnded.getLastTimeUpdate(streamId); + uint40 actualLastTimeUpdate = flow.getLastTimeUpdate(streamId); uint40 expectedLastTimeUpdate = uint40(block.timestamp - ONE_MONTH); assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); vm.expectEmit({ emitter: address(asset) }); emit IERC20.Transfer({ - from: address(openEnded), + from: address(flow), to: users.recipient, value: normalizeAmountWithStreamId(streamId, WITHDRAW_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit WithdrawFromOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit WithdrawFromFlowStream({ streamId: streamId, to: users.recipient, asset: asset, @@ -346,13 +338,13 @@ contract WithdrawAt_Integration_Test is Integration_Test { to: users.recipient, amount: normalizeAmountWithStreamId(streamId, WITHDRAW_AMOUNT) }); - openEnded.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); + flow.withdrawAt({ streamId: streamId, to: users.recipient, time: WITHDRAW_TIME }); - actualLastTimeUpdate = openEnded.getLastTimeUpdate(streamId); + actualLastTimeUpdate = flow.getLastTimeUpdate(streamId); expectedLastTimeUpdate = WITHDRAW_TIME; assertEq(actualLastTimeUpdate, expectedLastTimeUpdate, "last time updated"); - uint128 actualStreamBalance = openEnded.getBalance(streamId); + uint128 actualStreamBalance = flow.getBalance(streamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - WITHDRAW_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); } diff --git a/test/integration/withdraw-at/withdrawAt.tree b/test/integration/withdraw-at/withdrawAt.tree index 13530985..7696e473 100644 --- a/test/integration/withdraw-at/withdrawAt.tree +++ b/test/integration/withdraw-at/withdrawAt.tree @@ -45,7 +45,7 @@ withdrawAt.t.sol │ ├── it should set the remaining amount to zero │ ├── it should update the stream balance │ ├── it should perform the ERC-20 transfer - │ ├── it should emit a {Transfer} and {WithdrawFromOpenEndedStream} event + │ ├── it should emit a {Transfer} and {WithdrawFromFlowStream} event │ └── it should emit a {MetadataUpdate} event └── given the asset has 18 decimals ├── it should make the withdrawal @@ -53,5 +53,5 @@ withdrawAt.t.sol ├── it should update the time ├── it should update the stream balance ├── it should perform the ERC-20 transfer - ├── it should emit a {Transfer} and {WithdrawFromOpenEndedStream} event + ├── it should emit a {Transfer} and {WithdrawFromFlowStream} event └── it should emit a {MetadataUpdate} event \ No newline at end of file diff --git a/test/integration/withdraw-max/withdrawMax.t.sol b/test/integration/withdraw-max/withdrawMax.t.sol index b143eb96..6aaeefdd 100644 --- a/test/integration/withdraw-max/withdrawMax.t.sol +++ b/test/integration/withdraw-max/withdrawMax.t.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.22; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { Integration_Test } from "../Integration.t.sol"; @@ -16,63 +16,63 @@ contract WithdrawMax_Integration_Concrete_Test is Integration_Test { } function test_RevertWhen_DelegateCall() external { - bytes memory callData = abi.encodeCall(ISablierV2OpenEnded.withdrawMax, (defaultStreamId, users.recipient)); + bytes memory callData = abi.encodeCall(ISablierFlow.withdrawMax, (defaultStreamId, users.recipient)); expectRevertDueToDelegateCall(callData); } function test_WithdrawMax_Paused() external { - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); vm.expectEmit({ emitter: address(dai) }); - emit IERC20.Transfer({ from: address(openEnded), to: users.recipient, value: ONE_MONTH_STREAMED_AMOUNT }); + emit IERC20.Transfer({ from: address(flow), to: users.recipient, value: ONE_MONTH_STREAMED_AMOUNT }); - vm.expectEmit({ emitter: address(openEnded) }); - emit WithdrawFromOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit WithdrawFromFlowStream({ streamId: defaultStreamId, to: users.recipient, asset: dai, withdrawnAmount: ONE_MONTH_STREAMED_AMOUNT }); - openEnded.withdrawMax(defaultStreamId, users.recipient); + flow.withdrawMax(defaultStreamId, users.recipient); - uint128 actualStreamBalance = openEnded.getBalance(defaultStreamId); + uint128 actualStreamBalance = flow.getBalance(defaultStreamId); uint128 expectedStreamBalance = DEPOSIT_AMOUNT - ONE_MONTH_STREAMED_AMOUNT; assertEq(actualStreamBalance, expectedStreamBalance, "stream balance"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualRemainingAmount, 0, "remaining amount"); - assertEq(openEnded.getLastTimeUpdate(defaultStreamId), WARP_ONE_MONTH, "last time update not updated"); + assertEq(flow.getLastTimeUpdate(defaultStreamId), WARP_ONE_MONTH, "last time update not updated"); } function test_WithdrawMax() external givenNotPaused { - uint128 beforeStreamBalance = openEnded.getBalance(defaultStreamId); - uint128 beforeRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 beforeStreamBalance = flow.getBalance(defaultStreamId); + uint128 beforeRemainingAmount = flow.getRemainingAmount(defaultStreamId); vm.expectEmit({ emitter: address(dai) }); emit IERC20.Transfer({ - from: address(openEnded), + from: address(flow), to: users.recipient, value: normalizeAmountWithStreamId(defaultStreamId, ONE_MONTH_STREAMED_AMOUNT) }); - vm.expectEmit({ emitter: address(openEnded) }); - emit WithdrawFromOpenEndedStream({ + vm.expectEmit({ emitter: address(flow) }); + emit WithdrawFromFlowStream({ streamId: defaultStreamId, to: users.recipient, asset: dai, withdrawnAmount: beforeRemainingAmount + ONE_MONTH_STREAMED_AMOUNT }); - openEnded.withdrawMax(defaultStreamId, users.recipient); + flow.withdrawMax(defaultStreamId, users.recipient); - uint128 afterStreamBalance = openEnded.getBalance(defaultStreamId); - uint128 afterRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 afterStreamBalance = flow.getBalance(defaultStreamId); + uint128 afterRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq( beforeStreamBalance - ONE_MONTH_STREAMED_AMOUNT, afterStreamBalance, "stream balance not updated correctly" ); assertEq(afterRemainingAmount, 0, "remaining amount should be 0"); - assertEq(openEnded.getLastTimeUpdate(defaultStreamId), WARP_ONE_MONTH, "last time update not updated"); + assertEq(flow.getLastTimeUpdate(defaultStreamId), WARP_ONE_MONTH, "last time update not updated"); } } diff --git a/test/integration/withdraw-max/withdrawMax.tree b/test/integration/withdraw-max/withdrawMax.tree index 9e8188ea..e841a8a0 100644 --- a/test/integration/withdraw-max/withdrawMax.tree +++ b/test/integration/withdraw-max/withdrawMax.tree @@ -10,5 +10,5 @@ withdrawMax.t.sol ├── it should set the remaining amount to zero ├── it should update the stream balance ├── it should perform the ERC-20 transfer - ├── it should emit a {Transfer} and {WithdrawFromOpenEndedStream} event + ├── it should emit a {Transfer} and {WithdrawFromFlowStream} event └── it should emit a {MetadataUpdated} event \ No newline at end of file diff --git a/test/integration/withdrawable-amount-of/withdrawableAmountOf.t.sol b/test/integration/withdrawable-amount-of/withdrawableAmountOf.t.sol index 00d8d281..9687c148 100644 --- a/test/integration/withdrawable-amount-of/withdrawableAmountOf.t.sol +++ b/test/integration/withdrawable-amount-of/withdrawableAmountOf.t.sol @@ -10,12 +10,12 @@ contract WithdrawableAmountOf_Integration_Test is Integration_Test { function test_RevertGiven_Null() external { expectRevertNull(); - openEnded.withdrawableAmountOf(nullStreamId); + flow.withdrawableAmountOf(nullStreamId); } function test_WithdrawableAmountOf_BalanceZero() external view givenNotNull givenBalanceZero { - assertEq(openEnded.getBalance(defaultStreamId), 0, "stream balance"); - assertEq(openEnded.withdrawableAmountOf(defaultStreamId), 0, "withdrawable amount"); + assertEq(flow.getBalance(defaultStreamId), 0, "stream balance"); + assertEq(flow.withdrawableAmountOf(defaultStreamId), 0, "withdrawable amount"); } function test_WithdrawableAmountOf_BalanceLessThanRemainingAmount() external givenNotNull givenBalanceNotZero { @@ -24,16 +24,16 @@ contract WithdrawableAmountOf_Integration_Test is Integration_Test { // Deposit half of the streamed amount. uint128 depositAmount = ONE_MONTH_STREAMED_AMOUNT / 2; - openEnded.deposit(defaultStreamId, depositAmount); + flow.deposit(defaultStreamId, depositAmount); // Adjust the rate per second so that the remaining amount is updated. - openEnded.adjustRatePerSecond(defaultStreamId, RATE_PER_SECOND / 2); + flow.adjustRatePerSecond(defaultStreamId, RATE_PER_SECOND / 2); - uint128 actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); + uint128 actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); uint128 expectedWithdrawableAmount = depositAmount; assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); } @@ -46,14 +46,14 @@ contract WithdrawableAmountOf_Integration_Test is Integration_Test { vm.warp({ newTimestamp: WARP_ONE_MONTH }); // Pause the stream. - openEnded.pause(defaultStreamId); + flow.pause(defaultStreamId); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - uint128 actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); - uint128 expectedWithdrawableAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); + uint128 expectedWithdrawableAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); } @@ -63,26 +63,26 @@ contract WithdrawableAmountOf_Integration_Test is Integration_Test { // Deposit some funds. uint128 depositAmount = ONE_MONTH_STREAMED_AMOUNT + 100e18; - openEnded.deposit(defaultStreamId, depositAmount); + flow.deposit(defaultStreamId, depositAmount); // Adjust the rate per second so that the remaining amount is updated. - openEnded.adjustRatePerSecond(defaultStreamId, RATE_PER_SECOND * 2); + flow.adjustRatePerSecond(defaultStreamId, RATE_PER_SECOND * 2); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - uint128 actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); + uint128 actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); uint128 expectedWithdrawableAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); // Simulate passage of time. vm.warp({ newTimestamp: WARP_ONE_MONTH + 2 weeks }); - actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); + actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); expectedWithdrawableAmount = depositAmount; assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); } @@ -96,26 +96,26 @@ contract WithdrawableAmountOf_Integration_Test is Integration_Test { uint128 newRatePerSecond = RATE_PER_SECOND * 2; // Adjust the rate per second so that the remaining amount is updated. - openEnded.adjustRatePerSecond(defaultStreamId, newRatePerSecond); + flow.adjustRatePerSecond(defaultStreamId, newRatePerSecond); - uint128 actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + uint128 actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); uint128 expectedRemainingAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); - uint128 actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); + uint128 actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); uint128 expectedWithdrawableAmount = ONE_MONTH_STREAMED_AMOUNT; assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); // Simulate passage of time. vm.warp({ newTimestamp: WARP_ONE_MONTH + 2 weeks }); - actualRemainingAmount = openEnded.getRemainingAmount(defaultStreamId); + actualRemainingAmount = flow.getRemainingAmount(defaultStreamId); assertEq(actualRemainingAmount, expectedRemainingAmount, "remaining amount"); // The withdrawable amount should be the calculated streamed amount since the adjustment moment (2 weeks in the // past to know) and the remaining amount which was updated to `ONE_MONTH_STREAMED_AMOUNT`. - actualWithdrawableAmount = openEnded.withdrawableAmountOf(defaultStreamId); - expectedWithdrawableAmount = openEnded.streamedAmountOf(defaultStreamId) + ONE_MONTH_STREAMED_AMOUNT; + actualWithdrawableAmount = flow.withdrawableAmountOf(defaultStreamId); + expectedWithdrawableAmount = flow.streamedAmountOf(defaultStreamId) + ONE_MONTH_STREAMED_AMOUNT; assertEq(actualWithdrawableAmount, expectedWithdrawableAmount, "withdrawable amount"); } diff --git a/test/invariant/OpenEnded.t.sol b/test/invariant/Flow.t.sol similarity index 52% rename from test/invariant/OpenEnded.t.sol rename to test/invariant/Flow.t.sol index 55d81bd4..fbb53b1b 100644 --- a/test/invariant/OpenEnded.t.sol +++ b/test/invariant/Flow.t.sol @@ -2,19 +2,19 @@ pragma solidity >=0.8.22 <0.9.0; import { Invariant_Test } from "./Invariant.t.sol"; -import { OpenEndedHandler } from "./handlers/OpenEndedHandler.sol"; -import { OpenEndedCreateHandler } from "./handlers/OpenEndedCreateHandler.sol"; -import { OpenEndedStore } from "./stores/OpenEndedStore.sol"; +import { FlowHandler } from "./handlers/FlowHandler.sol"; +import { FlowCreateHandler } from "./handlers/FlowCreateHandler.sol"; +import { FlowStore } from "./stores/FlowStore.sol"; -/// @notice Common invariant test logic needed across contracts that inherit from {SablierV2openEnded}. -contract OpenEnded_Invariant_Test is Invariant_Test { +/// @notice Common invariant test logic needed across contracts that inherit from {SablierFlow}. +contract Flow_Invariant_Test is Invariant_Test { /*////////////////////////////////////////////////////////////////////////// TEST CONTRACTS //////////////////////////////////////////////////////////////////////////*/ - OpenEndedHandler internal openEndedHandler; - OpenEndedCreateHandler internal openEndedCreateHandler; - OpenEndedStore internal openEndedStore; + FlowHandler internal flowHandler; + FlowCreateHandler internal flowCreateHandler; + FlowStore internal flowStore; /*////////////////////////////////////////////////////////////////////////// SET-UP FUNCTION @@ -23,36 +23,28 @@ contract OpenEnded_Invariant_Test is Invariant_Test { function setUp() public virtual override { Invariant_Test.setUp(); - // Deploy and the OpenEndedStore contract. - openEndedStore = new OpenEndedStore(); + // Deploy and the FlowStore contract. + flowStore = new FlowStore(); // Deploy the handlers. - openEndedHandler = new OpenEndedHandler({ - asset_: dai, - timestampStore_: timestampStore, - openEndedStore_: openEndedStore, - openEnded_: openEnded - }); - openEndedCreateHandler = new OpenEndedCreateHandler({ - asset_: dai, - timestampStore_: timestampStore, - openEndedStore_: openEndedStore, - openEnded_: openEnded - }); + flowHandler = + new FlowHandler({ asset_: dai, timestampStore_: timestampStore, flowStore_: flowStore, flow_: flow }); + flowCreateHandler = + new FlowCreateHandler({ asset_: dai, timestampStore_: timestampStore, flowStore_: flowStore, flow_: flow }); // Label the contracts. - vm.label({ account: address(openEndedStore), newLabel: "openEndedStore" }); - vm.label({ account: address(openEndedHandler), newLabel: "openEndedHandler" }); - vm.label({ account: address(openEndedCreateHandler), newLabel: "openEndedCreateHandler" }); + vm.label({ account: address(flowStore), newLabel: "flowStore" }); + vm.label({ account: address(flowHandler), newLabel: "flowHandler" }); + vm.label({ account: address(flowCreateHandler), newLabel: "flowCreateHandler" }); - // Target the openEnded handlers for invariant testing. - targetContract(address(openEndedHandler)); - targetContract(address(openEndedCreateHandler)); + // Target the flow handlers for invariant testing. + targetContract(address(flowHandler)); + targetContract(address(flowCreateHandler)); // Prevent these contracts from being fuzzed as `msg.sender`. - excludeSender(address(openEndedStore)); - excludeSender(address(openEndedHandler)); - excludeSender(address(openEndedCreateHandler)); + excludeSender(address(flowStore)); + excludeSender(address(flowHandler)); + excludeSender(address(flowCreateHandler)); } /*////////////////////////////////////////////////////////////////////////// @@ -60,12 +52,12 @@ contract OpenEnded_Invariant_Test is Invariant_Test { //////////////////////////////////////////////////////////////////////////*/ function invariant_BlockTimestampGeLastTimeUpdate() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); + uint256 streamId = flowStore.streamIds(i); assertGe( uint40(block.timestamp), - openEnded.getLastTimeUpdate(streamId), + flow.getLastTimeUpdate(streamId), "Invariant violation: block timestamp < last time update" ); } @@ -74,12 +66,12 @@ contract OpenEnded_Invariant_Test is Invariant_Test { /// @dev The sum of all stream balances for a specific asset should be less than or equal to the contract /// `ERC20.balanceOf`. function invariant_ContractBalanceGeStreamBalances() external useCurrentTimestamp { - uint256 contractBalance = dai.balanceOf(address(openEnded)); + uint256 contractBalance = dai.balanceOf(address(flow)); - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); uint256 streamBalancesSumNormalized; for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); + uint256 streamId = flowStore.streamIds(i); streamBalancesSumNormalized += uint256(normalizeStreamBalance(streamId)); } @@ -91,13 +83,13 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_Debt_WithdrawableAmountEqBalance() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); - if (openEnded.streamDebtOf(streamId) > 0) { + uint256 streamId = flowStore.streamIds(i); + if (flow.streamDebtOf(streamId) > 0) { assertEq( - openEnded.withdrawableAmountOf(streamId), - openEnded.getBalance(streamId), + flow.withdrawableAmountOf(streamId), + flow.getBalance(streamId), "Invariant violation: withdrawable amount != balance" ); } @@ -105,8 +97,8 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_DepositAmountsSumGeExtractedAmountsSum() external useCurrentTimestamp { - uint256 streamDepositedAmountsSum = openEndedStore.streamDepositedAmountsSum(); - uint256 streamExtractedAmountsSum = openEndedStore.streamExtractedAmountsSum(); + uint256 streamDepositedAmountsSum = flowStore.streamDepositedAmountsSum(); + uint256 streamExtractedAmountsSum = flowStore.streamExtractedAmountsSum(); assertGe( streamDepositedAmountsSum, @@ -116,19 +108,19 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_DepositedAmountsSumGeExtractedAmountsSum() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); + uint256 streamId = flowStore.streamIds(i); assertGe( - openEndedStore.depositedAmounts(streamId), - openEndedStore.extractedAmounts(streamId), + flowStore.depositedAmounts(streamId), + flowStore.extractedAmounts(streamId), "Invariant violation: deposited amount < extracted amount" ); } - uint256 streamDepositedAmountsSum = openEndedStore.streamDepositedAmountsSum(); - uint256 streamExtractedAmountsSum = openEndedStore.streamExtractedAmountsSum(); + uint256 streamDepositedAmountsSum = flowStore.streamDepositedAmountsSum(); + uint256 streamExtractedAmountsSum = flowStore.streamExtractedAmountsSum(); assertGe( streamDepositedAmountsSum, @@ -138,21 +130,21 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_NextStreamId() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 nextStreamId = openEnded.nextStreamId(); + uint256 nextStreamId = flow.nextStreamId(); assertEq(nextStreamId, lastStreamId + 1, "Invariant violation: next stream id not incremented"); } } function invariant_NoDebt_StreamedPaused_WithdrawableAmountEqRemainingAmount() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); - if (openEnded.isPaused(streamId) && openEnded.streamDebtOf(streamId) == 0) { + uint256 streamId = flowStore.streamIds(i); + if (flow.isPaused(streamId) && flow.streamDebtOf(streamId) == 0) { assertEq( - openEnded.withdrawableAmountOf(streamId), - openEnded.getRemainingAmount(streamId), + flow.withdrawableAmountOf(streamId), + flow.getRemainingAmount(streamId), "Invariant violation: paused stream withdrawable amount != remaining amount" ); } @@ -160,13 +152,13 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_NoDebt_WithdrawableAmountEqStreamedAmountPlusRemainingAmount() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); - if (!openEnded.isPaused(streamId) && openEnded.streamDebtOf(streamId) == 0) { + uint256 streamId = flowStore.streamIds(i); + if (!flow.isPaused(streamId) && flow.streamDebtOf(streamId) == 0) { assertEq( - openEnded.withdrawableAmountOf(streamId), - openEnded.streamedAmountOf(streamId) + openEnded.getRemainingAmount(streamId), + flow.withdrawableAmountOf(streamId), + flow.streamedAmountOf(streamId) + flow.getRemainingAmount(streamId), "Invariant violation: withdrawable amount != streamed amount + remaining amount" ); } @@ -174,25 +166,25 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_StreamBalanceEqWithdrawableAmountPlusRefundableAmount() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); + uint256 streamId = flowStore.streamIds(i); assertEq( - openEnded.getBalance(streamId), - openEnded.withdrawableAmountOf(streamId) + openEnded.refundableAmountOf(streamId), + flow.getBalance(streamId), + flow.withdrawableAmountOf(streamId) + flow.refundableAmountOf(streamId), "Invariant violation: stream balance != withdrawable amount + refundable amount" ); } } function invariant_StreamBalanceGeRefundableAmount() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); - if (!openEnded.isPaused(streamId)) { + uint256 streamId = flowStore.streamIds(i); + if (!flow.isPaused(streamId)) { assertGe( - openEnded.getBalance(streamId), - openEnded.refundableAmountOf(streamId), + flow.getBalance(streamId), + flow.refundableAmountOf(streamId), "Invariant violation: stream balance < refundable amount" ); } @@ -200,25 +192,25 @@ contract OpenEnded_Invariant_Test is Invariant_Test { } function invariant_StreamBalanceGeWithdrawableAmount() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); + uint256 streamId = flowStore.streamIds(i); assertGe( - openEnded.getBalance(streamId), - openEnded.withdrawableAmountOf(streamId), + flow.getBalance(streamId), + flow.withdrawableAmountOf(streamId), "Invariant violation: withdrawable amount <= balance" ); } } function invariant_StreamPaused_RatePerSecondZero() external useCurrentTimestamp { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); for (uint256 i = 0; i < lastStreamId; ++i) { - uint256 streamId = openEndedStore.streamIds(i); - if (openEnded.isPaused(streamId)) { + uint256 streamId = flowStore.streamIds(i); + if (flow.isPaused(streamId)) { assertEq( - openEnded.getRatePerSecond(streamId), + flow.getRatePerSecond(streamId), 0, "Invariant violation: paused stream with a non-zero rate per second" ); diff --git a/test/invariant/Invariant.t.sol b/test/invariant/Invariant.t.sol index 2f5b74e5..a3355fb9 100644 --- a/test/invariant/Invariant.t.sol +++ b/test/invariant/Invariant.t.sol @@ -35,7 +35,7 @@ abstract contract Invariant_Test is Base_Test { vm.label({ account: address(timestampStore), newLabel: "TimestampStore" }); // Prevent these contracts from being fuzzed as `msg.sender`. - excludeSender(address(openEnded)); + excludeSender(address(flow)); excludeSender(address(timestampStore)); } } diff --git a/test/invariant/handlers/OpenEndedCreateHandler.sol b/test/invariant/handlers/FlowCreateHandler.sol similarity index 68% rename from test/invariant/handlers/OpenEndedCreateHandler.sol rename to test/invariant/handlers/FlowCreateHandler.sol index c9266379..25bc1d14 100644 --- a/test/invariant/handlers/OpenEndedCreateHandler.sol +++ b/test/invariant/handlers/FlowCreateHandler.sol @@ -3,22 +3,22 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; -import { OpenEndedStore } from "../stores/OpenEndedStore.sol"; +import { FlowStore } from "../stores/FlowStore.sol"; import { TimestampStore } from "../stores/TimestampStore.sol"; import { BaseHandler } from "./BaseHandler.sol"; -/// @dev This contract is a complement of {OpenEndedHandler}. The goal is to bias the invariant calls -/// toward the openEnded functions (especially the create stream functions) by creating multiple handlers for +/// @dev This contract is a complement of {FlowHandler}. The goal is to bias the invariant calls +/// toward the flow functions (especially the create stream functions) by creating multiple handlers for /// the contracts. -contract OpenEndedCreateHandler is BaseHandler { +contract FlowCreateHandler is BaseHandler { /*////////////////////////////////////////////////////////////////////////// TEST CONTRACTS //////////////////////////////////////////////////////////////////////////*/ - ISablierV2OpenEnded public openEnded; - OpenEndedStore public openEndedStore; + ISablierFlow public flow; + FlowStore public flowStore; /*////////////////////////////////////////////////////////////////////////// CONSTRUCTOR @@ -27,13 +27,13 @@ contract OpenEndedCreateHandler is BaseHandler { constructor( IERC20 asset_, TimestampStore timestampStore_, - OpenEndedStore openEndedStore_, - ISablierV2OpenEnded openEnded_ + FlowStore flowStore_, + ISablierFlow flow_ ) BaseHandler(asset_, timestampStore_) { - openEndedStore = openEndedStore_; - openEnded = openEnded_; + flowStore = flowStore_; + flow = flow_; } /*////////////////////////////////////////////////////////////////////////// @@ -57,7 +57,7 @@ contract OpenEndedCreateHandler is BaseHandler { useNewSender(params.sender) { // We don't want to create more than a certain number of streams. - if (openEndedStore.lastStreamId() >= MAX_STREAM_COUNT) { + if (flowStore.lastStreamId() >= MAX_STREAM_COUNT) { return; } @@ -67,10 +67,10 @@ contract OpenEndedCreateHandler is BaseHandler { // Create the stream. asset = asset; uint256 streamId = - openEnded.create(params.sender, params.recipient, params.ratePerSecond, asset, params.isTransferable); + flow.create(params.sender, params.recipient, params.ratePerSecond, asset, params.isTransferable); // Store the stream id. - openEndedStore.pushStreamId(streamId, params.sender, params.recipient); + flowStore.pushStreamId(streamId, params.sender, params.recipient); } function createAndDeposit( @@ -84,7 +84,7 @@ contract OpenEndedCreateHandler is BaseHandler { useNewSender(params.sender) { // We don't want to create more than a certain number of streams. - if (openEndedStore.lastStreamId() >= MAX_STREAM_COUNT) { + if (flowStore.lastStreamId() >= MAX_STREAM_COUNT) { return; } @@ -95,18 +95,18 @@ contract OpenEndedCreateHandler is BaseHandler { // Mint enough assets to the Sender. deal({ token: address(asset), to: params.sender, give: asset.balanceOf(params.sender) + depositAmount }); - // Approve {SablierV2OpenEnded} to spend the assets. - asset.approve({ spender: address(openEnded), value: depositAmount }); + // Approve {SablierFlow} to spend the assets. + asset.approve({ spender: address(flow), value: depositAmount }); // Create the stream. - uint256 streamId = openEnded.createAndDeposit( + uint256 streamId = flow.createAndDeposit( params.sender, params.recipient, params.ratePerSecond, asset, params.isTransferable, depositAmount ); // Store the stream id. - openEndedStore.pushStreamId(streamId, params.sender, params.recipient); + flowStore.pushStreamId(streamId, params.sender, params.recipient); // Store the deposited amount. - openEndedStore.updateStreamDepositedAmountsSum(streamId, depositAmount); + flowStore.updateStreamDepositedAmountsSum(streamId, depositAmount); } } diff --git a/test/invariant/handlers/OpenEndedHandler.sol b/test/invariant/handlers/FlowHandler.sol similarity index 70% rename from test/invariant/handlers/OpenEndedHandler.sol rename to test/invariant/handlers/FlowHandler.sol index cb652a54..54cb11aa 100644 --- a/test/invariant/handlers/OpenEndedHandler.sol +++ b/test/invariant/handlers/FlowHandler.sol @@ -3,19 +3,19 @@ pragma solidity >=0.8.22 <0.9.0; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import { ISablierV2OpenEnded } from "src/interfaces/ISablierV2OpenEnded.sol"; +import { ISablierFlow } from "src/interfaces/ISablierFlow.sol"; -import { OpenEndedStore } from "../stores/OpenEndedStore.sol"; +import { FlowStore } from "../stores/FlowStore.sol"; import { TimestampStore } from "../stores/TimestampStore.sol"; import { BaseHandler } from "./BaseHandler.sol"; -contract OpenEndedHandler is BaseHandler { +contract FlowHandler is BaseHandler { /*////////////////////////////////////////////////////////////////////////// TEST CONTRACTS //////////////////////////////////////////////////////////////////////////*/ - ISablierV2OpenEnded public openEnded; - OpenEndedStore public openEndedStore; + ISablierFlow public flow; + FlowStore public flowStore; /*////////////////////////////////////////////////////////////////////////// VARIABLES @@ -32,13 +32,13 @@ contract OpenEndedHandler is BaseHandler { constructor( IERC20 asset_, TimestampStore timestampStore_, - OpenEndedStore openEndedStore_, - ISablierV2OpenEnded openEnded_ + FlowStore flowStore_, + ISablierFlow flow_ ) BaseHandler(asset_, timestampStore_) { - openEndedStore = openEndedStore_; - openEnded = openEnded_; + flowStore = flowStore_; + flow = flow_; } /*////////////////////////////////////////////////////////////////////////// @@ -48,31 +48,31 @@ contract OpenEndedHandler is BaseHandler { /// @dev Picks a random stream from the store. /// @param streamIndexSeed A fuzzed value needed for picking the random stream. modifier useFuzzedStream(uint256 streamIndexSeed) { - uint256 lastStreamId = openEndedStore.lastStreamId(); + uint256 lastStreamId = flowStore.lastStreamId(); if (lastStreamId == 0) { return; } uint256 fuzzedStreamId = _bound(streamIndexSeed, 0, lastStreamId - 1); - currentStreamId = openEndedStore.streamIds(fuzzedStreamId); + currentStreamId = flowStore.streamIds(fuzzedStreamId); _; } modifier useFuzzedStreamRecipient() { - uint256 lastStreamId = openEndedStore.lastStreamId(); - currentRecipient = openEndedStore.recipients(currentStreamId); + uint256 lastStreamId = flowStore.lastStreamId(); + currentRecipient = flowStore.recipients(currentStreamId); resetPrank(currentRecipient); _; } modifier useFuzzedStreamSender() { - uint256 lastStreamId = openEndedStore.lastStreamId(); - currentSender = openEndedStore.senders(currentStreamId); + uint256 lastStreamId = flowStore.lastStreamId(); + currentSender = flowStore.senders(currentStreamId); resetPrank(currentSender); _; } /*////////////////////////////////////////////////////////////////////////// - SABLIER-V2-OPENENDED + SABLIER-FLOW //////////////////////////////////////////////////////////////////////////*/ function adjustRatePerSecond( @@ -87,7 +87,7 @@ contract OpenEndedHandler is BaseHandler { useFuzzedStreamSender { // Only non paused streams can have their rate per second adjusted. - if (openEnded.isPaused(currentStreamId)) { + if (flow.isPaused(currentStreamId)) { return; } @@ -95,12 +95,12 @@ contract OpenEndedHandler is BaseHandler { newRatePerSecond = uint128(_bound(newRatePerSecond, 0.0001e18, 1e18)); // The rate per second must be different from the current rate per second. - if (newRatePerSecond == openEnded.getRatePerSecond(currentStreamId)) { + if (newRatePerSecond == flow.getRatePerSecond(currentStreamId)) { newRatePerSecond += 1; } // Adjust the rate per second. - openEnded.adjustRatePerSecond(currentStreamId, newRatePerSecond); + flow.adjustRatePerSecond(currentStreamId, newRatePerSecond); } function pause( @@ -114,12 +114,12 @@ contract OpenEndedHandler is BaseHandler { useFuzzedStreamSender { // Paused streams cannot be paused again. - if (openEnded.isPaused(currentStreamId)) { + if (flow.isPaused(currentStreamId)) { return; } // Pause the stream. - openEnded.pause(currentStreamId); + flow.pause(currentStreamId); } function deposit( @@ -135,17 +135,17 @@ contract OpenEndedHandler is BaseHandler { depositAmount = uint128(_bound(depositAmount, 100e18, 1_000_000_000e18)); // Mint enough assets to the Sender. - address sender = openEndedStore.senders(currentStreamId); + address sender = flowStore.senders(currentStreamId); deal({ token: address(asset), to: sender, give: asset.balanceOf(sender) + depositAmount }); - // Approve {SablierV2OpenEnded} to spend the assets. - asset.approve({ spender: address(openEnded), value: depositAmount }); + // Approve {SablierFlow} to spend the assets. + asset.approve({ spender: address(flow), value: depositAmount }); // Deposit into the stream. - openEnded.deposit({ streamId: currentStreamId, amount: depositAmount }); + flow.deposit({ streamId: currentStreamId, amount: depositAmount }); // Store the deposited amount. - openEndedStore.updateStreamDepositedAmountsSum(currentStreamId, depositAmount); + flowStore.updateStreamDepositedAmountsSum(currentStreamId, depositAmount); } function refundFromStream( @@ -160,7 +160,7 @@ contract OpenEndedHandler is BaseHandler { useFuzzedStreamSender { // The protocol doesn't allow zero refund amounts. - uint128 refundableAmount = openEnded.refundableAmountOf(currentStreamId); + uint128 refundableAmount = flow.refundableAmountOf(currentStreamId); if (refundableAmount == 0) { return; } @@ -169,10 +169,10 @@ contract OpenEndedHandler is BaseHandler { refundAmount = uint128(_bound(refundAmount, 1, refundableAmount)); // Refund from stream. - openEnded.refundFromStream(currentStreamId, refundableAmount); + flow.refundFromStream(currentStreamId, refundableAmount); // Store the deposited amount. - openEndedStore.updateStreamExtractedAmountsSum(currentStreamId, refundAmount); + flowStore.updateStreamExtractedAmountsSum(currentStreamId, refundAmount); } function restartStream( @@ -187,7 +187,7 @@ contract OpenEndedHandler is BaseHandler { useFuzzedStreamSender { // Only paused streams can be restarted. - if (!openEnded.isPaused(currentStreamId)) { + if (!flow.isPaused(currentStreamId)) { return; } @@ -195,7 +195,7 @@ contract OpenEndedHandler is BaseHandler { ratePerSecond = uint128(_bound(ratePerSecond, 0.0001e18, 1e18)); // Restart the stream. - openEnded.restartStream(currentStreamId, ratePerSecond); + flow.restartStream(currentStreamId, ratePerSecond); } function restartStreamAndDeposit( @@ -211,7 +211,7 @@ contract OpenEndedHandler is BaseHandler { useFuzzedStreamSender { // Only paused streams can be restarted. - if (!openEnded.isPaused(currentStreamId)) { + if (!flow.isPaused(currentStreamId)) { return; } @@ -220,17 +220,17 @@ contract OpenEndedHandler is BaseHandler { depositAmount = uint128(_bound(depositAmount, 100e18, 1_000_000_000e18)); // Mint enough assets to the Sender. - address sender = openEndedStore.senders(currentStreamId); + address sender = flowStore.senders(currentStreamId); deal({ token: address(asset), to: sender, give: asset.balanceOf(sender) + depositAmount }); - // Approve {SablierV2OpenEnded} to spend the assets. - asset.approve({ spender: address(openEnded), value: depositAmount }); + // Approve {SablierFlow} to spend the assets. + asset.approve({ spender: address(flow), value: depositAmount }); // Restart the stream. - openEnded.restartStreamAndDeposit(currentStreamId, ratePerSecond, depositAmount); + flow.restartStreamAndDeposit(currentStreamId, ratePerSecond, depositAmount); // Store the deposited amount. - openEndedStore.updateStreamDepositedAmountsSum(currentStreamId, depositAmount); + flowStore.updateStreamDepositedAmountsSum(currentStreamId, depositAmount); } function withdrawAt( @@ -251,26 +251,26 @@ contract OpenEndedHandler is BaseHandler { } // If the balance and the remaining amount are zero, there is nothing to withdraw. - if (openEnded.getBalance(currentStreamId) == 0 && openEnded.getRemainingAmount(currentStreamId) == 0) { + if (flow.getBalance(currentStreamId) == 0 && flow.getRemainingAmount(currentStreamId) == 0) { return; } // Bound the time so that it is between last time update and current time. - time = uint40(_bound(time, openEnded.getLastTimeUpdate(currentStreamId), block.timestamp)); + time = uint40(_bound(time, flow.getLastTimeUpdate(currentStreamId), block.timestamp)); // There is an edge case when the sender is the same as the recipient. In this scenario, the withdrawal // address must be set to the recipient. - address sender = openEndedStore.senders(currentStreamId); + address sender = flowStore.senders(currentStreamId); if (sender == currentRecipient && to != currentRecipient) { to = currentRecipient; } - uint128 withdrawAmount = openEnded.withdrawableAmountOf(currentStreamId, time); + uint128 withdrawAmount = flow.withdrawableAmountOf(currentStreamId, time); // Withdraw from the stream. - openEnded.withdrawAt({ streamId: currentStreamId, to: to, time: time }); + flow.withdrawAt({ streamId: currentStreamId, to: to, time: time }); // Store the extracted amount. - openEndedStore.updateStreamExtractedAmountsSum(currentStreamId, withdrawAmount); + flowStore.updateStreamExtractedAmountsSum(currentStreamId, withdrawAmount); } } diff --git a/test/invariant/stores/OpenEndedStore.sol b/test/invariant/stores/FlowStore.sol similarity index 98% rename from test/invariant/stores/OpenEndedStore.sol rename to test/invariant/stores/FlowStore.sol index 41387823..df9e5c04 100644 --- a/test/invariant/stores/OpenEndedStore.sol +++ b/test/invariant/stores/FlowStore.sol @@ -2,7 +2,7 @@ pragma solidity >=0.8.22 <0.9.0; /// @dev Storage variables needed for handlers. -contract OpenEndedStore { +contract FlowStore { /*////////////////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////////////////*/ diff --git a/test/utils/Assertions.sol b/test/utils/Assertions.sol index 1ea43fb1..5284db6f 100644 --- a/test/utils/Assertions.sol +++ b/test/utils/Assertions.sol @@ -3,7 +3,7 @@ pragma solidity >=0.8.22; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { PRBMathAssertions } from "@prb/math/test/utils/Assertions.sol"; -import { OpenEnded } from "src/types/DataTypes.sol"; +import { Flow } from "src/types/DataTypes.sol"; abstract contract Assertions is PRBMathAssertions { /*////////////////////////////////////////////////////////////////////////// @@ -20,8 +20,8 @@ abstract contract Assertions is PRBMathAssertions { assertEq(address(a), address(b), err); } - /// @dev Compares two {OpenEnded.Stream} struct entities. - function assertEq(OpenEnded.Stream memory a, OpenEnded.Stream memory b) internal pure { + /// @dev Compares two {Flow.Stream} struct entities. + function assertEq(Flow.Stream memory a, Flow.Stream memory b) internal pure { assertEq(a.ratePerSecond, b.ratePerSecond, "ratePerSecond"); assertEq(a.asset, b.asset, "asset"); assertEq(a.assetDecimals, b.assetDecimals, "assetDecimals"); diff --git a/test/utils/Events.sol b/test/utils/Events.sol index 93dfc619..ea5930fb 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -17,14 +17,14 @@ abstract contract Events { event MetadataUpdate(uint256 _tokenId); /*////////////////////////////////////////////////////////////////////////// - OPEN-ENDED + SABLIER-FLOW //////////////////////////////////////////////////////////////////////////*/ - event AdjustOpenEndedStream( + event AdjustFlowStream( uint256 indexed streamId, uint128 recipientAmount, uint128 oldRatePerSecond, uint128 newRatePerSecond ); - event PauseOpenEndedStream( + event PauseFlowStream( uint256 streamId, address indexed sender, address indexed recipient, @@ -32,7 +32,7 @@ abstract contract Events { uint128 recipientAmount ); - event CreateOpenEndedStream( + event CreateFlowStream( uint256 streamId, address indexed sender, address indexed recipient, @@ -41,19 +41,19 @@ abstract contract Events { uint40 lastTimeUpdate ); - event DepositOpenEndedStream( + event DepositFlowStream( uint256 indexed streamId, address indexed funder, IERC20 indexed asset, uint128 depositAmount ); - event RefundFromOpenEndedStream( + event RefundFromFlowStream( uint256 indexed streamId, address indexed sender, IERC20 indexed asset, uint128 refundAmount ); - event RestartOpenEndedStream( + event RestartFlowStream( uint256 indexed streamId, address indexed sender, IERC20 indexed asset, uint128 ratePerSecond ); - event WithdrawFromOpenEndedStream( + event WithdrawFromFlowStream( uint256 indexed streamId, address indexed to, IERC20 indexed asset, uint128 withdrawnAmount ); } diff --git a/test/utils/Precompiles.t.sol b/test/utils/Precompiles.t.sol index b0e83058..103e63ca 100644 --- a/test/utils/Precompiles.t.sol +++ b/test/utils/Precompiles.t.sol @@ -18,14 +18,14 @@ contract Precompiles_Test is Base_Test { } } - function test_DeployOpenEnded() external onlyTestOptimizedProfile { - address actualOpenEnded = address(precompiles.deployOpenEnded()); - address expectedOpenEnded = address(deployOptimizedOpenEnded()); - bytes memory expectedOpenEndedCode = adjustBytecode(expectedOpenEnded.code, expectedOpenEnded, actualOpenEnded); - assertEq(actualOpenEnded.code, expectedOpenEndedCode, "bytecodes mismatch"); + function test_DeployFlow() external onlyTestOptimizedProfile { + address actualFlow = address(precompiles.deployFlow()); + address expectedFlow = address(deployOptimizedFlow()); + bytes memory expectedFlowCode = adjustBytecode(expectedFlow.code, expectedFlow, actualFlow); + assertEq(actualFlow.code, expectedFlowCode, "bytecodes mismatch"); } - /// @dev The expected bytecode has to be adjusted because {SablierV2OpenEnded} inherits from {NoDelegateCall}, which + /// @dev The expected bytecode has to be adjusted because {SablierFlow} inherits from {NoDelegateCall}, which /// saves the contract's own address in storage. function adjustBytecode( bytes memory bytecode,