Penetration Test Report (Consensys): 0x v3 staking audit 2019 10

0x v3 Staking Audit
1 Summary Date October 2019
2 Audit Scope
Lead Auditor Steve Marx
3 System Overview
Co-auditors Alex Wade
4 Risk Assessment
5 Issues
5.1 Anyone can remove a maker’s pending pool join status Major ✓ Fixed
5.2 Delegated stake weight reduction can be bypassed by using an external
contract Major Won't Fix
5.3 MixinParams.setParams bypasses safety checks made by standard
StakingProxy upgrade path. Medium ✓ Fixed
5.4 Authorized addresses can indenitely stall ZrxVaultBackstop catastrophic
failure mode Medium ✓ Fixed
5.5 Pool 0 can be used to temporarily prevent makers from joining another pool
Medium ✓ Fixed
5.6 Recommendation: Fix weak assertions in MixinStakingPool stemming from
use of NIL_POOL_ID Medium ✓ Fixed
5.7 LibFixedMath functions fail to catch a number of overows Medium
✓ Fixed
5.8 Recommendation: Remove MixinAbstract and fold
MixinStakingPoolRewards into MixinFinalizer and MixinStake Minor
Won't Fix
5.9 Recommendation: remove confusing access to activePoolsThisEpoch
Minor ✓ Fixed
5.10 Recommendation: remove
MixinFinalizer._getUnfinalizedPoolRewardsFromState Minor Won't Fix
5.11 Recommendation: remove complicating getters from
MixinStakingPoolRewards Minor Won't Fix
5.12 Recommendation: remove unneeded dependency on MixinStakeBalances
Minor Won't Fix
5.13 Misleading MoveStake event when moving stake from UNDELEGATED to
UNDELEGATED Minor ✓ Fixed
5.14 The staking contracts contain several artifacts of a quickly-changing
codebase Minor ✓ Fixed
5.15 Remove unneeded elds from StoredBalance and Pool structs Minor
✓ Fixed
5.16 Remove unnecessary fallback function in Staking contract Minor ✓ Fixed
5.17 Pool IDs can just be incrementing integers Minor ✓ Fixed
5.18 LibProxy.proxyCall() may overwrite important memory Minor ✓ Fixed
6 Tool-Based Analysis
6.1 MythX
6.2 Surya
Appendix 1 - Disclosure
1 Summary
ConsenSys Diligence conducted a security audit on the 0x staking contracts. These
contracts control the distribution of fees collected by the 0x Exchange to ZRX stakers.
The 0x v3 Exchange audit is good background reading to understand this report.
2 Audit Scope
The scope of this audit was the staking project within the 0x monorepo.
This audit covered the following les from commit b8e01d7 of the 0xProject/0x-monorepo:
File Name SHA-1 Hash
ReadOnlyProxy.sol 6ec64526446ebff87ec5528ee3b2786338cc4fa0
Staking.sol 67ddcb9ab75e433882e28d[PII_REDACTED]b7084c61
StakingProxy.sol 248f562d014d0b1ca6de3212966af3e52a7deef1
ZrxVault.sol 6c[PII_REDACTED]a2f5d0984122e8ab1413a5b521c9
fees/MixinExchangeFees.sol 9ac3b696baa8ba09305cfc83d3c08f17d9d528e1
File Name SHA-1 Hash
fees/MixinExchangeManager.sol 46f48136a49919cdb5588dc1b3d64c977c3367f2
immutable/MixinConstants.sol 97c2ac83ef97a09cfd485cb0d4b119ba0902cc79
immutable/MixinDeploymentConstants.sol 424f22c45df8e494c4a78f239ea07ff0400d694b
immutable/MixinStorage.sol 8ad475b0e424e7a3ff65eedf2e999cba98f414c8
interfaces/IStaking.sol ec1d7f214e3fd40e14716de412deee9769359bc0
interfaces/IStakingEvents.sol 25f16b814c4df9d[PII_REDACTED]c3f727d858456c4
interfaces/IStakingProxy.sol 02e35c6b51e08235b2a01d30a8082d60d9d61bee
interfaces/IStorage.sol eeaa798c262b46d1874e904cf7de0423d4132cee
interfaces/IStorageInit.sol b9899b03e474ea5adc3b4818a4357f71b8d288d4
interfaces/IStructs.sol fee17d036883d641afb1222b75eec8427f3cdb96
interfaces/IZrxVault.sol[PII_REDACTED]675317e000cfa92de9741e50c1c809
libs/LibCobbDouglas.sol 242d62d71cf8bc09177d240c0db59b83f9bb4e96
libs/LibFixedMath.sol 36311e7be09a947fa4e6cd8c544cacd13d65833c
libs/LibFixedMathRichErrors.sol 39cb3e07bbce3272bbf090e87002d5834d288ec2
libs/LibProxy.sol 29abe52857a782c8da39b053cc54e02e295c1ae2
libs/LibSafeDowncast.sol ae16ed2573d[PII_REDACTED]0253b060b9507729c3d
libs/LibStakingRichErrors.sol f5868ef6066a18277c932e59c0a516ec58920b00
stake/MixinStake.sol ade59ed356fe72521ffd2ef12ff8896c852f11f8
stake/MixinStakeBalances.sol cde6ca1a6200570ba18dd6d392ffabf68c2bb464
stake/MixinStakeStorage.sol cadf34d9d341efd2a85dd13ec3cd4ce8383e0f73
staking_pools/MixinCumulativeRewards.sol 664ea3e35376c81492457dc17832a4d0d602c8ae
staking_pools/MixinStakingPool.sol 74ba9cb2db29b8dd6376d112e9452d117a391b18
staking_pools/MixinStakingPoolRewards.sol a3b4e5c9b1c3568c94923e2dd9a93090ebdf8536
sys/MixinAbstract.sol 99fd4870c20d8fa03cfa30e8055d3dfb348ed5cd
sys/MixinFinalizer.sol cc658ed07241c1804cec75b12203be3cd8657b9b
sys/MixinParams.sol 7b395f4da7ed787d7aa4eb915f15377725ff8168
sys/MixinScheduler.sol 2fab6b83a6f9e1d0dd1b1bdcea4b129d166aef1d
The audit activities can be grouped into the following three broad categories:
1. Security: Identifying security related issues within the contract.
2. Architecture: Evaluating the system architecture through the lens of established
smart contract best practices.
3. Code quality: A full review of the contract source code. The primary areas of focus
include:
Correctness
Readability
Scalability
Code complexity
Quality of test coverage
3 System Overview
The staking contracts are a mechanism for distributed protocol fees collected by the 0x
Exchange. Fees are distributed to pools of ZRX stakeholders according to a formula that
takes into account:
1. how much ZRX is being staked by the pool and
2. the amount of protocol fees generated by liquidity providers (“makers”) in that pool.
The v3 staking specication is the best available documentation for understanding how
the staking contract system works.
4 Risk Assessment
The code that handles staking is very complex. We remain uncomfortable with parts of the
code that were too dicult to audit effectively. That said, this doesn’t mean it’s unsafe to
interact with the contract. There are three types of interactions where funds are potentially
at risk:
1. ZRX deposits and withdrawals by stakers.
2. The staking contracts hold WETH (wrapped ether) that is collected as protocol fees
from the Exchange contracts.
3. Collected WETH is distributed to stakers according to the internal logic of the staking
contract.
We can assess the risk associated with all three:
1. ZRX deposits and withdrawals make use of a fairly simple ZrxVault contract, which
includes a fail-safe mechanism which can be triggered by 0x if needed to allow stakers
to directly withdraw their ZRX. Excluding malicious action by 0x themselves, ZRX
deposits and withdrawals have low risk of fund loss.
2. Although WETH needs to be approved to the staking contracts, the only WETH
actually held by the staking contracts is what is collected in payProtocolFee , which
is invoked by the Exchange. There’s low risk of WETH being inappropriately transferred
from users.
3. Most of the complexity of the staking contracts deals with how the collected fees are
distributed. This is the part of the code the audit team has less condence in, meaning
there’s a relatively higher risk of errors being made here.
This risk assessment means that the most likely type of bug to encounter is one where
rewards are paid out incorrectly, or a bug prevents paying out rewards altogether. Those
outcomes are no worse for stakers than simply not staking at all.
5 Issues
Each issue has an assigned severity:
Minor issues are subjective in nature. They are typically suggestions around best
practices or readability. Code maintainers should use their own judgment as to
whether to address such issues.
Medium issues are objective in nature but are not security vulnerabilities. These
should be addressed unless there is a clear reason not to.
Major issues are security vulnerabilities that may not be directly exploitable or may
require certain conditions in order to be exploited. All major issues should be
addressed.
Critical issues are directly exploitable security vulnerabilities that need to be xed.
5.1 Anyone can remove a maker’s pending pool join status Major
✓ Fixed
Resolution
This is xed in 0xProject/0x-monorepo#2250 by removing the two-step handshake for
a maker to join a pool.
Description
Using behavior described in issue 5.6, it is possible to delete the pending join status of any
maker in any pool by passing i