MakerDAO Liquidations 2.0

QuantstampFiles named in the report

Quantstamp reviewed Sky (MakerDAO Liquidations 2.0) on 25 Feb 2021: 12 findings, 0 critical; 2 marked fixed, 9 acknowledged, 1 open.

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

Report hosted on certificate.quantstamp.com.

Trustblock does not review code.

Findings12

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

SeverityOpenAcknowledgedFixed
Critical000
High000
Medium110
Low082
Medium`Dog` and `Clipper` could potentially have mismatched componentsAcknowledged

The `Dog` and `Clipper` contracts are designed to be components in a modular system that works together consistently to achieve certain functions. These contracts also interact with components other than `Dog` and `Clipper`, and it is expected that these components are the same from both `Dog` and `Clipper` perspectives. However, given that `vow` can set quite trivially via `file` in both contracts, without any validation, there is potential that `vow` may diverge and therefore lead to aberrant unexpected behaviors. At the same time, it was also mentioned in the code walk-through call that the `Clipper.dog` state variable which is currently `immutable` may lose that status in the future, and therefore even components like `vat` could potentially be mismatched and lead to larger issues.

LowAuction parameters may change mid flightAcknowledged

There are several parameters in an auction that are deeply involved in tuning it, such as `cusp`, `tail`, `chip` or `tip`. In standard auctions, these parameters(or what they represent in terms of tuning) are usually set before the auction begins and held immutable until the end so that behaviour can be more predictable and fair to users and operators. However, it appears that in `Clipper`, all of these parameters can be mutated via `Clipper.file` at any time. This would mean that potentially an auction could be in flight and a subsequent parameter change in `file` abruptly stops the auction due to a `cusp` or `tail` decrement.

LowContracts may have no authorized wardAcknowledged

There is nothing preventing the single authorized address/user from calling `deny()` on themselves. This would cause the user to lock themselves out since they will no longer be able to call any function protected by the `auth` modifier in the smart contract.

LowIncorrect initialization behaviorAcknowledged

1. [ACKNOWLEDGED] The specification indicates that the `Clipper.dog` should be authorized to call `kick`. However, the `Clipper.constructor` does not set `wards[dog] = 1`. 2. [MITIGATED] The `cut` in the `StairstepExponentialDecrease.constructor` is set to zero. This is not good, because it will lead to the `price` function returning zero. It is also not inline with the specification, which gives an example of `cut = 0.99 * RAY`.

LowMissing input validationAcknowledged

The majority of auth-ed functions do not have any input parameter validation in place, which could lead to unexpected values being set by authenticated accounts. The following list contains a few instances of such functions, however, the list is not exhaustive as it would be too long: 1. `Clipper.setBreaker` does not check the value of `level` and therefore the circuit breaker could be set to any unsigned integer value. In the current code, this is not a problem as the `isStopped` modifier uses the less-than (<) sign. However, it could be problematic if some service listens for `SetBreaker` events and it doesn’t expect any values other than 0, 1 and 2. 2. `Clipper.file` does not check if the value of the `data` parameter corresponding to each value of what is in the right range. For example, `buf` seems to always need to be higher than 100%, while `chip` and `cusp` should always be less than 100%. `tail` should always be greater than zero. 3. `Dog.file` does not check if the value of the `data` parameter corresponding to each value of what is in the right range. For example, `chop` should probably never be 0; `Hole` and `hole` should also never be zero. 4. `LinearDecrease.file` does not check if the value of the `data` parameter corresponding to each value of what is in the right range. For example, `tau` should always be greater than 0, otherwise the `price` function will throw due to a division-by-zero error. 5. `StairstepExponentialDecrease.file` does not check if the value of the `data` parameter corresponding to each value of what is in the right range. For example, `step` should always be greater than 0, otherwise the `price` function will throw due to a division-by-zero error. Also `cut` should always be greater than 0, otherwise the `price` function will return 0.

LowOracle delay may lead to `redo`-ing and bad debtAcknowledged

In `Clipper`, the auction sets the `top` price as a function of the OSM result. It is stated in the MIP45 specification that: > Note that the current OSM price is between one and two hours delayed relative to the actual market price. This means that there is a possibility that the actual market price could be sufficiently under the OSM price that the Keepers have no incentive `take`, therefore leading to incomplete auctions that `redo`. Every `redo` incentivizes callers with `tip` and `chip` which is funded from `vat`, thereby draining it slowly. Auctions which are incomplete for longer amounts of time run a higher risk of accumulating bad debt. Combined, they may cause a persistent overall value loss. The potential loss is scaled by the length of the OSM delay, since this plausible event is bounded by it. This issue was foreshadowed by [MIP45c21](https://forum.makerdao.com/t/mip45-liquidations-2-0-liq-2-0-liquidation-system-redesign/6352#MIP45c21) and [MIP45c23](https://forum.makerdao.com/t/mip45-liquidations-2-0-liq-2-0-liquidation-system-redesign/6352#MIP45c23) of the specification, and can be thought of as similar but not the same due to the focus on the oracle delay.

LowPrivileged Roles and OwnershipAcknowledged

Smart contracts will often have `owner` variables to designate the person with special privileges to make modifications to the smart contract. In these contracts we have a homemade authentication system that guards key functions such as `file`, `cage`, `yank` or `setBreaker`. Whilst it is understood these contracts are designed with a multilateral governance system in mind for the privileged role, it is important to note the potential impact.

LowTips may not be enough to cover gas fees when network is congestedAcknowledged

The purpose of the `tip` state variable is to incentivize keepers to call `bark` such that they would be reimbursed for the gas fee. However, since this is a flat fee, it may not cover the gas costs when the network is highly congested and the gas prices are high.

LowUnlocked PragmaAcknowledged

Every Solidity file scoped specifies in the header a version number of the format `pragma solidity >=0.6.11`. The greater-or-equal (`>=`) before the version number implies an unlocked pragma, meaning that the compiler will use the specified version _and above_, hence the term "unlocked".

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 (3)

  • src/clip.sol
  • src/dog.sol
  • src/abaci.sol

Part of Sky’s security record

Sky
Audits150 audits by 3 firmsLast audit Nov 2026, by ChainSecurity.
Critical findingsNo open critical findingsAcross the 150 reports, 2 critical findings were reported. Each is marked fixed by the firm that reported it.
Open Sky’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