Q2 2026 Security & Compliance Report67 incidents, $764M in losses, 88% from operational failures.
Get the report →

Audit name:

[SCA] BlockRidge | BlockRidge-Contracts | Nov2024

Date:

Feb 24, 2025

Table of Content

→Introduction
→Audit Summary
→System Overview
→Potential Risks
→Findings
→Appendix 1. Definitions
→Appendix 2. Scope
→Appendix 3. Additional Valuables
→Disclaimer

Want a comprehensive audit report like this?

Introduction

We express our gratitude to the BlockRidge team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.

BlockRidge is a comprehensive RWA ecosystem that provides compliant tokenization services, creating scalable and equitable access to financing opportunities for asset owners. It enables a broad range of users to invest in various asset classes through a compliant and streamlined interface.

Document

NameSmart Contract Code Review and Security Analysis Report for BlockRidge
Audited ByIvan Bondar, Viktor Lavrenenko
Approved ByPrzemyslaw Swiatowiec
Websitehttps://blockridge.com/→
Changelog10/12/2024 - Preliminary Report
24/02/2025 - Final Report
PlatformBase
LanguageSolidity
TagsReal World Assets (RWA); Storage; Factory; Proxy; Upgradable; Centralization
Methodologyhttps://hackenio.cc/sc_methodology→
  • Document

    Name
    Smart Contract Code Review and Security Analysis Report for BlockRidge
    Audited By
    Ivan Bondar, Viktor Lavrenenko
    Approved By
    Przemyslaw Swiatowiec
    Changelog
    10/12/2024 - Preliminary Report
    24/02/2025 - Final Report
    Platform
    Base
    Language
    Solidity
    Tags
    Real World Assets (RWA); Storage; Factory; Proxy; Upgradable; Centralization

Review Scope

Repositoryhttps://github.com/valuit-official/valuit-smart-contracts→
Commit4a8e151
Retest Commiteb1bb6f

Audit Summary

45Total Findings
45Resolved
0Accepted
0Mitigated

The system users should acknowledge all the risks summed up in the risks section of the report

Documentation quality

  • Functional requirements are complete.

    • Project purpose is described.

    • Use cases are provided.

    • Project features are described.

    • Interactions are  described.

  • Technical requirements are provided.

    • Run instructions are provided.

    • Technical specification is sufficient.

    • The NatSpec documentation is sufficient.

    • Authorization and roles are provided.

Code quality

  • The development environment is configured.

Test coverage

Code coverage of the project is 56.32% (branch coverage).

  • Deployment and basic user interactions are covered with tests.

  • Interactions by several users are tested.

  • Not all branches are covered with tests.

System Overview

BlockRidge is a Real-World Asset (RWA) ecosystem designed to provide compliant tokenization services, facilitating financing opportunities for asset owners and offering investors access to a variety of asset classes through a regulatory-compliant interface. The platform's modular and scalable architecture comprises interconnected components that ensure compliance and flexibility across all operations.

At the core of BlockRidge is a compliance framework that enforces regulatory requirements by allowing dynamic configuration of rules tailored to specific jurisdictions or asset types. The platform also utilizes blockchain standards for identity management, maintaining a registry of verified identities and handling claims and attestations from trusted issuers, thereby ensuring that only compliant and verified users can participate in transactions.

BlockRidge offers escrow services for handling token deposits and settlements between users, supporting multiple stablecoins and administrative fee management. This provides flexible transaction mechanisms while maintaining compliance in financial operations. Additionally, the system enables the creation and management of funds, allowing asset owners to deploy new investment opportunities with specific parameters such as property type, valuation, and projected yield. It manages investment limits and financial metrics, supporting the compliant distribution of dividends to investors.

The tokenization module is responsible for creating and managing tokenized representations of real-world assets. By implementing compliance standards and handling token management, the platform ensures regulatory-compliant asset tokenization. BlockRidge also incorporates upgradeability mechanisms that allow contracts to be updated without changing their addresses, ensuring longevity and adaptability while maintaining continuous operation.

To ensure that only authorized entities can perform sensitive operations, the platform enforces role-based access controls. Key roles include owners, who control modules and perform administrative functions; agents, who execute operations such as settlements, identity verification, and token management; and compliance officers, who manage compliance modules and enforce regulatory adherence.

The modular design of BlockRidge promotes integration with other systems and adherence to protocols such as ERC-734, ERC-735, and ERC-3643. This ensures compatibility with various wallets, identity providers, and compliance services, fostering a versatile and interconnected ecosystem.

