$$\rightleftharpoonup{xx}$$
$$\longleftharp{xx}$$,
$$\longrightharp{xx}$$,
Study inputs
In this study, two Solidity smart contracts were used as verification inputs. The former was a Simple DAO-style contract that was used as a re-entrancy case study. The second one was a thinned-out ledger/state-transition contract designed to test contract-level constraints against double-spending. The original Solidity source code served as input to the abstraction and verification processes defined in this protocol. The general transformation process used for such contracts is illustrated in Figure 1, which shows the gradual transformation of the Solidity source code into the FSM, Event-B, and SMV models during verification.
Modeling boundary
Formal modeling focuses on the control-flow logic of smart contracts, including function entry and exit behavior, internal execution, and contract-level state transitions. Function visibility (public, external, internal, and private) was represented together with the corresponding call-stack behavior relevant to re-entrancy analysis. The types of abstract transitions (call, send, transfer) were treated as operations for transferring ethers.
Contract-level invariants were defined to ensure transaction uniqueness and prevent double-spending within the abstraction boundary. To represent the validation selection and block integrity requirements, the protocol-logic abstraction layer was defined in terms of the protocol-level state transitions of both Proof of Work and Proof of Stake.
The abstraction boundary did not include network-layer elements, including scheduling of messages to be delivered and delays caused by any number of hops, fork resolution, network adversaries employing Byzantine strategies, Ethereum Virtual Machine semantics, and gas semantics controlled by network nodes, exceptions propagation, asynchronous executions, intricate fallback behavior, and network-level finality. Thus, the outcomes of double-spending determination apply only to contract-level invariants and do not constitute a network-level agreement on finality.
Tools and configuration
The Rodin platform was used to model, refine, generate proof obligations, and discharge the Event-B (version 3.7.0) model, which enabled the PP, ML, SMT, and Atelier-B provers to discharge proofs automatically and interactively. nuXmv version 2.0.0 was run on the generated SMV models in full CTL exploration mode to do CTL model checking.
All verification executions were performed in a controlled computational environment using Ubuntu 22.04 LTS, OpenJDK 11, and Python 3.10.12. Web3 (7.6.0), NetworkX (3.4.2), Matplotlib (3.8.0), Graphviz (0.20.3), NumPy (1.26.4), and Pandas (2.2.2) were used to implement simulation and visualization elements. This design guaranteed that formal verification and simulation results could be reproduced when executed under the same execution conditions.
Transformation workflow
This verification process had four phases. Solidity contracts were first translated into a Finite State Machine (FSM-SC) representation. The FSM-SC model was subsequently encoded in Event-B, with clearly specified invariants and refinement degrees. The FSM-SC abstraction was translated into an SMV model in nuXmv. The verification results were reported as statistics on proof obligation discharge and CTL model checking, and counterexamples were provided as cases.
FSM construction
Each contract was abstracted as a Finite State Machine defined as:

Where:
S = set of states
S₀ = initial state
T = transition relation
V = visibility mapping
G = guard predicates
A = actions/state updates.
Algorithm 1: FSM construction from Solidity
Input: Solidity source code
Output: FSM-SC
1) Parse the Solidity contract abstract syntax tree.
2) Create the initial state S₀ from the constructor definition.
3) For each Solidity function f, create a distinct control state S_f and record visibility V(f) ∈ {public, external, internal, private}.
4) For each statement within function f, derive a transition t by extracting guard predicates from require/assert conditions and actions from state-variable updates.
5) Add transition t to T.
6) Create explicit transition types for Ether transfer operations (call, send, transfer), internal and external calls, delegatecall, selfdestruct, tx.origin usage, conditional branches, and loop constructs.
7) Return FSM-SC = (S, S₀, T, V, G, A).
And each Solidity function is associated with a different FSM control state. For vulnerability understanding, vulnerability-relevant execution flows, e.g., such flows with external calls followed by balance updates, were explicitly abstracted into ordered transitions. Figure 2 describes an example FSM-SC diagram for the SimpleDAO-style contract, showing how entry states, external-call transitions, and state-update sequences were abstracted during this construction stage.
Encoding FSM into Event-B
FSM transition was represented as Event-B constructs. All the transitions correspond to Event-B events, including particular guards and actions.
Algorithm 2: FSM to Event-B encoding
Input: FSM-SC
Output: Event-B machine and context
1) Define STATE_SET and FUNCTION in the contract context.
2) Declare variables representing FSM control state and contract-level state.
3) Represent each FSM control state s ∈ S using current_state ∈ STATE_SET.
4) For each transition (s → s′, g, a), create an Event-B event E_t with:
5) WHERE current_state = s ∧ g
6) THEN current_state := s′ ∥ apply(a)
7) Encode visibility constraints using guards derived from V(f).
8) Define invariants inv1–inv9 to capture safety and consistency properties.
9) Define INITIALISATION by assigning S₀ and default values.
The set of states, the current state, function visibility, call stack, transaction timestamp, Ether transfer status, delegate call flag, self-destruct flag, and verification condition are some of the variables that are captured in the Event-B model. The invariants (inv1-inv9) and the actions of the initializations (act1-act6) match the ones of the formal specification. Figure 3 also provides a graphical representation of how the key events relevant to vulnerabilities, especially re-entrancy-related transitions, are maintained in the Event-B encoding. This figure explains how the structural patterns of the FSM-SC model shown in Figure 2 are mapped into verifiable Event-B events.
Refinement strategy
Two levels of refinement were implemented. High-level contract control flow and core invariants were represented at the abstract level. The refined level added contract-specific restrictions, including call-stack restrictions, visibility restrictions, and re-entrancy prevention conditions.
Algorithm 3: Refinement and proof-obligation discharge
Input: Abstract machine and refined machine
Output: Discharged proof obligations and statistics
1) Generate proof obligations for the abstract machine in Rodin.
2) Execute enabled automatic provers and record discharge results.
3) Generate refinement proof obligations for the refined machine.
4) Apply automatic provers to refinement obligations.
5) Discharge remaining obligations interactively when necessary.
6) Export proof statistics and status reports.
Proof reporting included the number of invariants, refinement levels, proof obligations generated, automatic discharge rate, interactive discharge rate, and final discharge rate.
CTL property specification and model checking
The FSM-SC abstraction was translated into an SMV model for branching-time temporal verification in nuXmv.
Algorithm 4: FSM to SMV and CTL Checking
Output: PASS/FAIL verification result and counterexample traces (if any)
1. Record FSM control states as an enumerated SMV variable state.
2. Convert FSM transitions into guarded next(state) assignments.
3. Maintain flags for vulnerability-relevant conditions, such as external calls and balance updates.
4. Encode CTL properties in nuXmv and perform model checking.
5. If a property fails, generate counterexample traces representing FSM transition sequences.
CTL checking included re-entrancy order requirements, finalizing state updates after transfer operations, limiting unconstrained recursive entry into critical sections, and avoiding deadlock.
Security properties verified
The Simple DAO-style contract that prevents re-entrancy was confirmed by ensuring safe ordering between external calls and state updates via invariants and CTL constraints. Where permitted, these guards checked access-control constraints, ensuring that unauthorized transitions were restricted by invariants. The reduced ledger model verified the invariants of transaction uniqueness and ledger consistency at the level of prevention within the contract.
Outputs reported
The Results section provides reports on FSM structural metrics, Event-B model metrics, and statistics for the proof of obligation and CTL verification. The results of formal proof, and those of CTL model-checking, are given separately to distinguish the evidence of correctness guarantees by invariants, and the evidence of a time verification using temporal verification.