We express our gratitude to the Possum Labs team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Review Scope
10/10
9/10
96%
9/10
The system users should acknowledge all the risks summed up in the risks section of the report
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
The primary purpose of Possum Portals (Portals
) is to enable users to receive upfront, fixed-rate yield from DeFi staking opportunities instead of accruing yield over time at an unpredictable, variable rate. Portals enable duration-independent speculation on expected future yield rates of the composed yield sources (external protocols). Lastly, the funding mechanism of Portals allows PSM holders to deploy their tokens to a productive use case by lending them to the Portal for a potential profit. The protocol has the following contracts:
src/MintBurnToken.sol - an ERC20 contract with a permit and burnable extension, mintable by owner
src/PortalNFT.sol - This contract can save account information from a Portal user’s stake and also return this information upon redemption. It has a single metadata URI that is used for all ID mints because the relevant account data is saved inside the NFT itself instead of outsourcing this to metadata. The metadata is merely a generic description, name, and picture.
src/PortalV2MultiAsset.sol - contains the main business logic related to upfront yield. Most of the Portal functionality can only work when the vLP is activated. The contract accepts user deposits and withdrawals of a specific token, routing deposits to an external protocol for yield generation. Users accumulate portalEnergy points over time while staking their tokens, exchangeable for the PSM token via the internal Liquidity Pool or minted as ERC20. PortalEnergy Tokens can be burned to increase a recipient's internal balance, with users able to purchase more portalEnergy through the internal LP using PSM. bTokens received during funding initialize the internal LP and can be redeemed against the fundingRewardPool, consisting of PSM tokens. Users can mint NFTs representing their account balances, which are transferable and can be redeemed to add balances back internally.
src/VirtualLP.sol - The shared, virtual liquidity pool that facilitates the payout of upfront yield and the recovery of yield over time. Hosts the integration of the external protocol that generates the yield on staked user assets. This contract acts as the shared, virtual LP for multiple Portals, each requiring registration by the owner for a predetermined duration. Each Portal must be registered by the owner, and once registered, Portals cannot be removed to ensure integrity. The full PSM amount within the LP is accessible to provide upfront yield for each Portal, with capital staked through connected Portals redirected to an external yield source. Yield is claimed and collected by this contract, which also accepts PSM tokens during the funding phase, issuing bTokens as a receipt. These bTokens initialize the internal LP and can be redeemed against the fundingRewardPool, filled over time with a 10% cut from the Converter, an arbitrage mechanism sweeping token balances. Upon triggering the Converter, the caller (arbitrager) must send a fixed amount of PSM tokens to the contract.
src/interfaces/IPortalV2MultiAsset.sol - interface for the PortalV2MultiAsset contract
src/interfaces/IVirtualLP.sol - interface for the VirtualLP contract.
The owner of the MintBurnToken contract can mint tokens
The owner of the PortalNFT contract is the Portal that deploys it. Only the owner can call mint()
and redeem()
.
The owner of the VirtualLP can create new Portals. The owner can be revoked by anyone. Only the registered Portal can send PSM to a user, and deposit/withdraw assets to/from external protocols.
The total Documentation quality score is 9 out of 10.
Functional requirements are partially missed:
Intended outcome of mathematical operations.
Technical description is provided.
Natspec is sufficient.
The total Code quality score is 9 out of 10.
The development environment is configured.
Missing validations.
Rounding errors are present in the code.
Code coverage of the project is 96% (branch coverage).
Deployment and basic user interactions are covered with tests.
Test in the remediations are not running because the stack is too deep.
Upon auditing, the code was found to contain 1 critical, 0 high, 0 medium, and 2 low severity issues. Out of these, 3 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.
The comprehensive audit of the customer's smart contract yields an overall score of 9.6 This score reflects the combined evaluation of documentation, code quality, test coverage, and security aspects of the project.
There is no limit set for amount of ERC20 tokens can be created, as a result, the token owner can mint unlimited tokens, possibly disrupting the token supply and value.
The lack of documentation regarding the mathematics operations poses a significant risk. This makes it harder for reviewers to understand what the code is meant to do, which is essential for accurately assess both its security and correctness.
The ownership duration is configured for 9 days (7 days of the funding phase and 2 days of normal operation). Once this period elapses, the owner can be removed, effectively preventing the creation of new portals. Failure to register portals poses a risk to the protocol's functionality.
There are 2 out of scope contracts, IWater and PSM token. IWater in particular is interacted with a lot in the VirtualLP.sol contract, but the contract functionality cannot be checked since it's out of scope, this will lower the quality of the audit.
The convert() function in the VirtualLP.sol contract could potentially be exploited in scenarios where the liquidity pool is low on PSM tokens. An attacker could execute a sequence of transactions to extract value from the pool. The sequence involves selling a large amount of PSM tokens (thereby buying PE), executing the convert() function, and then buying back the initial amount of PSM tokens (by selling PE).
Code ― | Title | Status | Severity | |
---|---|---|---|---|
F-2024-2453 | Arbitrage vulnerability in quoteBuyPortalEnergy and quoteSellPortalEnergy functions | Fixed | Critical | |
F-2024-2256 | Impossible to mint token with ID equals 0 | Fixed | Low | |
F-2024-2252 | Missing registered portals validation | Fixed | Low | |
F-2024-2455 | Missing checks for the zero address | Accepted | Observation | |
F-2024-2454 | Unchecked return value from transfer functions | Accepted | Observation | |
F-2024-2365 | Documentation mismatch | Mitigated | Observation | |
F-2024-2363 | Missing validation before division | Accepted | Observation | |
F-2024-2359 | Use private rather than public for constants | Fixed | Observation | |
F-2024-2357 | Floating Point Precision by Rounding Error | Accepted | Observation | |
F-2024-2251 | Missing events emitting for important functions | Mitigated | Observation |
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
Severity
Description
Severity
Description
Severity
Description
The scope of the project includes the following smart contracts from the provided repository:
Scope Details
MintBurnToken.sol
PortalNFT.sol
PortalV2MultiAsset.sol
VirtualLP.sol
interfaces/IPortalV2MultiAsset.sol
interfaces/IVirtualLP.sol