Files in Scope

  • compliance/modular:

    • modules:

      • AbstractModule.sol: Defines the base functionality for compliance modules, handling the binding and unbinding of compliance contracts. It includes modifiers to restrict function calls to bound compliance contracts only, establishing a secure link between the module and Modular Compliance.

      • AbstractModuleUpgradeable.sol: An upgradeable version of AbstractModule, implementing OpenZeppelin's upgradeability features. This contract is structured to allow compliance modules to be upgraded without disrupting the compliance binding status, which is maintained in a custom storage structure.

      • CountryAllowModule.sol: A compliance module that manages country-specific allowances, enabling or disabling token manipulation permissions for users based on their country. It facilitates adding or removing countries from the allowed list, ensuring jurisdictional compliance.

      • CountryRestrictModule: A compliance module that manages country-specific restrictions, enabling or disabling token manipulation permissions for users based on their country.

      • HoldTimeModule.sol: Compliance module that enforces a minimum hold period for tokens. Users cannot transfer tokens until the hold time has passed, ensuring adherence to time-based restrictions.

      • SupplyLimitModule.sol: Compliance module that restricts the total supply of tokens that can be minted for a given compliance contract, preventing excessive token issuance.

      • ModuleProxy.sol: A proxy contract based on the ERC1967 standard, used to manage upgradeable modules within the Modular Compliance architecture. It facilitates upgrading module implementations while preserving their state.

      • MaxBalanceModule.sol: Compliance module that restricts the maximum token balance each user can hold. It also allows pre-setting balances to ensure compliant behavior across accounts and manages identity-based balances for transfers and compliance checks.

      • IModule.sol: Interface defining the standard for all compliance modules. It includes functions for binding and unbinding compliance contracts, performing transfer, mint, and burn actions, and conducting compliance checks.

    • ModularCompliance.sol: The main contract for Modular Compliance, implementing IModularCompliance and inheriting OwnableUpgradeable and MCStorage. It allows the owner to bind/unbind tokens, add/remove modules, and manage module interactions while ensuring that token transfers comply with specified rules.

    • MCStorage.sol: Storage contract for the Modular Compliance system, holding the token bound to the compliance contract and the list of bound modules. It includes mappings to track the binding status of modules and a variable to manage the wrapper status.

    • IModularCompliance.sol: Interface defining the Modular Compliance contract, which manages compliance rules for token transfers by binding tokens and modules, adding/removing modules, and facilitating module interactions. It outlines functions for enforcing compliance and events to track module interactions.

  • escrow:

    • EscrowController.sol: The main escrow contract managing token deposits and settlements for compliant users. It supports various stablecoins, applies an admin fee, and enables secure fund transfers for verified investors.

    • EscrowProxy.sol: A proxy contract for managing the upgradeability of the escrow implementation. It allows ownership control and maintenance mode, facilitating safe upgrades of the escrow contract.

    • EscrowStorage.sol: Storage contract for the escrow system, holding data such as admin wallet, admin fee, stablecoin mappings, and investor orders. It serves as the data layer for Escrow.sol to separate logic and storage.

    • IEscrowController: Interface for the EscrowController contract.

    • TransferHelper.sol: A utility library for safely interacting with ERC20 tokens and transferring ETH. It provides functions for safe approvals, transfers, and transferFrom operations, ensuring that token operations either succeed or revert.

  • factory:

    • FactoryProxy.sol: A proxy contract for managing the upgradeability of the fund factory implementation. It includes basic authorization controls for ownership, allows the owner to upgrade the implementation, and enables maintenance mode for controlled operations.

    • FundFactory.sol: The main contract for creating funds and equity configurations. It interacts with proxy contracts to deploy and initialize new fund or equity configuration instances based on stored implementations. It also includes a batch whitelisting function for user identities.

    • FundFactoryStorage.sol: Storage contract for FundFactory, holding references to the main factory address, fund and equity configuration implementations, and proxy address. It serves as a data layer, separating storage from the factory logic in FundFactory.sol.

    • TREXFactory.sol: Main contract for deploying the TREX token suite, which includes identity registries, compliance modules, claim topics, and trusted issuer registries. It uses the CREATE2 opcode to predetermine deployment addresses, facilitating standardized deployments across EVM-compatible chains.

    • ITREXFactory.sol: Interface defining the TREX Factory contract's core functionalities for deploying and managing tokenization suite contracts. It includes data structures for token and claim details and function signatures for deploying tokens and setting up compliant infrastructure.

  • fund:

    • EquityConfig.sol: A contract for managing equity configurations of a fund. It initializes parameters like minimum and maximum investment, valuation, projected yield, and Debt-to-Equity ratio. It allows authorized agents to update the fund's valuation.

    • EquityConfigStorage.sol: Storage contract for EquityConfig, holding data on fund name, Debt-to-Equity ratio, token address, and valuation metrics. This contract separates data storage from logic, supporting upgradeable architecture.

    • Fund.sol: The main contract for managing fund-related parameters and operations. It initializes with key details like property type, NAV (Net Asset Value), and projected yield. It allows token agents to update NAV, and distribute dividends in stablecoins to investors.

    • FundStorage.sol: Storage contract for Fund, holding key data like fund name, CUSIP, NAV, projected yield, and investment limits. This contract is used as a data layer for Fund.sol, maintaining the separation of storage from operational logic.

    • IFactory.sol: Interface for a factory contract, providing an external view of the factory owner's address. This is likely used to confirm authorization and ensure that only the owner can access certain functions.

    • IFund.sol: Interface for the Fund contract, providing a function signature for retrieving the Net Asset Value (NAV).

    • ITKN.sol: Interface for a token contract that includes functions to check if an address is an agent, get the token’s name, and retrieve its total supply. This interface is used in the Fund and EquityConfig contracts to validate agents and access token data.

  • onchainID:

    • factory:

      • IdFactory.sol: Main contract for managing the creation and linkage of on-chain identities (ONCHAINID) for both users and tokens. It allows the deployment of identity contracts using CREATE2 for deterministic addresses, linking and unlinking wallets to identities, and registering token factories authorized to create token identities.

      • IIdFactory.sol: Interface defining the core functions of the IdFactory, including creating identities, linking/unlinking wallets, adding/removing token factories, and providing view functions to retrieve linked identities, wallets, and token statuses.

    • interface:

      • IClaimIssuer.sol: Interface for a claim issuer, allowing claim revocation and validation.

      • IERC734.sol: Interface defining ERC-734 standard functions for identity management, including key handling and execution approvals.

      • IERC735.sol: Interface defining ERC-735 standard functions for claim management within an identity, including claim addition, removal, and retrieval.

      • IIdentity.sol: Composite interface for both IERC734 (Key Holder) and IERC735 (Claim Holder), establishing a comprehensive identity standard.

      • IImplementationAuthority.sol: Interface for managing and retrieving the current implementation of a proxy, with upgrade capabilities.

    • proxy:

      • IdentityProxy.sol: Acts as a proxy for the Identity contract. It delegates calls to an implementation contract whose address is managed by an ImplementationAuthority. This structure ensures that the proxy can dynamically update its implementation, enabling upgradability while maintaining the same address.

      • ImplementationAuthority.sol: Manages the current implementation address for the Identity proxy. It can be updated only by the owner, ensuring centralized control over the address of the actual implementation contract, which is beneficial for maintaining control over upgrades.

    • storage:

      • Storage.sol: Contains the storage layout for the Identity contract, including mappings for keys, executions, and claims. This setup enables modular contract structure and compatibility with proxy-based upgradability. The _initialized and _canInteract flags control initialization status and interaction permissions.

      • Structs.sol: Defines data structures used across the identity system.

    • verifiers:

      • Verifier.sol: Manages trusted issuers and required claim topics for identity verification, ensuring compliance by validating claims from approved sources.

    • version:

      • Version.sol: Provides a simple versioning function that returns the version string of the implementation contract, allowing external parties to check which version of the contract logic is being used.

    • Identity.sol: Implements an ERC-734 "KeyHolder" and ERC-735 "ClaimHolder" identity contract that supports identity management, including key management for various roles (management, action, claim signer, and encryption). It allows the addition, execution, and management of claims and keys for each identity. This contract is intended to be deployed as an upgradable contract with modular storage, making it suitable for managing complex identity structures with separate, upgradeable logic.

    • ClaimIssuer.sol: This contract extends the Identity contract to provide claim issuance and revocation functionalities. It enables claim validation and revocation based on signatures, allowing the contract to check the validity and status of claims linked to identities.

  • proxy:

    • authority:

      • IAFactory.sol: Manages deployment of new instances of TREXImplementationAuthority, ensuring they are created by the authorized factory.

      • IIAFactory.sol: Interface defining IAFactory contract functions.

      • ITREXImplementationAuthority.sol: Interface defining TREXImplementationAuthority contract functions, including managing contract versions and associated addresses.

      • TREXImplementationAuthority.sol: Manages contract versions and maintains the current set of TREXContracts implementations used across the T-REX suite. Allows updating and fetching contract versions.

    • interface:

      • IImplementationAuthority.sol: Interface providing a function to retrieve the current implementation address in use.

      • IProxy.sol: Interface for a proxy contract, allowing the setting and retrieval of the current implementation authority address.

    • AbstractProxy.sol: Abstract contract providing core proxy functions to delegate calls to an implementation authority.

    • ClaimTopicsRegistryProxy.sol: Proxy for the Claim Topics Registry, delegating calls to the appropriate logic contract set by the implementation authority.

    • IdentityRegistryProxy.sol: Proxy for the Identity Registry, initializing with registries and delegating to the implementation logic.

    • IdentityRegistryStorageProxy.sol: Proxy for storing identity data, initialized with implementation authority and delegates to the storage logic.

    • ModularComplianceProxy.sol: Proxy for the compliance module, which delegates all calls to the compliance logic contract.

    • ProxyV1.sol: A proxy contract allowing upgradeability and maintenance control, delegating calls to an implementation authority.

    • TokenProxy.sol: Proxy contract for token management, initialized with identity registry, compliance module, and token metadata, delegating to token logic.

    • TrustedIssuersRegistryProxy.sol: Proxy for the Trusted Issuers Registry, initialized with an implementation authority and delegating calls to the trusted issuers logic.

  • registry:

    • implementation:

      • ClaimTopicsRegistry.sol: Provides functionality to manage claim topics that are necessary for identity verification.

      • IdentityRegistry.sol: Manages user identities and verifies them based on trusted issuers and claim topics.

      • IdentityRegistryStorage.sol: Manages the storage of identities, including adding, modifying, and removing identities.

      • TrustedIssuersRegistry.sol: Manages trusted claim issuers and the topics they support.

    • interface:

      • IClaimTopicsRegistry.sol: Interface for managing claim topics, allowing only the owner to add or remove claim topics.

      • IIdentityRegistry.sol: Interface for managing identities within the registry, including functions to register, update, and verify identities.

      • IIdentityRegistryStorage.sol: Interface defining storage management functions for identities, such as adding, removing, and updating stored identities.

      • ITrustedIssuersRegistry.sol: Interface for managing trusted claim issuers and associated claim topics, only callable by the contract owner.

    • storage:

      • CTRStorage.sol: Provides internal storage for managing claim topics required for identity verification.

      • IRSStorage.sol: Manages identity-related data, specifically mapping between user addresses and identities (country and identity contract).

      • IRStorage.sol: Stores references to key registry contracts: Claim Topics Registry, Trusted Issuers Registry, and Identity Registry Storage.

      • TIRStorage.sol: Contains data structures for managing trusted issuers, including arrays and mappings for claim topics associated with each issuer.

  • roles:

    • AgentRole.sol: Implements role-based access for agents and "TA" roles, allowing only the owner to assign and remove these roles.

    • AgentRoleUpgradeable.sol: Upgradeable contract version of AgentRole, also enabling role-based access for agents and "TA" roles, managed by the owner.

    • Roles.sol: Library providing internal functions to add, remove, and check roles for specific addresses.

  • token:

    • Token.sol: Implements the token logic for minting, burning, transfers, and compliance checks. It integrates identity and compliance modules to enforce regulatory compliance.

    • TokenStorage.sol: Defines essential variables and mappings to manage ERC20 balances, allowances, and the token's freeze/pause status, along with identity and compliance contract references.

    • IToken.sol: Interface for the token contract, including functions for token management (freeze, pause, transfer) and linking identity and compliance registries.

    • VERC20.sol: Upgradeable ERC20 token contract, with basic initialization and restricted mint/burn functions.

  • wrapper:

    • Wrapper.sol: Manages the creation and wrapping of ERC3643 tokens into ERC20 tokens, allowing for minting and burning to simulate a bridge between token standards.

    • WrapperStorage.sol: Provides storage structures for managing token wrappers, tracking mappings between ERC20 and ERC3643 tokens, and logging locked tokens.

