Introduction
We express our gratitude to the Bertram The Pomeranian team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Bert is a flexible staking program that enables users to lock tokens or NFTs into different pool options that offer configurable settings such as lock periods, yield rates and max caps, in exchange for yield rewards, allowing users to select their staking strategy based on their preferences and goals.
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for Bertram The Pomeranian |
| Audited By | Kerem Solmaz, Panagiotis Konstantinidis |
| Approved By | Ataberk Yavuzer |
| Website | https://www.bert.global→ |
| Changelog | 21/07/2025 - Preliminary Report |
| 31/07/2025 - 2nd Review Report | |
| 05/08/2025 - 3rd Review Report | |
| 07/08/2025 - Final Report | |
| Platform | Solana |
| Language | Rust |
| Tags | Staking, Yield Farming |
| Methodology | https://hackenio.cc/sc_methodology→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for Bertram The Pomeranian
- Audited By
- Kerem Solmaz, Panagiotis Konstantinidis
- Approved By
- Ataberk Yavuzer
- Website
- https://www.bert.global→
- Changelog
- 21/07/2025 - Preliminary Report
- 31/07/2025 - 2nd Review Report
- 05/08/2025 - 3rd Review Report
- 07/08/2025 - Final Report
- Platform
- Solana
- Language
- Rust
- Tags
- Staking, Yield Farming
- Methodology
- https://hackenio.cc/sc_methodology→
Review Scope | |
|---|---|
| Repository | https://github.com/WebitLabs/bert-staking-sc→ |
| Initial Commit | 6c2f7c667e42af6a26dd85ca4b85ae8f6147dfa9 |
| 1st Remediation Commit | f427fd70e840f70594b36d470677dfbb1a3c6574 |
| 2nd Remediation Commit | 00046388d062d3486f2f52973fb48e1ea3328268 |
| Final Commit | 28f4679b0a09b887e3fbb1e6f7bd1bcdf9861159 |
Review Scope
- Initial Commit
- 6c2f7c667e42af6a26dd85ca4b85ae8f6147dfa9
- 1st Remediation Commit
- f427fd70e840f70594b36d470677dfbb1a3c6574
- 2nd Remediation Commit
- 00046388d062d3486f2f52973fb48e1ea3328268
- Final Commit
- 28f4679b0a09b887e3fbb1e6f7bd1bcdf9861159
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are provided in the PDF documentation, which outlines the intended process flow and high-level functionality of the system.
The project includes essential technical documentation, including a
README.mdfile that provides setup instructions, build and run steps, and usage of the API.The codebase contains partial inline comments, helping explain the purpose of variables and functions across most files.
Code quality
The code demonstrates strong Rust proficiency and effective use of the Anchor framework, aligning well with Solana ecosystem best practices.
The codebase is well-structured with a clear separation between administrative and user-facing instructions. Modules are logically grouped (
admin,context,state), promoting maintainability and readability.It includes robust error handling, using descriptive
StakingErrorvariants and consistentrequire!assertions to validate preconditions before any state changes occur.The project includes comprehensive test coverage, test files that simulate full staking and claiming flows using
solana-bankrunandanchor-bankrunenvironments, which provide a lightweight local test validator and Anchor-compatible interface for simulating transactions, time advancement, and cross-program invocations.
Test coverage
Code coverage of the project is N/A.
The Score is N/A since there is no reliable tool to calculate Solana test coverage.
The project includes meaningful integration testing for key functionalities.
The TypeScript tests cover most user flows and core logic.
Rust-based tests are not present in the codebase.
System Overview
BERT Staking smart contract is a Solana-based staking protocol that allows users to stake either tokens or NFTs to earn yield rewards over a configurable lock period.
The program is implemented using the Anchor framework and is composed of multiple smart contract modules, structured across the admin, context, and state folders, with lib.rs serving as the main entry point.
Staking Program
The bert_staking_sc folder contains the core logic and implements the following functionality:
initialize: Deploys a newConfigaccount to represent a staking configuration. It sets up core parameters such as maximum stake cap, NFT token-equivalent value, and per-user NFT limits.initialize_auth_vault: Creates an associated token account (ATA) owned by theConfigPDA to store yield tokens. These tokens are distributed to users during the claim phase.initialize_pool: Initializes staking pools under a given config. Each pool has its own lock period (in days), yield rate, and staking caps for NFTs, tokens, and total value.initiate_user: Initializes user-specific staking metadata. This step is optional, as it is automatically performed during the first staking action.stake_token/stake_nft: Allows users to stake tokens or NFTs into a selected pool. Each stake creates a new position with a lock duration as defined by the pool’s settings.claim_position_token/claim_position_nft: Enables users to claim both their original stake and the accrued yield after the lock period has passed. Yield is paid from theauthority_vault.admin_withdraw_tokens: Admin can withdraw tokens from theauthority_vault, which is designed to store the yield tokens required for the claim instructions, to a designated destination.admin_set_pool_config/admin_pause_pool/admin_activate_pool: Admin functions to update or toggle pool parameters and state.
Initialization Process
To start the staking system, a config must be initialized. This config acts as the root authority over all staking logic, and defines global parameters such as the NFT value in tokens, caps, and limits.
The authority of the Config is responsible for:
Initializing the
authority_vault, an associated token account that stores yield tokens intended for the claim distribution.Creating and configuring staking pools using
initialize_pool, where each pool is defined with:lock_period_days— how long funds are locked (in days).yield_rate— the yield in basis points.max_nfts_cap— maximum NFTs a user can stake.max_tokens_cap— maximum tokens a user can stake.max_value_cap— maximum total value across NFTs and tokens in the pool.
Yield tokens must be deposited into the authority vault to ensure claims will succeed once users complete the lock period.
Staking and Claim Functionality
Users may call initialize_user to explicitly set up their staking metadata, although this is also triggered automatically upon first stake.
The project allows staking of both tokens and NFTs into predefined pools, each configured with specific yield rates, lock durations, and staking limits. Every staking action creates a distinct position tied to the user's account, tracking the staked asset, pool reference, and lock duration time. Once the lock period elapses, users can claim their rewards using dedicated claim instructions depending on whether they staked tokens or NFTs. Claims return both the original staked asset and the calculated yield. The protocol enforces per-user and per-pool limits to ensure fair participation and prevent over-staking.
Privileged roles
The authority account (set per config) has the authority to:
Initialize and configure staking pools with custom parameters (lock period, yield rate, caps), and set the token mint and NFT collection allowed for staking in each config.
Set and fund the
authority_vaultused for yield distribution.Pause and reactivate pools via admin instructions.
Modify pool configurations at any time.
Withdraw yield tokens from the
authority_vault.Set the destination address for withdrawals of the yield tokens.
Potential Risks
Dependency on Unaudited External Libraries: The program depends on several standard Solana libraries (e.g., anchor-spl, mpl-core). While widely used, those components are not audited in the context of this project, introducing potential risks from indirect dependencies.
Owner's Unrestricted State Modification: The authority (config initializer) has control over multiple parameters, including vaults, pool creation, and configurations. Improper permission handling could lead to protocol disruption or misconfiguration.
Insufficient Multi-signature Controls for Critical Functions: All administrative actions, including withdrawals and pool configuration, are executed by a single authority without multi-signature safeguards. This creates a central point of failure and trust.
Absence of Time-lock Mechanisms for Critical Operations: Admin actions like fund withdrawal, pause or activate pools, and pool modifications can be executed immediately. Introducing time-locks could reduce the risk of sudden, unauthorized or harmful changes.
Single Points of Failure and Control: The staking configuration and pool parameters are fully controlled by a single authority. This centralization introduces trust assumptions around that admin’s key security and behavior.
Administrative Key Control Risks: The authority manage yield funding and withdrawals via admin_withdraw_tokens and is responsible for keeping the authority_vault funded for user claims. If compromised, it could result in a denial-of-service for all stakers.
Centralized Governance Mechanisms: Governance is not decentralized since all key logic, including staking setup, limits, fund withdrawals, and pause functionality, is governed by the authority without input from token holders or community consensus.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2025-1165 | Unrestricted Config Initialization Enables Full Admin Access and DoS Permanently Locking User-Staked Funds | fixed | Critical | |
| F-2025-1164 | Incorrect Time Conversion Causes Early Unlocks Due to Misinterpreted Lock Period | fixed | Critical | |
| F-2025-1173 | Missing Enforcement of Global NFT Cap Allows Excessive Cross-Pool NFT Staking | fixed | Medium | |
| F-2025-1165 | Mismatch Between Documentation and withdraw.rs Allows Full Yield Token Drain | accepted | Medium | |
| F-2025-1176 | Improper Error Handling | fixed | Low | |
| F-2025-1175 | Possible Arithmetic Overflow in Yield Calculation | fixed | Low | |
| F-2025-1173 | Missing Event Emissions on State Changing Instructions | accepted | Observation | |
| F-2025-1173 | Redundant Computation and Cloning Across Instructions Increases Code Complexity | fixed | Observation | |
| F-2025-1172 | NFTs Are Transferred to Config Account Instead of Dedicated NFTs Vault | accepted | Observation | |
| F-2025-1172 | Missing Account Closure Logic for Position and User Pool Stats Accounts | accepted | Observation |
Appendix 1. Definitions
Severities
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. |
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.
Potential Risks
The "Potential Risks" section identifies issues that are not direct security vulnerabilities but could still affect the project’s performance, reliability, or user trust. These risks arise from design choices, architectural decisions, or operational practices that, while not immediately exploitable, may lead to problems under certain conditions. Additionally, potential risks can impact the quality of the audit itself, as they may involve external factors or components beyond the scope of the audit, leading to incomplete assessments or oversight of key areas. This section aims to provide a broader perspective on factors that could affect the project's long-term security, functionality, and the comprehensiveness of the audit findings.
Appendix 2. Scope
The scope of the project includes the following smart contracts from the provided repository:
Scope Details | |
|---|---|
| Repository | https://github.com/WebitLabs/bert-staking-sc→ |
| Initial Commit | 6c2f7c667e42af6a26dd85ca4b85ae8f6147dfa9 |
| 1st Remediation Commit | f427fd70e840f70594b36d470677dfbb1a3c6574 |
| 2nd Remediation Commit | 00046388d062d3486f2f52973fb48e1ea3328268 |
| Final Commit | 28f4679b0a09b887e3fbb1e6f7bd1bcdf9861159 |
| Whitepaper | N/A |
| Requirements | README.md |
| Technical Requirements | README.md |
Scope Details
- Initial Commit
- 6c2f7c667e42af6a26dd85ca4b85ae8f6147dfa9
- 1st Remediation Commit
- f427fd70e840f70594b36d470677dfbb1a3c6574
- 2nd Remediation Commit
- 00046388d062d3486f2f52973fb48e1ea3328268
- Final Commit
- 28f4679b0a09b887e3fbb1e6f7bd1bcdf9861159
- Whitepaper
- N/A
- Requirements
- README.md
- Technical Requirements
- README.md
Assets in Scope
Appendix 3. Additional Valuables
Additional Recommendations
The smart contracts in the scope of this audit could benefit from the introduction of automatic emergency actions for critical activities, such as unauthorized operations like ownership changes or proxy upgrades, as well as unexpected fund manipulations, including large withdrawals or minting events. Adding such mechanisms would enable the protocol to react automatically to unusual activity, ensuring that the contract remains secure and functions as intended.
To improve functionality, these emergency actions could be designed to trigger under specific conditions, such as:
Detecting changes to ownership or critical permissions.
Monitoring large or unexpected transactions and minting events.
Pausing operations when irregularities are identified.
These enhancements would provide an added layer of security, making the contract more robust and better equipped to handle unexpected situations while maintaining smooth operations.