Brahma - K42's results

Brahma Console is a custody and DeFi execution environment.

General Information

Platform: Code4rena

Start Date: 13/10/2023

Pot Size: $31,250 USDC

Total HM: 4

Participants: 51

Period: 7 days

Judge: 0xsomeone

Id: 295

League: ETH

Brahma

Findings Distribution

Researcher Performance

Rank: 47/51

Findings: 1

Award: $14.47

Analysis:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

14.466 USDC - $14.47

Labels

analysis-advanced
grade-b
sufficient quality report
A-10

External Links

Advanced Analysis Report for Brahma by K42

Overview

  • For this analysis, I focus on key aspects of the ecosystem and include function interaction graphs for all contracts, seen in the Contract Details section.
  • Brahma is a multi-layered smart contract system designed for secure and flexible transactions specifically via ConsoleAccount and SubAccount. This analysis dives deep into the intricacies of the Brahma ecosystem, focusing on possible security loopholes, briefly detailing possible gas improvements, and in depth function-level interactions.

Understanding the Ecosystem:

  • ConsoleAccount: The primary account for initiating transactions. It has an optional SafeModeratorOverridable guard and policy layers.
  • SubAccount: A secondary account that can be operated by ConsoleAccount or external operators. It also has an optional SafeModerator guard and policy layers.
  • SafeModerator & SafeModeratorOverridable: These are the security layers that validate transactions through TransactionValidator and PolicyValidator.
  • TransactionValidator: This contract is responsible for ensuring that the guard is not being removed and validates the policyHash and Trusted Validator Signature.
  • PolicyValidator: This contract is responsible for validating policy commitments against a registry.
  • ExecutorPlugin: This contract allows third-party transaction execution after validating the executor against the ExecutorRegistry.
All Contracts In-Scope:
  1. TypeHashHelper.sol

    • Purpose: Generates EIP712 digests for signature validations.
    • Specifics: The contract should ensure that the struct hashes are generated efficiently to minimize gas costs. Consider using inline assembly for optimization.
  2. SafeHelper.sol

    • Purpose: Provides essential functions for interactions with Safe.
    • Specifics: The generateCalldata function should be optimized for gas efficiency. Ensure that storage slots are obtained in a gas-efficient manner.
  3. TransactionValidator.sol

    • Purpose: Provides hooks for transaction validation.
    • Specifics: The validatePreTransaction and validatePostTransaction functions should be carefully audited to ensure they enforce all policy/state compliance checks.
  4. SafeModeratorOverridable.sol

    • Purpose: Acts as a guard for Console accounts.
    • Specifics: The contract should explicitly handle edge cases where the guard is being overridden or removed.
  5. SafeEnabler.sol

    • Purpose: Provides bytecode for enabling modules and guards on Safe.
    • Specifics: The contract should ensure that the DELEGATECALL is executed securely, bypassing the selfAuthorized check only when absolutely necessary.
  6. SafeModerator.sol

    • Purpose: Validates transactions on console sub-accounts.
    • Specifics: The validateTransaction function should be optimized for gas efficiency and should include all necessary policy checks.
  7. Constants.sol

    • Purpose: Contains constants used by multiple contracts.
    • Specifics: Ensure that constants are declared as immutable to save on gas costs.
  8. ConsoleFallbackHandler.sol

    • Purpose: Acts as a fallback handler for Safe.
    • Specifics: The contract should maintain compatibility with both pre and post 1.3.0 Safe contracts. Ensure that the bytecode in methods is optimized for gas.
  9. AddressProvider.sol

    • Purpose: Manages and updates addresses of authorized contracts.
    • Specifics: The contract should include a mechanism for community governance to propose and vote on address updates.
  10. PolicyValidator.sol

    • Purpose: Validates validator signature against account policies.
    • Specifics: The contract should ensure that the EIP712 signatures are validated securely and efficiently.
  11. PolicyRegistry.sol

    • Purpose: Registry for policy commits.
    • Specifics: The setPolicy function should include a time-lock mechanism for added security.
  12. ExecutorRegistry.sol

    • Purpose: Manages the registration and removal of executor addresses.
    • Specifics: The contract should ensure that only the owner of a sub-account can register or deregister executors.
  13. WalletRegistry.sol

    • Purpose: Registry for wallets and sub-accounts.
    • Specifics: The registerWallet and registerSubAccount functions should be secured with the onlyOwner modifier.
  14. AddressProviderService.sol

    • Purpose: Provides AddressProvider as a dependency to inheriting contracts.
    • Specifics: The contract should ensure that the AddressProvider dependency is securely and efficiently integrated into inheriting contracts.
  15. SafeDeployer.sol

    • Purpose: Facilitates the deployment of Gnosis Safe accounts.
    • Specifics: The deploySafe function should be optimized for gas efficiency.
  16. ExecutorPlugin.sol

    • Purpose: Facilitates execution requests on Console accounts.
    • Specifics: The executeTransaction function should include rate-limiting mechanisms to prevent abuse.
