A floating $1.00 pegged stablecoin backed by Liquid Staking Tokens with NFT controlled vaults.
Platform: Code4rena
Start Date: 18/10/2023
End Date: 25/10/2023
Period: 7 days
Status: Completed
Pot Size: $36,500 USDC
Participants: 77
Reporter: PaperParachute
Judge: MiloTruck
Id: 297
League: ETH
hals | 1/77 | $2,698.44 | 6 | 0 | 0 | 5 | 1 | Grade A | 0 | 0 |
MrPotatoMagic | 2/77 | $2,583.24 | 5 | 0 | 0 | 4 | 1 | Grade A | 0 | 0 |
yashar | 3/77 | $2,468.82 | 3 | 0 | 0 | 3 | 1 | 0 | 0 | 0 |
klau5 | 4/77 | $2,455.71 | 4 | 0 | 0 | 4 | 1 | 0 | 0 | 0 |
nmirchev8 | 5/77 | $2,356.66 | 3 | 0 | 0 | 3 | 1 | 0 | 0 | 0 |
Saintcode_ | 6/77 | $2,000.24 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 |
T1MOH | 7/77 | $1,943.12 | 7 | 2 | 0 | 4 | 0 | Grade B | 0 | 0 |
falconhoof | 8/77 | $1,773.47 | 2 | 2 | 0 | 0 | 0 | 0 | 0 | 0 |
tnquanghuy0512 | 9/77 | $700.75 | 7 | 1 | 0 | 6 | 0 | 0 | 0 | 0 |
Haipls | 10/77 | $600.07 | 1 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Auditor per page
Open Dollar is a DeFi lending protocol that enables borrowing against liquid staking tokens while earning staking rewards and enabling liquidity via Non-Fungible Vaults (NFVs).
The 4naly3er report can be found here .
Automated findings output for the audit can be found here within 24 hours of audit opening.
Note for C4 wardens: Anything included in the 4naly3er or the automated findings output is considered a publicly known issue and is ineligible for awards.
Open Dollar is a floating $1.00 pegged stablecoin backed by Liquid Staking Tokens with NFT controlled vaults. Built specifically for Arbitrum. As the majority of the codebase is built with (the already audited) GEB framework, the focus of this audit is to review the major changes Open Dollar has made to the framework around proxies, vaults, and the safe manager.
Open Dollar contracts are built using the GEB framework, which uses Collateralized Debt Positions (CDPs) to allow accounts to generate debt against deposited collateral.
NOTE: The terms "CDP", "vault", and "safe" are used interchangeably here. They all refer to a collateralized debt-position in the protocol.
Our modifications to the existing GEB framework include the addition of a Non-Fungible Vault (NFV) feature, which ties CDP ownership to a specific NFT, rather than using the traditional account-based ownership for CDPs. This approach creates a new defi primitive, enabling the development of novel marketplaces, and generating new opportunities for users. Vaults can be sold through existing NFT marketplaces, automations can sell user vaults to arbitrageurs without having to pay liquidation penalties, and existing NFT infrastructure can be used in new ways. With a more capital efficient market for liquidatable vaults there is less risk when creating leveraged positions.
Here's a quick intro video that might help you get started and understand some of the basics: https://youtu.be/EjuvGs5SdAA
@opendollar/sdk
and Contract ABIs @opendollar/abis
v.1.5.5-audit release
Our contracts are forked from hai-on-op/core
at v0.1.2-rc.3
. Since that code has already been audited, we suggest that Wardens focus on the changes we've made since then. For convenience, we created a Pull Request showing these changes here: https://github.com/open-dollar/od-contracts/pull/187
Contract | SLOC | Purpose |
---|---|---|
contracts/AccountingEngine.sol | 185 | The AccountingEngine receives both system surplus and system debt. It covers deficits via debt auctions and disposes of surplus via auctions or transfers (to extraSurplusReceiver) |
contracts/oracles/CamelotRelayer.sol | 62 | Used by Oracle Relayer to fetch the current market price of the system coin (OD) using a Camelot pool on Arbitrum network |
contracts/factories/CamelotRelayerFactory.sol | 23 | |
contracts/factories/CamelotRelayerChild.sol | 11 | |
contracts/oracles/UniV3Relayer.sol | 61 | Potential alternative option to using CamelotRelayer.sol. Used by Oracle Relayer to fetch the current market price of the system coin (OD) using a Uniswap V3 pool on Arbitrum network |
contracts/gov/ODGovernor.sol | 86 | The DAO-managed contract which can modify protocol parameters, eg. add new collateral types and change PID settings |
contracts/proxies/ODProxy.sol | 22 | A more restrictive version of the DSProxy used by Maker Protocol, where the owner cannot be changed. The purpose of this is to ensure that only the Vault721 contract has the ability to transfer a safe. |
contracts/proxies/Vault721.sol | 106 | Serves as the Proxy Registry, Proxy Factory, and the ERC721 "Non-fungible Vault". Manages all safe ownership, transfers, and approvals via the ERC721 standard. Tracks proxy ownership and deploys new proxies- when called directly, or when a safe is transferred to an account which does not have a proxy. |
contracts/proxies/SAFEHandler.sol | 7 | Grants permission to the ODSafeManager to make modifications to a safe. A new SAFEHandler is deployed for each safe, whose address serves as a unique identifier within the SAFEEngine. |
contracts/proxies/ODSafeManager.sol | 167 | A more restrictive Safe Manager, which only allows the Vault721 contract to move a safe. Also calls Vault721 mint when a new safe is created. |
contracts/proxies/actions/BasicActions.sol | 268 |
Total: 998 lines
The Following contracts are where we have implemented the new NFV feature, and where we would like auditors to focus their attention:
All Open Zeppelin imports are from @openzeppelin/contracts
v4.8.2
contracts/proxies/actions/GlobalSettlementActions.sol
contracts/proxies/actions/RewardedActions.sol
contracts/for-test/**/*.sol
contracts/interfaces/**/*.sol
contracts/libraries/**/*.sol
src/contracts
Protocol will be deployed to Arbitrum One (ID: 42161)
updateNftRenderer()
to modify the contract used in creating the SVG image for the token URIsetSafeManager()
to modify the address for the ODSafeManager
.Vault721
: Should comply with ERC721
- If you have a public code repo, please share it here: - How many contracts are in scope?: 11 - Total SLoC for these contracts?: 998 - How many external imports are there?: 3 - How many separate interfaces and struct definitions are there for the contracts within scope?: 13 - Does most of your code generally use composition or inheritance?: Composition - How many external calls?: 0 - What is the overall line coverage percentage provided by your tests?: 95% - Is this an upgrade of an existing system?: True; - 1. Created a custom proxy (ODProxy) for user interactions - 2. The Proxy Registry is now an NFT Vault (Vault721.sol) - 3. Users can interact with their safe via NFT - 4. Safe transfers now also transfer the ownership NFT and vice versa - 5. Naming has changed and custom logic around using the NFT has been added - Check all that apply (e.g. timelock, NFT, AMM, ERC20, rollups, etc.): NFT, Uses L2, ERC-20 Token - Is there a need to understand a separate part of the codebase / get context in order to audit this part of the protocol?: False - Please describe required context: n/a - Does it use an oracle?: No - Describe any novel or unique curve logic or mathematical models your code uses: - Is this either a fork of or an alternate implementation of another project?: True - Does it use a side-chain?: Yes, Arbitrum - Describe any specific areas you would like addressed:
Clone open-dollar/od-contract
git clone git@github.com:open-dollar/od-contracts.git
⚠️ IMPORTANT: Switch to the tag v1.5.5-audit
. This is the specific release which is in-scope for the audit.
git checkout v1.5.5-audit
Install dependencies and compile
yarn yarn build
Setup the environment:
cp .env.example .env
The only required variables for running tests are:
MAINNET_RPC=https://arbitrum-one.publicnode.com GOERLI_RPC=https://arbitrum-goerli.publicnode.com
Run tests with foundry:
yarn test yarn test:e2e
We expect 22 failing tests:
- 1 failing test in test/nft/anvil/NFT.t.sol:NFTAnvil
- 1 failing test in test/nft/anvil/TransferOwnership.t.sol:TransferOwnershipAnvil
- 1 failing test in test/nft/goerli/NFT.t.sol:NFTGoerli
- 1 failing test in test/nft/goerli/governor/GovActions.t.sol:GovActions
- 5 failing tests in test/single/AccountingEngine.t.sol:SingleAccountingEngineTest
- 1 failing test in test/single/SAFEEngine.t.sol:SingleLiquidationTest
- 8 failing tests in test/unit/AccountingEngine.t.sol:Unit_AccountingEngine_AuctionSurplus
- 4 failing tests in test/unit/oracles/UniV3RelayerFactory.t.sol::Unit_UniV3RelayerFactory_DeployUniV3Relayer
Deploy to local Anvil environment:
yarn deploy:anvil
slither .
We are aware of errors
ContractSolcParsing
,SlitherSolcParsing
, etc when running slither. See output here: https://gist.github.com/pi0neerpat/0984343ca5c0f784f3387f1435af4a5e
Here's some helpful tips for using the od-contracts repo effectively.
Understand that the changes we have made are isolated from the rest of the internal accounting and SAFE engine. You do not need a full understanding of the SAFE engine to contribute to this audit. You may find it helpful to think of the SAFE engine as a black box.
Units. GEB uses different units for various levels of precision.
Unit | Meaning |
---|---|
WAD | Number with 18 decimals (10^18) |
RAY | Number with 27 decimals (10^27) |
RAD | Number with 45 decimals (10^45) |
Most of the tests in our repo are for contracts in other parts of the system that are out of scope for this audit. But they might still be helpful in understanding how users are expected to interact with the contracts or coming up with ideas or patterns for potential attacks.
The primary entry point for users into the rest of the protocol is through their ODProxy which is used to execute proxy actions. Except when the user does not have a proxy and is making one for the first time.
We're on your team! If you have questions, ask the Open Dollar devs for help. Seriously, don't be a stranger.