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
Rank: 37/51
Findings: 1
Award: $14.47
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: niroh
Also found by: 0xDetermination, 0xSmartContract, 0xbrett8571, 0xdice91, 0xweb3boy, Bauchibred, Bube, DadeKuma, JCK, K42, LinKenji, Myd, SAAJ, ZanyBonzy, albahaca, castle_chain, catellatech, digitizeworx, emerald7017, fouzantanveer, hunter_w3b, invitedtea, m4ttm, rahul, xiao
14.466 USDC - $14.47
Step | Task | Details |
1 | Run Tests | Tests run successfully |
2 | Coverage | 100% test coverage for contracts in audit scope |
3 | Slither | Reviewed Slither results, no vulnerabilities discovered |
4 | Surya | Generate graphs to understand the overall project structure. Provided an initial insight to the contract inheritance and function call flow |
5 | Solidity Metrics | Generate metrics reports to obtain initial insight on the codebase, noting areas of potential concern |
6 | Code Review | Line by line code review |
7 | Test Review | Review of each test and it's purpose |
Brahma aims to allow users to automate DeFi actions without giving up custody of their funds by using preconfigured Gnosis Safe accounts. Through the use of sub accounts, users are able to isolate their interactions and reduce their overall exposure to risk. ExecutorPlugin
is a contract which is authorised to make transactions on sub accounts via the use of modules. Transactions are validated through multiple stages, initially via SafeModerator
which uses TransactionValidator
to verify transactions before and after exection, and PolicyValidator
to ensure policy signature validity. Three registry contracts are used, ExecutorRegistry
, PolicyRegistry
and WalletRegistry
and a central source of truth for addresses is given by AddressProvider
. This is accessed via an abstract contract called AddressProviderService
.
The Governance has the ability to change the addresses authorised to use each policy. In the event of a Governance attack this could result in the addresses being set to malicious contracts, resulting in the loss of user funds.
According to the documentation, the guardian is supposed to handle emergency actions such as pausing and conducting emergency withdrawals, however it is unclear where this functionality is implemented or who controls this address. This could potentially place trust in a single centralised entity, allowing them to freeze the protocol at will or steal users funds.
The code is well structured and organised into separate contracts, each with a clear purpose. In depth functionality is logically separated into libraries. NatSpec comments are well used throughout the codebase. The automated findings show that some styling conventions such as line lengths, custom error descriptions and exposing interfaces are not adhered to
NatSpec comments are present throughout the code, although are incomplete in places. In depth details of how the contracts work can be found in the documentation. There are diagrams showing the main flows of execution but function names are incorrect in places.
Full test coverage is achieved for the contracts in scope, making use of both Hardhat and Foundry. Tests are well written and clearly structured. Testing could be further improved with the use of fuzz testing, or formal verification to give users the extra assurance that their funds are safe.
Multiple contracts are deployed for each registry and another for the address provider. ExecutorRegistry
, PolicyRegistry
, WalletRegistry
and AddressProvider
can be combined. Using a single deployed contract simplifies the system and makes this easier to read when using block explorers and tools using live data.
Contracts inherit from AddressProviderService to obtain the addresses from AddressProvider. Using an interface to expose its methods directly and setting the address for this in the constructor would be the cleaner and more conventional approach.
Internal functions such as _onlyGov
and _ensureAddressProvider
are implemented for access control where modifiers are the usual convention. The use of modifiers cleans the actual function body and makes it easier to read the code, obtaining key details before you dive into the function body.
20 hours
#0 - c4-pre-sort
2023-10-22T21:06:38Z
raymondfam marked the issue as sufficient quality report
#1 - 0xad1onchain
2023-10-23T11:02:20Z
Thanks for the analysis Using modifiers increases contract bytecode size a lot
#2 - alex-ppg
2023-10-27T14:01:32Z
The report is relatively brief, however, it contains correct statements throughout.
#3 - c4-judge
2023-10-27T14:01:37Z
alex-ppg marked the issue as grade-b