Privileged roles

  • ModularCompliance.sol:

    • Owner:

      • Can bind or unbind tokens to the compliance contract.

      • Can add or remove modules, subject to module binding checks.

      • Authorized to call module functions and set the wrapper address.

    • Only Token (modifier):

      • Ensures that only the token bound to the compliance contract can trigger certain functions, like transferred, created, and destroyed, which manage compliance checks for token actions.

  • AbstractModule.sol:

    • onlyBoundCompliance (modifier):

      • Restricts function access to only those compliance contracts that have been explicitly bound to this module.

    • onlyComplianceCall (modifier):

      • Allows function calls exclusively from addresses associated with bound compliance contracts.

  • AbstractModuleUpgradeable.sol:

    • Owner:

      • Authorized to upgrade the module's implementation.

    • onlyBoundCompliance (modifier):

      • Limits access to functions to bound compliance contracts.

    • onlyComplianceCall (modifier):

      • Ensures only bound compliance contracts can invoke specific functions within this module.

  • CountryAllowModule.sol:

    • Owner (through onlyComplianceCall modifier):

      • Permitted to batch allow or disallow countries, and to individually allow or disallow countries for token manipulation.

    • onlyComplianceCall (modifier):

      • Limits function calls for managing country allowances to bound compliance contracts, ensuring that only authorized compliance contracts can enforce these restrictions.

  • HoldTimeModule.sol:

    • onlyComplianceCall (modifier):

      • Ensures that only the compliance contract bound to this module can set the hold time for tokens.

    • Owner:

      • Authorized to set or update the hold time for tokens, enforcing transfer restrictions based on the specified period.

  • SupplyLimitModule.sol:

    • onlyComplianceCall (modifier):

      • Limits the ability to set the supply limit to the bound compliance contract, safeguarding against unauthorized adjustments.

    • Owner:

      • Permitted to define the maximum supply limit, capping token issuance to prevent oversupply.

  • MaxBalanceModule.sol:

    • onlyComplianceCall (modifier):

      • Allows only the compliance contract bound to this module to set or modify maximum balances, ensuring authorized access.

    • Owner (only compliance owner can access):

      • Can set maximum balance limits and pre-set balances for specific identities.

      • Authorized to complete the preset configuration for a compliance contract, allowing it to bind with the module.

  • Escrow.sol:

    • Owner:

      • Can set the admin fee and admin wallet.

      • Authorized to rescue any ERC20 tokens from the contract except for pending amounts in stablecoins.

    • Agent:

      • Can perform the settlement function, finalizing an order and transferring the amount to themselves and the admin wallet (less the admin fee). Ensures that only authorized agents can complete settlements.

  • EscrowProxy.sol

    • Proxy Owner (modifier onlyProxyOwner):

      • Controls upgradeability by authorizing changes to the escrow implementation.

      • Can enable or disable maintenance mode, restricting certain operations during maintenance.

      • Can transfer proxy ownership to a new owner, ensuring controlled access over upgradeability and management functions.

  • FactoryProxy.sol:

    • Proxy Owner (modifier onlyProxyOwner):

      • Controls upgradeability by authorizing updates to the factory implementation.

      • Can enable or disable maintenance mode, restricting operations during maintenance.

      • Has the authority to transfer proxy ownership, ensuring controlled management over the factory upgradeability.

  • FundFactory.sol:

    • Owner (determined by masterFactory owner):

      • Authorized to set fund and equity configuration implementations.

      • Permitted to create new fund and equity configuration contracts, ensuring only the factory owner can deploy new configurations.

    • Agent:

      • Can perform batchWhitelist for bulk registration of user identities within an identity registry associated with a token, provided they are registered as an agent within the registry.

  • TREXFactory.sol:

    • Owner:

      • Authorized to deploy a new TREX token suite using deployTREXSuite, allowing comprehensive setup of identity, compliance, and registry components for a compliant token ecosystem.

      • Can set or update the implementationAuthority and idFactory, ensuring that only authorized individuals can control core components related to token implementations and identity management.

      • Has exclusive access to recoverContractOwnership, which is typically used to transfer ownership of contracts previously owned by the factory, such as the Identity Registry Storage (IRS).

    • Agent (within Identity Registry and Token context):

      • The owner can add agents to the Identity Registry and Token, giving agents permission to perform functions related to identity verification and token management as required.

  • EquityConfig.sol:

    • Factory:

      • Initializes the contract with key fund parameters like minimum investment, maximum investment, and valuation metrics.

    • Token Agent:

      • Authorized to update the fund's valuation by calling setValuation, ensuring that only designated agents can alter financial metrics of the fund.

  • Fund.sol

    • Factory:

      • Initializes the fund with key parameters such as NAV and investment limits.

    • Token Agent:

      • Can update the NAV using setNAV, ensuring that only authorized agents can make adjustments to the fund's asset valuation.

      • Authorized to distribute dividends to a list of investors using shareDividend, allowing controlled and compliant distribution of fund proceeds.

  • Identity.sol

    • Management Key Holders:

      • Management key holders can perform actions such as executing transactions, adding and removing keys, approving executions, and modifying claims within the identity.

      • Management key holders can also directly interact with the identity contract for actions that affect the identity as a whole, including the execution of internal transactions.

    • Action Key Holders:

      • Action key holders can initiate external calls through the execute function. These keys have lower permissions than management keys and are intended for actions that do not modify the state of the identity.

    • Claim Key Holders:

      • Claim key holders are authorized to add and remove claims on behalf of the identity. They can issue claims to other identities and sign claims to validate user assertions within the addClaim and removeClaim functions.

    • Encryption Key Holders:

      • Encryption key holders manage data encryption, useful for holding claims or sensitive identity data securely. These keys are primarily used in contexts that require identity data to be encrypted before storage or transmission.

  • ClaimIssuer.sol

    • Manager (Identity Management Key):

      • The onlyManager modifier restricts claim revocation functions to only be called by accounts with a management key. Managers can revoke claims by their ID or revoke signatures, maintaining control over the status of each claim.

      • Managers can also check the validity of claims through isClaimValid, ensuring a robust verification process.

    • Claim Signers (Claim Key):

      • Claim signers are authorized to verify claims based on their signatures using the isClaimValid function, provided they have valid claim keys.

  • Verifier.sol:

    • Owner:

      • Has authority to add and remove trusted issuers, manage required claim topics, and update claim topics for trusted issuers.

  • AbstractProxy.sol:

    • Implementation Authority:

      • Only the current implementation authority can set a new implementation authority address.

  • ProxyV1.sol:

    • Proxy Owner:

      • Can transfer proxy ownership, toggle maintenance mode, upgrade implementation, and upgrade with initialization call.

  • IAFactory.sol:

    • TREX Implementation Authority:

      • Only the reference implementation authority can deploy a new instance of TREXImplementationAuthority through this factory.

  • TREXImplementationAuthority.sol:

    • Owner:

      • Can add new T-REX contract versions, set the TREXFactory and IAFactory addresses, and update the active version used by proxies.

    • Token Owner:

      • Only the token's owner can change the implementation authority for all linked contracts, including token proxies, registries, and compliance modules.

  • ClaimTopicsRegistry.sol:

    • Owner:

      • Can add or remove claim topics necessary for identity verification.

  • IdentityRegistry.sol:

    • Owner:

      • Can set the addresses of the Identity Registry Storage, Claim Topics Registry, and Trusted Issuers Registry.

    • Agent:

      • Can register, update, and delete identities.

      • Can update the country of residence for an identity.

  • IdentityRegistryStorage.sol:

    • Owner:

      • Initializes the contract and binds Identity Registries.

    • Agent:

      • Can add, modify, and remove identities in storage.

      • Can modify investor country information.

  • TrustedIssuersRegistry.sol:

    • Owner:

      • Can add, remove, or update trusted issuers and their associated claim topics.

  • AgentRole.sol / AgentRoleUpgradeable.sol:

    • Owner:

      • Can assign and remove both "Agent" and "TA" roles, providing privileged access to designated accounts.

    • Agent:

      • Granted permissions to execute functions restricted to the "Agent" role.

    • TA:

      • Granted permissions to execute functions restricted to the "TA" role and participate in actions alongside "Agent" role holders.

  • Token.sol:

    • Owner:

      • Authorized to initialize the token, set token information (name, symbol, onchain ID), configure Identity Registry and Compliance contracts, and manage ownership.

    • Agent:

      • Permitted to pause/unpause the token, freeze/unfreeze addresses and tokens, recover addresses, and enforce transfers, minting, and burning.

    • Agents (TAs):

      • Can perform partial token freezes and unfreezes and are allowed in certain transfer operations that require compliance with token policies.

  • VERC20.sol:

    • Owner:

      • Authorized to mint and burn tokens, restricted to only the owner for controlled token supply management.

  • Wrapper.sol:

    • Owner:

      • Has authority to set the on-chain ID for the wrapper.

    • Agents (in ERC3643):

      • Only agents associated with the ERC3643 token can create a wrapped ERC20 token through the createWrapToken function, ensuring controlled access to the wrapping process.

