Introduction
We express our gratitude to the Asymetrix Protocol team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Asymetrix protocol is a decentralized, non-custodial protocol for asymmetric yield distribution generated from staking.
title | content |
---|---|
Platform | Ethereum |
Language | Solidity |
Tags | ERC20 token, Staking, Yielding |
Timeline | 10/03/2023 - 19/04/2023 |
Methodology | https://hackenio.cc/sc_methodology→ |
Review Scope | |
---|---|
Repository | https://bitbucket.ideasoft.io/projects/PBON/repos/solidity/browse→ |
Commit | 5dcc0ba3c17ab271ad624cbf5a9a8d16c737b448 |
Review Scope
- Commit
- 5dcc0ba3c17ab271ad624cbf5a9a8d16c737b448
Audit Summary
10/10
99.17%
9/10
10/10
The system users should acknowledge all the risks summed up in the risks section of the report
Document Information
This report may contain confidential information about IT systems and the intellectual property of the Customer, as well as information about potential vulnerabilities and methods of their exploitation.
The report can be disclosed publicly after prior consent by another Party. Any subsequent publication of this report shall be without mandatory consent.
Document | |
---|---|
Name | Smart Contract Code Review and Security Analysis Report for Asymetrix Protocol |
Audited By | Hacken |
Website | https://asymetrix.io/→ |
Changelog | 17/03/2023 – Initial Review |
10/04/2023 – Second Review | |
14/04/2023 - Third Review | |
19/04/2023 - Fourth Review |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Asymetrix Protocol
- Audited By
- Hacken
- Website
- https://asymetrix.io/→
- Changelog
- 17/03/2023 – Initial Review
- 10/04/2023 – Second Review
- 14/04/2023 - Third Review
- 19/04/2023 - Fourth Review
System Overview
Asymetrix protocol is the decentralized, non-custodial protocol for asymmetric yield distribution generated from staking. The files in the scope:
PrizePool.sol - Escrows assets and deposits them into a yield source. Exposes interest to Prize Flush. Users deposit and withdraw from this contract to participate in the Prize Pool.
Ticket.sol - The Ticket extends the standard ERC20 and ControlledToken interfaces with time-weighted average balance functionality. The average balance held by a user between two timestamps can be calculated, as well as the historic balance. The historic total supply is available, as well as the average total supply between two timestamps.
TwabRewards.sol - Reward distributing contract. Distributes rewards to depositors in a pool.
TWABDelegator.sol - Delegator contract allows accounts to easily delegate a portion of their tickets to multiple delegates.
TwabLib.sol - Adds on-chain historical lookups to a user(s) time-weighted average balance.
PrizeDistributor.sol - Holds Tickets (captured interest) and distributes tickets to users with winning draw claims.
DrawBeacon.sol - Manages pushing Draws onto DrawBuffer.
Reserve.sol - Provides historical lookups of a token balance increase during a target time range.
PrizeDistributionFactory.sol - Populates a Prize Distribution Buffer for a prize pool.
PrizeFlush.sol - The PrizeFlush contract helps capture interest from the PrizePool and move collected funds to a designated PrizeDistributor contract.
DrawBuffer.sol - Provides historical lookups of Draws via a circular ring buffer. Historical Draws can be accessed on-chain using a drawId to calculate ring buffer storage slot.
DrawCalculator.sol - Calculates the amount of user picks based on the user average weighted balance (during each draw period).
EIP2612PermitAndDeposit.sol – Allows users to approve and deposit EIP-2612 compatible tokens into a prize pool in a single transaction.
ControlledToken.sol - ERC20 contract with a controller for minting & burning.
ASX.sol - ERC20 contract with voting and burning feature.
PermitAndMulticall.sol - Allows a user to permit token spend and then call multiple functions on a contract.
DrawRingBufferLib.sol - Library for creating and managing a draw ring buffer.
ObservationLib.sol - Library allows one to store an array of timestamped values and efficiently binary search them.
BeaconTimelockTrigger.sol - Passes the information about the current draw to the
prizeDistributionFactory
for the creation of aprizeDistribution
.DrawCalculatorTimelock.sol - Pushes Draws to a
DrawBuffer
and routing claim requests from aPrizeDistributor
to aDrawCalculator
.Ownable.sol - Provides a basic access control mechanism, where there is an account (an owner) that can be granted exclusive access to specific functions.
StakePrizePool.sol \- The Stake Prize Pool is a prize pool in which users can deposit an ERC20 token.
Delegation.sol - A Delegation allows his owner to execute calls on behalf of the contract.
Manageable.sol - Abstract manageable contract which provides a basic access control mechanism.
BinarySearchLib.sol - BinarySearchLib uses binary search to find a parent contract struct with the drawId parameter.
LowLevelDelegator.sol - Allows users to create delegations very cheaply.
OverflowSafeComparatorLib.sol - OverflowSafeComparatorLib library to share comparator functions between contracts.
RingBufferLib.sol - Library for managing the TWAB index.
ExtendedSafeCastLib.sol - Downcasting from uint256/uint224, uint256/uint208, uint256/uint104
ICompLike.sol - An interface contract for CompLike token.
IPrizePool.sol - An interface contract for PrizePool.sol.
ITicket.sol - An interface contract for Ticket.sol.
IPrizeDistributor.sol - An interface contract for PrizeDistributor.sol.
IPrizeDistributionBuffer.sol - An interface contract for PrizeDistributionBuffer.sol.
IDrawBeacon.sol - An interface contract for DrawBeacon.sol.
IPrizeFlush.sol - An interface contract for PrizeFlush.sol.
IDrawCalculator.sol - An interface contract for DrawCalculator.sol.
IDrawBuffer.sol - An interface contract for DrawBuffer.sol.
IBeaconTimelockTrigger.sol - An interface contract for BeaconTimelockTrigger.sol.
IDrawCalculatorTimelock.sol - An interface contract for DrawCalculatorTimelock.sol.
IReserve.sol - An interface contract for Reserve.sol.
IControlledToken.sol - An interface contract for ControlledToken.sol.
IPrizeDistributionSource.sol - An interface contract for PrizeDistributionSource.sol.
IPrizeDistributionFactory.sol \- An interface contract for PrizeDistributionFactory.sol.
Privileged roles
Owner:
The PrizePool and StakePrizePool owner has the authority to set balance and liquidity caps, reward per second, claim interval, free exit duration, Lido APR, as well as set Ticket,
DrawBeacon
, andPrizeFlush
addresses.The DrawBeacon owner can set a new DrawBuffer address and adjust the
beaconPeriodSeconds
.The DrawBuffer owner can create and set a new Draw, and can also set a new
prizeDistributor
address.The PrizeDistributionBuffer owner can create and set a new
prizeDistribution
.The PrizeDistributor owner can distribute rewards to winner addresses, withdraw ERC20 token from the contract, and set new
DrawBuffer
andprizeDistributionBuffer
addresses and distribution percentages.The Reserve owner can withdraw ERC20 token from the contract.
The Manageable owner can set a new manager address.
The Ownable owner can renounce or transfer ownership.
The PrizeDistributionFactory owner can create and set a prize distribution, as well as set minimum pick cost and end timestamps offset.
The PrizeFlush owner can set destination, reserve,
prizePool
,protocolFeeRecipient
addresses, andProtocolFeePercentage
. The owner can withdraw the reserve balance to the destination address.The BeaconTimelockTrigger owner can lock and push new prize distribution.
The DrawCalculatorTimelock owner can set and edit the timelock.
The Delegation owner can set delegation lock timestamp and execute low-level calls.
The TWABDelegator owner can set minimum and maximum lock durations.
PendingOwner:
The Ownable pendingOwner can claim ownership.
OnlyController:
The controller address for the ControlledToken contract can mint and burn tokens.
Manager:
The DrawBuffer manager can push a new Draw.
The PrizeDistributionBuffer manager can create and set a new
prizeDistribution
.The PrizeDistributor manager can distribute rewards to winner addresses.
The Reserve manager can withdraw ERC20 token from the contract.
The PrizeDistributionFactory manager can create and set a new prize distribution.
The PrizeFlush manager can withdraw the reserve balance to the destination address.
The BeaconTimelockTrigger manager can lock and push a new prize distribution.
The DrawCalculatorTimelock manager can set a new timelock.
Executive Summary
Documentation quality
The total Documentation quality score is 10 out of 10.
Functional requirements are provided.
Technical description is provided.
Code quality
The total Code quality score is 9 out of 10.
The code is heavily based on the following project: pool together →.
The project follows style guidelines and best practices.
The development environment is configured.
Test coverage
Code coverage of the project is 99.17% (branch coverage).
Deployment and basic user interactions are covered with tests.
PrizeDistributor.sol throws exceptions in draws and randomness.
Two tests throw an “TypeError: ethers.getContract is not a function” exception.
Security score
Upon auditing, the code was found to contain 1 critical, 1 high, 12 medium, and 2 low severity issues. Out of these, 13 issues have been addressed and resolved, leading to a security score of 10 out of 10.
All identified issues are detailed in the “Findings” section of this report.
Summary
The comprehensive audit of the customer's smart contract yields an overall score of 9.7. This score reflects the combined evaluation of documentation, code quality, test coverage, and security aspects of the project.
Risks
The project uses different types of uint variables, and performs conversions between them, this may cause reverts due to their upper bounds.
The prize distribution process depends on an out of scope off-chain system. The admin is allowed to pass any index of their choosing to IPFS. Thus Hacken cannot fully guarantee the security for the randomness in the prize distribution process. However, the validity of the prize distribution can be validated at each round, and the intermediary calculation step is stored on IPFS. (The win chances for each address are calculated based on the contract state, but the costly calculation is done off-chain, and its results are pinned to IPFS for external verification). Random numbers are generated using on-chain VRF and the admin supplies the random addresses to the contract based on those. This process can be tracked via the protocol website.
Findings
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2023-1493 | Weak Source of Randomness | mitigated | Critical | |
F-2023-1494 | Highly Permissive Role Access | fixed | High | |
F-2023-150 | Contradiction - Missing Validation | fixed | Medium | |
F-2023-150 | Best Practice Violation - Redundant Calculation | mitigated | Medium | |
F-2023-1504 | Tautology | mitigated | Medium | |
F-2023-150 | Best Practice Violation - Checks-Effects-Interactions Pattern Violation | fixed | Medium | |
F-2023-150 | Inconsistent Data - Unused Return Value | fixed | Medium | |
F-2023-1501 | Inconsistent Data - Natspec Mismatch | fixed | Medium | |
F-2023-150 | Contradiction - Missing Validation | fixed | Medium | |
F-2023-1499 | Contradiction - Missing Validation | fixed | Medium |
Identify vulnerabilities in your smart contracts.
Appendix 1. Severity Definitions
When auditing smart contracts, Hacken is using a risk-based approach that considers Likelihood, Impact, Exploitability and Complexity metrics to evaluate findings and score severities.
Reference on how risk scoring is done is available through the repository in our Github organization:
Severity | Description |
---|---|
Critical | Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation. |
High | High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation. |
Medium | Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category. |
Low | Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution, do not affect security score but can affect code quality score. |
Severity
- Critical
Description
- Critical vulnerabilities are usually straightforward to exploit and can lead to the loss of user funds or contract state manipulation.
Severity
- High
Description
- High vulnerabilities are usually harder to exploit, requiring specific conditions, or have a more limited scope, but can still lead to the loss of user funds or contract state manipulation.
Severity
- Medium
Description
- Medium vulnerabilities are usually limited to state manipulations and, in most cases, cannot lead to asset loss. Contradictions and requirements violations. Major deviations from best practices are also in this category.
Severity
- Low
Description
- Major deviations from best practices or major Gas inefficiency. These issues will not have a significant impact on code execution, do not affect security score but can affect code quality score.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
---|---|
Repository | https://bitbucket.ideasoft.io/projects/PBON/repos/solidity/browse→ |
Commit | 5dcc0ba3c17ab271ad624cbf5a9a8d16c737b448 |
Whitepaper | Not provided |
Requirements | Provided→ |
Technical Requirements | Provided→ |