Open Dollar - Smart Contract Audit

QuantstampRepository at commit 6fbe167

Audit · firm’s term: smart contract audit

Quantstamp reviewed Open Dollar (Open Dollar - Smart Contract Audit) on 23 Apr 2024: 13 findings, 0 critical; 9 marked fixed, 4 acknowledged.

No open critical findings
Open the reportOpen Open Dollar’s security record

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings13

Statuses are the security firm’s own, from its report.

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium013
Low036
MediumDebt Can Be Generated without a VaultFixed

The Open Dollar Protocol introduces the ability of Safe ownership via an NFT. This is done via a `Vault721` contract that acts as the minter of the NFTs and an `ODSafeManager` that is the entry point to manage all the NFV (Non-Fungible Vault) positions. However, by calling `SafeEngine.modifySAFECollateralization()` directly, a user can open a position that does not map to an NFV. Users also have the ability to bypass the `ITaxCollector(taxCollector).taxSingle`, as this call is done in `ODSafeManager` and not in `SAFEEngine` directly. This would allow the user to directly manage the Vault position without interacting with the tax collector and hence take on debt without having to fund the surplus fund, which would be used to cover bad debt.

MediumMissing Checks for Sequencer Uptime when Fetching Chainlink PricesFixed

The `ChainlinkRelayer.latestRoundData()` function fetches the latest price of an asset from Chainlink price feeds. However, as the protocol is intended to be deployed on Arbitrum, checking the sequencer's uptime before querying price data is crucial. If the sequencer is down, there is a chance of using an incorrect or stale price. Please refer to the [Chainlink L2 Sequencer Uptime Feeds](https://docs.chain.link/data-feeds/l2-sequencer-feeds) document for more details.

MediumSafe Saviour Is Difficult to Maintain Whilst Listing an NFV for SaleFixed

A user can assign an `ISAFESaviour` to their NFV. If a liquidation attempt is ever made, the `LiquidationEngine` will first make a call to `ISAFESaviour.saveSAFE()` to give the savior an opportunity to restore the safe to a healthy collateralization ratio before it is liquidated. The current implementation maintains the assigned savior after an `NFV` transfer. Whilst the savior implementations may vary, the `LiquidationEngine.protectSAFE()` call assigns a savior to a particular safe rather than the safe owner. A user may want to maintain their savior to protect their NFV until a sale is guaranteed, but there is no clear way to facilitate the removal of a savior before an NFV transfer. Though this behavior is documented, we would like to note that this behavior is restrictive for listed NFV's.

Low`blockDelay` only Adds a 1 Min Buffer to Check ChangesFixed

One of the protections introduced for issue OD-1 is the `blockdelay` for addresses on the `_allowlist`. It adds an extra check that the last `_hashState[_tokenId].lastBlockNumber` is at least `blockdelay` blocks old compared to the current `block.number`. This is a good idea, but `blockDelay` is a `uint8`, which can maximum be 256 blocks, which may be insufficient for validating NFV purchases.

Low`NFTRenderer` Does Not Fully Reflect a Safe's ValueFixed

To help marketplaces accurately list NFVs and protect users from trading NFV's whose prices have recently changed, the `NFTRenderer` calculates a `stateHash` that reflects the value of each vault. `Vault721` validates that a sufficient number of blocks have passed for a given `stateHash` before facilitating a transfer, giving users to time to be accurately informed about the value of a safe. However, the current `stateHash` only includes a vault's `SAFE.lockedCollateral` and `SAFE.generatedDebt`. This does not capture the additional value held in a vault's `SafeEngine.coinBalance` and `SafeEngine.tokenCollateral`. Additionally, a vault's `stateHash` is not updated when `ODSafeManager.transferInternalCoins()` is called. If a vault transfers its internal coins to another address, its value would drop, and thus the transfer should enforce the time delay.

Low`SAFEHandler` Cannot Call `ODSafeManager.allowHandler()`Fixed

The `handlerCan[]` mapping in `ODSafeManager` tracks permissions for performing operations on a specific `SafeHandler`. It is used in the `quitSystem()` and `enterSystem()` functions. However, there is no way for a `SafeHandler` to call `ODSafeManager.allowHandler()`, making the functions uncallable.

LowLittle Incentives to Restart AuctionsFixed

`DebtAuctionHouse` facilitates auctions to pay off bad debt. Users bid to pay off debt in exchange for governance tokens. If an auction expires without any users placing a bid, the auction can be restarted by calling `restartAuction()` with a more favorable payout of governance tokens. However, it is unclear who would be responsible for restarting the auction. A user who calls `restartAuction()`, places a bid, and then is later outbid will have fronted the gas costs for restarting the auction. This may disincentivize users from restarting auctions, in hopes that a different user might pay the gas costs.

