F-2024-0008·uninitialized-state

Uninitialized variables in ProofConsumer contract

Acknowledgedbridgenearrainbow-bridgegithub.com/Near-One/rainbow-token-connector
TL;DR

ProofConsumer has no constructor or initializer; prover, nearTokenLocker, and minBlockAcceptanceHeight default to zero, making the contract unusable until set.

Severity
INFO
Impact
MEDIUM
Likelihood
LOW
Method
MManual review
CAT.
Complexity
LOW
Exploitability
LOW
02Section · Description

Description

The issue is found in the ProofConsumer contract, specifically affecting the variables prover, nearTokenLocker, and minBlockAcceptanceHeight.

The ProofConsumer contract lacks a constructor, resulting in the critical state variables prover, nearTokenLocker, and minBlockAcceptanceHeight being left uninitialized. This leads to:

  • The prover being set to the zero address.
  • The nearTokenLocker being an empty byte array.
  • The minBlockAcceptanceHeight being set to zero.

These uninitialized variables cause the _parseAndConsumeProof function to fail in various require statements, which are crucial for the proper validation and processing of proofs from the NEAR blockchain.

03Section · Impact

Impact

Uninitialized variables can cause significant operational issues, including:

  • The contract will revert on critical functions due to failed validations, rendering it unusable.
  • The prover variable pointing to address(0) will cause the proveOutcome function to always fail, leading to the failure of any proof validation.
  • The nearTokenLocker being empty will cause the keccak256 hash comparison to fail, preventing legitimate proofs from being accepted.
  • The minBlockAcceptanceHeight defaulting to zero will cause the height check in _parseAndConsumeProof to always revert, as the block height will always be considered "ancient."
04Section · Recommendation

Recommendation

Recommendations:

  • Add a constructor: ensure all critical variables are properly initialized during contract deployment.
  • Use initializers for upgradeable contracts: if the contract is intended to be upgradeable, use an initializer function instead of a constructor.
  • Add setter functions: provide functions to set these variables if they need to be changed after deployment, with appropriate access control.
solidity
constructor(
bytes memory _nearTokenLocker,
INearProver _prover,
uint64 _minBlockAcceptanceHeight
) {
require(_nearTokenLocker.length > 0, "Invalid Near Token Locker address");
require(address(_prover) != address(0), "Invalid Near prover address");
nearTokenLocker = _nearTokenLocker;
prover = _prover;
minBlockAcceptanceHeight = _minBlockAcceptanceHeight;
}
solidity
function initialize(
bytes memory _nearTokenLocker,
INearProver _prover,
uint64 _minBlockAcceptanceHeight
) external initializer {
require(_nearTokenLocker.length > 0, "Invalid Near Token Locker address");
require(address(_prover) != address(0), "Invalid Near prover address");
nearTokenLocker = _nearTokenLocker;
prover = _prover;
minBlockAcceptanceHeight = _minBlockAcceptanceHeight;
}
solidity
function setProver(INearProver _prover) external onlyOwner {
require(address(_prover) != address(0), "Invalid Near prover address");
prover = _prover;
}
function setNearTokenLocker(bytes memory _nearTokenLocker) external onlyOwner {
require(_nearTokenLocker.length > 0, "Invalid Near Token Locker address");
nearTokenLocker = _nearTokenLocker;
}
function setMinBlockAcceptanceHeight(uint64 _minBlockAcceptanceHeight) external onlyOwner {
minBlockAcceptanceHeight = _minBlockAcceptanceHeight;
}
05Section · Resolution

Resolution

Unresolved.

F-2024-0008

oog
zealynx

Smart Contract Security Digest

Monthly exploit breakdowns, audit checklists, and DeFi security research — straight to your inbox

© 2026 Zealynx