Platform: Code4rena
Start Date: 23/02/2024
Pot Size: $36,500 USDC
Total HM: 2
Participants: 39
Period: 7 days
Judge: Dravee
Id: 338
League: ETH
Rank: 8/39
Findings: 1
Award: $318.83
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: hunter_w3b
Also found by: 0xbrett8571, DarkTower, Myd, ZanyBonzy, aariiif
318.8332 USDC - $318.83
The Spectra protocol enables permissionless tokenization of yield from interest bearing assets like Aave and Compound using Principal Tokens (PT) and Yield Tokens (YT).
Components
Principal Token (PT) - An ERC-5095 tokenized vault holding an interest bearing asset
Yield Token (YT) - An ERC-20 representing fractionalized ownership of the yield
Interest Bearing Asset (IBT) - External ERC-4626 asset like Aave, Compound supplying yield
Registry - Maintains protocol settings and parameters
Mechanisms
Users deposit assets into PT vaults which mints paired PT + YT tokens
Interest yield from the external IBT continuously accrues to YT holders
Upon redemption PT burns, yield in YT can be withdrawn
Governance roles defined in AccessManager contracts
Invariants
PT and YT have equal supplies
Yields accumulate to YT holders
Users redeem initial PT deposits + earned yield
Spectra seems to focus on tokenized exposures to interest bearing assets via paired token systems representing principal + yield.
Description of the contracts (in scope):
Proxy Contracts
Core Protocol
Supporting
The proxies facilitate upgradeability using the AccessManager for permissioning. PrincipalToken and YieldToken are the core interest yield tokenization contracts. Utility libraries provide supporting math and calculations.
+-------------------------+ | | | Governance | | | +---------┬---------------+ │ │ +------------+ Set Fees +--------------------------+ | |--------------->| Registry | | | +--------------------------+ | | | | +----v-----------v---------------------------+ | Spectra | | +-------------+ +-------------+ +------+ | | |PrincipalToken| |YieldToken | |Proxy | | | +-------------+ +-------------+ |Admin| | | ^ ^ ^ | +------+ | | | | | | | +-┼------------+ | | | | +-----+ | | | | | | +--v-------v---+ +------v----------+ | | | | | Interest | | External | | Bearing | <----> | Incentives | | Asset | IBT | Contract | | (ERC4626) | <------> (Rewards) | | | | | +------------|--------+------------------+
Overview:
User Spectra Protocol +------------------+ Deposit assets | | | PrincipalToken + | | YieldToken | +---------┬------+ │ │ +-------+ Approve & Deposit +------------+--------------------+ | |-------------------------->| | | | Tokens Minted | Mint paired PT + YT tokens | | User |<--------------------------| | | | +------------+--------------------+ | | ▲ +-------+ Earn yield │ │ ▲◄-----------------------------┘ │ Withdraw yield │ ▲ +-------+ Redeem Tokens +------------+--------------------+ | |-------------------------->| | | | Burn Tokens | Burn PT and withdraw yield | | User | Assets Returned | | | |<--------------------------| | +-------+ +------------+--------------------+
Overview
DAO / Admins Spectra Protocol +---------------+ Set | | | AccessManager | +------+ +------+ | | |Admin | |DAO | +-------+-------+ +------+ +------+ ▲ │ +-----------+ +------+ | | | | |<---------------+ | | Upgrade |Proxy | | v |Admin | +------+ | +------------+ | Beacon| | | | New Logic | <----┼---+ +|---------►|Logic | | +------------+ | | |Contract| +-----------+ +------+ +-------+ +------+ +------+ |Admin | |DAO | +------+ +------+ + | | Pause / | Unpause | v +------------+ |PrincipalToken| +------------+
Overview
Spectra Protocol +--------------------------------+ | PrincipalToken | +------------------+-------------+ | | +------------------v-------------+ | | | | +----------+ | +--v--+ | | | | | | +----> | User +--------->+ |Asset | | | | |Deposit| | |(ERC4626)| | | +------+---+---+---+ | | | +----------| | +-->+ | | Accrue | | | | Yield +<-----------+ | | | | +-------------+------+ | | | YieldToken | | | +-------------+------+ | | ^ | | | Withdraw | | | Yield | | +-------------+ | | | +---------------------------+ | | Registry | | +---------------------------+----+
Overview
PrincipalToken
vaultPrincipalToken
deposits into external interest bearing assetYieldToken
holdersPrincipalTokens
Admin Role
Upgrader Role
Pauser Role
Fee Setter Role
Registry Role
Rewards Harvester Role
Having well-defined protocol roles with minimal privilege promotes sound governance. Role permissions and trust models should be critically examined.
PrincipalToken
The PrincipalToken is the core vault contract that holds users' deposited assets.
YieldToken
The YieldToken
represents fractionalized ownership of interest yield.
PrincipalToken
shares.PrincipalToken
.PrincipalToken
.Proxy Admin
The ProxyAdmin manages upgradeability.
Readability
Security
Maintenance
Best Practices
Overall the codebase demonstrates sound engineering, but has areas that can mature particularly around testing, events, and validation. The focus on readability, security, and governance positions it well for community ownership.
Governance
Asset Custody
Interest Rate Oracles
Protocol Ownership
Mitigations
There is potential for the emergency PAUSER_ROLE
to be abused for malicious purposes if adequate precautions are not taken. Some ways this could occur:
Profit from Predictable Pause
If a malicious actor gains access to the PAUSER_ROLE
, they could pause the protocol right before major expected deposits or withdrawals. This would allow them to front-run the transactions for profit once unpaused.
The predictability of pauses can benefit the attacker.
Discourage Participation
Similarly, the power to pause could be used to discourage protocol participation by users if they expect functionality to halt randomly or frequently. Slowing adoption aids attackers.
Brute Force Upgrades
An attacker might try repeatedly pausing and then manually upgrading protocols to introduce bugs. With enough tries, they may succeed.
Mitigations
Improper access control could allow unauthorized parties to extract funds, manipulate rates to their benefit, or halt protocol operations. This breaks the trust model and intended permissions, leading to loss of funds for users or the protocol.
Root Cause Analysis:
The root cause lies in how role capabilities are defined and assigned in the AccessManager contract used for access control.
Failure Scenario:
An example failure scenario would be:
The UPGRADER_ROLE is granted to an external attacker address during initialization.
After deployment, the attacker calls upgradeTo()
in AMBeacon.sol as they have the UPGRADER_ROLE.
They set the implementation to a malicious contract that simply extracts all IBT funds from PrincipalToken.sol.
Now all funds have been stolen due to improper role assignment.
Specific Code:
In AMBeacon.sol:
function upgradeTo(address newImplementation) public virtual restricted { _setImplementation(newImplementation); }
The restricted
modifier checks that msg.sender
has a role that is allowed to call this function. But if UPGRADER_ROLE is granted incorrectly, an attacker can call this.
In AMProxyAdmin.sol
function upgradeAndCall(IAMTransparentUpgradeableProxy proxy, address implementation, bytes memory data) public payable virtual restricted { proxy.upgradeToAndCall{value: msg.value}(implementation, data); }
Same issue, the restricted
modifier depends on correct role assignments.
Mitigations:
Carefully review each role and its capabilities compared to the intended permissions.
Validate role assignments in initializers and that roles can't be manipulated post-deployment.
Consider time-locking changes to critical role assignments like UPGRADER_ROLE
.
Monitor role changes and upgrades to quickly detect unauthorized modifications.
Overly Centralized Control
The AccessManager admin role has tremendous power. It can upgrade contracts, update implementations, and extract assets. This places immense trust in the admin.
Making one address the gatekeeper for all protocol changes centralizes too much control in one place. Compromise of the admin can compromise the entire system.
Lack of Decentralized Checks & Balances
There are no decentralized checks to admin powers. For example, a DAO vote to approve upgrades or pause the system.
A major protocol decision like upgrading core logic rests solely in the hands of the admin. This increases risks from bribes, hacks, or malicious admins.
Ideally there would be a separation of powers - admin handles day to day tasks but major upgrades need DAO vote.
Potential for Governance Manipulation
If the admin address is a governance contract like a MultiSig
or Timelock
, this still represents a central point of failure.
If the keys controlling the admin contract were compromised, it risks complete governance control. Additional delegated governance contracts also multiply the attack surface.
There should be redundant and distributed authority using multisig thresholds across ecosystem stakeholders to mitigate governance manipulation risks.
Overall the current governance is too centralized with a single admin role that can unilaterally control Spectra. There are also no checks against governance manipulation by delegated contracts. Both these need to evolve to sustain security over the long term.
Malicious Contract Upgrades
If the ProxyAdmin
and Beacon
were compromised, an attacker could upgrade critical contracts like PrincipalToken
to drain assets.
For example, they could set a malicious implemenation that simply transfers all assets in redeem()
to the attacker address. Or manipulate rates to their benefit. Users could lose funds.
This presents a major risk as users believe they interact with the original audited contracts when using the Proxy. A malicious upgrade breaks that trust.
Freezing Funds via Pauser Role
The Pauser Role can arbitrarily pause deposits and redeems by calling pause()
.
A compromised Pauser role could freeze all protocol funds by maliciously pausing contract functions indefinitely. This denies users access to their own assets.
Impersonation by Compromised Upgraders
If an Upgrader address is compromised, the attacker can mimic protocol-side authorized contract upgrades.
For example, push a fake migration contract to extract funds from users. Upgraders hold "code is law" powers to alter protocol without checks.
Mitigations
Timelock/MultiSig with decentralized holders to make Roles more resilient
DAO vote approvals required for any Pausing or Upgrades
Explicit public upgrade announcements from multi-channel sources
There needs to be an extensive process around upgrades and pauses to mitigate the immense powers the roles possess today. Securityaudits on any new implementations can add further reassurance.
Vulnerability
The AMProxyAdmin relies on the AccessManager role checks in the restricted
modifier to control access. This could be bypassed if the AccessManager itself is compromised.
Root cause
The AMProxyAdmin trusts the AccessManager to properly manage permissions after deployment. Subverting this manager would break that trust.
Attack vector
If an attacker gained the ROLE_CONTROLLER
role in the AccessManager, they could add other malicious actors to privileged roles.
Scenario
AccessManager.grantRole(DEFAULT_ADMIN_ROLE, attackerAddress)
restricted
modifier checkupgradeAndCall
to steal fundsCode
AccessManager.sol:
function grantRole(bytes32 roleId, address account) public virtual authorized(ROLE_CONTROLLER)
AMProxyAdmin.sol:
function upgradeAndCall( IAMTransparentUpgradeableProxy proxy, address implementation, bytes calldata data ) public payable virtual restricted
Impact
An attacker could upgrade proxy logic to drain user funds. Severity depends on compromised proxy purpose.
Requires compromise of a privileged AccessManager role. Estimated as unlikely but has high impact.
Macro Conditions
Technical Risks
Financial Risks
Governance Risks
Mitigants
Analyzing protocol risks across various axes - technical, financial, organizational - provides stability.
Decentralize Control
** Bolster Extensibility**
Enhance Upgradeability
Strengthen Security
Improve Performance
Refine Incentives
The focus should be enhancing decentralization, extensibility, security and sustainability of the system over time.
27 hours
#0 - c4-pre-sort
2024-03-03T14:05:57Z
gzeon-c4 marked the issue as high quality report
#1 - jeanchambras
2024-03-06T16:34:02Z
The report is quite good; however, some elements are too generic, offering advice that might apply to any DeFi protocols, or advice that does not apply. For example, in the section on centralization risks, it mentions a centralization risk associated with Rate Oracles, while the Spectra Protocol does not rely on any oracle to function.
#2 - c4-sponsor
2024-03-06T16:34:11Z
jeanchambras (sponsor) acknowledged
#3 - c4-judge
2024-03-11T00:50:55Z
JustDravee marked the issue as grade-a