Introduction
We express our gratitude to the VOLTARA team for the collaborative engagement that enabled the execution of this Smart Contract Security Assessment.
Voltara is a Proof of Green Work (PoGW) protocol that tokenizes verified renewable energy generation. Energy producers submit IoT sensor data through oracle-authorized transactions, which are validated on-chain and converted into VTRX (Voltara Impact Token) rewards representing environmental impact, with optional minting of soulbound NFT certificates at achievement milestones.
Document | |
|---|---|
| Name | Smart Contract Code Review and Security Analysis Report for VOLTARA |
| Audited By | Olesia Bilenka |
| Approved By | Kornel Światłowski |
| Website | https://voltara.ca/→ |
| Changelog | 13/07/2026 - Preliminary Report |
| 17/07/2026 - Final Report | |
| Platform | Polygon |
| Language | Solidity |
| Tags | Fungible Token; Non-fungible Token (NFT); Oracle; Centralization; Incentives; Real World Assets (RWA) |
| Methodology | https://docs.hacken.io/methodologies/smart-contracts→ |
Document
- Name
- Smart Contract Code Review and Security Analysis Report for VOLTARA
- Audited By
- Olesia Bilenka
- Approved By
- Kornel Światłowski
- Website
- https://voltara.ca/→
- Changelog
- 13/07/2026 - Preliminary Report
- 17/07/2026 - Final Report
- Platform
- Polygon
- Language
- Solidity
- Tags
- Fungible Token; Non-fungible Token (NFT); Oracle; Centralization; Incentives; Real World Assets (RWA)
Review Scope | |
|---|---|
| Repository | **https://github.com/bambonova-beep/Voltara-Smart-Contracts-Audit**→ |
| Commit | f09b9c5 |
| Remediation commit | 8feee57 |
Review Scope
- Commit
- f09b9c5
- Remediation commit
- 8feee57
Audit Summary
The system users should acknowledge all the risks summed up in the risks section of the report
Documentation quality
Functional requirements are partially documented. Technical description is provided in code comments but lacks a formal specification document.
README.md provides a high-level protocol overview with architecture flow and quick start instructions.
AUDIT_SCOPE.md clearly defines the six in-scope contracts and explicitly excludes
deprecated/andphase2/directories.CONTRACT_REFERENCE.md contains detailed descriptions of each contract's purpose, key functions, and session-by-session modification history including all audit fixes (V-01 through V-18).
NatSpec comments are present throughout contracts with
@noticeand@devannotations documenting security fixes and design decisions.Audit fix comments (V-01 through V-18, plus F-2026-18xxx series) document security improvements with rationale.
No whitepaper or formal architecture diagrams are provided.
Code quality
The codebase properly reuses well-audited libraries instead of reimplementing common patterns. Development environment is fully configured with appropriate tooling.
OpenZeppelin v5.0.1 contracts are used for ERC-20, ERC-721, AccessControl, Pausable, SafeERC20, and ReentrancyGuard.
Chainlink Functions v1.2.0 library is used for oracle integration.
Hardhat development environment is configured with Solidity 0.8.20 (locked pragma), optimizer enabled (200 runs).
Custom errors are used throughout for gas-efficient reverts.
TypeChain is configured for type-safe contract interactions.
Code follows consistent naming conventions and logical grouping.
Legacy
sendVerificationRequestfunction has been removed from VoltaraChainlinkConsumer.Constructor role separation implemented across all contracts (FIBTreasury, PoGWUnified, VoltaraImpactNFT).
Consistent
whenNotPausedmodifier application across all state-changing functions.
Test coverage
Code coverage of the project is 50.64% (branch coverage).
130 passing tests covering deployment, authorization, energy calculations, idempotency, reward distribution, pausable behavior, and integration scenarios.
VoltaraChainlinkConsumer has lower coverage due to Chainlink DON callback simulation limitations.
Negative cases coverage includes error handling paths for access control, input validation, and boundary conditions.
Integration stress test validates 20 sessions across 2 projects without reverts.
System Overview
The protocol follows a hub-and-spoke architecture centered on PoGWUnified, which serves as the sole processing engine for energy data and VTRX minting. Authorized oracles submit verified energy readings (in watt-hours) along with cryptographic payload hashes for idempotency. The contract calculates VTRX rewards using a configurable rate multiplied by a grid emission factor, splitting minted tokens 98% to the project owner and 2% to the FIBTreasury. Cumulative energy is tracked in watt-hours (preserving sub-kWh precision), and when thresholds are reached, the engine may mint tiered soulbound NFT certificates through VoltaraImpactNFT.
VoltaraRegistry maintains an on-chain registry of projects and energy snapshots but has been decoupled from VTRX token operations. The contract anchors verified data and records units for audit purposes but no longer mints or burns tokens—this architectural change eliminates the cross-path double-minting risk that previously existed. Both PoGWUnified and VoltaraRegistry enforce hash-based deduplication to prevent processing of the same energy reading twice. VoltaraChainlinkConsumer provides an optional verification layer by querying Chainlink Functions to validate IoT readings against off-chain APIs before allowing reward processing.
The system implements OpenZeppelin's AccessControl throughout, with distinct roles governing minting (MINTER_ROLE, ORACLE_ROLE), burning (BURNER_ROLE), treasury operations (TREASURY_ADMIN), and oracle submissions (ISSUER_ROLE). Emergency controls via Pausable exist on all six contracts. Constructor-level role separation enforces distinct addresses for administrative and operational roles at deployment. VoltaraImpactToken implements ERC-20 with a hard cap of 1 billion tokens, administrative burn capabilities, and pause exemption for burns. VoltaraImpactNFT implements ERC-721 with soulbound transfer restrictions, an adjustable five-tier classification system, and role-protected burning for certificate revocation.
VoltaraImpactToken.sol — ERC-20 reward token representing verified energy impact. Implements role-gated mint and adminBurn functions, enforces a 1 billion token supply cap with warnings at 90%, and provides pausable transfers with burn exemption for emergency revocations.
VoltaraImpactNFT.sol — Soulbound ERC-721 certificate representing verified clean energy milestones. Implements a five-tier system (SEED through DIAMOND) based on kWh thresholds, blocks all transfers between addresses (allows minting and burning), supports tier-aware minting via
mintCertificateWithTier, retirement certificates viamintRetirementCertificate, and role-protected burning viaburn.VoltaraChainlinkConsumer.sol — Oracle connector integrating Chainlink Functions for off-chain verification of IoT energy data. Manages concurrent request tracking via
pendingRequestsmapping, correlates request IDs to payload hashes, validates subscription and DON configuration before requests, exposesisVerifiedfor gating reward processing, and supports configurable callback gas limits.FIBTreasury.sol — Treasury contract holding the 2% protocol fee from all VTRX minting. Implements tiered withdrawal controls with a 48-hour timelock for amounts exceeding 100,000 tokens via
queueWithdrawalandcancelWithdrawal. Supports release of both native POL and ERC-20 tokens viareleaseFundsusing SafeERC20 for non-compliant token compatibility.VoltaraRegistry.sol — Decentralized registry for projects and energy snapshots. Anchors verified data via
anchorSnapshotwith impact hash deduplication and configurable maximum units per snapshot. Stores subproject details (name, capacity, GPS) on-chain with retrieval viagetSubprojectDetails. Supports snapshot revocation with hash clearing to allow resubmission. No longer performs VTRX minting or burning operations.PoGWUnified.sol — Core protocol engine and sole VTRX minting path. Processes verified energy sessions from oracles with enforced on-chain idempotency via payload hash tracking. Calculates and distributes VTRX rewards with 98/2 split, maintains cumulative energy in watt-hours per project for accurate NFT tier assignment, and optionally gates processing on Chainlink verification status. Separate
registerProjectandupdateProjectfunctions prevent accidental overwrites.
Privileged roles
VoltaraImpactTokensol
DEFAULT_ADMIN_ROLE: Controls emergency operations and role management.
Can call
pauseto halt all token transfers (mints and user transfers).Can call
unpauseto resume token transfers.Can grant and revoke
MINTER_ROLEandBURNER_ROLE.
MINTER_ROLE: Authorized to create new VTRX tokens.
Can call
mintto mint VTRX tokens to any address (subject to hard cap of 1 billion VTRX).
BURNER_ROLE: Authorized to destroy tokens without owner approval.
Can call
adminBurnto burn VTRX from any address unilaterally (without allowance). Burns bypass pause restriction.
VoltaraImpactNFTsol
DEFAULT_ADMIN_ROLE: Controls tier configuration, emergency operations, and role management.
Can call
setTierThresholdsto modify kWh thresholds for SEED/BRONZE/SILVER/GOLD/DIAMOND tiers.Can call
pauseto halt minting operations.Can call
unpauseto resume minting operations.Can grant and revoke
MINTER_ROLE,RETIREMENT_ROLE, andBURNER_ROLE.
MINTER_ROLE: Authorized to issue impact certificates.
Can call
mintCertificateto mint soulbound impact certificates to any address.Can call
mintCertificateWithTierto mint certificates with tier assignment based on kWh.
RETIREMENT_ROLE: Authorized to issue retirement certificates.
Can call
mintRetirementCertificateto mint soulbound retirement certificates for VTRX offsetting.
BURNER_ROLE: Authorized to revoke certificates.
Can call
burnto destroy any certificate (NFT). Burns bypass pause restriction.
VoltaraChainlinkConsumersol
DEFAULT_ADMIN_ROLE: Controls oracle configuration, emergency operations, and role management.
Can call
setDefaultConfigto set default JavaScript source, Chainlink subscription ID, DON ID, and callback gas limit.Can call
pauseto halt verification requests.Can call
unpauseto resume verification requests.Can grant and revoke
ISSUER_ROLE.
ISSUER_ROLE: Authorized to initiate Chainlink verification requests.
Can call
requestVerificationto send verification requests using default configuration.Can call
requestVerificationWithSourceto send requests with custom JavaScript source (validates subscription and DON configuration).
FIBTreasurysol
DEFAULT_ADMIN_ROLE: Controls emergency operations and role management.
Can call
pauseto halt all fund operations.Can call
unpauseto resume fund operations.Can grant and revoke TREASURY_ADMIN.
TREASURY_ADMIN: Authorized to manage fund releases from the treasury.
Can call
queueWithdrawalto queue withdrawals exceeding 100,000 tokens with 48-hour timelock.Can call
cancelWithdrawalto cancel queued withdrawals.Can call
releaseFundsto transfer native POL or any ERC-20 token to any recipient. Amounts exceeding 100,000 tokens require prior queuing and timelock expiration.
VoltaraRegistrysol
DEFAULT_ADMIN_ROLE: Controls project management, snapshot revocation, and emergency operations.
Can call
adminRegisterSubprojectto register new global subprojects with beneficiary addresses and on-chain details.Can call
registerProjectto register projects with beneficiary and metadata.Can call
setProjectActiveto activate or deactivate existing projects (respects pause).Can call
updateProjectMetadatato modify project metadata URIs (respects pause).Can call
updateProjectBeneficiaryto change project beneficiary address.Can call
setMaxUnitsPerSnapshotto configure maximum units allowed per snapshot.Can call
revokeSnapshotto revoke fraudulent snapshots (clears processed hash for resubmission).Can call
pauseto halt snapshot anchoring and project registration.Can call
unpauseto resume registry operations.Can grant and revoke ISSUER_ROLE.
ISSUER_ROLE: Authorized to anchor energy snapshots.
Can call
anchorSnapshotto record verified energy data with units (no longer triggers VTRX minting).
PoGWUnifiedsol
DEFAULT_ADMIN_ROLE: Controls protocol configuration, project management, and emergency operations.
Can call
registerProjectto register new projects with owners and reward rates (rejects duplicates).Can call
updateProjectto modify existing project owners, reward rates, and active status (rejects non-existent projects).Can call
deactivateProjectto disable a project from receiving further rewards.Can call
setFibTreasuryto change the FIB treasury address for the 2% fee split (emits event).Can call
setMaxSessionWhto adjust the maximum Wh allowed per energy report (emits event).Can call
setMaxGridEmissionFactorto bound the oracle-supplied grid emission factor (emits event).Can call
setChainlinkConsumerto set the Chainlink verification contract address (emits event).Can call
setChainlinkVerificationto enable or disable mandatory Chainlink verification.Can call
pauseto halt all energy report processing.Can call
unpauseto resume energy report processing.Can grant and revoke ORACLE_ROLE.
ORACLE_ROLE: Authorized to submit verified energy data and trigger rewards.
Can call
processSessionto process energy reports, mint VTRX (98% to owner, 2% to FIB), accumulate cumulative Wh, and optionally mint NFT certificates.
Potential Risks
Reliance on Chainlink Functions infrastructure: The VoltaraChainlinkConsumer contract inherits from FunctionsClient and relies on the Chainlink Functions Router to process verification requests via _sendRequest. The fulfillRequest callback depends on the Chainlink Decentralized Oracle Network executing JavaScript source code and returning results. Any unavailability, misconfiguration, or vulnerability in the Chainlink Functions infrastructure could prevent verification callbacks from completing, leaving requests perpetually pending or producing incorrect verification outcomes.
Dependency on external Chainlink verification for reward gating: When chainlinkVerificationEnabled is set to true in PoGWUnified, the processSession function requires isVerified on VoltaraChainlinkConsumer to return true before processing energy reports and minting VTRX. This creates a hard dependency on the VoltaraChainlinkConsumer contract's verification state, which in turn depends on successful Chainlink Functions callbacks. A failure in the Chainlink callback pipeline would block all reward distribution for verified energy data.
Admin-controlled reward rate configuration: The projectRewardRates mapping in PoGWUnified determines VTRX minted per kWh and is set via registerProject and updateProject by DEFAULT_ADMIN_ROLE. While the remediation separates registration from updates (preventing accidental overwrites), no bounds validation, timelock, or governance approval exists for rate values. An admin could set an arbitrarily high rate for a project, enabling rapid depletion of the remaining mintable supply through session reports.
Oracle-controlled critical input parameters: The processSession function in PoGWUnified accepts energyWh and gridEmissionFactor directly from ORACLE_ROLE callers. Although bounds exist (maxSessionWh and maxGridEmissionFactor), these limits are themselves admin-configurable via setMaxSessionWh and setMaxGridEmissionFactor. A compromised oracle operating within configured bounds could still submit systematically inflated but technically valid energy data, resulting in over-issuance of VTRX rewards.
Immediate admin parameter changes without delay (Partially Mitigated): Critical configuration functions including setFibTreasury, setMaxSessionWh, setMaxGridEmissionFactor, setChainlinkConsumer, and setChainlinkVerification in PoGWUnified, as well as setTierThresholds in VoltaraImpactNFT and setDefaultConfig in VoltaraChainlinkConsumer, execute immediately upon admin invocation. No timelock or delay mechanism exists to allow users or monitoring systems to react to potentially harmful parameter changes before they take effect. Note: FIBTreasury now implements a 48-hour timelock for withdrawals exceeding 100,000 tokens, but other admin functions remain immediate.
Multi-signature enforcement absent for most operations (Partially Mitigated): The releaseFunds function in FIBTreasury now requires a 48-hour timelock via queueWithdrawal for amounts exceeding WITHDRAWAL_LIMIT (100,000 tokens), providing a response window. However, withdrawals below this threshold execute immediately, and adminBurn in VoltaraImpactToken still allows a single BURNER_ROLE holder to destroy tokens from any address without that user's consent. Neither function enforces multi-signature requirements on-chain.
Unilateral token destruction from user wallets: The adminBurn function in VoltaraImpactToken bypasses the standard ERC-20 allowance pattern and allows BURNER_ROLE holders to burn tokens directly from any address. Note: VoltaraRegistry has been decoupled from VTRX token operations and no longer invokes adminBurn during snapshot revocation. However, a compromised or malicious BURNER_ROLE holder could still destroy legitimate user balances without recourse.
Administrative authority with role separation (Mitigated): The remediation implements constructor-level role separation across all contracts: PoGWUnified separates admin and oracle addresses, FIBTreasury separates roleAdmin and treasuryAdmin, and VoltaraImpactNFT separates admin, minter, retirement, and burner roles. This reduces single-key compromise impact but does not eliminate centralization risk—each role holder still has unilateral authority within their domain.
Treasury disbursement controls (Mitigated): FIBTreasury now implements tiered withdrawal controls: withdrawals exceeding WITHDRAWAL_LIMIT (100,000 tokens) require a 48-hour timelock via queueWithdrawal, and queued withdrawals can be cancelled. Withdrawals below the limit execute immediately. While this provides a response window for large extractions, a compromised TREASURY_ADMIN key could still drain funds incrementally below the daily limit or wait out the timelock if undetected.
Centralized oracle trust for energy data: All energy reports in PoGWUnified originate from ORACLE_ROLE holders who supply energyWh, gridEmissionFactor, projectCode, deviceAlias, and payloadHash values. While optional Chainlink verification exists (chainlinkVerificationEnabled), it is disabled by default and can be toggled off by the admin. When disabled, the protocol places full trust in the oracle's reported values with no independent on-chain data validation beyond configured bounds.
Protocol throughput dependent on oracle availability: The PoGWUnified contract cannot autonomously detect or process energy production; all data must be submitted by ORACLE_ROLE holders invoking processSession. If the off-chain oracle infrastructure experiences downtime, no energy reports can be anchored and no VTRX rewards or NFT certificates will be issued during the outage period.
Chainlink Functions subscription funding requirement: The VoltaraChainlinkConsumer uses defaultSubscriptionId to pay for Chainlink Functions requests. If the associated subscription runs out of LINK tokens, calls to requestVerification or requestVerificationWithSource will fail at the Chainlink Router level, preventing any new verification requests from being submitted until the subscription is refunded. Note: The remediation adds validation for defaultSubscriptionId > 0 and defaultDonId != bytes32(0) before sending requests, providing clearer error messages but not preventing subscription exhaustion.
Off-chain data integrity with limited on-chain validation: The payloadHash parameter in PoGWUnified provides a cryptographic commitment to off-chain IoT data but cannot be verified against source data on-chain. The processedHashes mapping prevents replay of the same hash but does not validate that the underlying energy readings (energyWh, gridEmissionFactor) correspond to actual physical measurements. Falsified data with a unique hash would pass all on-chain checks and mint rewards based on fabricated energy production.
Findings
Code ― | Title | Status | Severity | |
|---|---|---|---|---|
| F-2026-1801 | Inconsistent Reward Distribution Between Minting Paths Results in Unpredictable Treasury Funding | fixed | Medium | |
| F-2026-1801 | Pause Mechanism in _update Hook Blocks adminBurn and Prevents Fraud Revocation During Emergencies | fixed | Medium | |
| F-2026-1803 | Empty projectCode Creates Deterministic Hash Collision Between Projects | fixed | Low | |
| F-2026-1803 | configureProject Silently Overwrites Existing Project Configuration Without Validation | fixed | Low | |
| F-2026-1801 | Pause State Cascade Creates Inconsistent Emergency Response Across Protocol Contracts | fixed | Low | |
| F-2026-1800 | Ambiguous Distinction Between Project and Subproject Registration Functions Reduces Code Clarity | fixed | Low | |
| F-2026-1804 | Missing Function to Update Project Beneficiary Results in Irrecoverable Reward Loss | fixed | Low | |
| F-2026-1803 | anchorSnapshot Lacks Maximum Limit on units Parameter Allowing Unlimited VTRX Minting | fixed | Low | |
| F-2026-1801 | Missing payloadHash Parameter in sendVerificationRequest Causes Verification Data Loss | fixed | Low | |
| F-2026-1800 | Separate Hash Tracking Between Contracts Enables Cross-Contract Double Minting of VTRX | fixed | Low |
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/bambonova-beep/Voltara-Smart-Contracts-Audit**→ |
| Commit | f09b9c5fdf24ce5a3ca4bf9d8141230d906b70c8 |
| Remediation commit | 8feee5756d67682a47acc5833e86e7e5a317a3fc |
| Requirements | https://github.com/hknio/bambonova-beep___Voltara-Smart-Contracts-Audit/blob/f09b9c5fdf24ce5a3ca4bf9d8141230d906b70c8/README.md→ |
Scope Details
- Commit
- f09b9c5fdf24ce5a3ca4bf9d8141230d906b70c8
- Remediation commit
- 8feee5756d67682a47acc5833e86e7e5a317a3fc
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.
Frameworks and Methodologies
This security assessment was conducted in alignment with recognised penetration testing standards, methodologies and guidelines, including the NIST SP 800-115 – Technical Guide to Information Security Testing and Assessment →, and the Penetration Testing Execution Standard (PTES) →, These assets provide a structured foundation for planning, executing, and documenting technical evaluations such as vulnerability assessments, exploitation activities, and security code reviews. Hacken’s internal penetration testing methodology extends these principles to Web2 and Web3 environments to ensure consistency, repeatability, and verifiable outcomes.