Platform: Code4rena
Start Date: 18/10/2023
Pot Size: $36,500 USDC
Total HM: 17
Participants: 77
Period: 7 days
Judge: MiloTruck
Total Solo HM: 5
Id: 297
League: ETH
Rank: 14/77
Findings: 3
Award: $419.75
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xmystery
Also found by: 0x6d6164616e, 0xWaitress, 0xsurena, Tendency, ZanyBonzy, cryptothemex, hals, lsaudit, ni8mare, niki, phoenixV110, spark, tnquanghuy0512, twcctop
26.0735 USDC - $26.07
The Relayer contracts, UniV3Relayer.sol
and CamelotRelayer.sol
consult their respective TWAPs for token prices. To deal with different token decimals, the contracts use a multiplier
to convert the quote into an 18 decimanls format. However, the multiplier
doesn't take into consideration ERC20 tokens with decimals greater than 18. Calling these token types will cause a reversion.
uint256 public multiplier;
multiplier = 18 - IERC20Metadata(_quoteToken).decimals();
The multiplier is a uint256 parameter, any token with more than 18 decimlals will cause the contract initialization to fail.
Manual code review
Consider checking if decimals > 18 before calculating the multiplier
ERC20
#0 - c4-pre-sort
2023-10-26T00:17:18Z
raymondfam marked the issue as sufficient quality report
#1 - c4-pre-sort
2023-10-26T00:17:30Z
raymondfam marked the issue as duplicate of #18
#2 - c4-pre-sort
2023-10-27T05:07:57Z
raymondfam marked the issue as duplicate of #323
#3 - c4-judge
2023-11-02T08:45:41Z
MiloTruck marked the issue as satisfactory
🌟 Selected for report: lsaudit
Also found by: 0xPsuedoPandit, 0xhacksmithh, Stormreckson, ZanyBonzy, klau5, tnquanghuy0512, twicek, xAriextz
40.8849 USDC - $40.88
https://github.com/open-dollar/od-contracts/blob/f4f0246bb26277249c1d5afe6201d4d9096e52e6/src/contracts/proxies/ODSafeManager.sol#L105 https://github.com/open-dollar/od-contracts/blob/f4f0246bb26277249c1d5afe6201d4d9096e52e6/src/contracts/proxies/ODSafeManager.sol#L136
A safe owner can grant other users permission to act on his safe by calling the allowSAFE
function. However, this permissions aren't revoked when the owner transfers the safe to another owner. This gives those users access to the new owner's safe.
Alice gives Bob permissions to act on her safe using the allowSAFE
functions. Alice then transfers the safe to Charlie by calling the transferSAFEOwnership
function.
_usrSafes[_sData.owner].remove(_safe); _usrSafesPerCollat[_sData.owner][_sData.collateralType].remove(_safe); _usrSafes[_dst].add(_safe); _usrSafesPerCollat[_dst][_sData.collateralType].add(_safe); _safeData[_safe].owner = _dst; emit TransferSAFEOwnership(msg.sender, _safe, _dst); }
The safe is removed from Alice's list of safe and added to Charlie's. However, Bob's given permissions are not revoked. Consequently, every function involving the safeAllowed
modifier is now accesible to both Charlie and Bob which is undesirable.
Manual code review
Revoke all user's permissions when transfering ownership.
Access Control
#0 - c4-pre-sort
2023-10-25T23:55:52Z
raymondfam marked the issue as low quality report
#1 - c4-pre-sort
2023-10-25T23:55:56Z
raymondfam marked the issue as primary issue
#2 - c4-pre-sort
2023-10-27T04:35:46Z
raymondfam marked the issue as duplicate of #142
#3 - c4-pre-sort
2023-10-27T04:37:47Z
raymondfam marked the issue as sufficient quality report
#4 - c4-judge
2023-11-02T08:00:07Z
MiloTruck marked the issue as partial-50
#5 - MiloTruck
2023-11-02T08:02:04Z
While this report does correctly identify that permissions in safeCan
are not cleared in transferSAFEOwnership()
, it incorrectly states that previously approved addresses will have access to the safe when it belongs to the new owner. This is untrue; the problem only arises when the initial owner regains ownership of the safe.
As such, I believe this report only deserves partial credit.
#6 - c4-judge
2023-11-02T08:47:40Z
MiloTruck marked the issue as satisfactory
#7 - c4-judge
2023-11-03T16:46:31Z
MiloTruck marked the issue as partial-50
🌟 Selected for report: hunter_w3b
Also found by: 0xbrett8571, 0xweb3boy, JCK, Myd, SAAJ, ZanyBonzy, clara, fouzantanveer, jauvany, wei3erHase
352.796 USDC - $352.80
We began by thoroughly reviewing the provided documentations, as well as reviewing the video provided. We compared them to the GEB framework on which the Opendollar protocol is based. Here, we made note of important information, noted down unclear parts and overall tried to fully understand how the protocol should function. We also took notes of integrated and inherited protocols and mapped out possible risk areas.
While we were studying the docs, we had ran static analyzers and linters through the contracts to detect basic vulnerabilities and other non critical errors. The result of our static analysis was then compared to the provided bot reports and those deemed known were removed.
After the documentation review and static analysis, we started the process of manual code inspection. We noted how the contracts were divided into different modules and we inspected the contracts in each module carefully. We stuidied each of the contracts, tested how each function behaves and compared that to how they're expected to behave. We then tried out various attack ideas, including the ones provided by the sponsors. We noted the dependencies, inheritancies, and possible vulnerabilities that can arise from them. We made comparisons to issues found in protocols of the same kind (including older commits) to see if the same mistakes were repeated and how effective the provided fixes were.
After this was done, we made notes on the issues we found and prepared the analysis report.
The codebase in scope is divided into four major modules.
The Proxy module enhances the user experience when interacting with the protocol. It includes contract interfaces, proxies, and actions that are essential for vault management. In scope, the module comprises
The Oracle module ensures that the system has access to up-to-date and accurate price information which are then used to set up system parameters. Contracts in scope here include
CamelotRelayer.sol - The Oracle Relayer this contract to find out how much the open dollar coin is currently worth from the Camelot pool on the Arbitrum network. The quote obtained from the pool is converted into an 18 decimals format.
CamelotRelayerChild.sol - inherits the functionality of CamelotRelayer contract to be factory deployed
CamelotRelayerFactory.sol - is the factory for creating/deploying CamelotRelayerChild contracts.
UniV3Relayer.sol - is the same as the CamelotRelayer contract, but it consults the UniswapV3 pool instead.
The Core Module stores all the SAFE data, allows external actors to trigger liquidations in case SAFEs are underwater and also handles debt and surplus auctions. The AccountingEngine is the only contract here in scope.
The Governance Module modifies and upgrades the protocol.
The codebase contracts are well commented, although the documentation provided seems to be outdated. Some of the contracts in scope don't appear in the documentation. We recommend updating these for users and future audits.
Unit tests were performed for these contracts, however some of the contracts appear to have low coverages. The AccountEngine contract has a quite complicated codebase, codebases like these are recommended to have invariant tests. We also recommend implementing and performing more tests to improve the coverages. This can help catch basic bugs and improve safety.
Some basic contract safety measures also seemed to be ignored. Castings are done without unsafely, there are non zero checks when initializing the Vault721 and ODProxy contracts, some polymorphic functions and there seems to be a case of a loop in an external functions. These are by no means very serious issues, but they cause a host of inconvienieces to the protocol implementation.
Error handling is quite good. A mix of custom and require errors are used. We recommend using the same error approach throughout the codebase, preferably custom errors because they're more gas-efficient. Other improvements include adding descriptions and NatSpec comments to the errors (some are lacking) and making sure the descriptions are not cryptic.
Events are emitted for important parameter changes, although in some cases, they seemed to not follow the checks-effects-interaction patterns. Also, to save gas, its recommended to use assembly to emint these events.
Overall, the codebase is solid, well written and is of high quality, however improvements can be made in certain areas. We recomment using linters and static analysis tools to clean up the codebase before deployment.
Risk from centralization exists and is quite great. Some contracts are controlled by governace and owners, every actions from these parties have impacts on the users and the protocols. They have to be trusted not to act maliciously, and to also be careful to not get hacked.
Risk from smart contracts also pose a risk to the system. Critical security flaws, access control errors, logical inconsistencies can lead to loss of assets or system manipulations. We recommend constant sytem upgrades and audits, and also taking into consideration auditors' recommendations before deploying these contracts.
Risks from third party contracts also exist. The contract imports OZ contracts,any vulnerability in these contracts are likely to have an effect in the system. The ODGovernace
contract for instance, fully inherits the OZ Governance contracts. Any issue with these contracts means the ODGovernace
is also vulnerable to that issue. Also, an older version of OZ is being used, 4.8.2, we recommend upgrading to version 5.0 which as of time of auditing is the latest version.
Risks from Oracles. The protocol relies on a number of TWAPs to fetch token price data, this makes the contracts vulnerable to manipulation attacks, inaccurate data feeds and so on.
OpenDollar is a DeFi lending protocol that enables borrowing against liquid staking tokens while earning staking rewards and enabling liquidity. The contracts are built around the GEB framework, it uses collaterized debt positions (CDP) to allow accounts to generate debt agaisnt deposited collateral. As a modification of the GEB framework, Non-Fungible Vaults were added. It ties a CDP to an NFT unlike the traditional based account to CDP (non transferable). These CDPs can be then sold through existing NFT market places.
The OpenDollar in general codebase is well-designed, but identified risks need to be fixed. Measures should be implemented to protect the protocol from potential attacks. Finally, we recommend updating the documentation and comments to make it easier for users, developers and auditors to understand and work on the code.
32 hours
#0 - c4-pre-sort
2023-10-27T01:48:02Z
raymondfam marked the issue as sufficient quality report
#1 - c4-judge
2023-11-03T17:23:18Z
MiloTruck marked the issue as grade-a