Potential Risks

Reliance on Off-Chain Systems for Key Settings: The project heavily depends on off-chain components to manage and define critical settings, such as NAV and valuation updates, which are essential for the accurate operation. Since the off-chain infrastructure is not part of the audit, its security, reliability, and integrity cannot be guaranteed. Any issues or vulnerabilities within the off-chain systems could lead to incorrect on-chain behavior, manipulation of key metrics, or operational disruptions.

Single Points of Failure and Control: The project is fully or partially centralized, introducing single points of failure and control. This centralization can lead to vulnerabilities in decision-making and operational processes, making the system more susceptible to targeted attacks or manipulation.

Administrative Key Control Risks: The digital contract architecture relies on administrative keys for critical operations. Centralized control over these keys presents a significant security risk, as compromise or misuse can lead to unauthorized actions or loss of funds.

Dynamic Array Iteration Gas Limit Risks: The project iterates over large dynamic arrays, which leads to excessive gas costs, risking denial of service due to out-of-gas errors, directly impacting contract usability and reliability.

External Calls in Iteration Risks: Making external calls within loops increases the risk of gas exhaustion, potentially leading to failed transactions and reduced contract reliability, especially when processing large datasets.

Flexibility and Risk in Contract Upgrades: The project's contracts are upgradable, allowing the administrator to update the contract logic at any time. While this provides flexibility in addressing issues and evolving the project, it also introduces risks if upgrade processes are not properly managed or secured, potentially allowing for unauthorized changes that could compromise the project's integrity and security.

