Quantstamp reviewed Quadrata (Quadrata Lending) on 21 Mar 2023: 11 findings, 0 critical; 5 marked fixed, 6 open.
Report hosted on certificate.quantstamp.com.
Trustblock does not review code.
Statuses are the security firm’s own, from its report.
| Severity | Open | Acknowledged | Fixed |
|---|---|---|---|
| Critical | 0 | 0 | 0 |
| High | 3 | 0 | 0 |
| Medium | 0 | 0 | 0 |
| Low | 3 | 0 | 5 |
One of the custom changes to the Compound code base was changing the constructors to publicly callable normal functions. The `Maximillion` constructor changed to a publicly callable function `setCEther()`. As it is no longer a constructor, or has an `initializer` modifier as i.e. known from [OpenZeppelin's `Initializable` library](https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#initializers), or any other way of preventing multiple calls and is public, anyone can call said contract and re-initialize it and thereby modify the `cEther` state variable.
If a user has their passport burnt, no actions can be taken on their `CToken`s or any accumulated debt. This is because `getHighestAMLScore()` makes a call to `reader.getAttributesFree()`, which requires the user to have a passport. Not only will `CToken`'s be locked with the user being unable to call `redeem()`, but their collateral cannot be liquidated either, as `repayBorrowFresh()` requires a passport for both the `borrower` and the `payer`. <br><br> Additionally, a borrower below their collateral requirements cannot be liquidated if their AML score becomes greater than 8 after they've already borrowed funds.
The code base is a modified fork of the [Compound project](https://compound.finance/), based on commit hash [eb7a6c9831198a19736bc4c1f8f66d41b98f4eaf](https://github.com/compound-finance/compound-protocol/tree/eb7a6c9831198a19736bc4c1f8f66d41b98f4eaf). As that commit hash is from 10th August 2021 it is missing many changes. For example, it is missing critical security fixes, like the ERC777-based re-entrancy fix introduced in [078356d5e2e37e1032e61cf1ff586b5b51b5725b](https://github.com/compound-finance/compound-protocol/pull/153/commits/078356d5e2e37e1032e61cf1ff586b5b51b5725b).
It is important to validate inputs, even if they only come from trusted addresses, to avoid human error. Specifically, in the following functions arguments of type `address` may be initialized with value `0x0`: 1. `BaseJumpRateModelV2.sol`: Validate `_owner` in the constructor. 2. `CDaiDelegate.sol`: Validate the addresses passed to `_becomeImplementation()`. 3. `CDaiDelegate.sol`: `accrueInterest()` should confirm that `potAddress` is set. 4. `CErc20Delegator.sol`: `underlying_`, `comptroller_`, `interestRateModel_`, `admin_`, and `implementation_` should be checked in the constructor. Any setter functions for the variables should confirm they aren't the zero address as well. 5. `CErc20Immutable.sol`: `underlying_`, `comptroller_`, `interestRateModel_`, and `admin_` should be checked in the constructor. 6. `CEther.sol`: `comptroller_`, `interestRateModel_`, and `admin_` should be checked in the constructor. 7. `ComptrollerG7.sol`: Check the address passed into `_setPriceOracle()`. 8. `Maximillion.sol`: Check the value of `cEther_` in `setCEther()`. 9. `Resevoir.sol`: Validate `token_` and `target_` in the constructor. 10. `Timelock.sol`: Validate `admin` in the constructor and `setPendingAdmin()`. 1. `UniswapAnchoredViewProxy.setWhitelistedMethods()` does not check that `_uav` is different from `address(0)`. 1. `UniswapAnchoredViewProxy.setTargetDecimals()` does not check that `_target` is smaller than `type(int256).max` (Alternatively use [SafeCast's](https://docs.openzeppelin.com/contracts/3.x/api/utils#SafeCast) `.toInt256()` in `scalePriceInternal()`). 1. `UniswapAnchoredViewProxy.setPriceDecimals()` does not check that `_priceDecimals` is smaller than `type(int256).max` (Alternatively use [SafeCast's](https://docs.openzeppelin.com/contracts/3.x/api/utils#SafeCast) `.toInt256()` in `scalePriceInternal()`).
As security standards develop, so does the Solidity language. In order to stay up to date with current practices, it's important to use a recent version of Solidity and recent conventions. Apart from syntax changes, new solidity versions introduce important security fixes, [like implicit integer overflow/underflow checks](https://docs.soliditylang.org/en/v0.8.13/080-breaking-changes.html#silent-changes-of-the-semantics), and features and it is therefore recommended to use the latest version if possible.
Every Solidity file specifies in the header a version number of the format `pragma solidity (^)0.8.*`. The caret (`^`) before the version number implies an unlocked pragma, meaning that the compiler will use the specified version _and above_, hence the term "unlocked".
The report names a repository or files. Open the report to see its scope.
Repository and files the report names (88)
236 projects reviewed · 332 reports · latest Oct 2026
See Quantstamp’s auditsSomething 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