From e72c473d0faff5c7d5f872dd47b972664c10711e Mon Sep 17 00:00:00 2001 From: Ryan Sauge Date: Tue, 3 Sep 2024 15:32:09 +0200 Subject: [PATCH] Add version + clean up with prettier --- src/DebtEngine.sol | 80 ++++++++----- src/DebtEngineInvariantStorage.sol | 7 +- test/DebtEngine.t.sol | 182 +++++++++++++++++------------ 3 files changed, 158 insertions(+), 111 deletions(-) diff --git a/src/DebtEngine.sol b/src/DebtEngine.sol index 278aa9d..e3f6291 100644 --- a/src/DebtEngine.sol +++ b/src/DebtEngine.sol @@ -7,12 +7,18 @@ import "./DebtEngineInvariantStorage.sol"; import {IDebtGlobal} from "CMTAT/interfaces/IDebtGlobal.sol"; contract DebtEngine is IDebtEngine, AccessControl, DebtEngineInvariantStorage { + /** + * @notice + * Get the current version of the smart contract + */ + string public constant VERSION = "0.1.0"; + // Mapping of debts and credit events to specific smart contracts mapping(address => DebtBase) private _debts; mapping(address => CreditEvents) private _creditEvents; constructor(address admin) { - if(admin == address(0)){ + if (admin == address(0)) { revert AdminAddressZeroNotAllowed(); } _grantRole(DEFAULT_ADMIN_ROLE, admin); @@ -23,57 +29,68 @@ contract DebtEngine is IDebtEngine, AccessControl, DebtEngineInvariantStorage { //////////////////////////////////////////////////////////////*/ /* ============ USER-FACING FUNCTIONS ============ */ - /** - * @notice Function to get the debt for the sender's smart contract - */ + /** + * @notice Function to get the debt for the sender's smart contract + */ function debt() external view returns (DebtBase memory) { return debt(msg.sender); } - /** - * @notice Function to get the debt for a specific smart contract - */ - function debt(address smartContract_) public view returns (DebtBase memory) { + /** + * @notice Function to get the debt for a specific smart contract + */ + function debt( + address smartContract_ + ) public view returns (DebtBase memory) { DebtBase memory d = _debts[smartContract_]; return d; } /** - * @notice Function to get the credit events for the sender's smart contract - */ + * @notice Function to get the credit events for the sender's smart contract + */ function creditEvents() external view returns (CreditEvents memory) { return creditEvents(msg.sender); } /** - * @notice Function to get the credit events for a specific smart contract - */ - function creditEvents(address smartContract_) public view returns (CreditEvents memory) { + * @notice Function to get the credit events for a specific smart contract + */ + function creditEvents( + address smartContract_ + ) public view returns (CreditEvents memory) { CreditEvents memory ce = _creditEvents[smartContract_]; return ce; } - - /* ============ RESTRICTED-FACING FUNCTIONS ============ */ /** - * @notice Function to set the debt for a given smart contract - */ - function setDebt(address smartContract_, DebtBase calldata debt_) external onlyRole(DEBT_MANAGER_ROLE) { + * @notice Function to set the debt for a given smart contract + */ + function setDebt( + address smartContract_, + DebtBase calldata debt_ + ) external onlyRole(DEBT_MANAGER_ROLE) { _debts[smartContract_] = debt_; } /* - * @notice Function to set the credit events for a given smart contract - */ - function setCreditEvents(address smartContract_, CreditEvents calldata creditEvents_) external onlyRole(CREDIT_EVENTS_MANAGER_ROLE) { + * @notice Function to set the credit events for a given smart contract + */ + function setCreditEvents( + address smartContract_, + CreditEvents calldata creditEvents_ + ) external onlyRole(CREDIT_EVENTS_MANAGER_ROLE) { _creditEvents[smartContract_] = creditEvents_; } /* - * @notice Batch version of {setCreditEventsBatch} - */ - function setCreditEventsBatch(address[] calldata smartContracts, CreditEvents[] calldata creditEventsList) external onlyRole(CREDIT_EVENTS_MANAGER_ROLE) { + * @notice Batch version of {setCreditEventsBatch} + */ + function setCreditEventsBatch( + address[] calldata smartContracts, + CreditEvents[] calldata creditEventsList + ) external onlyRole(CREDIT_EVENTS_MANAGER_ROLE) { if (smartContracts.length != creditEventsList.length) { revert InvalidInputLength(); } @@ -84,9 +101,12 @@ contract DebtEngine is IDebtEngine, AccessControl, DebtEngineInvariantStorage { } /* - * @notice Batch version of {setDebtBatch} - */ - function setDebtBatch(address[] calldata smartContracts, DebtBase[] calldata debts) external onlyRole(DEBT_MANAGER_ROLE) { + * @notice Batch version of {setDebtBatch} + */ + function setDebtBatch( + address[] calldata smartContracts, + DebtBase[] calldata debts + ) external onlyRole(DEBT_MANAGER_ROLE) { if (smartContracts.length != debts.length) { revert InvalidInputLength(); } @@ -99,8 +119,8 @@ contract DebtEngine is IDebtEngine, AccessControl, DebtEngineInvariantStorage { /* ============ ACCESS CONTROL ============ */ /* - * @dev Returns `true` if `account` has been granted `role`. - */ + * @dev Returns `true` if `account` has been granted `role`. + */ function hasRole( bytes32 role, address account @@ -111,4 +131,4 @@ contract DebtEngine is IDebtEngine, AccessControl, DebtEngineInvariantStorage { } return AccessControl.hasRole(role, account); } -} \ No newline at end of file +} diff --git a/src/DebtEngineInvariantStorage.sol b/src/DebtEngineInvariantStorage.sol index 148ad1f..7f4ac82 100644 --- a/src/DebtEngineInvariantStorage.sol +++ b/src/DebtEngineInvariantStorage.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; -contract DebtEngineInvariantStorage { +contract DebtEngineInvariantStorage { // CreditEvents bytes32 public constant CREDIT_EVENTS_MANAGER_ROLE = - keccak256("CREDIT_EVENTS_MANAGER_ROLE"); + keccak256("CREDIT_EVENTS_MANAGER_ROLE"); // DebtModule bytes32 public constant DEBT_MANAGER_ROLE = keccak256("DEBT_MANAGER_ROLE"); @@ -12,5 +12,4 @@ contract DebtEngineInvariantStorage { // custom error error AdminAddressZeroNotAllowed(); error InvalidInputLength(); - -} \ No newline at end of file +} diff --git a/test/DebtEngine.t.sol b/test/DebtEngine.t.sol index f7b7b60..c7686e8 100644 --- a/test/DebtEngine.t.sol +++ b/test/DebtEngine.t.sol @@ -8,7 +8,12 @@ import {IDebtGlobal} from "CMTAT/interfaces/IDebtGlobal.sol"; import "../src/DebtEngineInvariantStorage.sol"; import "OZ/access/AccessControl.sol"; import "CMTAT/CMTAT_STANDALONE.sol"; -contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariantStorage { +contract DebtEngineTest is + Test, + AccessControl, + IDebtGlobal, + DebtEngineInvariantStorage +{ DebtEngine private debtEngine; address private admin = address(0x1); address private attacker = address(0x2); @@ -19,78 +24,93 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant CMTAT_STANDALONE cmtat; // Sample data for DebtBase and CreditEvents - DebtEngine.DebtBase private debtSample = DebtBase({ - interestRate: 5, - parValue: 1000, - guarantor: "Guarantor A", - bondHolder: "Bond Holder B", - maturityDate: "2025-01-01", - interestScheduleFormat: "Annual", - interestPaymentDate: "2024-12-31", - dayCountConvention: "30/360", - businessDayConvention: "Modified Following", - publicHolidaysCalendar: "US", - issuanceDate: "2023-01-01", - couponFrequency: "Semi-Annual" - }); - - DebtEngine.CreditEvents private creditEventSample = CreditEvents({ - flagDefault: false, - flagRedeemed: true, - rating: "AAA" - }); - + DebtEngine.DebtBase private debtSample = + DebtBase({ + interestRate: 5, + parValue: 1000, + guarantor: "Guarantor A", + bondHolder: "Bond Holder B", + maturityDate: "2025-01-01", + interestScheduleFormat: "Annual", + interestPaymentDate: "2024-12-31", + dayCountConvention: "30/360", + businessDayConvention: "Modified Following", + publicHolidaysCalendar: "US", + issuanceDate: "2023-01-01", + couponFrequency: "Semi-Annual" + }); + + DebtEngine.CreditEvents private creditEventSample = + CreditEvents({flagDefault: false, flagRedeemed: true, rating: "AAA"}); // Sample data for DebtBase and CreditEvents - DebtEngine.DebtBase private debtSample1 = DebtBase({ - interestRate: 5, - parValue: 1000, - guarantor: "Guarantor A", - bondHolder: "Bond Holder B", - maturityDate: "2025-01-01", - interestScheduleFormat: "Annual", - interestPaymentDate: "2024-12-31", - dayCountConvention: "30/360", - businessDayConvention: "Modified Following", - publicHolidaysCalendar: "US", - issuanceDate: "2023-01-01", - couponFrequency: "Semi-Annual" - }); - - DebtEngine.DebtBase private debtSample2 = DebtBase({ - interestRate: 6, - parValue: 2000, - guarantor: "Guarantor B", - bondHolder: "Bond Holder C", - maturityDate: "2026-01-01", - interestScheduleFormat: "Monthly", - interestPaymentDate: "2025-12-31", - dayCountConvention: "Actual/Actual", - businessDayConvention: "Following", - publicHolidaysCalendar: "UK", - issuanceDate: "2024-01-01", - couponFrequency: "Quarterly" - }); - - DebtEngine.CreditEvents private creditEventSample1 = CreditEvents({ - flagDefault: false, - flagRedeemed: true, - rating: "AAA" - }); - - DebtEngine.CreditEvents private creditEventSample2 = CreditEvents({ - flagDefault: true, - flagRedeemed: false, - rating: "BBB" - }); + DebtEngine.DebtBase private debtSample1 = + DebtBase({ + interestRate: 5, + parValue: 1000, + guarantor: "Guarantor A", + bondHolder: "Bond Holder B", + maturityDate: "2025-01-01", + interestScheduleFormat: "Annual", + interestPaymentDate: "2024-12-31", + dayCountConvention: "30/360", + businessDayConvention: "Modified Following", + publicHolidaysCalendar: "US", + issuanceDate: "2023-01-01", + couponFrequency: "Semi-Annual" + }); + + DebtEngine.DebtBase private debtSample2 = + DebtBase({ + interestRate: 6, + parValue: 2000, + guarantor: "Guarantor B", + bondHolder: "Bond Holder C", + maturityDate: "2026-01-01", + interestScheduleFormat: "Monthly", + interestPaymentDate: "2025-12-31", + dayCountConvention: "Actual/Actual", + businessDayConvention: "Following", + publicHolidaysCalendar: "UK", + issuanceDate: "2024-01-01", + couponFrequency: "Quarterly" + }); + + DebtEngine.CreditEvents private creditEventSample1 = + CreditEvents({flagDefault: false, flagRedeemed: true, rating: "AAA"}); + + DebtEngine.CreditEvents private creditEventSample2 = + CreditEvents({flagDefault: true, flagRedeemed: false, rating: "BBB"}); function setUp() public { // Deploy the DebtEngine contract with admin role debtEngine = new DebtEngine(admin); - ICMTATConstructor.ERC20Attributes memory erc20Attributes = ICMTATConstructor.ERC20Attributes('CMTA Token', 'CMTAT', 0); - ICMTATConstructor.BaseModuleAttributes memory baseModuleAttributes = ICMTATConstructor.BaseModuleAttributes('CMTAT_ISIN', 'https://cmta.ch', 'CMTAT_info'); - ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine(IRuleEngine(AddressZero), IDebtEngine(AddressZero), IAuthorizationEngine(AddressZero), IERC1643(AddressZero)); - cmtat = new CMTAT_STANDALONE(AddressZero, admin, erc20Attributes, baseModuleAttributes, engines); + ICMTATConstructor.ERC20Attributes + memory erc20Attributes = ICMTATConstructor.ERC20Attributes( + "CMTA Token", + "CMTAT", + 0 + ); + ICMTATConstructor.BaseModuleAttributes + memory baseModuleAttributes = ICMTATConstructor + .BaseModuleAttributes( + "CMTAT_ISIN", + "https://cmta.ch", + "CMTAT_info" + ); + ICMTATConstructor.Engine memory engines = ICMTATConstructor.Engine( + IRuleEngine(AddressZero), + IDebtEngine(AddressZero), + IAuthorizationEngine(AddressZero), + IERC1643(AddressZero) + ); + cmtat = new CMTAT_STANDALONE( + AddressZero, + admin, + erc20Attributes, + baseModuleAttributes, + engines + ); } function testSetDebtAsAdmin() public { @@ -126,7 +146,9 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant // Act // Verify that credit events were set correctly - DebtEngine.CreditEvents memory credit = debtEngine.creditEvents(testContract); + DebtEngine.CreditEvents memory credit = debtEngine.creditEvents( + testContract + ); assertEq(credit.flagDefault, false); assertEq(credit.flagRedeemed, true); assertEq(credit.rating, "AAA"); @@ -143,7 +165,7 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant CREDIT_EVENTS_MANAGER_ROLE ) ); - debtEngine.setCreditEvents(testContract, creditEventSample) ; + debtEngine.setCreditEvents(testContract, creditEventSample); } function testCanReturnCMTATDebt() public { @@ -164,7 +186,6 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant vm.prank(admin); debtEngine.setCreditEvents(address(cmtat), creditEventSample); - vm.prank(admin); cmtat.setDebtEngine(debtEngine); @@ -174,7 +195,7 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant assertEq(credit.flagRedeemed, true); } - function testSetDebtsBatchAsAdmin() public { + function testSetDebtsBatchAsAdmin() public { // Call as admin to set multiple debts address[] memory contracts = new address[](2); contracts[0] = testContract1; @@ -224,7 +245,8 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant contracts[0] = testContract1; contracts[1] = testContract2; - DebtEngine.CreditEvents[] memory creditEventsList = new DebtEngine.CreditEvents[](2); + DebtEngine.CreditEvents[] + memory creditEventsList = new DebtEngine.CreditEvents[](2); creditEventsList[0] = creditEventSample1; creditEventsList[1] = creditEventSample2; @@ -232,11 +254,15 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant debtEngine.setCreditEventsBatch(contracts, creditEventsList); // Verify that both credit events were set correctly - DebtEngine.CreditEvents memory credit1 = debtEngine.creditEvents(testContract1); + DebtEngine.CreditEvents memory credit1 = debtEngine.creditEvents( + testContract1 + ); assertEq(credit1.flagDefault, false); assertEq(credit1.rating, "AAA"); - DebtEngine.CreditEvents memory credit2 = debtEngine.creditEvents(testContract2); + DebtEngine.CreditEvents memory credit2 = debtEngine.creditEvents( + testContract2 + ); assertEq(credit2.flagDefault, true); assertEq(credit2.rating, "BBB"); } @@ -247,7 +273,8 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant contracts[0] = testContract1; contracts[1] = testContract2; - DebtEngine.CreditEvents[] memory creditEventsList = new DebtEngine.CreditEvents[](2); + DebtEngine.CreditEvents[] + memory creditEventsList = new DebtEngine.CreditEvents[](2); creditEventsList[0] = creditEventSample1; creditEventsList[1] = creditEventSample2; @@ -281,7 +308,8 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant address[] memory contracts = new address[](1); contracts[0] = testContract1; - DebtEngine.CreditEvents[] memory creditEventsList = new DebtEngine.CreditEvents[](2); + DebtEngine.CreditEvents[] + memory creditEventsList = new DebtEngine.CreditEvents[](2); creditEventsList[0] = creditEventSample1; creditEventsList[1] = creditEventSample2; @@ -289,4 +317,4 @@ contract DebtEngineTest is Test, AccessControl, IDebtGlobal, DebtEngineInvariant vm.expectRevert(abi.encodeWithSelector(InvalidInputLength.selector)); debtEngine.setCreditEventsBatch(contracts, creditEventsList); } -} \ No newline at end of file +}