Single Entity Upgrade Authority: The ecosystem grants a single entity the authority to implement upgrades or changes. This centralization of power risks unilateral decisions that may not align with the community or stakeholders' interests, undermining trust and security.

Absence of Upgrade Window Constraints: The contract suite allows for immediate upgrades without a mandatory review or waiting period, increasing the risk of rapid deployment of malicious or flawed code, potentially compromising the system's integrity and user assets.

Frontrunning During The Initialization Of The Implementation Contract: If the deployment and the initialization of the proxy implementation contracts will not be handled within one transaction, it can cause the frontrunning of the initialize functions by the attacker which will lead to unexpected system behavior.

Not a Traditional Escrow: Despite its name, the contract does not escrow (hold) user funds upon deposit. Instead, a user’s stablecoins remain in the user’s wallet until “settlement,” at which time the contract attempts to pull stablecoins via safeTransferFrom. If the user depletes or revokes approval of their stablecoin allowance after calling deposit, the settlement will revert. This design is intentional, but it differs from a typical “deposit and lock” escrow mechanism.

In the EscrowController contract, the redemptionAndBurn function relies on token agents to accurately provide the _principalAmount and _profitAmount. If the agent includes the profit in _principalAmount but sets _profitAmount to zero, the protocol will not apply the redemption fee, resulting in uncollected fees. This places responsibility on agents to report profits correctly, introducing risks of fee evasion, either through negligence or intentional manipulation.

Findings

F-2024-7530Lack of Wrapper Status Validation in createWrapToken and toERC20 Functions
Status
fixed
Severity

Medium
F-2024-7260MaxBalanceModule Restriction Interferes with Wrapping Process in ERC3643 Token System
Status
fixed
Severity

Medium
F-2024-7243Incorrect Order of Checks in canTransfer Leads to Potential Bypass of HoldTimeModule Restrictions
Status
fixed
Severity

Medium
F-2024-7528Stale Total Supply Data Leads to Incorrect Fee Calculation
Status
fixed
Severity

Medium
F-2024-7527Precision Loss in Fee Calculation for toERC20 and toERC3643 Functions Leads to Incorrect or Zero Fees
Status
fixed
Severity

Medium
F-2024-7282Inadequate Validation in deposit Function Leading to Potential Denial of Service
Status
fixed
Severity

Medium
F-2024-7529Overwriting Parameters When Creating Funds or Equity Configurations for the Same Token
Status
fixed
Severity

Low
F-2024-7285Mismanagement of Compliance Preset Status in MaxBalanceModule Allows Circumvention of Max Balance Enforcement
Status
fixed
Severity

Low
F-2024-7262Lack of Wrapper Disabling Mechanism in ModularCompliance Contract
Status
fixed
Severity

Low
F-2024-7244Compliance Gap in ERC3643 to ERC20 Wrapping Process
Status
fixed
Severity

Low
Code
―
Title
Status
Severity
F-2024-7530Lack of Wrapper Status Validation in createWrapToken and toERC20 Functions
fixed

Medium
F-2024-7260MaxBalanceModule Restriction Interferes with Wrapping Process in ERC3643 Token System
fixed

Medium
F-2024-7243Incorrect Order of Checks in canTransfer Leads to Potential Bypass of HoldTimeModule Restrictions
fixed

Medium
F-2024-7528Stale Total Supply Data Leads to Incorrect Fee Calculation
fixed

Medium
F-2024-7527Precision Loss in Fee Calculation for toERC20 and toERC3643 Functions Leads to Incorrect or Zero Fees
fixed

Medium
F-2024-7282Inadequate Validation in deposit Function Leading to Potential Denial of Service
fixed

Medium
F-2024-7529Overwriting Parameters When Creating Funds or Equity Configurations for the Same Token
fixed

Low
F-2024-7285Mismanagement of Compliance Preset Status in MaxBalanceModule Allows Circumvention of Max Balance Enforcement
fixed

Low
F-2024-7262Lack of Wrapper Disabling Mechanism in ModularCompliance Contract
fixed

Low
F-2024-7244Compliance Gap in ERC3643 to ERC20 Wrapping Process
fixed

Low
1-10 of 45 findings

Identify vulnerabilities in your smart contracts.

Appendix 1. Definitions

Severities

When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.

Reference on how risk scoring is done is available through the repository in our Github organization:

Severity

Description