LowMissing Input ValidationFixed

It is important to validate inputs, even if they only come from trusted addresses, to avoid human error. Specifically, in the following functions: * `AccountingEngine.constructor()`: Validate that `_debtAuctionHouse` is a non-zero address. * `AccountingEngine._validateParameters()`: Validate that `debtAuctionMintedTokens` is non-zero. * `Authorizable._addAuthorization()`: Validate that `_account` is a non-zero address. * `CollateralAuctionHouse._validateParameters()`: Validate that `minimumBid` is non-zero. * `DebtAuctionHouse._validateParameters()`: Validate that `bidDecrease` and `amountSoldIncrease` are non-zero. * `SurplusAuctionHouse._validateParameters()`: * Validate that `bidIncrease`, `bidDuration`, and `totalAuctionLength` are non-zero. * Validate that `totalAuctionLength` is greater than `bidDuration`. * Validate that `recyclingPercentage` is less than 100%. * `Vault721.updateVaultHashState()` doesn't check if SAFE exists. * `initializeManager()` and `initializeRenderer()`should have access controls.

LowSending an NFV to an `ODProxy` Will Deploy Another `ODProxy`Fixed

`Vault721._afterTokenTransfer()` checks whether the NFV recipient has an `ODProxy` contract deployed. If no `ODProxy` is linked to their address, it will deploy and link a new `ODProxy` to the recipient. However, this assumes that the `_from` address will be an EOA. If the `_from` address is an `ODProxy`, a new `ODProxy` will be deployed and the original `ODProxy` will be added to the `_userRegistry[]`.

Contracts in scope

No deployed address is recorded for this audit.

The report names a repository or files. Open the report to see its scope.

Repository and files the report names (68)

  • https://github.com/open-dollar/od-contracts/src/contracts/CollateralAuctionHouse.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/PostSettlementSurplusBidActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/GlobalSettlementActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/ChainlinkRelayerFactory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/CollateralJoin.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/CommonActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/Disableable.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/oracles/DenominatedOracle.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/settlement/GlobalSettlement.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/MintableVoteERC20.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/PIDController.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/OracleRelayer.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/tokens/ProtocolToken.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/TaxCollector.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/ETHJoin.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/tokens/SystemCoin.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/FactoryChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/DebtAuctionHouse.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/jobs/AccountingJob.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/OracleForTestnet.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/RewardedActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/jobs/LiquidationJob.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/oracles/ChainlinkRelayer.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/CollateralJoinChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/SurplusAuctionHouse.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/DelayedOracleChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/PIDRateSetter.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/LiquidationEngine.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/AuthorizableUpgradeable.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/CollateralJoinFactory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/ModifiablePerCollateral.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/HardcodedOracle.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/Vault721.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/DeviatedOracle.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/DisableableChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/gov/ODGovernor.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/settlement/SettlementSurplusAuctioneer.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/oracles/DelayedOracle.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/jobs/Job.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/CollateralJoinDelegatableChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/settlement/PostSettlementSurplusAuctionHouse.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/CollateralAuctionHouseFactory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/DenominatedOracleChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/AccountingEngine.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/SurplusBidActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/ChainlinkRelayerChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/BasicActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/ODProxy.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/CollateralAuctionHouseChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/CollateralBidActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/Modifiable.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/NFTRenderer.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/DenominatedOracleFactory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/jobs/OracleJob.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/ODCreate2Factory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/AuthorizableChild.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/tokens/TokenDistributor.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/Ownable.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/OracleForTest.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/ODSafeManager.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/for-test/MintableERC20.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/Authorizable.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/SAFEHandler.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/utils/CoinJoin.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/StabilityFeeTreasury.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/SAFEEngine.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/proxies/actions/DebtBidActions.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e
  • https://github.com/open-dollar/od-contracts/src/contracts/factories/DelayedOracleFactory.sol at commit 6fbe167b696f1583350c5ddfa0ea01d9bde21b4e

Part of Open Dollar’s security record

Open Dollar
Audits3 audits by 2 firmsLast audit Apr 2024, by Quantstamp.
Critical findingsNo open critical findingsAcross 3 reports.
Open Open Dollar’s security record

Security firm

Quantstamp

236 projects reviewed · 332 reports · latest Oct 2026

See Quantstamp’s audits

Something wrong on this page? A missing report, a wrong date, a finding that was fixed since. Tell us and we check it against its source.

Tell us