Brahma - hunter_w3b'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: 21/51

Findings: 1

Award: $113.54

Analysis:
grade-a

🌟 Selected for report: 0

🚀 Solo Findings: 0

Awards

113.5407 USDC - $113.54

Labels

analysis-advanced
grade-a
sufficient quality report
A-05

External Links

Analysis - Brahma Contest

Brahma

Description

Brahma is a DeFi orchestration platform, exemplified by Brahma Console v2, designed to enhance the DeFi experience on smart contract wallets. It offers users user-configurable automation and strategies for DeFi interactions, all powered by the efficient Brahma Protocol. Users can enjoy automation without compromising custody of their funds, and SafeSub-accounts reduce risks by isolating interactions. The platform's nomenclature includes Console Accounts, SubAccounts, Operators, and Executors, each contributing to a secure and user-friendly DeFi ecosystem.

The key contracts of the protocol for this Audit are:

  • TypeHashHelper.sol : This library provides functions for building struct hashes used in generating EIP712 digests for signature validations.

  • SafeHelper.sol : Serving as a helper library, it offers essential functions for various interactions with Safe, including executing transactions, generating calldata, and parsing data.

  • TransactionValidator.sol: This contract provides hooks for validating different types of transactions on Console and SubAccount. It checks policy and state compliance before and after transactions and facilitates module execution on SubAccount via ExecutorPlugin.

  • SafeModeratorOverridable.sol: A safe guard for Console accounts, this contract validates transactions for policy compliance using the TransactionValidator contract, both before and after execution.

  • SafeEnabler.sol: This contract provides bytecode for enabling modules and guards on Safe during initialization. It bypasses selfAuthorized checks on Safe's ModuleManager and GuardManager.

  • SafeModerator.sol: As a safe guard, it validates transactions to be executed on Console sub-accounts, ensuring adherence to predefined policies. It performs pre- and post-execution checks for policy compliance on sub-accounts.

  • Constants.sol: Contains constants used by multiple contracts within the Brahma Protocol.

  • ConsoleFallbackHandler.sol: This contract acts as a fallback handler for Safe, ensuring compatibility between different Safe contract versions. It also performs policy validation for ConsoleAccounts/SubAccounts.

  • AddressProvider.sol: Manages and updates addresses of authorized contracts and registries, serving as a singular source of truth when reading addresses. It enforces governance control over these updates.

  • PolicyValidator.sol: This contract validates validator signatures against account policies, checking the validity of transaction signatures and expiry timestamps based on EIP712 signatures.

  • PolicyRegistry.sol: A registry contract for registering policy commits corresponding to wallets and subaccounts, allowing authorized entities to set and update policy commitments.

  • ExecutorRegistry.sol: Manages the registration and removal of executor addresses associated with sub-accounts, ensuring that only the owner of a sub-account can register or deregister executors.

  • WalletRegistry.sol: A registry for wallets and their associated sub-accounts, providing functions for registering wallets and sub-accounts, querying sub-account lists for a wallet, and verifying ownership relationships.

  • AddressProviderService.sol: An abstract contract inherited by all core contracts, providing AddressProvider as a dependency and equipping them with constants and helper functions to interact with it.

  • SafeDeployer.sol: Facilitates the deployment of Gnosis Safe accounts and configures them as console accounts, allowing the creation of console accounts and sub-accounts with optional policy commitments.

  • ExecutorPlugin.sol: Acts as a safe module, enabling execution requests on Console accounts with permissions, and validating executor signatures and policy compliance using the TransactionValidator contract.

Approach Taken-in Evaluating The Brahma Protocol