Critical
Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

High
High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

Medium
Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

Low
Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.
  • Severity

    Critical

    Description

    Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.

    Severity

    High

    Description

    High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.

    Severity

    Medium

    Description

    Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.

    Severity

    Low

    Description

    Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution.

Potential Risks

The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.

Appendix 2. Scope

The scope of the project includes the following smart contracts from the provided repository:

Asset

Type

compliance/modular/IModularCompliance.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/MCStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/ModularCompliance.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/AbstractModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/AbstractModuleUpgradeable.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/CountryAllowModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/CountryRestrictModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/HoldTimeModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/IModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/MaxBalanceModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/ModuleProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
compliance/modular/modules/SupplyLimitModule.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
escrow/EscrowController.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
escrow/EscrowControllerProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
escrow/EscrowStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
escrow/IEscrowController.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
escrow/TransferHelper.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/FactoryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/FundFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/FundFactoryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/IFundFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/ITREXFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
factory/TREXFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/EquityConfig.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/EquityConfigStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/Fund.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/FundStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/IFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/IFund.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
fund/ITKN.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/ClaimIssuer.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/factory/IdFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/factory/IIdFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/Identity.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/interface/IClaimIssuer.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/interface/IERC734.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/interface/IERC735.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/interface/IIdentity.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/interface/IImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/proxy/IdentityProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/proxy/ImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/storage/Storage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/storage/Structs.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/verifiers/Verifier.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
onchainID/version/Version.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/AbstractProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/authority/IAFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/authority/IIAFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/authority/ITREXImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/authority/TREXImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/ClaimTopicsRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/IdentityRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/IdentityRegistryStorageProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/interface/IImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/interface/IProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/ModularComplianceProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/ProxyV1.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/TokenProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
proxy/TrustedIssuersRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/implementation/ClaimTopicsRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/implementation/IdentityRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/implementation/IdentityRegistryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/implementation/TrustedIssuersRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/interface/IClaimTopicsRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/interface/IIdentityRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/interface/IIdentityRegistryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/interface/ITrustedIssuersRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/storage/CTRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/storage/IRSStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/storage/IRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
registry/storage/TIRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
roles/AgentRole.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
roles/AgentRoleUpgradeable.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
roles/Roles.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
token/IToken.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
token/Token.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
token/TokenStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
token/VERC20.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
wrapper/Wrapper.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
wrapper/WrapperProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
wrapper/WrapperStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]Smart Contract
  • Asset

    compliance/modular/IModularCompliance.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/MCStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/ModularCompliance.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/AbstractModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/AbstractModuleUpgradeable.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/CountryAllowModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/CountryRestrictModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/HoldTimeModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/IModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/MaxBalanceModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/ModuleProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    compliance/modular/modules/SupplyLimitModule.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    escrow/EscrowController.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    escrow/EscrowControllerProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    escrow/EscrowStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    escrow/IEscrowController.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    escrow/TransferHelper.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/FactoryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/FundFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/FundFactoryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/IFundFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/ITREXFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    factory/TREXFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/EquityConfig.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/EquityConfigStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/Fund.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/FundStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/IFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/IFund.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    fund/ITKN.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/ClaimIssuer.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/factory/IdFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/factory/IIdFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/Identity.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/interface/IClaimIssuer.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/interface/IERC734.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/interface/IERC735.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/interface/IIdentity.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/interface/IImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/proxy/IdentityProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/proxy/ImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/storage/Storage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/storage/Structs.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/verifiers/Verifier.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    onchainID/version/Version.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/AbstractProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/authority/IAFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/authority/IIAFactory.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/authority/ITREXImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/authority/TREXImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/ClaimTopicsRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/IdentityRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/IdentityRegistryStorageProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/interface/IImplementationAuthority.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/interface/IProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/ModularComplianceProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/ProxyV1.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/TokenProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    proxy/TrustedIssuersRegistryProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/implementation/ClaimTopicsRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/implementation/IdentityRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/implementation/IdentityRegistryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/implementation/TrustedIssuersRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/interface/IClaimTopicsRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/interface/IIdentityRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/interface/IIdentityRegistryStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/interface/ITrustedIssuersRegistry.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/storage/CTRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/storage/IRSStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/storage/IRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    registry/storage/TIRStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    roles/AgentRole.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    roles/AgentRoleUpgradeable.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    roles/Roles.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    token/IToken.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    token/Token.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    token/TokenStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    token/VERC20.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    wrapper/Wrapper.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    wrapper/WrapperProxy.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

    Asset

    wrapper/WrapperStorage.sol [https://github.com/valuit-official/valuit-smart-contracts]

    Type

    Smart Contract

Assets in Scope

compliance
modular
IModularCompliance.sol - compliance › modular › IModularCompliance.sol
MCStorage.sol - compliance › modular › MCStorage.sol
ModularCompliance.sol - compliance › modular › ModularCompliance.sol
modules
AbstractModuleUpgradeable.sol - compliance › modular › modules › AbstractModuleUpgradeable.sol
CountryAllowModule.sol - compliance › modular › modules › CountryAllowModule.sol
HoldTimeModule.sol - compliance › modular › modules › HoldTimeModule.sol
IModule.sol - compliance › modular › modules › IModule.sol
MaxBalanceModule.sol - compliance › modular › modules › MaxBalanceModule.sol
ModuleProxy.sol - compliance › modular › modules › ModuleProxy.sol
SupplyLimitModule.sol - compliance › modular › modules › SupplyLimitModule.sol
AbstractModule.sol - compliance › modular › modules › AbstractModule.sol
CountryRestrictModule.sol - compliance › modular › modules › CountryRestrictModule.sol
escrow
Escrow.sol - escrow › Escrow.sol
EscrowStorage.sol - escrow › EscrowStorage.sol
TransferHelper.sol - escrow › TransferHelper.sol
EscrowController.sol - escrow › EscrowController.sol
EscrowControllerProxy.sol - escrow › EscrowControllerProxy.sol
factory

Appendix 3. Additional Valuables

Verification of System Invariants

During the audit of BlockRidge, Hacken followed its methodology by performing fuzz-testing on the project's main functions. Echidna →, a tool used for fuzz-testing, was employed to check how the protocol behaves under various inputs. Due to the complex and dynamic interactions within the protocol, unexpected edge cases might arise. Therefore, it was important to use fuzz-testing to ensure that several system invariants hold true in all situations.

Fuzz-testing allows the input of many random data points into the system, helping to identify issues that regular testing might miss. A specific Echidna fuzzing suite was prepared for this task, and throughout the assessment, 59 invariants were tested over 5,000,000 runs. This thorough testing ensured that the system works correctly even with unexpected or unusual inputs.

Invariant

Test Result

Run Count

Stateful Invariants
[ERC20 Invariants]
Total supply should change only by means of VERC20::mint() or VERC20::burn()Passed5M
User balance must not exceed total supplyPassed5M
Sum of users balance must not exceed total supplyPassed5M
Address zero should have zero balancePassed5M
Transfers to zero address should not be allowed via VERC20::transfer() and VERC20::transferFrom() functionsPassed5M
Self transfers should not break accounting via VERC20::transfer() and VERC20::transferFrom() functionsPassed5M
Transfers for more than available balance should not be allowed via VERC20::transfer() and VERC20::transferFrom() functionsPassed5M
Zero amount transfers should not break accounting via VERC20::transfer() and VERC20::transferFrom() functionsPassed5M
Transfers via VERC20::transfer() and VERC20::transferFrom() functions should update accounting correctlyPassed5M
Approving tokens via VERC20::approve() should set correct allowancesPassed5M
Transferring tokens via VERC20::transferFrom() should decrease allowancePassed5M
Minting tokens via VERC20::mint() should update user balance and total supplyPassed5M
Burning tokens via VERC20::burn() should update user balance and total supplyPassed5M
Allowance should be modified correctly via VERC20::increaseAllowance/decreaseAllowance() functionsPassed5M
[Initialization Invariants]
Token::initialize() should not revert when it is passed the correct addresses of Identity and Compliance contractsPassed5M
Token::initialize() should not revert when it is passed the correct not empty symbol and name parametersPassed5M
Token::initialize() should not revert when it is passed the correct decimals value which is not bigger than 18Passed5M
IdentityRegistry::init() should not revert when it is passed the correct  trustedIssuersRegistry, claimTopicsRegistry, and _identityStorage addressesPassed5M
Identity::initialize() should not revert when it is passed the correct initialManagementKey addressPassed5M
Fund::init() should not revert when it is passed the correct non-zero token address and data value, which cannot be smaller than 4 bytesPassed5M
EquityConfig::init() should not revert when it is passed the correct _data value, which cannot be smaller than 5 bytesPassed5M
[Authorization Invariants]
VERC20::mint() should revert if the caller of the function is not the contract ownerPassed5M
VERC20::burn() should revert if the caller of the function is not the contract ownerPassed5M
Token::setName() should revert if the caller of the function is not the contract ownerPassed5M
Token::setSymbol() should revert if the caller of the function is not the contract ownerPassed5M
Token::setOnchainID() should revert if the caller of the function is not the contract ownerPassed5M
Token::setIdentityRegistry() should revert if the caller of the function is not the contract ownerPassed5M
Token::setCompliance() should revert if the caller of the function is not the contract ownerPassed5M
Token::mint() should revert if the caller of the function is not related to the agent rolePassed5M
Token::setAddressFrozen() should revert if the caller of the function is not related to the AgentRolePassed5M
Token::freezePartialTokens() should revert if the caller of the function is not related to the AgentRole or TARolePassed5M
Token::pause() should revert if the caller of the function is not related to the AgentRolePassed5M
Token::unpause() should revert if the caller of the function is not related to the AgentRolePassed5M
IdentityRegistry::updateIdentity() should revert if the caller of the function is not related to the AgentRolePassed5M
IdentityRegistry::setIdentityRegistryStorage() should revert if the caller of the function is not the contract ownerPassed5M
IdentityRegistry::setClaimTopicsRegistry() should revert if the caller of the function is not the contract ownerPassed5M
IdentityRegistry::setTrustedIssuersRegistry() should revert if the caller of the function is not the contract ownerPassed5M
Fund::setNAV() should always revert if the caller of the function is not the token agentPassed5M
Fund::shareDividend() should always revert if the caller of the function is not the token agentPassed5M
Fund::setMinInvestment() should always revert if the caller of the function is not the token agentPassed5M
Fund::setMaxInvestment() should always revert if the caller of the function is not the token agentPassed5M
Wrapper::setOnchainID() should always revert if the caller of the function is not the owner of the masteryFactory contractPassed5M
Wrapper::setFundFactory() should always revert if the caller of the function is not the owner of the masteryFactory contractPassed5M
Wrapper::setEscrowController() should always revert if the caller of the function is not the owner of the masteryFactory contractPassed5M
[Roles Management Invariants]
Roles::add() should always add the role which was not previously addedPassed5M
Roles::remove() should always remove the role from the account which has this rolePassed5M
Roles::has() should always return the existing role of a non address(0) account.Passed5M
[ClaimTopicsRegistry Management Invariants]
ClaimTopicsRegistry::addClaimTopic() should always add a claimTopic to the _claimTopics arrayPassed5M
ClaimTopicsRegistry::addClaimTopic() should always revert if the length of the _claimTopics array exceeds 14Passed5M
ClaimTopicsRegistry::addClaimTopic() should always revert if the claimTopic already exists in the _claimTopics arrayPassed5M
ClaimTopicsRegistry::removeClaimTopic() should always remove the claimTopic from the _claimTopics arrayPassed5M
[IdFactory Management Invariants]
IdFactory::addTokenFactory() should always add a valid TokenFactory, which is not address(0) to the _tokenFactories mappingPassed5M
IdFactory::addTokenFactory() should always revert if the address of the TokenFactory already exists in _tokenFactories mappingPassed5M
IdFactory::removeTokenFactory() should always remove a valid existing TokenFactory address from the _tokenFactories mappingPassed5M
IdFactory::removeTokenFactory() should always revert if the address of the TokenFactory to be deleted does not exist in the _tokenFactories mappingPassed5M
[Fund Management Invariants]
Fund::shareDividend() should always transfer the stablecoin dividents to the specified addressesPassed5M
[Wrapper Management Invariants]
If the _amount is zero, Wrapper::toERC20() and Wrapper::toERC3643() will always calculate orderValue and taxAmount as 0Passed5M
if the getTokenTotalSupply() is zero, the calculation in Wrapper::toERC20() and Wrapper::toERC3643() will always revertPassed5M
If the NAV multiplied by 1018 is smaller than getTokenTotalSupply() value, orderValue, tokenPrice and taxAmount will be caclulated as zero in Wrapper::toERC20() and Wrapper::toERC3643()** functionsPassed5M
  • Invariant

    Stateful Invariants

    Test Result

    Run Count

    Invariant

    [ERC20 Invariants]

    Test Result

    Run Count

    Invariant

    Total supply should change only by means of VERC20::mint() or VERC20::burn()

    Test Result

    Passed

    Run Count

    5M

    Invariant

    User balance must not exceed total supply

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Sum of users balance must not exceed total supply

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Address zero should have zero balance

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Transfers to zero address should not be allowed via VERC20::transfer() and VERC20::transferFrom() functions

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Self transfers should not break accounting via VERC20::transfer() and VERC20::transferFrom() functions

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Transfers for more than available balance should not be allowed via VERC20::transfer() and VERC20::transferFrom() functions

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Zero amount transfers should not break accounting via VERC20::transfer() and VERC20::transferFrom() functions

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Transfers via VERC20::transfer() and VERC20::transferFrom() functions should update accounting correctly

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Approving tokens via VERC20::approve() should set correct allowances

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Transferring tokens via VERC20::transferFrom() should decrease allowance

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Minting tokens via VERC20::mint() should update user balance and total supply

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Burning tokens via VERC20::burn() should update user balance and total supply

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Allowance should be modified correctly via VERC20::increaseAllowance/decreaseAllowance() functions

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [Initialization Invariants]

    Test Result

    Run Count

    Invariant

    Token::initialize() should not revert when it is passed the correct addresses of Identity and Compliance contracts

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::initialize() should not revert when it is passed the correct not empty symbol and name parameters

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::initialize() should not revert when it is passed the correct decimals value which is not bigger than 18

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdentityRegistry::init() should not revert when it is passed the correct  trustedIssuersRegistry, claimTopicsRegistry, and _identityStorage addresses

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Identity::initialize() should not revert when it is passed the correct initialManagementKey address

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Fund::init() should not revert when it is passed the correct non-zero token address and data value, which cannot be smaller than 4 bytes

    Test Result

    Passed

    Run Count

    5M

    Invariant

    EquityConfig::init() should not revert when it is passed the correct _data value, which cannot be smaller than 5 bytes

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [Authorization Invariants]

    Test Result

    Run Count

    Invariant

    VERC20::mint() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    VERC20::burn() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setName() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setSymbol() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setOnchainID() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setIdentityRegistry() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setCompliance() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::mint() should revert if the caller of the function is not related to the agent role

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::setAddressFrozen() should revert if the caller of the function is not related to the AgentRole

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::freezePartialTokens() should revert if the caller of the function is not related to the AgentRole or TARole

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::pause() should revert if the caller of the function is not related to the AgentRole

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Token::unpause() should revert if the caller of the function is not related to the AgentRole

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdentityRegistry::updateIdentity() should revert if the caller of the function is not related to the AgentRole

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdentityRegistry::setIdentityRegistryStorage() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdentityRegistry::setClaimTopicsRegistry() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdentityRegistry::setTrustedIssuersRegistry() should revert if the caller of the function is not the contract owner

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Fund::setNAV() should always revert if the caller of the function is not the token agent

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Fund::shareDividend() should always revert if the caller of the function is not the token agent

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Fund::setMinInvestment() should always revert if the caller of the function is not the token agent

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Fund::setMaxInvestment() should always revert if the caller of the function is not the token agent

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Wrapper::setOnchainID() should always revert if the caller of the function is not the owner of the masteryFactory contract

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Wrapper::setFundFactory() should always revert if the caller of the function is not the owner of the masteryFactory contract

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Wrapper::setEscrowController() should always revert if the caller of the function is not the owner of the masteryFactory contract

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [Roles Management Invariants]

    Test Result

    Run Count

    Invariant

    Roles::add() should always add the role which was not previously added

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Roles::remove() should always remove the role from the account which has this role

    Test Result

    Passed

    Run Count

    5M

    Invariant

    Roles::has() should always return the existing role of a non address(0) account.

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [ClaimTopicsRegistry Management Invariants]

    Test Result

    Run Count

    Invariant

    ClaimTopicsRegistry::addClaimTopic() should always add a claimTopic to the _claimTopics array

    Test Result

    Passed

    Run Count

    5M

    Invariant

    ClaimTopicsRegistry::addClaimTopic() should always revert if the length of the _claimTopics array exceeds 14

    Test Result

    Passed

    Run Count

    5M

    Invariant

    ClaimTopicsRegistry::addClaimTopic() should always revert if the claimTopic already exists in the _claimTopics array

    Test Result

    Passed

    Run Count

    5M

    Invariant

    ClaimTopicsRegistry::removeClaimTopic() should always remove the claimTopic from the _claimTopics array

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [IdFactory Management Invariants]

    Test Result

    Run Count

    Invariant

    IdFactory::addTokenFactory() should always add a valid TokenFactory, which is not address(0) to the _tokenFactories mapping

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdFactory::addTokenFactory() should always revert if the address of the TokenFactory already exists in _tokenFactories mapping

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdFactory::removeTokenFactory() should always remove a valid existing TokenFactory address from the _tokenFactories mapping

    Test Result

    Passed

    Run Count

    5M

    Invariant

    IdFactory::removeTokenFactory() should always revert if the address of the TokenFactory to be deleted does not exist in the _tokenFactories mapping

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [Fund Management Invariants]

    Test Result

    Run Count

    Invariant

    Fund::shareDividend() should always transfer the stablecoin dividents to the specified addresses

    Test Result

    Passed

    Run Count

    5M

    Invariant

    [Wrapper Management Invariants]

    Test Result

    Run Count

    Invariant

    If the _amount is zero, Wrapper::toERC20() and Wrapper::toERC3643() will always calculate orderValue and taxAmount as 0

    Test Result

    Passed

    Run Count

    5M

    Invariant

    if the getTokenTotalSupply() is zero, the calculation in Wrapper::toERC20() and Wrapper::toERC3643() will always revert

    Test Result

    Passed

    Run Count

    5M

    Invariant

    If the NAV multiplied by 1018 is smaller than getTokenTotalSupply() value, orderValue, tokenPrice and taxAmount will be caclulated as zero in Wrapper::toERC20() and Wrapper::toERC3643()** functions

    Test Result

    Passed

    Run Count

    5M

Additional Recommendations

The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.

To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:

  • Detecting changes to ownership or critical permissions.

  • Monitoring large or unexpected transactions and minting events.

  • Pausing operations when irregularities are identified.

These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.

Disclaimer