diff --git a/script/Base.s.sol b/script/Base.s.sol index 8c941cc..7278470 100644 --- a/script/Base.s.sol +++ b/script/Base.s.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -pragma solidity ^0.8.20; +pragma solidity ^0.8.22; import { Script } from "forge-std/Script.sol"; diff --git a/script/DeployDeterministicInvoiceModule.s.sol b/script/DeployDeterministicInvoiceModule.s.sol index a8d3081..6ff7639 100644 --- a/script/DeployDeterministicInvoiceModule.s.sol +++ b/script/DeployDeterministicInvoiceModule.s.sol @@ -21,7 +21,11 @@ contract DeployDeterministicInvoiceModule is BaseScript { bytes32 salt = bytes32(abi.encodePacked(create2Salt)); // Deterministically deploy the {InvoiceModule} contracts - invoiceModule = - new InvoiceModule{ salt: salt }(sablierLockupLinear, sablierLockupTranched, brokerAdmin, baseURI); + invoiceModule = new InvoiceModule{ salt: salt }( + sablierLockupLinear, + sablierLockupTranched, + brokerAdmin, + baseURI + ); } } diff --git a/src/ModuleKeeper.sol b/src/ModuleKeeper.sol index a794e6d..fda2c70 100644 --- a/src/ModuleKeeper.sol +++ b/src/ModuleKeeper.sol @@ -20,7 +20,7 @@ contract ModuleKeeper is IModuleKeeper, Ownable { //////////////////////////////////////////////////////////////////////////*/ /// @dev Initializes the initial owner of the {ModuleKeeper} - constructor(address _initialOwner) Ownable(_initialOwner) { } + constructor(address _initialOwner) Ownable(_initialOwner) {} /*////////////////////////////////////////////////////////////////////////// NON-CONSTANT FUNCTIONS diff --git a/src/Space.sol b/src/Space.sol index a97833e..16aaa56 100644 --- a/src/Space.sol +++ b/src/Space.sol @@ -37,11 +37,11 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { //////////////////////////////////////////////////////////////////////////*/ /// @dev Initializes the address of the EIP 4337 factory and EntryPoint contract - constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) { } + constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) {} /// @notice Initializes the {ModuleKeeper}, enables initial modules and configures the {Space} smart account function initialize(address _defaultAdmin, bytes calldata _data) public override { - (,, address[] memory initialModules) = abi.decode(_data, (uint256, uint256, address[])); + (, , address[] memory initialModules) = abi.decode(_data, (uint256, uint256, address[])); // Enable the initial module(s) ModuleKeeper moduleKeeper = StationRegistry(factory).moduleKeeper(); @@ -153,9 +153,21 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { // therefore the `onERC1155Received` hook must be implemented // - depending on the length of the `ids` array, we're using `safeBatchTransferFrom` or `safeTransferFrom` if (ids.length > 1) { - collection.safeBatchTransferFrom({ from: address(this), to: msg.sender, ids: ids, values: amounts, data: "" }); + collection.safeBatchTransferFrom({ + from: address(this), + to: msg.sender, + ids: ids, + values: amounts, + data: "" + }); } else { - collection.safeTransferFrom({ from: address(this), to: msg.sender, id: ids[0], value: amounts[0], data: "" }); + collection.safeTransferFrom({ + from: address(this), + to: msg.sender, + id: ids[0], + value: amounts[0], + data: "" + }); } // Log the successful ERC-1155 token withdrawal @@ -163,14 +175,12 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { } /// @inheritdoc ISpace - function withdrawNative( - uint256 amount - ) public onlyAdminOrEntrypoint { + function withdrawNative(uint256 amount) public onlyAdminOrEntrypoint { // Checks: the native balance of the space minus the amount locked for operations is greater than the requested amount if (amount > address(this).balance) revert Errors.InsufficientNativeToWithdraw(); // Interactions: withdraw by transferring the amount to the sender - (bool success,) = msg.sender.call{ value: amount }(""); + (bool success, ) = msg.sender.call{ value: amount }(""); // Revert if the call failed if (!success) revert Errors.NativeWithdrawFailed(); @@ -179,9 +189,7 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { } /// @inheritdoc IModuleManager - function enableModule( - address module - ) public override onlyAdminOrEntrypoint { + function enableModule(address module) public override onlyAdminOrEntrypoint { // Retrieve the address of the {ModuleKeeper} ModuleKeeper moduleKeeper = StationRegistry(factory).moduleKeeper(); @@ -190,9 +198,7 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { } /// @inheritdoc IModuleManager - function disableModule( - address module - ) public override onlyAdminOrEntrypoint { + function disableModule(address module) public override onlyAdminOrEntrypoint { // Effects: disable the module _disableModule(module); } @@ -202,10 +208,7 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc ERC1271 - function isValidSignature( - bytes32 _hash, - bytes memory _signature - ) public view override returns (bytes4 magicValue) { + function isValidSignature(bytes32 _hash, bytes memory _signature) public view override returns (bytes4 magicValue) { // Compute the hash of message the should be signed bytes32 targetDigest = getMessageHash(_hash); @@ -230,20 +233,19 @@ contract Space is ISpace, AccountCore, ERC1271, ModuleManager { } /// @inheritdoc ISpace - function getMessageHash( - bytes32 _hash - ) public view returns (bytes32) { + function getMessageHash(bytes32 _hash) public view returns (bytes32) { bytes32 messageHash = keccak256(abi.encode(_hash)); bytes32 typedDataHash = keccak256(abi.encode(MSG_TYPEHASH, messageHash)); return keccak256(abi.encodePacked("\x19\x01", _domainSeparatorV4(), typedDataHash)); } /// @inheritdoc IERC165 - function supportsInterface( - bytes4 interfaceId - ) public pure returns (bool) { - return interfaceId == type(ISpace).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId - || interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; + function supportsInterface(bytes4 interfaceId) public pure returns (bool) { + return + interfaceId == type(ISpace).interfaceId || + interfaceId == type(IERC1155Receiver).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + interfaceId == type(IERC165).interfaceId; } /// @inheritdoc IERC721Receiver diff --git a/src/StationRegistry.sol b/src/StationRegistry.sol index c19b638..cbb0c30 100644 --- a/src/StationRegistry.sol +++ b/src/StationRegistry.sol @@ -111,9 +111,7 @@ contract StationRegistry is IStationRegistry, BaseAccountFactory, PermissionsEnu } /// @inheritdoc IStationRegistry - function updateModuleKeeper( - ModuleKeeper newModuleKeeper - ) external onlyRole(DEFAULT_ADMIN_ROLE) { + function updateModuleKeeper(ModuleKeeper newModuleKeeper) external onlyRole(DEFAULT_ADMIN_ROLE) { // Effects: update the {ModuleKeeper} address moduleKeeper = newModuleKeeper; @@ -126,9 +124,7 @@ contract StationRegistry is IStationRegistry, BaseAccountFactory, PermissionsEnu //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc IStationRegistry - function totalAccountsOfSigner( - address signer - ) public view returns (uint256) { + function totalAccountsOfSigner(address signer) public view returns (uint256) { return accountsOfSigner[signer].length(); } diff --git a/src/utils/BaseAccountFactory.sol b/src/utils/BaseAccountFactory.sol index 6892c94..f728f9f 100644 --- a/src/utils/BaseAccountFactory.sol +++ b/src/utils/BaseAccountFactory.sol @@ -75,9 +75,7 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall { //////////////////////////////////////////////////////////////*/ /// @notice Callback function for an Account to register itself on the factory. - function onRegister( - bytes32 _salt - ) external { + function onRegister(bytes32 _salt) external { address account = msg.sender; require(_isAccountOfFactory(account, _salt), "AccountFactory: not an account."); @@ -112,9 +110,7 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall { //////////////////////////////////////////////////////////////*/ /// @notice Returns whether an account is registered on this factory. - function isRegistered( - address _account - ) external view returns (bool) { + function isRegistered(address _account) external view returns (bool) { return allAccounts.contains(_account); } @@ -147,9 +143,7 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall { } /// @notice Returns all accounts that the given address is a signer of. - function getAccountsOfSigner( - address signer - ) external view returns (address[] memory accounts) { + function getAccountsOfSigner(address signer) external view returns (address[] memory accounts) { return accountsOfSigner[signer].values(); } @@ -163,9 +157,7 @@ abstract contract BaseAccountFactory is IAccountFactory, Multicall { return _account == predicted; } - function _getImplementation( - address cloneAddress - ) internal view returns (address) { + function _getImplementation(address cloneAddress) internal view returns (address) { bytes memory code = cloneAddress.code; return BytesLib.toAddress(code, 10); } diff --git a/test/Base.t.sol b/test/Base.t.sol index bafd1df..a5b37e2 100644 --- a/test/Base.t.sol +++ b/test/Base.t.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.20; +pragma solidity ^0.8.22; import { Events } from "./utils/Events.sol"; import { Users } from "./utils/Types.sol"; @@ -98,8 +98,11 @@ abstract contract Base_Test is Test, Events { } vm.stopPrank(); - bytes memory data = - computeCreateAccountCalldata({ deployer: _owner, stationId: _spaceId, initialModules: _initialModules }); + bytes memory data = computeCreateAccountCalldata({ + deployer: _owner, + stationId: _spaceId, + initialModules: _initialModules + }); vm.prank({ msgSender: _owner }); _container = Space(payable(stationRegistry.createAccount({ _admin: _owner, _data: data }))); @@ -118,17 +121,18 @@ abstract contract Base_Test is Test, Events { } vm.stopPrank(); - bytes memory data = - computeCreateAccountCalldata({ deployer: _owner, stationId: _spaceId, initialModules: _initialModules }); + bytes memory data = computeCreateAccountCalldata({ + deployer: _owner, + stationId: _spaceId, + initialModules: _initialModules + }); vm.prank({ msgSender: _owner }); _badSpace = MockBadSpace(payable(stationRegistry.createAccount({ _admin: _owner, _data: data }))); vm.stopPrank(); } - function allowlistModule( - address _module - ) internal { + function allowlistModule(address _module) internal { moduleKeeper.addToAllowlist({ module: _module }); } @@ -137,9 +141,7 @@ abstract contract Base_Test is Test, Events { //////////////////////////////////////////////////////////////////////////*/ /// @dev Generates a user, labels its address, and funds it with test assets - function createUser( - string memory name - ) internal returns (address payable) { + function createUser(string memory name) internal returns (address payable) { address payable user = payable(makeAddr(name)); vm.deal({ account: user, newBalance: 100 ether }); deal({ token: address(usdt), to: user, give: 10_000_000e18 }); @@ -160,8 +162,11 @@ abstract contract Base_Test is Test, Events { bytes32 salt = keccak256(abi.encode(deployer, data)); // Use {Clones} library to predict the smart account address based on the smart account implementation, salt and account factory - expectedAddress = - Clones.predictDeterministicAddress(stationRegistry.accountImplementation(), salt, address(stationRegistry)); + expectedAddress = Clones.predictDeterministicAddress( + stationRegistry.accountImplementation(), + salt, + address(stationRegistry) + ); } /// @dev Constructs the calldata passed to the {StationRegistry}.createAccount method diff --git a/test/integration/Integration.t.sol b/test/integration/Integration.t.sol index 181d3d5..621d3e7 100644 --- a/test/integration/Integration.t.sol +++ b/test/integration/Integration.t.sol @@ -61,8 +61,10 @@ abstract contract Integration_Test is Base_Test { /// @dev Deploys the {InvoiceModule} module by initializing the Sablier v2-required contracts first function deployInvoiceModule() internal { mockNFTDescriptor = new MockNFTDescriptor(); - sablierV2LockupLinear = - new SablierV2LockupLinear({ initialAdmin: users.admin, initialNFTDescriptor: mockNFTDescriptor }); + sablierV2LockupLinear = new SablierV2LockupLinear({ + initialAdmin: users.admin, + initialNFTDescriptor: mockNFTDescriptor + }); sablierV2LockupTranched = new SablierV2LockupTranched({ initialAdmin: users.admin, initialNFTDescriptor: mockNFTDescriptor, diff --git a/test/integration/concrete/invoice-module/create-invoice/createInvoice.t.sol b/test/integration/concrete/invoice-module/create-invoice/createInvoice.t.sol index 6dd4c51..161384f 100644 --- a/test/integration/concrete/invoice-module/create-invoice/createInvoice.t.sol +++ b/test/integration/concrete/invoice-module/create-invoice/createInvoice.t.sol @@ -36,7 +36,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the call to revert with the {SpaceUnsupportedInterface} error @@ -58,7 +59,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the call to revert with the {ZeroPaymentAmount} error @@ -86,7 +88,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the call to revert with the {StartTimeGreaterThanEndTime} error @@ -119,7 +122,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the call to revert with the {EndTimeInThePast} error @@ -147,7 +151,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the module call to emit an {InvoiceCreated} event @@ -205,7 +210,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the call to revert with the {PaymentIntervalTooShortForSelectedRecurrence} error @@ -233,7 +239,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the module call to emit an {InvoiceCreated} event @@ -293,7 +300,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Run the test @@ -324,7 +332,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Run the test @@ -356,7 +365,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Run the test @@ -381,7 +391,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the module call to emit an {InvoiceCreated} event @@ -441,7 +452,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Run the test @@ -466,7 +478,8 @@ contract CreateInvoice_Integration_Concret_Test is CreateInvoice_Integration_Sha // Create the calldata for the Invoice Module execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the module call to emit an {InvoiceCreated} event diff --git a/test/integration/concrete/invoice-module/pay-invoice/payInvoice.t.sol b/test/integration/concrete/invoice-module/pay-invoice/payInvoice.t.sol index 5fb2473..c7d2f50 100644 --- a/test/integration/concrete/invoice-module/pay-invoice/payInvoice.t.sol +++ b/test/integration/concrete/invoice-module/pay-invoice/payInvoice.t.sol @@ -78,7 +78,8 @@ contract PayInvoice_Integration_Concret_Test is PayInvoice_Integration_Shared_Te // Expect the call to be reverted with the {PaymentAmountLessThanInvoiceValue} error vm.expectRevert( abi.encodeWithSelector( - Errors.PaymentAmountLessThanInvoiceValue.selector, invoices[invoiceId].payment.amount + Errors.PaymentAmountLessThanInvoiceValue.selector, + invoices[invoiceId].payment.amount ) ); diff --git a/test/integration/concrete/invoice-module/transfer-from/transferFrom.t.sol b/test/integration/concrete/invoice-module/transfer-from/transferFrom.t.sol index 8486d27..51acb07 100644 --- a/test/integration/concrete/invoice-module/transfer-from/transferFrom.t.sol +++ b/test/integration/concrete/invoice-module/transfer-from/transferFrom.t.sol @@ -42,8 +42,10 @@ contract TransferFrom_Integration_Concret_Test is TransferFrom_Integration_Share uint256 balanceOfBefore = usdt.balanceOf(address(space)); // Get the maximum withdrawable amount from the stream before transferring the stream NFT - uint128 maxWithdrawableAmount = - invoiceModule.withdrawableAmountOf({ streamType: Types.Method.LinearStream, streamId: streamId }); + uint128 maxWithdrawableAmount = invoiceModule.withdrawableAmountOf({ + streamType: Types.Method.LinearStream, + streamId: streamId + }); // Make Eve's space the caller which is the recipient of the invoice vm.startPrank({ msgSender: address(space) }); diff --git a/test/integration/concrete/invoice-module/withdraw-invoice-stream/withdrawStream.t.sol b/test/integration/concrete/invoice-module/withdraw-invoice-stream/withdrawStream.t.sol index 5002a08..e5d0e44 100644 --- a/test/integration/concrete/invoice-module/withdraw-invoice-stream/withdrawStream.t.sol +++ b/test/integration/concrete/invoice-module/withdraw-invoice-stream/withdrawStream.t.sol @@ -31,8 +31,10 @@ contract WithdrawLinearStream_Integration_Concret_Test is WithdrawLinearStream_I uint256 balanceOfBefore = usdt.balanceOf(address(space)); // Get the maximum withdrawable amount from the stream - uint128 maxWithdrawableAmount = - invoiceModule.withdrawableAmountOf({ streamType: Types.Method.LinearStream, streamId: streamId }); + uint128 maxWithdrawableAmount = invoiceModule.withdrawableAmountOf({ + streamType: Types.Method.LinearStream, + streamId: streamId + }); // Make Eve's space the caller in this test suite as his space is the recipient of the invoice vm.startPrank({ msgSender: address(space) }); @@ -66,8 +68,10 @@ contract WithdrawLinearStream_Integration_Concret_Test is WithdrawLinearStream_I uint256 balanceOfBefore = usdt.balanceOf(address(space)); // Get the maximum withdrawable amount from the stream - uint128 maxWithdrawableAmount = - invoiceModule.withdrawableAmountOf({ streamType: Types.Method.TranchedStream, streamId: streamId }); + uint128 maxWithdrawableAmount = invoiceModule.withdrawableAmountOf({ + streamType: Types.Method.TranchedStream, + streamId: streamId + }); // Make Eve's space the caller in this test suite as her space is the owner of the invoice vm.startPrank({ msgSender: address(space) }); diff --git a/test/integration/fuzz/createInvoice.t.sol b/test/integration/fuzz/createInvoice.t.sol index d569232..499d416 100644 --- a/test/integration/fuzz/createInvoice.t.sol +++ b/test/integration/fuzz/createInvoice.t.sol @@ -40,8 +40,12 @@ contract CreateInvoice_Integration_Fuzz_Test is CreateInvoice_Integration_Shared vm.assume(amount > 0); // Calculate the number of payments if this is a transfer-based invoice - (bool valid, uint40 numberOfPayments) = - Helpers.checkFuzzedPaymentMethod(paymentMethod, recurrence, startTime, endTime); + (bool valid, uint40 numberOfPayments) = Helpers.checkFuzzedPaymentMethod( + paymentMethod, + recurrence, + startTime, + endTime + ); if (!valid) return; // Create a new invoice with a transfer-based payment @@ -61,7 +65,8 @@ contract CreateInvoice_Integration_Fuzz_Test is CreateInvoice_Integration_Shared // Create the calldata for the {InvoiceModule} execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Expect the module call to emit an {InvoiceCreated} event diff --git a/test/integration/fuzz/payInvoice.t.sol b/test/integration/fuzz/payInvoice.t.sol index 2b23124..44564c2 100644 --- a/test/integration/fuzz/payInvoice.t.sol +++ b/test/integration/fuzz/payInvoice.t.sol @@ -38,8 +38,12 @@ contract PayInvoice_Integration_Fuzz_Test is PayInvoice_Integration_Shared_Test vm.assume(amount > 0); // Calculate the number of payments if this is a transfer-based invoice - (bool valid, uint40 numberOfPayments) = - Helpers.checkFuzzedPaymentMethod(paymentMethod, recurrence, startTime, endTime); + (bool valid, uint40 numberOfPayments) = Helpers.checkFuzzedPaymentMethod( + paymentMethod, + recurrence, + startTime, + endTime + ); if (!valid) return; // Create a new invoice with the fuzzed payment method @@ -59,7 +63,8 @@ contract PayInvoice_Integration_Fuzz_Test is PayInvoice_Integration_Shared_Test // Create the calldata for the {InvoiceModule} execution bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); uint256 invoiceId = _nextInvoiceId; diff --git a/test/integration/shared/createInvoice.t.sol b/test/integration/shared/createInvoice.t.sol index db17468..c32bf03 100644 --- a/test/integration/shared/createInvoice.t.sol +++ b/test/integration/shared/createInvoice.t.sol @@ -106,11 +106,9 @@ abstract contract CreateInvoice_Integration_Shared_Test is Integration_Test { } /// @dev Creates an invoice with a recurring transfer payment - function createInvoiceWithRecurringTransfer(Types.Recurrence recurrence) - internal - view - returns (Types.Invoice memory invoice) - { + function createInvoiceWithRecurringTransfer( + Types.Recurrence recurrence + ) internal view returns (Types.Invoice memory invoice) { invoice = _createInvoice(uint40(block.timestamp), uint40(block.timestamp) + 4 weeks); invoice.payment = Types.Payment({ @@ -138,11 +136,9 @@ abstract contract CreateInvoice_Integration_Shared_Test is Integration_Test { } /// @dev Creates an invoice with a tranched stream-based payment - function createInvoiceWithTranchedStream(Types.Recurrence recurrence) - internal - view - returns (Types.Invoice memory invoice) - { + function createInvoiceWithTranchedStream( + Types.Recurrence recurrence + ) internal view returns (Types.Invoice memory invoice) { invoice = _createInvoice(uint40(block.timestamp), uint40(block.timestamp) + 4 weeks); invoice.payment = Types.Payment({ @@ -181,7 +177,8 @@ abstract contract CreateInvoice_Integration_Shared_Test is Integration_Test { // Create the invoice bytes memory data = abi.encodeWithSignature( - "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", invoice + "createInvoice((uint8,uint40,uint40,(uint8,uint8,uint40,address,uint128,uint256)))", + invoice ); // Select the according {Space} of the user diff --git a/test/integration/shared/withdrawLinearStream.t.sol b/test/integration/shared/withdrawLinearStream.t.sol index f78fa6d..acbc493 100644 --- a/test/integration/shared/withdrawLinearStream.t.sol +++ b/test/integration/shared/withdrawLinearStream.t.sol @@ -4,10 +4,7 @@ pragma solidity ^0.8.26; import { Integration_Test } from "../Integration.t.sol"; import { PayInvoice_Integration_Shared_Test } from "./payInvoice.t.sol"; -abstract contract WithdrawLinearStream_Integration_Shared_Test is - Integration_Test, - PayInvoice_Integration_Shared_Test -{ +abstract contract WithdrawLinearStream_Integration_Shared_Test is Integration_Test, PayInvoice_Integration_Shared_Test { function setUp() public virtual override(Integration_Test, PayInvoice_Integration_Shared_Test) { PayInvoice_Integration_Shared_Test.setUp(); createMockInvoices(); diff --git a/test/mocks/MockBadSpace.sol b/test/mocks/MockBadSpace.sol index 34c1c70..c0d3973 100644 --- a/test/mocks/MockBadSpace.sol +++ b/test/mocks/MockBadSpace.sol @@ -37,7 +37,7 @@ contract MockBadSpace is ISpace, AccountCore, ERC1271, ModuleManager { //////////////////////////////////////////////////////////////////////////*/ /// @dev Initializes the address of the {Space} owner, {ModuleKeeper} and enables the initial module(s) - constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) { } + constructor(IEntryPoint _entrypoint, address _factory) AccountCore(_entrypoint, _factory) {} /*////////////////////////////////////////////////////////////////////////// RECEIVE & FALLBACK @@ -145,9 +145,21 @@ contract MockBadSpace is ISpace, AccountCore, ERC1271, ModuleManager { // therefore the `onERC1155Received` hook must be implemented // - depending on the length of the `ids` array, we're using `safeBatchTransferFrom` or `safeTransferFrom` if (ids.length > 1) { - collection.safeBatchTransferFrom({ from: address(this), to: msg.sender, ids: ids, values: amounts, data: "" }); + collection.safeBatchTransferFrom({ + from: address(this), + to: msg.sender, + ids: ids, + values: amounts, + data: "" + }); } else { - collection.safeTransferFrom({ from: address(this), to: msg.sender, id: ids[0], value: amounts[0], data: "" }); + collection.safeTransferFrom({ + from: address(this), + to: msg.sender, + id: ids[0], + value: amounts[0], + data: "" + }); } // Log the successful ERC-1155 token withdrawal @@ -160,7 +172,7 @@ contract MockBadSpace is ISpace, AccountCore, ERC1271, ModuleManager { if (amount > address(this).balance) revert Errors.InsufficientNativeToWithdraw(); // Interactions: withdraw by transferring the amount to the sender - (bool success,) = msg.sender.call{ value: amount }(""); + (bool success, ) = msg.sender.call{ value: amount }(""); // Revert if the call failed if (!success) revert Errors.NativeWithdrawFailed(); @@ -185,10 +197,7 @@ contract MockBadSpace is ISpace, AccountCore, ERC1271, ModuleManager { //////////////////////////////////////////////////////////////////////////*/ /// @inheritdoc ERC1271 - function isValidSignature( - bytes32 _hash, - bytes memory _signature - ) public view override returns (bytes4 magicValue) { + function isValidSignature(bytes32 _hash, bytes memory _signature) public view override returns (bytes4 magicValue) { // Compute the hash of message the should be signed bytes32 targetDigest = getMessageHash(_hash); @@ -221,8 +230,11 @@ contract MockBadSpace is ISpace, AccountCore, ERC1271, ModuleManager { /// @inheritdoc IERC165 function supportsInterface(bytes4 interfaceId) public pure returns (bool) { - return interfaceId == type(ISpace).interfaceId || interfaceId == type(IERC1155Receiver).interfaceId - || interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; + return + interfaceId == type(ISpace).interfaceId || + interfaceId == type(IERC1155Receiver).interfaceId || + interfaceId == type(IERC721Receiver).interfaceId || + interfaceId == type(IERC165).interfaceId; } /// @inheritdoc IERC721Receiver diff --git a/test/mocks/MockERC20NoReturn.sol b/test/mocks/MockERC20NoReturn.sol index 373f0f1..1216491 100644 --- a/test/mocks/MockERC20NoReturn.sol +++ b/test/mocks/MockERC20NoReturn.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.0; +pragma solidity ^0.8.22; /// @notice An implementation of ERC-20 standard forked from the OpenZeppelin v4 library that do not return a boolean upon calling {transferFrom} or {transfer} /// @dev Reference https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.0/contracts/token/ERC20/ERC20.sol @@ -158,7 +158,8 @@ contract MockERC20NoReturn { emit Transfer(sender, recipient, amount); } - /** @dev Creates `amount` tokens and assigns them to `account`, increasing + /** + * @dev Creates `amount` tokens and assigns them to `account`, increasing * the total supply. * * Emits a {Transfer} event with `from` set to the zero address. diff --git a/test/mocks/MockOwnable.sol b/test/mocks/MockOwnable.sol index e9db589..53e8dc6 100644 --- a/test/mocks/MockOwnable.sol +++ b/test/mocks/MockOwnable.sol @@ -6,5 +6,5 @@ import { Ownable } from "./../../src/abstracts/Ownable.sol"; /// @title MockOwnable /// @notice A mock implementation that uses the `onlyOwner` auth mechanism contract MockOwnable is Ownable { - constructor(address _owner) Ownable(_owner) { } + constructor(address _owner) Ownable(_owner) {} } diff --git a/test/mocks/MockStreamManager.sol b/test/mocks/MockStreamManager.sol index 3acbb46..2334112 100644 --- a/test/mocks/MockStreamManager.sol +++ b/test/mocks/MockStreamManager.sol @@ -12,5 +12,5 @@ contract MockStreamManager is StreamManager { ISablierV2LockupLinear _sablierLockupLinear, ISablierV2LockupTranched _sablierLockupTranched, address _brokerAdmin - ) StreamManager(_sablierLockupLinear, _sablierLockupTranched, _brokerAdmin) { } + ) StreamManager(_sablierLockupLinear, _sablierLockupTranched, _brokerAdmin) {} } diff --git a/test/unit/concrete/helpers/computeNumberOfPayments.t.sol b/test/unit/concrete/helpers/computeNumberOfPayments.t.sol index 61f437b..df5dcc2 100644 --- a/test/unit/concrete/helpers/computeNumberOfPayments.t.sol +++ b/test/unit/concrete/helpers/computeNumberOfPayments.t.sol @@ -16,8 +16,10 @@ contract ComputeNumberOfPayments_Helpers_Test is Base_Test { uint40 endTime = uint40(block.timestamp + 11 weeks); // Run the test - uint40 numberOfPayments = - Helpers.computeNumberOfPayments({ recurrence: Types.Recurrence.Weekly, interval: endTime - startTime }); + uint40 numberOfPayments = Helpers.computeNumberOfPayments({ + recurrence: Types.Recurrence.Weekly, + interval: endTime - startTime + }); // Assert the actual and expected number of payments assertEq(numberOfPayments, 11); @@ -29,8 +31,10 @@ contract ComputeNumberOfPayments_Helpers_Test is Base_Test { uint40 endTime = uint40(block.timestamp + 2 * 4 weeks); // Run the test - uint40 numberOfPayments = - Helpers.computeNumberOfPayments({ recurrence: Types.Recurrence.Monthly, interval: endTime - startTime }); + uint40 numberOfPayments = Helpers.computeNumberOfPayments({ + recurrence: Types.Recurrence.Monthly, + interval: endTime - startTime + }); // Assert the actual and expected number of payments assertEq(numberOfPayments, 2); @@ -42,8 +46,10 @@ contract ComputeNumberOfPayments_Helpers_Test is Base_Test { uint40 endTime = uint40(block.timestamp + 3 * 48 weeks); // Run the test - uint40 numberOfPayments = - Helpers.computeNumberOfPayments({ recurrence: Types.Recurrence.Yearly, interval: endTime - startTime }); + uint40 numberOfPayments = Helpers.computeNumberOfPayments({ + recurrence: Types.Recurrence.Yearly, + interval: endTime - startTime + }); // Assert the actual and expected number of payments assertEq(numberOfPayments, 3); diff --git a/test/unit/concrete/space/fallback/fallback.t.sol b/test/unit/concrete/space/fallback/fallback.t.sol index 49d321f..2b676c8 100644 --- a/test/unit/concrete/space/fallback/fallback.t.sol +++ b/test/unit/concrete/space/fallback/fallback.t.sol @@ -18,7 +18,7 @@ contract Fallback_Unit_Concrete_Test is Space_Unit_Concrete_Test { emit Events.NativeReceived({ from: users.bob, amount: 1 ether }); // Run the test - (bool success,) = address(space).call{ value: 1 ether }("test"); + (bool success, ) = address(space).call{ value: 1 ether }("test"); if (!success) revert(); // Assert the {Space} contract balance diff --git a/test/unit/concrete/space/receive/receive.t.sol b/test/unit/concrete/space/receive/receive.t.sol index 9d74f39..7a73912 100644 --- a/test/unit/concrete/space/receive/receive.t.sol +++ b/test/unit/concrete/space/receive/receive.t.sol @@ -18,7 +18,7 @@ contract Receive_Unit_Concrete_Test is Space_Unit_Concrete_Test { emit Events.NativeReceived({ from: users.bob, amount: 1 ether }); // Run the test - (bool success,) = address(space).call{ value: 1 ether }(""); + (bool success, ) = address(space).call{ value: 1 ether }(""); if (!success) revert(); // Assert the {Space} contract balance diff --git a/test/unit/concrete/space/withdraw-native/withdrawNative.t.sol b/test/unit/concrete/space/withdraw-native/withdrawNative.t.sol index d92f006..4549b22 100644 --- a/test/unit/concrete/space/withdraw-native/withdrawNative.t.sol +++ b/test/unit/concrete/space/withdraw-native/withdrawNative.t.sol @@ -51,7 +51,7 @@ contract WithdrawNative_Unit_Concrete_Test is Space_Unit_Concrete_Test { modifier whenSufficientNativeToWithdraw(Space space) { // Deposit sufficient native tokens (ETH) into the space to enable the withdrawal - (bool success,) = payable(space).call{ value: 2 ether }(""); + (bool success, ) = payable(space).call{ value: 2 ether }(""); if (!success) revert(); _; } diff --git a/test/unit/concrete/station-registry/create-account/createAccount.t.sol b/test/unit/concrete/station-registry/create-account/createAccount.t.sol index e3a0dc9..d0b5242 100644 --- a/test/unit/concrete/station-registry/create-account/createAccount.t.sol +++ b/test/unit/concrete/station-registry/create-account/createAccount.t.sol @@ -19,8 +19,11 @@ contract CreateAccount_Unit_Concrete_Test is StationRegistry_Unit_Concrete_Test // The {StationRegistry} contract deploys each new {Space} contract. // Therefore, we need to calculate the current nonce of the {StationRegistry} // to pre-compute the address of the new {Space} before deployment. - (address expectedSpace, bytes memory data) = - computeDeploymentAddressAndCalldata({ deployer: users.bob, stationId: 0, initialModules: mockModules }); + (address expectedSpace, bytes memory data) = computeDeploymentAddressAndCalldata({ + deployer: users.bob, + stationId: 0, + initialModules: mockModules + }); // Allowlist the mock modules on the {ModuleKeeper} contract from the admin account vm.startPrank({ msgSender: users.admin }); @@ -61,8 +64,11 @@ contract CreateAccount_Unit_Concrete_Test is StationRegistry_Unit_Concrete_Test function test_RevertWhen_CallerNotStationOwner() external whenStationIdNonZero { // Construct the calldata to be used to initialize the {Space} smart account - bytes memory data = - computeCreateAccountCalldata({ deployer: users.eve, stationId: 1, initialModules: mockModules }); + bytes memory data = computeCreateAccountCalldata({ + deployer: users.eve, + stationId: 1, + initialModules: mockModules + }); // Make Eve the caller in this test suite vm.prank({ msgSender: users.eve }); @@ -82,8 +88,11 @@ contract CreateAccount_Unit_Concrete_Test is StationRegistry_Unit_Concrete_Test // The {StationRegistry} contract deploys each new {Space} contract. // Therefore, we need to calculate the current nonce of the {StationRegistry} // to pre-compute the address of the new {Space} before deployment. - (address expectedSpace, bytes memory data) = - computeDeploymentAddressAndCalldata({ deployer: users.bob, stationId: 1, initialModules: mockModules }); + (address expectedSpace, bytes memory data) = computeDeploymentAddressAndCalldata({ + deployer: users.bob, + stationId: 1, + initialModules: mockModules + }); // Allowlist the mock modules on the {ModuleKeeper} contract from the admin account vm.startPrank({ msgSender: users.admin }); diff --git a/test/unit/concrete/station-registry/update-module-keeper/updateModuleKeeper.t.sol b/test/unit/concrete/station-registry/update-module-keeper/updateModuleKeeper.t.sol index 75ab7f5..8bcd281 100644 --- a/test/unit/concrete/station-registry/update-module-keeper/updateModuleKeeper.t.sol +++ b/test/unit/concrete/station-registry/update-module-keeper/updateModuleKeeper.t.sol @@ -19,7 +19,9 @@ contract UpdateModuleKeeper_Unit_Concrete_Test is StationRegistry_Unit_Concrete_ // Expect the next call to revert with the {PermissionsUnauthorizedAccount} error vm.expectRevert( abi.encodeWithSelector( - Errors.PermissionsUnauthorizedAccount.selector, users.bob, Constants.DEFAULT_ADMIN_ROLE + Errors.PermissionsUnauthorizedAccount.selector, + users.bob, + Constants.DEFAULT_ADMIN_ROLE ) ); diff --git a/test/utils/Constants.sol b/test/utils/Constants.sol index 5d67554..c7b456b 100644 --- a/test/utils/Constants.sol +++ b/test/utils/Constants.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.22; library Constants { /// @dev Role identifier for addresses with the default admin role diff --git a/test/utils/Errors.sol b/test/utils/Errors.sol index 3d9865f..aa90988 100644 --- a/test/utils/Errors.sol +++ b/test/utils/Errors.sol @@ -93,9 +93,6 @@ library Errors { /// @notice Thrown when a payer attempts to pay a canceled invoice error InvoiceCanceled(); - /// @notice Thrown when the invoice ID references a null invoice - error InvoiceNull(); - /// @notice Thrown when `msg.sender` is not the creator (recipient) of the invoice error OnlyInvoiceRecipient(); diff --git a/test/utils/Events.sol b/test/utils/Events.sol index 4626337..8071cc5 100644 --- a/test/utils/Events.sol +++ b/test/utils/Events.sol @@ -92,35 +92,27 @@ abstract contract Events { event ModuleDisabled(address indexed module, address indexed owner); /*////////////////////////////////////////////////////////////////////////// - INVOICE + PAYMENT-MODULE //////////////////////////////////////////////////////////////////////////*/ - /// @notice Emitted when a regular or recurring invoice is created - /// @param id The ID of the invoice + /// @notice Emitted when a payment request is created + /// @param id The ID of the payment request /// @param recipient The address receiving the payment - /// @param status The status of the invoice - /// @param startTime The timestamp when the invoice takes effect - /// @param endTime The timestamp by which the invoice must be paid - /// @param payment Struct representing the payment details associated with the invoice - event InvoiceCreated( - uint256 id, - address indexed recipient, - Types.Status status, - uint40 startTime, - uint40 endTime, - Types.Payment payment - ); - - /// @notice Emitted when an invoice is paid - /// @param id The ID of the invoice + /// @param startTime The timestamp when the payment request takes effect + /// @param endTime The timestamp by which the payment request must be paid + /// @param config Struct representing the payment details associated with the payment request + event RequestCreated(uint256 id, address indexed recipient, uint40 startTime, uint40 endTime, Types.Config config); + + /// @notice Emitted when a payment is made for a payment request + /// @param id The ID of the payment request /// @param payer The address of the payer - /// @param status The status of the invoice - /// @param payment Struct representing the payment details associated with the invoice - event InvoicePaid(uint256 indexed id, address indexed payer, Types.Status status, Types.Payment payment); + /// @param status The status of the payment request + /// @param config Struct representing the payment details + event RequestPaid(uint256 indexed id, address indexed payer, Types.Status status, Types.Config config); - /// @notice Emitted when an invoice is canceled - /// @param id The ID of the invoice - event InvoiceCanceled(uint256 indexed id); + /// @notice Emitted when a payment request is canceled + /// @param id The ID of the payment request + event RequestCanceled(uint256 indexed id); /// @notice Emitted when the broker fee is updated /// @param oldFee The old broker fee diff --git a/test/utils/Helpers.sol b/test/utils/Helpers.sol index 4fd0042..853e317 100644 --- a/test/utils/Helpers.sol +++ b/test/utils/Helpers.sol @@ -6,19 +6,20 @@ import { Helpers as InvoiceHelpers } from "./../../src/modules/invoice-module/li library Helpers { function createInvoiceDataType() public view returns (Types.Invoice memory) { - return Types.Invoice({ - status: Types.Status.Pending, - startTime: 0, - endTime: uint40(block.timestamp) + 1 weeks, - payment: Types.Payment({ - method: Types.Method.Transfer, - recurrence: Types.Recurrence.OneOff, - paymentsLeft: 1, - asset: address(0), - amount: uint128(1 ether), - streamId: 0 - }) - }); + return + Types.Invoice({ + status: Types.Status.Pending, + startTime: 0, + endTime: uint40(block.timestamp) + 1 weeks, + payment: Types.Payment({ + method: Types.Method.Transfer, + recurrence: Types.Recurrence.OneOff, + paymentsLeft: 1, + asset: address(0), + amount: uint128(1 ether), + streamId: 0 + }) + }); } /// @dev Calculates the number of payments that must be done based on a Recurring invoice