Accordingly, I analyzed and audited the subject in the following steps;

  1. Core Protocol Contract Overview:

    I focused on thoroughly understanding the codebase and providing recommendations to improve its functionality. The main goal was to take a close look at the important contracts and how they work together in the Braham Protocol.

    I divided the audit into two main parts. First checked the main contracts that represent critical components of the Brahma Protocol, I needed to focus on for the contest. Then, I looked at how they connect with other contracts in the Brahma Protocol.

    Main Contracts I Looked At

    TransactionValidator.sol SafeModeratorOverridable.sol SafeModerator.sol SafeDeployer.sol ExecutorPlugin.sol

    I started my analysis by examining the TransactionValidator.sol contract. This contract is essential for validating various types of transactions on both Console and SubAccount. It includes hooks for transaction validation and policy compliance checks. Ensuring the correctness and security of transaction validation is crucial.

    Then, I turned our attention to the SafeModeratorOverridable.sol contract. As a safe guard for Console accounts, this contract validates transactions and ensures policy compliance using the TransactionValidator. It's vital for security, and any vulnerabilities here could have significant consequences.

    Then audit the SafeModerator.sol contract, This contract serves as a safe guard for validating transactions on Console sub-accounts. It plays a critical role in ensuring that transactions adhere to predefined policies, and thorough auditing is necessary to verify the correctness of policy enforcement.

    SafeDeployer.sol: Since it facilitates the deployment of Gnosis Safe accounts and configuration as console accounts, ensuring its correctness and the security of deployed accounts is paramount.

    These contracts represent critical components of the Brahma Protocol, and auditing them first provide me a strong foundation for assessing the overall security and functionality of the protocol. Additionally, auditing the libraries (TypeHashHelper.sol and SafeHelper.sol) should be considered as they are utilized by many of the core contracts.

  2. Documentation Review:

    Then went to Review this document for a more detailed and technical explanation of Brahma.

  3. Test Coverage Evaluation: During this phase, I play with the tests, initially encountering challenges when attempting to run them first. However, after resolving the issues, I found the well-written tests to be quite interesting.

  4. Manuel Code Review In this phase, I initially conducted a line-by-line analysis, following that, I engaged in a comparison mode.

    • Line by Line Analysis: Pay close attention to the contract's intended functionality and compare it with its actual behavior on a line-by-line basis.

    • Comparison Mode: Compare the implementation of each function with established standards or existing implementations, focusing on the function names to identify any deviations.

Architecture Description and Diagram

Architecture of the key contracts that are part of the Brahma protocol:

The Brahma Protocol architecture integrates core contracts, libraries, registries, and utility contracts to provide a secure and flexible platform for DeFi interactions within smart contract wallets. The system is meticulously designed to validate transactions, enforce policies, and manage addresses, while enabling users to configure their accounts according to their specific needs. The interaction of Console Accounts, Sub-Accounts, Operators, and Executors further enhances the protocol's usability and user control while maintaining a strong focus on security and policy compliance.

  1. Core Contracts

    TypeHashHelper.sol library serves as a fundamental building block for generating EIP712 digests used in signature validations. It plays a crucial role in enhancing security by ensuring the correctness of struct hashes.

    SafeHelper.sol A vital helper library that streamlines interactions with Safe. It provides essential functions for executing transactions, generating calldata, acquiring storage slots, and parsing data.

    TransactionValidator.so The linchpin of the protocol's security, this contract validates various types of transactions on Console and SubAccounts. It encompasses hooks for policy compliance and state checks before and after transactions. Additionally, it manages module execution on SubAccounts via ExecutorPlugin, a key component of the architecture.

  2. Registries

    PolicyRegistry.sol A registry contract responsible for registering policy commitments associated with wallets and subaccounts. It enables authorized entities to set and update policy commitments for specific accounts.

    ExecutorRegistry.sol A registry contract that governs the registration and removal of executor addresses linked to sub-accounts. It ensures that only the owner of a sub-account can register or deregister executors, adding an extra layer of control and security.

    WalletRegistry.sol This registry contract manages wallets and their associated sub-accounts. It provides functions for registering wallets and sub-accounts, querying sub-account lists, and verifying ownership relationships.

  3. Utilities

    AddressProviderService.sol An abstract contract inherited by core contracts, providing them with dependencies and essential functions for interacting with the AddressProvider. This streamlined approach enhances efficiency and code consistency.

  4. Deployment and Module Execution

    SafeDeployer.sol contract is responsible for facilitating the deployment of Gnosis Safe accounts and configuring them as Console Accounts. It allows the creation of console accounts with optional policy commitments and the registration of sub-accounts with policy commitments.

  5. User Interaction and DeFi Operations

    Console Accounts, Sub-Accounts, Operators, and Executors form the dynamic entities through which users interact with the protocol. Console Accounts serve as user-controlled smart contract wallets, Sub-Accounts are managed by Operators and owned by Console Accounts, and Executors enable controlled module transactions on Console Accounts. The protocol's architecture ensures that interactions are policy-compliant and secure, promoting a safe and efficient DeFi experience for users.

Codebase Quality

Overall, I consider the quality of the Brahma codebase to be excellent. The code appears to be very mature and well-developed. We have noticed the implementation of various standards. Details are explained below:

Codebase Quality CategoriesComments
Code Clarity and ReadabilityThe codebase demonstrates good coding practices in terms of clarity and readability. It's well-documented, organized, and follows best practices for Solidity development. This should contribute to easier maintenance and auditing of the code, for-exampe: The TransactionValidator.sol contract has validatePreTransactionOverridable() function this function contains conditional logic to check if certain conditions are met before validating the policy signature. The conditions are checked using the _isConsoleBeingOverriden function and The SafeTransactionParams struct is defined to encapsulate the parameters required for a safe transaction, improving code readability and maintainability.
Code CommentsThe codebase contains comments explaining the purpose and functionality of various functions and methods, making it easier to understand the contract's behavior. These comments enhance the code's readability and maintainability, helping developers and auditors to navigate and review the contract more effectively.
DocumentationThese documentation are essential for maintaining and communicating a clear understanding of a complex project. They help developers, auditors, and other stakeholders grasp the project's architecture, design, and functionality without having to dive deep into the code.for-example the Architecture part It's effectively describes different transaction and execution flows within the project. It is clear, concise, and follows a logical order, making it easy to understand the various processes involved in the system. The use of images alongside the textual descriptions enhances comprehension. So overall, the documentation is of good quality and helps readers gain a clear understanding of the project's architecture and flows.
TestingThe test introduction in the readme file is not complete; it only provides minimal information. More details and context should be included to help users understand the purpose and steps of the test. The current section focuses on changing the working directory and installing JavaScript dependencies but lacks explanations or instructions on what the test aims to achieve or how it should be executed. Please consider expanding the test introduction in the readme to provide a more comprehensive guide for users.
Code Structure and FormattingMust contracts in codebase follows a structured and well-formatted pattern:It begins with license and version declarations, followed by imports of external contracts and libraries.The most contracts defines state variables, including events, error types, and a constructor to initialize the contract.Various functions are organized, each documented with purpose and usage comments, with private helper functions encapsulated for clarity.The some contracts includes error handling and custom error types for specific conditions, ensuring readability and maintainability.
Custom Error TypesThe custom error types are designed to handle specific exceptional conditions consistently across the codebase of various contracts. They are part of a unified error-handling approach, providing clarity and precision in handling exceptional scenarios across the entire codebase.For-Example: ExecutorPlugin.sol contract defines custom error types to handle specific exceptional conditions as follows: InvalidExecutor(): Raised when an executor is not valid for a given account during an execution request.InvalidSignature(): Triggered when the executor's signature is invalid or not provided for a non-externally owned account (EOA) executor.ModuleExecutionFailed(): Signifies that the execution of a module transaction on a safe failed.Also SafeHelper.sol contract contains several custom error types like InvalidMultiSendCall, SafeExecTransactionFailed, and UnableToParseOperation, but it does not provide detailed explanations or reasons for these errors. This lack of clarity makes it difficult to understand the specific issues that may arise and how to mitigate them, increasing systemic risks.

Systemic & Centralization Risks

The analysis provided highlights several significant systemic and centralization risks present in the Brahma protocol. These risks encompass concentration risk in TransactionValidator, SafeModeratorOverridable and AddressProvider risk and more, third-party dependency risk, and centralization risks arising from the existence of an “owner” role in specific contracts. However, the documentation lacks clarity on whether this address represents an externally owned account (EOA) or a contract, warranting the need for clarification. Additionally, the absence of fuzzing and invariant tests could also pose risks to the protocol’s security.

  1. In TypeHashHelper contract if any of the addresses used for constructing the type hashes (e.g., TRANSACTION_PARAMS_TYPEHASH or VALIDATION_PARAMS_TYPEHASH) are centralized or controlled by a single entity, it could pose centralization risks. For example, if an oracle provides these addresses, it might have undue influence on the system.

  2. THe SafeHelper library depends on specific storage slots within the Gnosis Safe contract, such as _GUARD_STORAGE_SLOT and _FALLBACK_HANDLER_STORAGE_SLOT. If the Gnosis Safe contract undergoes changes or upgrades that affect these storage slots, it could disrupt the functionality of this codebase. This creates a systemic risk where changes in external dependencies can impact the system.Also The _generateSingleThresholdSignature function generates a pre-validated signature for executing transactions on the Gnosis Safe. While this can enhance efficiency, it also poses a risk. If an entity gains unauthorized access to this signature generation mechanism, it could potentially execute arbitrary transactions on the Gnosis Safe without proper authorization, leading to a systemic security risk.

  3. The SafeEnabler.sol uses delegate calls to enable modules and guards for a Gnosis Safe. While delegate calls can be a powerful mechanism, they can also introduce security risks. By bypassing certain checks during initialization, this contract allows for behavior that would otherwise be disallowed. This introduces a centralization risk since the contract's behavior is different during initialization.

  4. SafeModerator.sol contract's includes a function called checkModuleTransaction, which does not contain any checks. This is mentioned as compatibility with Safe 1.5 guard over modules, but it's not clear how this compatibility is maintained and whether it introduces any systemic risks.

  5. The _ensureAddressProvider function in AddressProvider.sol contract is designed to check if a new address supports the AddressProviderService interface and is pointing to the current AddressProvider. However, this check can be bypassed if _overrideCheck is set to true when setting an authorized address. This could allow the introduction of unsupported addresses, which might lead to unforeseen issues and centralization risks.

  6. The PolicyValidator code assumes that there is a single trusted validator (EIP 712 signature) that can validate policy signatures. Depending on a single trusted validator introduces centralization risks because the entire system relies on the actions and decisions of this one entity. If the trusted validator becomes compromised or makes incorrect decisions, it can have a systemic impact on policy validation.

  7. The SafeDeployer.sol generates safe addresses based on deterministic nonces, which are derived from the owner's addresses and a salt. While this can be useful for address determinism, it may introduce risks. If an actor precomputes addresses with bumped nonces, it can lead to out-of-gas situations and user inconvenience.

  8. No having, fuzzing and invariant tests could open the door to future vulnerabilities.