Data Structures:
  • policyHash: A keccak256 hash that represents the transaction policy. It's crucial for ensuring that the transaction adheres to predefined rules.
  • Trusted Validator Signature: A digital signature from a trusted validator, usually an EOA, that is verified in PolicyValidator before transaction execution.
  • Guard: The address of the guard contract, which can be either SafeModerator or SafeModeratorOverridable, depending on the account type.
Key Contracts:
  • ConsoleAccount.sol: Main contract for user-initiated transactions.
  • SubAccount.sol: Allows transactions to be initiated by a ConsoleAccount or an external operator.
  • SafeModerator.sol: Validates transactions for SubAccount.
  • SafeModeratorOverridable.sol: An extended version of SafeModerator with additional features, used in ConsoleAccount.
  • TransactionValidator.sol: Validates the integrity and rules of transactions.
  • PolicyValidator.sol: Validates policy commitments.
  • ExecutorPlugin.sol: Enables third-party transaction execution.
Inter-Contract Communication:
  • SafeModerator and SafeModeratorOverridable interact with TransactionValidator and PolicyValidator through internal function calls.
  • ExecutorPlugin interfaces with TransactionValidator through a series of function calls to validate third-party transactions.

Codebase Quality Analysis:

Data Structures:
  • policyHash: Ensure that the hash is generated using keccak256 and is stored efficiently to minimize gas costs.
  • Trusted Validator Signature: Use EIP-712 for generating structured and secure signatures. Store only the hash of the signature to optimize storage costs.
  • Guard: Use a contract interface to enforce a standard set of functions for any guard contract.
Modifiers:
  • onlyOwner: This should be used in functions like setGuard to ensure that only the contract owner can change the guard.
  • nonReentrant: Apply this modifier to execTransaction() to prevent re-entrancy attacks.
Security:
  • Implement SafeMath library specifically in the execTransaction() function to prevent integer overflow and underflow.
  • Use OpenZeppelin's Ownable contract for robust and secure ownership management, especially in ConsoleAccount and SubAccount.

Architecture Recommendations:

  • Implement a time-lock mechanism specifically in setGuard function to allow for community vetting.
  • Use the Diamond pattern for contract upgradability, particularly for SafeModerator and SafeModeratorOverridable to allow for future security enhancements.
  • Implement a rate-limiting mechanism in ExecutorPlugin to prevent abuse by external executors.

Centralization Risks:

  • The SafeModerator contract has the power to validate or invalidate transactions, creating a central point of failure.
  • The Trusted Validator is a single EOA that has the authority to validate transactions, creating a centralization risk.

Mechanism Review:

  • TransactionValidator uses isPolicySignatureValid() to validate the policyHash and Trusted Validator Signature, making it the cornerstone of transaction validation.
  • PolicyValidator uses a registry to validate policy commitments, making it crucial for ensuring that transactions adhere to predefined rules.
  • The Guard mechanism in ConsoleAccount and SubAccount can be optionally set, providing flexibility but also adding complexity in understanding the security model.

Systemic Risks:

  • Re-entrancy attacks could be possible if nonReentrant is not properly implemented in execTransaction().
  • Front-running risks exist in TransactionValidator due to the lack of transaction ordering enforcement.
Specific Risks and Mitigations in Each Contract:

ConsoleAccount:

  • Risks: Unauthorized guard removal through setGuard(address(0)).
  • Mitigations: Require multi-signature or DAO approval for guard removal and implement a time-lock.

SubAccount:

  • Risks: policyHash manipulation by unauthorized external executors.
  • Mitigations: Use onlyOwner modifier for policy updates and validate policyHash against a registry.

SafeModerator:

  • Risks: Bypassing transaction checks through direct contract calls.
  • Mitigations: Implement function-level access controls and re-verify transactions post-execution.

TransactionValidator:

  • Risks: Signature replay attacks due to lack of nonce.
  • Mitigations: Implement a nonce mechanism for each transaction.

Areas of Concern

  • The optional nature of guards in ConsoleAccount and SubAccount can lead to inconsistent security postures.
  • The ExecutorPlugin allows external transaction execution but lacks robust rate-limiting mechanisms.
  • The PolicyValidator relies on a centralized registry, creating a single point of failure.

Recommendations

  • Use a DAO structure for governance to mitigate centralization risks.
  • Implement Layer 2 solutions like zk-Rollups for scalability.
  • Use Chainlink oracles for external data verification, especially in PolicyValidator.

Contract Details

I made function interaction graphs for the key contracts to better visualize interactions, as seen below:

Conclusion

  • Brahma offers a robust but complex architecture. While it provides flexibility and modularity, it needs to address specific security and centralization risks to be fully resilient.

Time spent:

16 hours

#0 - c4-pre-sort

2023-10-22T21:13:51Z

raymondfam marked the issue as sufficient quality report

#1 - alex-ppg

2023-10-27T13:35:41Z

While the report does analyze each module in detail, it does not have a solid grasp of the Brahma system. Upgrade-ability and ownership-related recommendations are incorrect as a result (i.e. the setGuard operation of address(0) is a multi-signature process by definition as being the result of a Gnosis Safe vote).

#2 - c4-judge

2023-10-27T13:35:46Z

alex-ppg marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter