diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..ff8f3f4 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,55 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + build: + name: Build + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: foundry-rs/foundry-toolchain@v1 + with: + version: stable + + - name: Build + run: forge build + + - name: Contract sizes (informational) + run: forge build --sizes || true + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: foundry-rs/foundry-toolchain@v1 + with: + version: stable + + - name: Run tests + run: forge test -v + + fmt: + name: Format + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: recursive + + - uses: foundry-rs/foundry-toolchain@v1 + with: + version: stable + + - name: Check formatting + run: forge fmt --check diff --git a/src/interfaces/IB20.sol b/src/interfaces/IB20.sol index f8f2151..6901ecc 100644 --- a/src/interfaces/IB20.sol +++ b/src/interfaces/IB20.sol @@ -516,7 +516,7 @@ interface IB20 { /// @notice Updates the token's `name`. Requires `METADATA_ROLE`. /// No length restrictions. Emits `NameUpdated` followed by /// the ERC-5267 `EIP712DomainChanged()` event (in that - /// order). + /// order). /// @dev Several customers (Coinbase Tokenized Equities, Coinbase /// Wrapped Assets) need the ability to update name and symbol /// post-deployment for re-branding or legal-restructuring diff --git a/src/lib/B20FactoryLib.sol b/src/lib/B20FactoryLib.sol index fe7dee4..487be26 100644 --- a/src/lib/B20FactoryLib.sol +++ b/src/lib/B20FactoryLib.sol @@ -146,10 +146,7 @@ library B20FactoryLib { { return abi.encode( IB20Factory.B20CreateParams({ - version: B20_CREATE_PARAMS_VERSION, - name: name, - symbol: symbol, - initialAdmin: initialAdmin + version: B20_CREATE_PARAMS_VERSION, name: name, symbol: symbol, initialAdmin: initialAdmin }) ); } @@ -399,11 +396,7 @@ library B20FactoryLib { /// @param holders The security role-holder bundle. /// /// @return initCalls The ABI-encoded `grantRole` initCalls. - function buildRoleGrants(B20SecurityRoleHolders memory holders) - internal - pure - returns (bytes[] memory initCalls) - { + function buildRoleGrants(B20SecurityRoleHolders memory holders) internal pure returns (bytes[] memory initCalls) { bytes32[] memory roles = new bytes32[](8); roles[0] = B20Constants.MINT_ROLE; roles[1] = B20Constants.BURN_ROLE; diff --git a/test/lib/B20FactoryLibTest.sol b/test/lib/B20FactoryLibTest.sol index 30d6cff..7eefc7e 100644 --- a/test/lib/B20FactoryLibTest.sol +++ b/test/lib/B20FactoryLibTest.sol @@ -17,5 +17,5 @@ import {BaseTest} from "test/lib/BaseTest.sol"; /// Re-using those gives the test contracts a uniform vocabulary with /// the rest of the suite. No `setUp` extension is needed. contract B20FactoryLibTest is BaseTest { -// No additional state; `BaseTest`'s actor labels and helpers are sufficient. + // No additional state; `BaseTest`'s actor labels and helpers are sufficient. } diff --git a/test/lib/PolicyRegistryTest.sol b/test/lib/PolicyRegistryTest.sol index 598667d..c9be657 100644 --- a/test/lib/PolicyRegistryTest.sol +++ b/test/lib/PolicyRegistryTest.sol @@ -58,8 +58,7 @@ contract PolicyRegistryTest is BaseTest { /// sentinels before consuming it; the prediction matches by /// clamping pre-init reads up to `BUILTIN_POLICY_COUNT`. function _predictNextPolicyId(IPolicyRegistry.PolicyType policyType) internal view returns (uint64) { - uint56 counter = - uint56(uint256(vm.load(address(policyRegistry), MockPolicyRegistryStorage.nextCounterSlot()))); + uint56 counter = uint56(uint256(vm.load(address(policyRegistry), MockPolicyRegistryStorage.nextCounterSlot()))); if (counter < PolicyRegistryConstants.BUILTIN_POLICY_COUNT) { counter = PolicyRegistryConstants.BUILTIN_POLICY_COUNT; } diff --git a/test/lib/mocks/MockB20Factory.sol b/test/lib/mocks/MockB20Factory.sol index f180050..7cdec8f 100644 --- a/test/lib/mocks/MockB20Factory.sol +++ b/test/lib/mocks/MockB20Factory.sol @@ -313,11 +313,7 @@ contract MockB20Factory is IB20Factory { function _writeSecurityStorage(address token, string memory isin_, uint256 minimumRedeemable_) internal { _writeString(token, MockB20SecurityStorage.identifierSlot("ISIN"), isin_); _writeUint(token, MockB20RedeemStorage.minimumRedeemableSlot(), minimumRedeemable_); - _writeUint( - token, - MockB20RedeemStorage.redeemPolicyIdsSlot(), - uint256(PolicyRegistryConstants.ALWAYS_BLOCK_ID) - ); + _writeUint(token, MockB20RedeemStorage.redeemPolicyIdsSlot(), uint256(PolicyRegistryConstants.ALWAYS_BLOCK_ID)); } // ============================================================ diff --git a/test/lib/mocks/MockB20Storage.sol b/test/lib/mocks/MockB20Storage.sol index a3e91c0..cd8e161 100644 --- a/test/lib/mocks/MockB20Storage.sol +++ b/test/lib/mocks/MockB20Storage.sol @@ -407,10 +407,13 @@ library MockB20SecurityStorage { // TOP-LEVEL FIELD SLOTS // ============================================================ + // forgefmt: disable-start function sharesToTokensRatioSlot() internal pure returns (bytes32) { return slotOf(SHARES_TO_TOKENS_RATIO_OFFSET); } function usedAnnouncementIdsBaseSlot() internal pure returns (bytes32) { return slotOf(USED_ANNOUNCEMENT_IDS_OFFSET); } function identifiersBaseSlot() internal pure returns (bytes32) { return slotOf(IDENTIFIERS_OFFSET); } + // forgefmt: disable-end + // ============================================================ // MAPPING MEMBER SLOTS // ============================================================ @@ -493,8 +496,10 @@ library MockB20RedeemStorage { // TOP-LEVEL FIELD SLOTS // ============================================================ + // forgefmt: disable-start function minimumRedeemableSlot() internal pure returns (bytes32) { return slotOf(MINIMUM_REDEEMABLE_OFFSET); } function redeemPolicyIdsSlot() internal pure returns (bytes32) { return slotOf(REDEEM_POLICY_IDS_OFFSET); } + // forgefmt: disable-end } /// @title MockB20StablecoinStorage diff --git a/test/unit/B20/roles/renounceLastAdmin.t.sol b/test/unit/B20/roles/renounceLastAdmin.t.sol index c19e979..1c1698a 100644 --- a/test/unit/B20/roles/renounceLastAdmin.t.sol +++ b/test/unit/B20/roles/renounceLastAdmin.t.sol @@ -129,21 +129,14 @@ contract B20RenounceLastAdminTest is B20Test { /// here too. function test_renounceLastAdmin_success_adminCountDrivenToZero() public { bytes32 adminCountSlot = MockB20Storage.adminCountSlot(); - assertEq( - uint256(vm.load(address(token), adminCountSlot)), 1, "precondition: adminCount is 1" - ); + assertEq(uint256(vm.load(address(token), adminCountSlot)), 1, "precondition: adminCount is 1"); _assertInitialized(address(token), "precondition: initialized marker is set"); vm.prank(admin); token.renounceLastAdmin(); - assertEq( - uint256(vm.load(address(token), adminCountSlot)), 0, "adminCount must be 0 post-renounce" - ); - _assertInitialized( - address(token), - "initialized marker must remain set (renounce only clears adminCount)" - ); + assertEq(uint256(vm.load(address(token), adminCountSlot)), 0, "adminCount must be 0 post-renounce"); + _assertInitialized(address(token), "initialized marker must remain set (renounce only clears adminCount)"); } /// @notice Verifies renounceLastAdmin emits LastAdminRenounced(previousAdmin) diff --git a/test/unit/B20/roles/renounceRole.t.sol b/test/unit/B20/roles/renounceRole.t.sol index 0a8fc1e..8188559 100644 --- a/test/unit/B20/roles/renounceRole.t.sol +++ b/test/unit/B20/roles/renounceRole.t.sol @@ -112,9 +112,7 @@ contract B20RenounceRoleTest is B20Test { uint256(1), "roles[ADMIN][otherAdmin] slot must still be set" ); - assertEq( - uint256(vm.load(address(token), MockB20Storage.adminCountSlot())), 1, "adminCount must drop to 1" - ); + assertEq(uint256(vm.load(address(token), MockB20Storage.adminCountSlot())), 1, "adminCount must drop to 1"); _assertInitialized(address(token), "initialized marker must stay set"); } diff --git a/test/unit/B20Factory/createToken.t.sol b/test/unit/B20Factory/createToken.t.sol index 5489807..30fed40 100644 --- a/test/unit/B20Factory/createToken.t.sol +++ b/test/unit/B20Factory/createToken.t.sol @@ -63,7 +63,9 @@ contract B20FactoryCreateB20Test is B20FactoryTest { IB20Factory.B20CreateParams memory p = _b20Params(); p.version = badVersion; vm.prank(caller); - vm.expectRevert(abi.encodeWithSelector(IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.DEFAULT)); + vm.expectRevert( + abi.encodeWithSelector(IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.DEFAULT) + ); factory.createB20(IB20Factory.B20Variant.DEFAULT, salt, abi.encode(p), new bytes[](0)); } @@ -78,7 +80,11 @@ contract B20FactoryCreateB20Test is B20FactoryTest { IB20Factory.B20StablecoinCreateParams memory p = _stablecoinParams(); p.version = badVersion; vm.prank(caller); - vm.expectRevert(abi.encodeWithSelector(IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.STABLECOIN)); + vm.expectRevert( + abi.encodeWithSelector( + IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.STABLECOIN + ) + ); factory.createB20(IB20Factory.B20Variant.STABLECOIN, salt, abi.encode(p), new bytes[](0)); } @@ -108,15 +114,15 @@ contract B20FactoryCreateB20Test is B20FactoryTest { /// @notice Verifies createToken reverts for any unsupported version byte on the SECURITY variant /// @dev Each variant arm has its own version check; this exercises the security arm's check. - function test_createB20_revert_unsupportedVersion_security(address caller, uint8 badVersion, bytes32 salt) - public - { + function test_createB20_revert_unsupportedVersion_security(address caller, uint8 badVersion, bytes32 salt) public { _assumeValidCaller(caller); vm.assume(badVersion != 1); IB20Factory.B20SecurityCreateParams memory p = _securityParams(); p.version = badVersion; vm.prank(caller); - vm.expectRevert(abi.encodeWithSelector(IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.SECURITY)); + vm.expectRevert( + abi.encodeWithSelector(IB20Factory.UnsupportedVersion.selector, badVersion, IB20Factory.B20Variant.SECURITY) + ); factory.createB20(IB20Factory.B20Variant.SECURITY, salt, abi.encode(p), new bytes[](0)); } @@ -251,9 +257,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { /// `base.b20.security` namespace and `minimumRedeemable` at the /// `base.b20.redeem` namespace. Paired slot assertions confirm both fields /// land at the expected slots with the correct encodings. - function test_createB20_success_securitySeedsInitialState(address caller, bytes32 salt, uint256 minRedeem) - public - { + function test_createB20_success_securitySeedsInitialState(address caller, bytes32 salt, uint256 minRedeem) public { _assumeValidCaller(caller); IB20Factory.B20SecurityCreateParams memory p = _securityParams("Security Test", "SEC", admin, APPLE_ISIN, minRedeem); @@ -297,11 +301,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { PolicyRegistryConstants.ALWAYS_BLOCK_ID, "redeemPolicyIds slot lane 0 must hold ALWAYS_BLOCK_ID" ); - assertEq( - packed >> 64, - uint256(0), - "redeemPolicyIds slot reserved lanes must be zero on a fresh token" - ); + assertEq(packed >> 64, uint256(0), "redeemPolicyIds slot reserved lanes must be zero on a fresh token"); } /// @notice Verifies the security REDEEM_SENDER_POLICY default does NOT leak into other @@ -310,9 +310,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { /// namespace (`base.b20.redeem`); the base packed policy slots (`transferPolicyIds`, /// `mintPolicyIds` in the base `base.b20` namespace) must remain at their EVM zero /// defaults so the four base scopes still read as ALWAYS_ALLOW_ID. - function test_createB20_success_securityOtherPolicySlotsDefaultToAllow(address caller, bytes32 salt) - public - { + function test_createB20_success_securityOtherPolicySlotsDefaultToAllow(address caller, bytes32 salt) public { _assumeValidCaller(caller); address token = _createSecurity(caller, salt, _securityParams(), new bytes[](0)); @@ -355,9 +353,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { /// in `initCalls`. The privileged-window bypass on the token means the factory-originated /// call succeeds without the role check. Post-creation the slot reflects the overridden /// value, NOT the factory-seeded default. - function test_createB20_success_securityRedeemPolicyOverridableViaInitCall(address caller, bytes32 salt) - public - { + function test_createB20_success_securityRedeemPolicyOverridableViaInitCall(address caller, bytes32 salt) public { _assumeValidCaller(caller); bytes[] memory initCalls = new bytes[](1); initCalls[0] = abi.encodeWithSelector( @@ -404,11 +400,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { assertFalse(MockB20(token).hasRole(B20Constants.DEFAULT_ADMIN_ROLE, caller), "caller must not hold admin"); assertEq(IB20Security(token).securityIdentifier(IDENTIFIER_ISIN), DEFAULT_ISIN, "ISIN must still be set"); - assertEq( - uint256(vm.load(token, MockB20Storage.adminCountSlot())), - 0, - "adminCount must be 0 on zero-admin path" - ); + assertEq(uint256(vm.load(token, MockB20Storage.adminCountSlot())), 0, "adminCount must be 0 on zero-admin path"); _assertInitialized(token, "initialized must still be set on zero-admin path"); } @@ -444,11 +436,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { _stablecoinParams("Test", "TST", admin, xFiat[i]), new bytes[](0) ); - assertEq( - IB20Stablecoin(token).currency(), - xFiat[i], - "multi-country X-prefix fiat code must round-trip" - ); + assertEq(IB20Stablecoin(token).currency(), xFiat[i], "multi-country X-prefix fiat code must round-trip"); } } @@ -471,8 +459,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { /// way the default emitter test pins decimals=18. function test_createB20_success_emitsB20Created_security(address caller, bytes32 salt) public { _assumeValidCaller(caller); - IB20Factory.B20SecurityCreateParams memory p = - _securityParams("Security Test", "SEC", admin, DEFAULT_ISIN, 0); + IB20Factory.B20SecurityCreateParams memory p = _securityParams("Security Test", "SEC", admin, DEFAULT_ISIN, 0); address predicted = factory.getB20Address(IB20Factory.B20Variant.SECURITY, caller, salt); vm.expectEmit(true, true, false, true, address(factory)); @@ -517,9 +504,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { "factory must NOT appear in roles[ADMIN] slot" ); assertEq( - uint256(vm.load(token, MockB20Storage.adminCountSlot())), - 1, - "adminCount must be 1 after bootstrap grant" + uint256(vm.load(token, MockB20Storage.adminCountSlot())), 1, "adminCount must be 1 after bootstrap grant" ); _assertInitialized(token, "initialized marker must be set after bootstrap closes"); } @@ -590,11 +575,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { // Paired slot assertion: packed adminCount lane is 0 (no // bootstrap grant happened) but the initialized bit is still // set (the factory closed the bootstrap window after returning). - assertEq( - uint256(vm.load(token, MockB20Storage.adminCountSlot())), - 0, - "adminCount must be 0 on zero-admin path" - ); + assertEq(uint256(vm.load(token, MockB20Storage.adminCountSlot())), 0, "adminCount must be 0 on zero-admin path"); _assertInitialized(token, "initialized must still be set on zero-admin path"); } @@ -613,11 +594,7 @@ contract B20FactoryCreateB20Test is B20FactoryTest { // The stablecoin still got its variant data: currency is set. assertEq(IB20Stablecoin(token).currency(), "USD", "stablecoin currency must still be set"); - assertEq( - uint256(vm.load(token, MockB20Storage.adminCountSlot())), - 0, - "adminCount must be 0 on zero-admin path" - ); + assertEq(uint256(vm.load(token, MockB20Storage.adminCountSlot())), 0, "adminCount must be 0 on zero-admin path"); _assertInitialized(token, "initialized must still be set on zero-admin path"); assertEq( vm.load(token, MockB20StablecoinStorage.currencySlot()), diff --git a/test/unit/B20Factory/getTokenAddress.t.sol b/test/unit/B20Factory/getTokenAddress.t.sol index 37adc07..8a69761 100644 --- a/test/unit/B20Factory/getTokenAddress.t.sol +++ b/test/unit/B20Factory/getTokenAddress.t.sol @@ -11,10 +11,7 @@ contract B20FactoryGetTokenAddressTest is B20FactoryTest { /// is happy with the raw byte but Solidity reverts at function entry on an /// out-of-range enum input from a fuzzer. function _boundVariant(uint8 variantInt) internal pure returns (IB20Factory.B20Variant) { - return - IB20Factory.B20Variant( - uint8(bound(uint256(variantInt), 0, uint256(type(IB20Factory.B20Variant).max))) - ); + return IB20Factory.B20Variant(uint8(bound(uint256(variantInt), 0, uint256(type(IB20Factory.B20Variant).max)))); } /// @notice Verifies getTokenAddress is deterministic for the same inputs diff --git a/test/unit/B20FactoryLib/buildRoleGrants.t.sol b/test/unit/B20FactoryLib/buildRoleGrants.t.sol index 9e7974c..823a532 100644 --- a/test/unit/B20FactoryLib/buildRoleGrants.t.sol +++ b/test/unit/B20FactoryLib/buildRoleGrants.t.sol @@ -174,9 +174,7 @@ contract B20FactoryLibBuildRoleGrantsTest is B20FactoryLibTest { assertEq(result[3], abi.encodeCall(IB20.grantRole, (B20Constants.PAUSE_ROLE, pauser_)), "3: PAUSE_ROLE"); assertEq(result[4], abi.encodeCall(IB20.grantRole, (B20Constants.UNPAUSE_ROLE, unpauser_)), "4: UNPAUSE_ROLE"); assertEq( - result[5], - abi.encodeCall(IB20.grantRole, (B20Constants.METADATA_ROLE, metadataAdmin_)), - "5: METADATA_ROLE" + result[5], abi.encodeCall(IB20.grantRole, (B20Constants.METADATA_ROLE, metadataAdmin_)), "5: METADATA_ROLE" ); } @@ -279,9 +277,7 @@ contract B20FactoryLibBuildRoleGrantsTest is B20FactoryLibTest { assertEq(result[4], abi.encodeCall(IB20.grantRole, (B20Constants.PAUSE_ROLE, pauser_)), "4: PAUSE_ROLE"); assertEq(result[5], abi.encodeCall(IB20.grantRole, (B20Constants.UNPAUSE_ROLE, unpauser_)), "5: UNPAUSE_ROLE"); assertEq( - result[6], - abi.encodeCall(IB20.grantRole, (B20Constants.METADATA_ROLE, metadataAdmin_)), - "6: METADATA_ROLE" + result[6], abi.encodeCall(IB20.grantRole, (B20Constants.METADATA_ROLE, metadataAdmin_)), "6: METADATA_ROLE" ); assertEq( result[7], diff --git a/test/unit/B20FactoryLib/buildSecurityIdentifierUpdates.t.sol b/test/unit/B20FactoryLib/buildSecurityIdentifierUpdates.t.sol index 2c78365..a989d62 100644 --- a/test/unit/B20FactoryLib/buildSecurityIdentifierUpdates.t.sol +++ b/test/unit/B20FactoryLib/buildSecurityIdentifierUpdates.t.sol @@ -29,9 +29,7 @@ contract B20FactoryLibBuildSecurityIdentifierUpdatesTest is B20FactoryLibTest { /// `identifierValues` differ in length. /// @dev Mirrors the length-check semantics of /// `buildRoleGrants(bytes32[], address[])`. - function test_buildSecurityIdentifierUpdates_revert_lengthMismatch(uint8 typesLenSeed, uint8 valuesLenSeed) - public - { + function test_buildSecurityIdentifierUpdates_revert_lengthMismatch(uint8 typesLenSeed, uint8 valuesLenSeed) public { uint256 typesLen = bound(uint256(typesLenSeed), 0, 16); uint256 valuesLen = bound(uint256(valuesLenSeed), 0, 16); vm.assume(typesLen != valuesLen); diff --git a/test/unit/B20FactoryLib/encodeDefaultCreateParams.t.sol b/test/unit/B20FactoryLib/encodeDefaultCreateParams.t.sol index d2e20b6..21d15bb 100644 --- a/test/unit/B20FactoryLib/encodeDefaultCreateParams.t.sol +++ b/test/unit/B20FactoryLib/encodeDefaultCreateParams.t.sol @@ -37,10 +37,7 @@ contract B20FactoryLibEncodeDefaultCreateParamsTest is B20FactoryLibTest { ) public pure { bytes memory expected = abi.encode( IB20Factory.B20CreateParams({ - version: B20FactoryLib.B20_CREATE_PARAMS_VERSION, - name: name, - symbol: symbol, - initialAdmin: initialAdmin + version: B20FactoryLib.B20_CREATE_PARAMS_VERSION, name: name, symbol: symbol, initialAdmin: initialAdmin }) ); bytes memory actual = B20FactoryLib.encodeDefaultCreateParams(name, symbol, initialAdmin); diff --git a/test/unit/B20FactoryLib/encodeSecurityCreateParams.t.sol b/test/unit/B20FactoryLib/encodeSecurityCreateParams.t.sol index ac679ab..eabf720 100644 --- a/test/unit/B20FactoryLib/encodeSecurityCreateParams.t.sol +++ b/test/unit/B20FactoryLib/encodeSecurityCreateParams.t.sol @@ -19,10 +19,10 @@ contract B20FactoryLibEncodeSecurityCreateParamsTest is B20FactoryLibTest { string memory isin, uint256 minimumRedeemable ) public pure { - bytes memory blob = - B20FactoryLib.encodeSecurityCreateParams(name, symbol, initialAdmin, isin, minimumRedeemable); - IB20Factory.B20SecurityCreateParams memory decoded = - abi.decode(blob, (IB20Factory.B20SecurityCreateParams)); + bytes memory blob = B20FactoryLib.encodeSecurityCreateParams( + name, symbol, initialAdmin, isin, minimumRedeemable + ); + IB20Factory.B20SecurityCreateParams memory decoded = abi.decode(blob, (IB20Factory.B20SecurityCreateParams)); assertEq( decoded.version, diff --git a/test/unit/B20FactoryLib/encodeStablecoinCreateParams.t.sol b/test/unit/B20FactoryLib/encodeStablecoinCreateParams.t.sol index 375eb93..a0d1488 100644 --- a/test/unit/B20FactoryLib/encodeStablecoinCreateParams.t.sol +++ b/test/unit/B20FactoryLib/encodeStablecoinCreateParams.t.sol @@ -19,8 +19,7 @@ contract B20FactoryLibEncodeStablecoinCreateParamsTest is B20FactoryLibTest { string memory currency ) public pure { bytes memory blob = B20FactoryLib.encodeStablecoinCreateParams(name, symbol, initialAdmin, currency); - IB20Factory.B20StablecoinCreateParams memory decoded = - abi.decode(blob, (IB20Factory.B20StablecoinCreateParams)); + IB20Factory.B20StablecoinCreateParams memory decoded = abi.decode(blob, (IB20Factory.B20StablecoinCreateParams)); assertEq( decoded.version, diff --git a/test/unit/B20FactoryLib/encodeUpdatePolicy.t.sol b/test/unit/B20FactoryLib/encodeUpdatePolicy.t.sol index 5f81f78..f058740 100644 --- a/test/unit/B20FactoryLib/encodeUpdatePolicy.t.sol +++ b/test/unit/B20FactoryLib/encodeUpdatePolicy.t.sol @@ -11,10 +11,7 @@ contract B20FactoryLibEncodeUpdatePolicyTest is B20FactoryLibTest { /// @dev Pins both the selector and the (bytes32, uint64) argument /// order. A swapped-arg regression would land scope bytes in /// the policy-id slot and vice versa. - function test_encodeUpdatePolicy_success_matchesAbiEncodeCall(bytes32 policyScope, uint64 newPolicyId) - public - pure - { + function test_encodeUpdatePolicy_success_matchesAbiEncodeCall(bytes32 policyScope, uint64 newPolicyId) public pure { bytes memory expected = abi.encodeCall(IB20.updatePolicy, (policyScope, newPolicyId)); bytes memory actual = B20FactoryLib.encodeUpdatePolicy(policyScope, newPolicyId); assertEq(actual, expected, "init-call must match abi.encodeCall(IB20.updatePolicy, ...)"); diff --git a/test/unit/PolicyRegistry/writeBuiltins.t.sol b/test/unit/PolicyRegistry/writeBuiltins.t.sol index 54dec68..4ee97bd 100644 --- a/test/unit/PolicyRegistry/writeBuiltins.t.sol +++ b/test/unit/PolicyRegistry/writeBuiltins.t.sol @@ -30,16 +30,14 @@ contract PolicyRegistryWriteBuiltinsTest is PolicyRegistryTest { // Sanity: sentinel slots start empty before any create. assertEq( vm.load( - address(policyRegistry), - MockPolicyRegistryStorage.policySlot(PolicyRegistryConstants.ALWAYS_ALLOW_ID) + address(policyRegistry), MockPolicyRegistryStorage.policySlot(PolicyRegistryConstants.ALWAYS_ALLOW_ID) ), bytes32(0), "ALWAYS_ALLOW_ID slot must be empty before init" ); assertEq( vm.load( - address(policyRegistry), - MockPolicyRegistryStorage.policySlot(PolicyRegistryConstants.ALWAYS_BLOCK_ID) + address(policyRegistry), MockPolicyRegistryStorage.policySlot(PolicyRegistryConstants.ALWAYS_BLOCK_ID) ), bytes32(0), "ALWAYS_BLOCK_ID slot must be empty before init" diff --git a/test/unit/storage/B20FullLayout.t.sol b/test/unit/storage/B20FullLayout.t.sol index a379911..e16dbe9 100644 --- a/test/unit/storage/B20FullLayout.t.sol +++ b/test/unit/storage/B20FullLayout.t.sol @@ -57,6 +57,7 @@ contract B20FullLayoutTest is B20Test { uint64 internal transferReceiverMarker; uint64 internal transferExecutorMarker; uint64 internal mintReceiverMarker; + /// @notice Cross-cuts every field of MockB20Storage.Layout in a single /// populated snapshot. /// @dev Setup writes non-default values to every reachable storage @@ -179,11 +180,7 @@ contract B20FullLayoutTest is B20Test { assertEq(packedTransfer >> 192, 0, "slot 9 bits 192..255: reserved lane must be zero"); uint256 packedMint = uint256(vm.load(tokenAddr, MockB20Storage.mintPolicyIdsSlot())); - assertEq( - packedMint & 0xFFFFFFFFFFFFFFFF, - uint256(mintReceiverMarker), - "slot 10 bits 0..63: mint RECEIVER lane" - ); + assertEq(packedMint & 0xFFFFFFFFFFFFFFFF, uint256(mintReceiverMarker), "slot 10 bits 0..63: mint RECEIVER lane"); assertEq(packedMint >> 64, 0, "slot 10 bits 64..255: three reserved lanes must be zero"); // ---------- pausedVectors (slot 11) ---------- @@ -198,7 +195,9 @@ contract B20FullLayoutTest is B20Test { assertEq(pausedRaw, expectedPaused, "slot 11: pausedVectors must hold exactly the four defined bits"); // No bits set outside the defined PausableFeature range. Computed // as the complement of the union of all defined bits. - assertEq(pausedRaw & ~expectedPaused, 0, "slot 11: no bits may be set outside the defined PausableFeature range"); + assertEq( + pausedRaw & ~expectedPaused, 0, "slot 11: no bits may be set outside the defined PausableFeature range" + ); // ---------- supplyCap (slot 12) ---------- assertEq(uint256(vm.load(tokenAddr, MockB20Storage.supplyCapSlot())), token.supplyCap(), "slot 12: supplyCap"); @@ -265,14 +264,12 @@ contract B20FullLayoutTest is B20Test { // precondition rejects arbitrary uint64s, so we can't use synthetic // hex markers like `0x1111...`. Mixing ALLOWLIST + BLOCKLIST types // makes the top byte vary between lanes too, not just the counter. - transferSenderMarker = - StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST); + transferSenderMarker = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST); transferReceiverMarker = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.BLOCKLIST); transferExecutorMarker = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST); - mintReceiverMarker = - StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.BLOCKLIST); + mintReceiverMarker = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.BLOCKLIST); _setPolicy(B20Constants.TRANSFER_SENDER_POLICY, transferSenderMarker); _setPolicy(B20Constants.TRANSFER_RECEIVER_POLICY, transferReceiverMarker); _setPolicy(B20Constants.TRANSFER_EXECUTOR_POLICY, transferExecutorMarker); diff --git a/test/unit/storage/B20SecurityFullLayout.t.sol b/test/unit/storage/B20SecurityFullLayout.t.sol index 7cbc1f0..0055137 100644 --- a/test/unit/storage/B20SecurityFullLayout.t.sol +++ b/test/unit/storage/B20SecurityFullLayout.t.sol @@ -139,11 +139,7 @@ contract B20SecurityFullLayoutTest is B20SecurityTest { uint256(redeemSenderMarker), "redeem slot 1 bits 0..63: REDEEM_SENDER_POLICY lane must hold the marker" ); - assertEq( - packedRedeem >> 64, - uint256(0), - "redeem slot 1 bits 64..255: three reserved lanes must be zero" - ); + assertEq(packedRedeem >> 64, uint256(0), "redeem slot 1 bits 64..255: three reserved lanes must be zero"); } /// @notice Verifies the factory-seeded default in `redeemPolicyIds` @@ -154,18 +150,13 @@ contract B20SecurityFullLayoutTest is B20SecurityTest { /// (the populate's `_setRedeemPolicy` would overwrite whatever /// the seed left behind). function test_b20SecurityLayout_success_freshTokenSeedsRedeemPolicyToBlock() public view { - uint256 packedRedeem = - uint256(vm.load(address(token), MockB20RedeemStorage.redeemPolicyIdsSlot())); + uint256 packedRedeem = uint256(vm.load(address(token), MockB20RedeemStorage.redeemPolicyIdsSlot())); assertEq( packedRedeem & 0xFFFFFFFFFFFFFFFF, uint256(PolicyRegistryConstants.ALWAYS_BLOCK_ID), "fresh token: redeem slot 1 bits 0..63 must be ALWAYS_BLOCK_ID from factory seed" ); - assertEq( - packedRedeem >> 64, - uint256(0), - "fresh token: redeem slot 1 bits 64..255 reserved lanes must be zero" - ); + assertEq(packedRedeem >> 64, uint256(0), "fresh token: redeem slot 1 bits 64..255 reserved lanes must be zero"); } /// @notice Verifies the `base.b20.security` and `base.b20.redeem` @@ -208,8 +199,7 @@ contract B20SecurityFullLayoutTest is B20SecurityTest { // uint64 marker. Using a fresh real policy (distinct from the // ALWAYS_BLOCK_ID default) gives us a recognizable post-write // observable. - redeemSenderMarker = - StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST); + redeemSenderMarker = StdPrecompiles.POLICY_REGISTRY.createPolicy(admin, IPolicyRegistry.PolicyType.ALLOWLIST); _setRedeemPolicy(redeemSenderMarker); } } diff --git a/test/unit/storage/PolicyRegistryFullLayout.t.sol b/test/unit/storage/PolicyRegistryFullLayout.t.sol index 04c5ca8..77b6c47 100644 --- a/test/unit/storage/PolicyRegistryFullLayout.t.sol +++ b/test/unit/storage/PolicyRegistryFullLayout.t.sol @@ -93,9 +93,7 @@ contract PolicyRegistryFullLayoutTest is PolicyRegistryTest { uint256(0), "policies[allowlistId] bits 160..254: reserved must be zero" ); - assertEq( - packedA >> 255, uint256(1), "policies[allowlistId] bit 255: exists flag must be set" - ); + assertEq(packedA >> 255, uint256(1), "policies[allowlistId] bit 255: exists flag must be set"); assertEq( MockPolicyRegistryStorage.policyTypeFromId(allowlistId), uint8(IPolicyRegistry.PolicyType.ALLOWLIST), @@ -115,9 +113,7 @@ contract PolicyRegistryFullLayoutTest is PolicyRegistryTest { uint256(0), "policies[blocklistId] bits 160..254: reserved must be zero" ); - assertEq( - packedB >> 255, uint256(1), "policies[blocklistId] bit 255: exists flag must be set" - ); + assertEq(packedB >> 255, uint256(1), "policies[blocklistId] bit 255: exists flag must be set"); assertEq( MockPolicyRegistryStorage.policyTypeFromId(blocklistId), uint8(IPolicyRegistry.PolicyType.BLOCKLIST),