Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .changeset/test-initializer-coverage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
---
"@hashgraph/asset-tokenization-contracts": patch
---

test(contracts): close branch coverage gaps in InitializerFacet and clean up redundant test file.

- add tests for the three uncovered branches in `Initializer.sol`: `ZeroValueNotAllowed` revert
on `initializeInitializer(0)`, `ZeroValueNotAllowed` on `updateMaxInitializerFacetIndex(0)`,
and `AccountHasNoRole` on `setOperationalStatus` called by a non-admin
- add test for the `if (length == 0) return` early-exit in
`InitializerStorageWrapper.checkFacetRegistered` via a new `upgradeMockFacet1AnyVersion()`
mock method that passes an empty `_fromLastVersions` array
- add test for `InitializerStorageWrapper.setConfigVersion` via `MockDiamondCut.forceNonOperational`,
covering the remaining uncovered function and verifying that forcing non-operational state
blocks `onlyOperational` guards
- fix `MockDiamondCut` BLR version reference in `deploySystemWithNewBlr.ts`: it occupies v2 of
`RESOLVER_KEY_DIAMOND` (v1 is taken by `DiamondFacetTimeTravel`), so `INITIALIZE_MOCK_VERSION_MAPS`
now pins it at `2` in both config versions
- delete `untested_initializers.test.ts`; all 10 initializer methods it covered have complete
three-case tests in their respective facet test files, making the file pure duplication
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ bytes32 constant STORAGE_LOCATION_BOND = 0xa99cdff87e8b13602d53b3661888bce1eb21f
* @custom:storage-location erc7201:security.token.standard.storage.Bond
*/
struct BondDataStorage {
// ─── R1 Lifecycle (bool flags) ───────────────────────────
bool initialized;
// ─── R2 Packed scalars (uint8, bytes3, address, enum) ────
// ─── R3 Single-slot scalars (uint256, bytes32, string) ───
// ─── R2 Single-slot scalars (uint256, bytes32, string) ───
uint256 startingDate;
uint256 maturityDate;
// ─── R4 Aggregates (mapping, array, EnumerableSet) ───────
Expand All @@ -46,7 +43,6 @@ library BondStorageWrapper {
// solhint-disable-next-line func-name-mixedcase
function initialize_bond(IBondTypes.BondDetailsData calldata bondDetailsData) internal {
BondDataStorage storage bs = _bondStorage();
bs.initialized = true;
bs.startingDate = bondDetailsData.startingDate;
bs.maturityDate = bondDetailsData.maturityDate;
}
Expand Down Expand Up @@ -109,14 +105,6 @@ library BondStorageWrapper {
principalFor_.denominator = DecimalsLib.pow10(ERC20StorageWrapper.decimalsAdjustedAt(blockTimestamp));
}

/**
* @notice Indicates whether the bond storage has been initialised.
* @return Whether {initialize_bond} has already been executed for this token.
*/
function isBondInitialized() internal view returns (bool) {
return _bondStorage().initialized;
}

/**
* @notice Reverts if the supplied maturity date does not strictly extend the current one.
* @dev Enforces a monotonic-extension invariant — maturity may only move forward in time.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ bytes32 constant STORAGE_LOCATION_EQUITY = 0x94fe8bd2c421847f50afb78366b145478e2
*/
struct EquityDataStorage {
// ─── R1 Lifecycle (bool flags) ───────────────────────────
bool initialized;
bool votingRight;
bool informationRight;
bool liquidationRight;
Expand Down Expand Up @@ -66,7 +65,6 @@ library EquityStorageWrapper {
$.redemptionRight = equityDetailsData.redemptionRight;
$.putRight = equityDetailsData.putRight;
$.dividendRight = equityDetailsData.dividendRight;
$.initialized = true;
}

/**
Expand Down Expand Up @@ -240,14 +238,6 @@ library EquityStorageWrapper {
: ERC20StorageWrapper.decimalsAdjustedAt(date);
}

/**
* @notice Indicates whether the equity storage has been initialised.
* @return Whether {initializeEquityDetails} has already been executed for this token.
*/
function isEquityInitialized() internal view returns (bool) {
return _equityStorage().initialized;
}

/**
* @notice Performs the storage write that cancels a scheduled balance adjustment.
* @param corporateActionId The corporate-action identifier linked to the balance adjustment.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,7 @@ bytes32 constant STORAGE_LOCATION_LOAN = 0x2af22e338cd16bdeda633a06c0ad54c1b9d04
* @custom:storage-location erc7201:security.token.standard.storage.Loan
*/
struct LoanDataStorage {
// ─── R1 Lifecycle (bool flags) ───────────────────────────
bool initialized;
// ─── R2 Packed scalars (uint8, bytes3, address, enum) ────
// ─── R1 Packed scalars (uint8, bytes3, address, enum) ────
bytes3 currency;
uint8 loanStructureType;
uint8 repaymentType;
Expand All @@ -58,7 +56,7 @@ struct LoanDataStorage {
uint8 performanceStatus;
address originatorAccount;
address servicerAccount;
// ─── R3 Single-slot scalars (uint256, bytes32, string) ───
// ─── R2 Single-slot scalars (uint256, bytes32, string) ───
uint256 startingDate;
uint256 maturityDate;
uint256 signingDate;
Expand Down Expand Up @@ -95,7 +93,6 @@ library LoanStorageWrapper {
*/
function initializeLoan(ILoan.LoanDetailsData calldata _loanDetailsData) internal {
LoanDataStorage storage ls = _loanStorage();
ls.initialized = true;
_writeLoanDetails(_loanDetailsData, ls);
}

Expand Down Expand Up @@ -161,14 +158,6 @@ library LoanStorageWrapper {
});
}

/**
* @notice Reports whether the loan storage has been initialised.
* @return True once `initializeLoan` has been called, false otherwise.
*/
function isLoanInitialized() internal view returns (bool) {
return _loanStorage().initialized;
}

/**
* @notice Persists every field of a `LoanDetailsData` DTO into storage.
* @dev Enum-typed source fields are narrowed to `uint8` for tight packing in
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,10 @@ bytes32 constant STORAGE_LOCATION_NOMINAL_VALUE = 0xf4ae98634996e72bf90c5471fce1
* @custom:storage-location erc7201:security.token.standard.storage.NominalValue
*/
struct NominalValueDataStorage {
// ─── R1 Lifecycle (bool flags) ───────────────────────────
// ─── R2 Packed scalars (uint8, bytes3, address, enum) ────
// ─── R1 Packed scalars (uint8, bytes3, address, enum) ────
uint8 nominalValueDecimals;
bytes3 nominalValueCurrency;
// ─── R3 Single-slot scalars (uint256, bytes32, string) ───
// ─── R2 Single-slot scalars (uint256, bytes32, string) ───
uint256 nominalValue;
// ─── R4 Aggregates (mapping, array, EnumerableSet) ───────
// ─── APPEND-ONLY ZONE BELOW ───
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ library InitializerStorageWrapper {
uint256 i;
uint256 lastVersion = InitializerStorageWrapper.getFacetLastVersion(_facetId);
uint256 length = _fromLastVersions.length;
if (length == 0) return;
while (i < length) {
if (lastVersion == _fromLastVersions[i]) {
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,13 @@ abstract contract Initializer is IInitializer, Modifiers {
/// @inheritdoc IInitializer
function initializeInitializer(
uint256 _maxInitializerFacetIndex
) external onlyFacetNotRegistered(RESOLVER_KEY_INITIALIZER) onlyRole(DEFAULT_ADMIN_ROLE) {
)
external
override
notZeroValue(_maxInitializerFacetIndex)
onlyFacetNotRegistered(RESOLVER_KEY_INITIALIZER)
onlyRole(DEFAULT_ADMIN_ROLE)
{
InitializerStorageWrapper.setMaxInitializerFacetIndex(_maxInitializerFacetIndex);
InitializerStorageWrapper.setFacetToReady(RESOLVER_KEY_INITIALIZER);
emit InitializerInitialized(_maxInitializerFacetIndex);
Expand All @@ -23,13 +29,18 @@ abstract contract Initializer is IInitializer, Modifiers {
/// @inheritdoc IInitializer
function updateMaxInitializerFacetIndex(
uint256 _newMaxInitializerFacetIndex
) external onlyRole(DEFAULT_ADMIN_ROLE) {
) external override notZeroValue(_newMaxInitializerFacetIndex) onlyRole(DEFAULT_ADMIN_ROLE) {
InitializerStorageWrapper.setMaxInitializerFacetIndex(_newMaxInitializerFacetIndex);
emit MaxInitializerFacetIndexUpdated(EvmAccessors.getMsgSender(), _newMaxInitializerFacetIndex);
}

/// @inheritdoc IInitializer
function setOperationalStatus() external returns (bool isOperational_, uint256 lastFacetIndex_) {
function setOperationalStatus()
external
override
onlyRole(DEFAULT_ADMIN_ROLE)
returns (bool isOperational_, uint256 lastFacetIndex_)
{
bytes32 configId;
uint256 versionId;
(isOperational_, lastFacetIndex_, configId, versionId) = InitializerStorageWrapper.setOperationalStatus();
Expand All @@ -46,22 +57,28 @@ abstract contract Initializer is IInitializer, Modifiers {
}

/// @inheritdoc IInitializer
function getOperationalStatus(bytes32 _configId, uint256 _versionId) external view returns (uint256 status_) {
function getOperationalStatus(
bytes32 _configId,
uint256 _versionId
) external view override returns (uint256 status_) {
status_ = InitializerStorageWrapper.getOperationalStatus(_configId, _versionId);
}

/// @inheritdoc IInitializer
function getFacetVersionStatus(bytes32 _facetId, uint256 _versionId) external view returns (uint256 status_) {
function getFacetVersionStatus(
bytes32 _facetId,
uint256 _versionId
) external view override returns (uint256 status_) {
status_ = InitializerStorageWrapper.getFacetVersionStatus(_facetId, _versionId);
}

/// @inheritdoc IInitializer
function getFacetLastVersion(bytes32 _facetId) external view returns (uint256 lastVersion_) {
function getFacetLastVersion(bytes32 _facetId) external view override returns (uint256 lastVersion_) {
lastVersion_ = InitializerStorageWrapper.getFacetLastVersion(_facetId);
}

/// @inheritdoc IInitializer
function getMaxInitializerFacetIndex() external view returns (uint256 maxInitializerFacetIndex_) {
function getMaxInitializerFacetIndex() external view override returns (uint256 maxInitializerFacetIndex_) {
maxInitializerFacetIndex_ = InitializerStorageWrapper.getMaxInitializerFacetIndex();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ abstract contract BondUSA is IBondUSA, Modifiers {
) external override onlyRole(DEFAULT_ADMIN_ROLE) onlyFacetNotRegistered(_bondInitializerKey()) {
InitializerStorageWrapper.setFacetToReady(_bondInitializerKey());
BondStorageWrapper.initialize_bond(_bondDetailsData);
emit BondUSAInitialized();
emit BondUSAInitialized(_bondDetailsData);
}

function _bondInitializerKey() internal view virtual returns (bytes32);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ interface IBondUSA is IBondTypes {
/**
* @notice Emitted once when the bond-USA capability is initialised on a token.
* @dev Fires exclusively from `initializeBondUSA`.
* @param bondDetailsData Bond configuration data initialised.
*/
event BondUSAInitialized();
event BondUSAInitialized(IBondTypes.BondDetailsData bondDetailsData);

/**
* @notice Initialises the bond-USA capability on the token.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@ abstract contract EquityUSA is IEquityUSA, Equity {
) external override onlyRole(DEFAULT_ADMIN_ROLE) onlyFacetNotRegistered(RESOLVER_KEY_EQUITY) {
InitializerStorageWrapper.setFacetToReady(RESOLVER_KEY_EQUITY);
_initializeEquity(_equityDetailsData);
emit EquityUSAInitialized();
emit EquityUSAInitialized(_equityDetailsData);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,30 @@ pragma solidity >=0.8.0 <0.9.0;
import { IEquity } from "../../layer_2/equity/IEquity.sol";

/// @custom:hash resolverKey Equity
/// @dev Resolver key used to register and resolve the Equity USA capability.
/// Must remain stable across deployments to preserve resolver compatibility.
bytes32 constant RESOLVER_KEY_EQUITY = 0x32d1b4f5d593b1e786f1c491656e2db7e35a80754244b3c5e787a03db7fcef31;

/**
* @title IEquityUSA
* @notice Interface for initialising USA-specific equity metadata on a token.
* @dev Extends the base equity interface with a one-time capability initialiser.
* Implementations are expected to enforce admin-only access and registration guards.
* @author Hashgraph
*/
interface IEquityUSA is IEquity {
/**
* @notice Emitted once when the equity-USA capability is initialised on a token.
* @dev Fires exclusively from `initializeEquityUSA`.
* @notice Emitted once when the Equity USA capability is initialised on a token.
* @param equityDetailsData The equity metadata applied during initialisation.
*/
event EquityUSAInitialized();
event EquityUSAInitialized(EquityDetailsData equityDetailsData);

/**
* @notice Initialises the equity-USA capability on the token.
* @notice Initialises the Equity USA capability on the token.
* @dev Callable once; subsequent calls revert with `FacetAlreadyRegistered`.
* Requires `DEFAULT_ADMIN_ROLE`. Called by the factory during deployment.
* Requires `DEFAULT_ADMIN_ROLE` and is intended to be called by the factory.
* Emits `EquityUSAInitialized` after successful initialisation.
* @param _equityDetailsData The equity metadata to store for the token.
*/
function initializeEquityUSA(EquityDetailsData calldata _equityDetailsData) external;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ abstract contract DiamondCutManager is AccessControl, Pause, DiamondCutManagerWr
_;
}

// TODO: Format validations in all transactions.
function createConfiguration(
bytes32 _configurationId,
FacetConfiguration[] calldata _facetConfigurations
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ pragma solidity >=0.8.0 <0.9.0;

import { ActionValidationModifiers } from "./ActionValidationModifiers.sol";
import { AdjustBalancesModifiers } from "./AdjustBalancesModifiers.sol";
import { BondModifiers } from "./BondModifiers.sol";
import { ClearingModifiers } from "./ClearingModifiers.sol";
import { CouponModifiers } from "./CouponModifiers.sol";
import { ComplianceModifiers } from "./ComplianceModifiers.sol";
import { EquityModifiers } from "./EquityModifiers.sol";
import { ERC1410Modifiers } from "./ERC1410Modifiers.sol";
import { ERC3643Modifiers } from "./ERC3643Modifiers.sol";
import { ExpirationModifiers } from "./ExpirationModifiers.sol";
Expand All @@ -31,11 +29,9 @@ import { LoansPortfolioModifiers } from "./LoansPortfolioModifiers.sol";
* Asset Modifiers:
* - ActionValidationModifiers: Action validation
* - AdjustBalancesModifiers: Adjust balances validation
* - BondModifiers: Bond-specific validation
* - ClearingModifiers: Clearing state validation
* - CouponModifiers: Coupon date validation
* - ComplianceModifiers: Compliance validation
* - EquityModifiers: Equity-specific validation
* - ERC3643Modifiers: ERC3643 initialization validation
* - ExpirationModifiers: Expiration validation
* - HoldModifiers: Hold validation
Expand All @@ -52,11 +48,9 @@ abstract contract AssetModifiers is
ActionValidationModifiers,
AdjustBalancesModifiers,
AmortizationModifiers,
BondModifiers,
ClearingModifiers,
CouponModifiers,
ComplianceModifiers,
EquityModifiers,
ERC1410Modifiers,
ERC3643Modifiers,
ExpirationModifiers,
Expand Down

This file was deleted.

This file was deleted.

Loading
Loading