Belobog Concolic Executor
- The paper introduces a concolic executor that combines concrete and symbolic execution to systematically synthesize well-typed transactions for uncovering deep vulnerabilities in Move smart contracts.
- It employs a dual execution model with symbolic overlays and path constraint collection, leveraging SMT-guided mutations to explore unexplored paths.
- The executor successfully reproduced real-world exploits like the Cetus and Nemo attacks, demonstrating its impact on automated smart contract security validation.
The concolic executor in Belobog is a specialized symbolic-plus-concrete execution engine integrated into a type-aware fuzzing framework for Move smart contracts. It systematically augments coverage by combining concrete transaction execution with symbolic reasoning and SMT-guided mutation, enabling Belobog to synthesize well-typed transactions that traverse deep, value-dependent paths often invisible to random or purely type-graph fuzzing. This capability is key for detecting and reproducing exploits in deployed Move modules, particularly where strict type constraints intersect with intricate arithmetic or resource logic, as demonstrated in the reproduction of the Cetus and Nemo attacks (Xia et al., 2 Dec 2025).
1. Architectural Role and Workflow in Belobog
The concolic executor operates as an intermediary between Belobog’s type-graph-driven transaction generator and the MoveVM execution environment. After transaction construction with strict adherence to Move type and resource semantics, the executor initiates a dual execution of the transaction: one along the concrete path and another overlaying symbolic expressions for all primitive arguments. This dual execution produces both coverage feedback and path constraints. If the run uncovers new branch opportunities (via previously unseen coverage or branch inversion), the executor may synthesize mutated transactions—using solver outputs—and feeds these into the seed corpus that guides subsequent fuzzing passes.
2. Formal Model: Symbolic States and Path Constraints
Each MoveVM state during concolic execution is paired with a symbolic overlay. Formally:
- , the symbolic state, maps each live variable to a symbolic expression over uninterpreted symbols and concrete constants.
- , the path constraint, encodes the conjunction of Boolean formulas required for the path traversed thus far.
- The concolic state is a pair , where is the concrete VM state (stack, locals, memory).
Bytecode execution proceeds by updating both and for each Move instruction:
- For non-branching opcodes: variables are updated via symbolic operators, and overflow guards (e.g., ) are appended to .
- For conditional branches: both the concrete result and symbolic condition formula are recorded, and is extended with either the positive or negated symbolic branch constraint.
These constraints are encoded in bit-vector (BV) theory for SMT solving and are always type-checked against Move’s type system to preclude ill-typed mutations (Xia et al., 2 Dec 2025).
3. Core Algorithms for Concolic Execution
The executor consists of three principal algorithmic phases:
Symbolic Run and Constraint Collection
A transaction initiated with concrete inputs and symbolic names proceeds instruction by instruction, collecting branch sites and symbolic constraints into a log and updating coverage bitmaps. Branch conditions record both the symbolic predicate and the observed concrete outcome.
Solver-Guided Mutation
At any branch site, the path constraint prefix up to that site is conjoined with the negation of the concrete branch taken. The SMT solver (Z3) attempts to solve for inputs that would flip the outcome. If the constraint set is satisfiable ( is sat), new primitive arguments for the transaction are extracted.
Trace-Driven Transaction Mutation
Given new input assignments, mutated transactions are synthesized by replacing original arguments with those derived from solver outputs. These follow-up transactions are queued for subsequent dual execution runs.
4. Move-Specific Symbolic Semantics
Move’s features necessitate multiple symbolic semantics adjustments:
- Type safety: Every symbolic expression is annotated with its Move type, and resource types (e.g., Coin<T>) are filtered out of symbolic input domains.
- Resource abilities: Resource-type arguments are managed via the type graph rather than direct symbolic instrumentation, ensuring correct production/consumption semantics.
- Vectors: Move vectors are modeled concretely with symbolic elements, with all index/bound constraints encoded symbolically ().
Enforcement of these checks ensures that all synthesized mutations are semantically correct and pass MoveVM’s runtime validation; transactions failing type/resource checks are never proposed (Xia et al., 2 Dec 2025).
5. Constraint Management, Heuristics, and Solver Integration
To maintain efficiency and avoid solver bottlenecks:
- Local algebraic simplification (e.g., ) reduces expression complexity.
- Bound constraints are tightened (e.g., and becomes ).
- When mutating branches, only constraints up to the selected site are retained.
- Branch-flipping selection is random, but weighted to prioritize shallower branches and unexplored control-flow.
SMT queries are encoded in SMTLIB2 and submitted to Z3 with bounded timeouts (typically 200 ms), operating on Move-legal bit-widths (capped at 256 bits for arithmetic) (Xia et al., 2 Dec 2025).
6. Illustrative Example: Assertion Inversion
In the case of a repay<T> function asserting , the executor:
- Symbolically represents and as and
- At the assertion, records that the transaction fails when
- Inverts the assertion in the path constraint:
- Solves for inputs such that , e.g., ,
- Synthesizes a new transaction satisfying this relationship, exposing the assertion bug (Xia et al., 2 Dec 2025)
7. Limitations and Impact
Belobog’s concolic executor currently does not symbolically model on-chain storage beyond transaction arguments; complex stateful patterns across calls are mitigated via forking seeded on-chain objects. The system is also limited in non-linear and large-bit arithmetic, delegating those to Z3’s BV engine within capped widths. Invariant-specific oracles are not automatically synthesized; user-provided oracles and an API are available.
The concolic executor proved central in reproducing real-world exploits:
- Cetus attack (May 2025, $200M loss): Solver-guided mutation solved subtle bit-vector constraints arising from overflow operations, enabling rapid exploit synthesis that random fuzzing could not reach.
- Nemo attack (Nov 2025, $3M loss): The symbolic executor correctly sequenced resource-affecting calls and solved price-arithmetic mutations needed to synthesize profitable attacks (Xia et al., 2 Dec 2025).
Without concolic reasoning, neither type-graph nor random fuzzing approaches can meet the path constraint inversion required to discover such deep, value-dependent bugs.
The concolic executor in Belobog establishes an effective methodology for systematic exploration of smart contract paths under strict typing and resource regimes, enabling efficient, well-typed input synthesis and exposing vulnerabilities that evade conventional testing and fuzzing approaches (Xia et al., 2 Dec 2025). The approach synthesizes coverage-centric symbolic execution principles with the Move language’s advanced type and resource model, defining an impactful paradigm for automated smart contract security validation in modern blockchain systems.