Properly managing these risks and implementing best practices in security and decentralization will contribute to the sustainability and long-term success of the Brahma protocol.

Gas Optimization

Brahma demonstrates a strong commitment to gas optimization, incorporating many widely accepted techniques. In addition to the major optimizations mentioned automatic finding, I have compiled a list of 28 gas optimization suggestions.

To improve code clarity in the provided code snippets, we have occasionally used function abbreviations to highlight specific sections. It's important for developers to exercise caution when integrating these proposed changes to prevent potential vulnerabilities. Even though we have conducted prior testing on these optimizations, developers should take on the responsibility of conducting a thorough reevaluation.

Summary

NumberIssuesInstances
[G-01]Using mappings instead of arrays to avoid length checks2
[G-02]Shorten the array rather than copying to a new one3
[G-03]Use assembly to validate msg.sender7
[G-04]Using a positive conditional flow to save a NOT opcode9
[G-05]Use selfdestruct in the constructor if the contract is one-time use
[G-06]Consider using alternatives to OpenZeppelin
[G-07]Using assembly to revert with an error message40
[G-08]Use SUB or XOR instead of ISZERO(EQ()) to check for inequality (more efficient in certain scenarios)1
[G-09]Split revert statements5
[G-10]It is sometimes cheaper to cache calldata3
[G-11]Expressions for constant values such as a call to keccak256(), should use immutable rather than constant1
[G-12]Cache storage variables: write and read storage variables exactly once7
[G-13]Always use Named Returns27
[G-14]Use bitmaps instead of bools when a significant amount of booleans are used1
[G-15]Internal functions not called by the contract should be removed to save deployment Gas5
[G-16]Empty blocks should be removed or emit something14
[G-17]Using Storage instead of memory for structs/arrays saves gas2
[G-18]Use assembly to write address storage values4
[G-19]Avoid contract existence checks by using low level calls10
[G-20]Use solidity version 0.8.20 to gain some gas boost15
[G-21]Use ++i instead of i++ to increment2
[G-22]Using fixed bytes is cheaper than using string5
[G-23]Multiple accesses of a mapping/array should use a local variable cache8
[G-24]abi.encode() is less efficient than abi.encodePacked()4
[G-25]Use assembly to reuse memory space when making more than one external call.8
[G-26]Missing zero address checks in the constructor2
[G-27]Use hardcode address instead address(this)2
[G-28]Use bytes.concat() instead of abi.encodePacked(), since this is preferred since 0.8.46

Conclusion

In general, the brahma project exhibits an interesting and well-developed architecture we believe the team has done a good job regarding the code, but the identified risks need to be addressed, and measures should be implemented to protect the protocol from potential malicious use cases. Additionally, it is recommended to improve the documentation and comments in the code to enhance understanding and collaboration among developers. It is also highly recommended that the team continues to invest in security measures such as mitigation reviews, audits, and bug bounty programs to maintain the security and reliability of the project, Thanks for this beautiful Project.

Time spent:

14 hours

#0 - c4-pre-sort

2023-10-22T21:27:21Z

raymondfam marked the issue as sufficient quality report

#1 - alex-ppg

2023-10-27T13:52:26Z

The overall report is great, well-formatted, and highlights a lot of things in relation to Brahma that would be garnered during an in-depth review of the system. While slightly rudimentary, it is still eligible for an A rating.

#2 - c4-judge

2023-10-27T13:52:31Z

alex-ppg marked the issue as grade-a

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