Penetration Test Report (TrailOfBits): LiquityProtocolandStabilityPoolFinalReport

Liquity
Security Assessment
March 2 5, 2 021
Prepared For:
Robert Lauko | L iquity
robert@liquity.org
Rick Pardoe | L iquity
rick@liquity.org
Prepared By:
Michael Colburn | T rail of Bits
michael.colburn@trailofbits.com
Maximilian Krüger | T rail of Bits
max.kruger@trailofbits.com
Alexander Remie | T rail of Bits
alexander.remie@trailofbits.com
Changelog:
February 12, 2021: Delivered initial report
March 2, 2021: Added Appendix E (Fix Log)
March 25, 2021: Added results of StabilityPool review
Executive Summary
Project Dashboard
Code Maturity Evaluation
Engagement Goals
Coverage
Automated Testing and Verification
Automated Testing with Echidna
Unipool Properties
Recommendations Summary
Short Term
Long Term
Findings Summary
1. exit reverts if there are no claimable rewards
2. Chainlink may report erroneous prices when unfrozen
3. Chainlink may report erroneous prices when Tellor remains untrusted after the last
update
4. frontEnd mechanism may confuse users
5. Underflow in _computeRewardsPerUnitStaked might cause DoS during liquidation
A. Vulnerability Classifications
B. Code Maturity Classifications
C. Code Quality
D. Recommendations for Simplifying fetchPrice
State Variables
fetchPrice
Determining the Next Oracle State
E. Fix Log
Detailed Fix Log
© 2021 Trail of Bits Liquity Assessment | 1
Executive Summary
From February 1 to February 12, 2021, Liquity engaged Trail of Bits to review the security of
the Liquity protocol. Trail of Bits conducted this assessment over four person-weeks, with
two engineers working from commit hash 8 cec3fd from the l iquity/dev repository. Trail
of Bits r eviewed a previous version of this codebase in December 2020.
During the first week of the assessment, we familiarized ourselves with the changes
introduced in this version of the codebase, focusing on the new recovery mode liquidation
logic, the token lockup contract and its factory, and the Unipool contract. In the second
week, we focused on the changes to borrower logic, the proposed gas optimizations, and
the oracle components.
We identified three issues—two of medium severity and one of informational severity. The
medium-severity issues involve situations in which the price feed may be allowed to report
extreme price fluctuations. The informational-severity issue pertains to a situation in which
a user could unexpectedly receive an error when trying to exit the staking pool. We discuss
code quality concerns not related to any particular security issue in A ppendix C. In
Appendix D, we propose an alternative way to track the state of the oracles.
Overall, the code follows a high software development standard and adheres to best
practices. It has suitable architecture and is properly documented. The interactions
between components are well defined, and the testing is extensive.
Trail of Bits recommends addressing the findings presented in this report, continuing to
simplify the system’s logic where possible, and developing a playbook for handling incident
response, especially with respect to oracle degradation.
Update: On February 23, 2021, Trail of Bits reviewed fixes implemented by Liquity for the issues
presented in this report. See A ppendix E for a detailed review of each issue’s current status.
Update: From March 15 to March 17, 2021, Trail of Bits performed a two-person-day review of
the StabilityPool contract (from commit 2 f05955) . This resulted in two additional low-severity
issues (T OB-LQT-019 and T OB-LQT-020) .
© 2021 Trail of Bits Liquity Assessment | 2
Project Dashboard
Application Summary
Name Liquity
Version 8cec3fd, 2 f05955
Type Smart Contracts
Platforms Solidity
Engagement Summary
Dates February 1 – February 12, 2021
March 15 – March 17, 2021
Method Whitebox
Consultants Engaged 3
Level of Effort 4 person-weeks + 2 person-days
Vulnerability Summary
Total High-Severity Issues 0
◼◼
Total Medium-Severity Issues 2
◼◼
Total Low-Severity Issues 2
◼
Total Informational-Severity Issues 1
Total Undetermined-Severity Issues 0
Total 5
Category Breakdown
◼◼◼◼
Data Validation 4
◼
Arithmetic 1
Total 5
© 2021 Trail of Bits Liquity Assessment | 3
Code Maturity Evaluation
In the table below, we review the maturity of the codebase and the likelihood of future
issues. In each area of control, we rate the maturity from strong to weak, or missing, and
briefly explain our reasoning.
Category Name Description
Access Controls Strong. There were appropriate access controls for privileged
operations performed by certain contracts.
Arithmetic Moderate. The contracts used safe arithmetic. No overflows were
possible in areas where these S afeMath functions were not used.
However, it may be possible to trigger an underflow, which could
cause a DoS during liquidation.
Assembly Use Strong. The contracts used assembly only to fetch the c hainID for
the ERC2612 p ermit functionality.
Centralization Strong. O wnership was renounced during the post-deployment
setup process, and the system had a backup price oracle.
Contract Not Applicable. The contracts contained no upgradeability
Upgradeability mechanisms.
Function Satisfactory. Most of the functions and contracts were organized
Composition and scoped appropriately. Areas of improper function composition
identified in the previous report have been somewhat improved.
Front-Running Moderate. The Liquity team previously identified front-running
scenarios that could occur in the stability pool or during
price-fetching operations. No additional front-running concerns
were identified.
Monitoring Satisfactory. T he events produced by the smart contract code were
sufficient to monitor on-chain activity.
Specification Satisfactory. The system had comprehensive documentation that
was updated prior to or during our review.
Testing & Strong. The contracts included numerous unit tests and even used
Verification automated tools such as fuzzers.
© 2021 Trail of Bits Liquity Assessment | 4
Engagement Goals
The engagement was scoped to provide a security assessment of the changes made to the
Liquity codebase in the l iquity/dev repository since our D ecember 2020 review.
Specifically, we sought to answer the following questions:
● Can the oracle be manipulated to fall back when it shouldn’t?
● Have all possible combinations of oracle states been accounted for?
● Is it possible to evade the timelock in the token lockup contract?
● Can a trove adjustment move the trove or the system into an inconsistent state?
● Do the changes to liquidation logic introduce any cases that could allow troves in
good standing to be liquidated?
● Can staker funds be locked in the staking pool?
● Are staking reward calculations sound?
Coverage
Our review focused on commit 8 cec3fd, changes to the PriceFeed contract in commit
dce38b7, and a P R that introduced some gas optimizations. The following contracts in
particular underwent significant changes:
TroveManager. The T roveManager contract exposed trove management functionality,
including liquidation. Prior to this review, Liquity modified some recovery mode liquidation
logic, removing the option to conduct partial liquidation processes. We reviewed this
contract to ensure that it still properly executed liquidation transactions.
PriceFeed. The P riceFeed contract managed interactions with the system’s two redundant
price oracles and provided pricing data to the rest of the Liquity system. We reviewed this
contract to ensure that it returned the appropriate oracle’s price and properly handled all
combinations of oracle states.
BorrowerOperations. T his contract was an important entry point for the management of
a trove’s lifecycle as a borrower. The _ adjustTrove function at the core of this contract
underwent several changes. We reviewed these changes to ensure that the function
correctly handled balance tracking and the recording of trove state changes.
Unipool. T he U nipool contract incentivized early users of the pool to provide liquidity for a
Uniswap LUSD/ETH pair by rewarding them with LQTY. We reviewed the c