Provably Correct Smart Contracts using DeepSEA

Daniel Britten

Ethereum Engineering Group Meetup 2023

It's great to be here...

The talks are from 40 to 90 minutes long, including question time.

Overall Goal: Demonstate a technique for showing the correctness of smart contracts

Overview:

Introduction to theorem-proving in Coq

Example: Even and odd numbers

Definition Even (n : nat) := exists k, n = 2 * k.
Definition Odd  (m : nat) := exists l, m = 2 * l + 1.


forall n : nat, Even n -> Odd (n + 1)

forall n : nat, Even n -> Odd (n + 1)
n: nat
H: Even n

Odd (n + 1)
n: nat
H: exists k : nat, n = 2 * k

Odd (n + 1)
n, k: nat
H: n = 2 * k

Odd (n + 1)
n, k: nat
H: n = 2 * k

exists l : nat, n + 1 = 2 * l + 1
n, k: nat
H: n = 2 * k

n + 1 = 2 * k + 1
n, k: nat
H: n = 2 * k

n + 1 = n + 1
reflexivity. Qed.

DeepSEA

Introduction to creating a DeepSEA smart contract

Example: Trivial contract converting bool to int

object signature trivial = {
    const boolToInt : bool -> int
}

object Trivial : trivial {
    let boolToInt b =
      if b then 1 else 0
}

layer CONTRACT = { o = Trivial }
object signature trivial = {
    const boolToInt : bool -> int;
    boolToIntTracker : bool -> int
}

object Trivial : trivial {
    let seenTrueYet : bool := false

    let boolToInt b =
      if b then 1 else 0

    let boolToIntTracker b =
      if b then
        begin
            seenTrueYet := true;
            1
        end
      else 0
}

layer CONTRACT = { o = Trivial }
$ dsc trivial.ds bytecode
5b60005b60206109205101610920525b61022660006020610920510301525b60006020
610920510301516101005260206101002060006020610920510301525b600060006020
61092051030151555b60206109205103610920525b60005b9050386300000073600039
386000f35b60006000fd5b610940610920527c01000000000000000000000000000000
000000000000000000000000006000350480635192f3c01463000000495780631e01e7
071463000000965760006000fd5b6004355b60006109205101610920525b8063000000
67576300000085565b600190505b60006109205103610920525b805b90506000526020
6000f35b60009050630000006c565b60006000fd5b6004355b60206109205101610920
525b8063000000b4576300000111565b61022660006020610920510301525b60006020
610920510301516101005260206101002060006020610920510301525b600160006020
61092051030151555b600190505b60206109205103610920525b805b90506000526020
6000f35b6000905063000000f8565b60006000fd

$ dsc trivial.ds abi

[ {"type":"constructor",
  "name":"constructor",
  "inputs":[], "outputs":[], "payable":false,
  "constant":false, "stateMutability":"nonpayable"},
{"type":"function",
  "name":"boolToInt",
  "inputs":[{"name":"b", "type":"bool"}],
  "outputs":[{"name":"", "type":"uint256"}],
  "payable":false,
  "constant":true,
  "stateMutability":"view"},
{"type":"function",
  "name":"boolToIntTracker",
  "inputs":[{"name":"b", "type":"bool"}],
  "outputs":[{"name":"", "type":"uint256"}],
  "payable":true,
  "constant":false,
  "stateMutability":"payable"}]

Next slide is a reminder of the contract definition.

object signature trivial = {
    const boolToInt : bool -> int;
    boolToIntTracker : bool -> int
}

object Trivial : trivial {
    let seenTrueYet : bool := false

    let boolToInt b =
      if b then 1 else 0

    let boolToIntTracker b =
      if b then
        begin
            seenTrueYet := true;
            1
        end
      else 0
}

layer CONTRACT = { o = Trivial }

$ dsc trivial.ds coq ...

if f then ret 1 else ret 0
Trivial_boolToInt_opt = fun (memModelOps : MemoryModelOps mem) (f : bool) (_ : machine_env GetHighData) => if f then ret 1 else ret 0 : forall memModelOps : MemoryModelOps mem, bool -> machine_env GetHighData -> DS Z32 Arguments Trivial_boolToInt_opt {memModelOps} _%bool_scope _
Trivial_boolToInt = fun memModelOps : MemoryModelOps mem => {| FC_ident_start := 10%positive; FC_params := [int_bool_pair]; FC_returns := int_Z32_pair; FC_body := CCifthenelse (ECtempvar tint_bool 11%positive) (CCyield (ECconst_int256 tint_Z32 1 (Int256.repr 1))) (CCyield (ECconst_int256 tint_Z32 0 (Int256.repr 0))) |} : forall memModelOps : MemoryModelOps mem, function_constr Arguments Trivial_boolToInt {memModelOps}

$ dsc trivial.ds coq ...

if f then
  MonadState.modify (update_Trivial_seenTrueYet true) ;;
  ret 1
else
  ret 0
Trivial_boolToIntTracker_opt = fun (memModelOps : MemoryModelOps mem) (f : bool) (_ : machine_env GetHighData) => if f then MonadState.modify (update_Trivial_seenTrueYet true);; ret 1 else ret 0 : forall memModelOps : MemoryModelOps mem, bool -> machine_env GetHighData -> DS Z32 Arguments Trivial_boolToIntTracker_opt {memModelOps} _%bool_scope _
Trivial_boolToIntTracker = fun memModelOps : MemoryModelOps mem => {| FC_ident_start := 10%positive; FC_params := [int_bool_pair]; FC_returns := int_Z32_pair; FC_body := CCifthenelse (ECtempvar tint_bool 11%positive) (CCsequence (CCstore (LCvar Trivial_seenTrueYet_var) (ECconst_int256 tint_bool true Int256.one)) (CCyield (ECconst_int256 tint_Z32 1 (Int256.repr 1)))) (CCyield (ECconst_int256 tint_Z32 0 (Int256.repr 0))) |} : forall memModelOps : MemoryModelOps mem, function_constr Arguments Trivial_boolToIntTracker {memModelOps}

A proof about our Trivial contract

contract_address: addr
memModelOps: MemoryModelOps mem

forall (input : bool) (context : CallContext) (before : BlockchainState) (result : Z32) (after : GetHighData), let machine_environment := make_machine_env contract_address before context (fun (_ : option global_abstract_data_type) (_ _ : addr) (_ : wei) => true) in runStateT (Trivial_boolToInt_opt input machine_environment) (contract_state before) = Some (result, after) -> result = 1 <-> input = true

Main goal:

result = 1 <-> input = true
contract_address: addr

forall (input : bool) (context : CallContext) (before : BlockchainState) (result : Z32) (after : GetHighData), let machine_environment := make_machine_env contract_address before context (fun (_ : option global_abstract_data_type) (_ _ : addr) (_ : wei) => true) in runStateT (Trivial_boolToInt_opt input machine_environment) (contract_state before) = Some (result, after) -> result = 1 <-> input = true
contract_address: addr
input: bool
context: CallContext
before: BlockchainState
result: Z32
after: GetHighData
H: runStateT (Trivial_boolToInt_opt input machine_environment) (contract_state before) = Some (result, after)

result = 1 <-> input = true
H: runStateT (Trivial_boolToInt_opt input machine_environment) (contract_state before) = Some (result, after)

result = 1 <-> input = true
H: runStateT (if input then ret 1 else ret 0) (contract_state before) = Some (result, after)

result = 1 <-> input = true

input = true

result = 1
H: runStateT (if input then ret 1 else ret 0) (contract_state before) = Some (result, after)
H0: result = 1

input = true
Heqb: input = true
H0: result = 1
H1: 1 = result
H2: contract_state before = after

true = true
Heqb: input = false
H0: result = 1
H1: 0 = result
H2: contract_state before = after
false = true
Heqb: input = true
H0: result = 1
H1: 1 = result
H2: contract_state before = after

true = true
reflexivity.
Heqb: input = false
H0: result = 1
H1: 0 = result
H2: contract_state before = after

false = true
H1: 0 = 1

false = true
discriminate.
H: runStateT (if input then ret 1 else ret 0) (contract_state before) = Some (result, after)
H0: input = true

result = 1
Heqb: input = true
H0: true = true
H1: 1 = result
H2: contract_state before = after

result = 1
Heqb: input = false
H0: false = true
H1: 0 = result
H2: contract_state before = after
result = 1
Heqb: input = true
H0: true = true
H1: 1 = result
H2: contract_state before = after

result = 1
H0: true = true

1 = 1
reflexivity.
Heqb: input = false
H0: false = true
H1: 0 = result
H2: contract_state before = after

result = 1
discriminate. Qed.

Remember to click the extra button to show hypotheses for both goals when they are there.

Note that some hypothesis are hidden in the visualisations for clarity.

Next slide has a copy of the contract definition.

object signature trivial = {
    const boolToInt : bool -> int;
    boolToIntTracker : bool -> int
}

object Trivial : trivial {
    let seenTrueYet : bool := false

    let boolToInt b =
      if b then 1 else 0

    let boolToIntTracker b =
      if b then
        begin
            seenTrueYet := true;
            1
        end
      else 0
}

layer CONTRACT = { o = Trivial }
contract_address: addr

forall (input : bool) (context : CallContext) (before : BlockchainState) (result : Z32) (after : GetHighData), let machine_environment := make_machine_env contract_address before context (fun (_ : option global_abstract_data_type) (_ _ : addr) (_ : wei) => true) in runStateT (Trivial_boolToIntTracker_opt input machine_environment) (contract_state before) = Some (result, after) -> result = 1 <-> input = true
contract_address: addr

forall (input : bool) (context : CallContext) (before : BlockchainState) (result : Z32) (after : GetHighData), let machine_environment := make_machine_env contract_address before context (fun (_ : option global_abstract_data_type) (_ _ : addr) (_ : wei) => true) in runStateT (Trivial_boolToIntTracker_opt input machine_environment) (contract_state before) = Some (result, after) -> result = 1 <-> input = true
contract_address: addr
input: bool
context: CallContext
before: BlockchainState
result: Z32
after: GetHighData
H: runStateT (Trivial_boolToIntTracker_opt input machine_environment) (contract_state before) = Some (result, after)

result = 1 <-> input = true
H: runStateT (Trivial_boolToIntTracker_opt input machine_environment) (contract_state before) = Some (result, after)

result = 1 <-> input = true
H: runStateT (if input then MonadState.modify (update_Trivial_seenTrueYet true);; ret 1 else ret 0) (contract_state before) = Some (result, after)

result = 1 <-> input = true

input = true

result = 1
H: runStateT (if input then MonadState.modify (update_Trivial_seenTrueYet true);; ret 1 else ret 0) (contract_state before) = Some (result, after)
H0: result = 1

input = true
Heqb: input = true
H0: result = 1
H3: update_Trivial_seenTrueYet true (contract_state before) = m
H1: 1 = result
H4: m = after

true = true
Heqb: input = false
H0: result = 1
H1: 0 = result
false = true
Heqb: input = true
H0: result = 1
H3: update_Trivial_seenTrueYet true (contract_state before) = m
H1: 1 = result
H4: m = after

true = true
reflexivity.
Heqb: input = false
H0: result = 1
H1: 0 = result
H2: contract_state before = after

false = true
H1: 0 = 1

false = true
discriminate.
H: runStateT (if input then MonadState.modify (update_Trivial_seenTrueYet true);; ret 1 else ret 0) (contract_state before) = Some (result, after)
H0: input = true

result = 1
Heqb: input = true
H0: true = true
H3: update_Trivial_seenTrueYet true (contract_state before) = m
H1: 1 = result
H4: m = after

result = 1
Heqb: input = false
H0: false = true
H1: 0 = result
result = 1
Heqb: input = true
H0: true = true
H3: update_Trivial_seenTrueYet true (contract_state before) = m
H1: 1 = result
H4: m = after

result = 1
H0: true = true

1 = 1
reflexivity.
Heqb: input = false
H0: false = true
H1: 0 = result
H2: contract_state before = after

result = 1
discriminate. Qed.

A Crowdfunding Correctness Property

Definition since_as_long (Property1 : BlockchainState -> Prop)
    (Property2 : BlockchainState -> Prop) (PropertyAboutAction : Step -> Prop) :=
  forall actions start finish helper,
    ReachableVia start finish helper actions ->
    Property1 start
    -> (forall act, List.In act actions -> PropertyAboutAction act)
    -> Property2 finish.

Notation "Property2 `since` Property1 `as-long-as` PropertyAboutAction" :=
  (since_as_long Property1 Property2 PropertyAboutAction) (at level 1).

snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool

forall (user : addr) (amount : Z), (donation_recorded user amount) `since` donation_recorded user amount `as-long-as` (no_claims_from user)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool

forall (user : addr) (amount : Z), (donation_recorded user amount) `since` donation_recorded user amount `as-long-as` (no_claims_from user)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool

forall (user : addr) (amount : Z) (actions : list Step) (start finish : BlockchainState) (helper : Step), ReachableVia start finish helper actions -> donation_recorded user amount start -> (forall act : Step, In act actions -> no_claims_from user act) -> donation_recorded user amount finish
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
actions: list Step
start, finish: BlockchainState
helper: Step
H: ReachableVia start finish helper actions
H0: donation_recorded user amount start
H1: forall act : Step, In act actions -> no_claims_from user act

donation_recorded user amount finish
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt

donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt

donation_recorded user amount prevSt
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt
donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt

forall act : Step, In act prevList -> no_claims_from user act
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt
donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
act: Step
H2: In act prevList

no_claims_from user act
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt
donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
act: Step
H2: In act prevList

In act (stepOnceAndWrap prev next_action :: prevList)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt
donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H0: donation_recorded user amount start
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt

donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
IHReachableVia: (forall act : Step, In act prevList -> no_claims_from user act) -> donation_recorded user amount prevSt
H2: donation_recorded user amount prevSt

donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: donation_recorded user amount prevSt

donation_recorded user amount (stepOnce prev)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList

no_claims_from user prev
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList

In prev (stepOnceAndWrap prev next_action :: prevList)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
x: list Step
H0: prev :: x = prevList

In prev (stepOnceAndWrap prev next_action :: prevList)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start: BlockchainState
prev: Step
x: list Step
H: ReachableVia start (Step_state prev) prev (prev :: x)
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prev :: x) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state (Step_state prev))) > 0

In prev (stepOnceAndWrap prev next_action :: prev :: x)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start: BlockchainState
prev: Step
x: list Step
H: ReachableVia start (Step_state prev) prev (prev :: x)
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prev :: x) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state (Step_state prev))) > 0

In prev (prev :: x)
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start: BlockchainState
prev: Step
x: list Step
H: ReachableVia start (Step_state prev) prev (prev :: x)
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prev :: x) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state (Step_state prev))) > 0

prev = prev
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev
get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prev: Step
prevList: list Step
H: ReachableVia start prevSt prev prevList
next_action: Action (stepOnce prev)
H1: forall act : Step, In act (stepOnceAndWrap prev next_action :: prevList) -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state prev
HReachableViaLinkStepToList: exists tl : list Step, prev :: tl = prevList
H0: no_claims_from user prev

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce prev))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H: ReachableVia start prevSt {| Step_state := Step_state0; Step_action := Step_action0 |} prevList
next_action: Action (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |})
H1: forall act : Step, {| Step_state := stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}; Step_action := next_action |} = act \/ In act prevList -> no_claims_from user act
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
HReachableViaLinkStepToList: exists tl : list Step, {| Step_state := Step_state0; Step_action := Step_action0 |} :: tl = prevList
H0: no_claims_from user {| Step_state := Step_state0; Step_action := Step_action0 |}

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H: ReachableVia start prevSt {| Step_state := Step_state0; Step_action := Step_action0 |} prevList
next_action: Action (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |})
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
HReachableViaLinkStepToList: exists tl : list Step, {| Step_state := Step_state0; Step_action := Step_action0 |} :: tl = prevList
H0: no_claims_from user {| Step_state := Step_state0; Step_action := Step_action0 |}

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H: ReachableVia start prevSt {| Step_state := Step_state0; Step_action := Step_action0 |} prevList
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
HReachableViaLinkStepToList: exists tl : list Step, {| Step_state := Step_state0; Step_action := Step_action0 |} :: tl = prevList
H0: no_claims_from user {| Step_state := Step_state0; Step_action := Step_action0 |}

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
HReachableViaLinkStepToList: exists tl : list Step, {| Step_state := Step_state0; Step_action := Step_action0 |} :: tl = prevList
H0: no_claims_from user {| Step_state := Step_state0; Step_action := Step_action0 |}

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
H0: no_claims_from user {| Step_state := Step_state0; Step_action := Step_action0 |}

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
H0: match Step_action {| Step_state := Step_state0; Step_action := Step_action0 |} with | @call_Crowdfunding_claim _ _ _ _ _ _ => False | _ => True end

get_default 0 user (Crowdfunding_backers (contract_state (stepOnce {| Step_state := Step_state0; Step_action := Step_action0 |}))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
H0: match Step_action {| Step_state := Step_state0; Step_action := Step_action0 |} with | @call_Crowdfunding_claim _ _ _ _ _ _ => False | _ => True end

get_default 0 user (Crowdfunding_backers (contract_state (step (Step_state {| Step_state := Step_state0; Step_action := Step_action0 |}) (Step_action {| Step_state := Step_state0; Step_action := Step_action0 |})))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
H0: match Step_action {| Step_state := Step_state0; Step_action := Step_action0 |} with | @call_Crowdfunding_claim _ _ _ _ _ _ => False | _ => True end

get_default 0 user (Crowdfunding_backers (contract_state (step Step_state0 Step_action0))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt, Step_state0: BlockchainState
Step_action0: Action Step_state0
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
HReachableViaLinkStateToStep: prevSt = Step_state0
H0: match Step_action {| Step_state := Step_state0; Step_action := Step_action0 |} with | @call_Crowdfunding_claim _ _ _ _ _ _ => False | _ => True end

get_default 0 user (Crowdfunding_backers (contract_state (step Step_state0 Step_action0))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_donate_prf: runStateT (Crowdfunding_donate_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_getFunds_prf: runStateT (Crowdfunding_getFunds_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_claim_prf: runStateT (Crowdfunding_claim_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: False
get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
sender, recipient: addr
amount0: wei
prf: sender <> contract_address /\ noOverflowOrUnderflowInTransfer sender recipient amount0 (balance prevSt) && address_accepts_funds_assumption None sender recipient amount0 = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
block_count, time_passing: int256
prf: validTimeChange block_count time_passing (block_number prevSt) (timestamp prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_donate_prf: runStateT (Crowdfunding_donate_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_donate_prf: runStateT (Crowdfunding_donate_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_donate_prf: runStateT ((v <- ret (negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)));; guard v);; (v <- ret ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0);; guard v);; gets Crowdfunding_backers;; spec2 <- ret (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption));; spec3 <- gets Crowdfunding_max_block;; (if Int256.ltu spec3 spec2 then ret tt;; v <- ret false;; guard v else spec4 <- gets (fun s : GetHighData => get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers s));; (if (spec4 =? 0)%Z then MonadState.modify (fun s : GetHighData => update_Crowdfunding_backers (set (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) (Crowdfunding_backers s)) s) else ret tt;; v <- ret false;; guard v))) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
H19: false = true

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = false
H21: false = true
get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
H19: false = true

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
match goal with H : false = true |- _ => inversion H end.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: (user =? caller context) = true

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: (user =? caller context) = false
get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: (user =? caller context) = true

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: user = caller context

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: user = caller context

get_default 0 user (set user (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: user = caller context

(let (intval, _) := callvalue context in intval) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: user = caller context

False
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true

False
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true

False
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) = 0

False
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: 0 > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: get_default 0 (caller context) (Crowdfunding_backers (contract_state prevSt)) = 0

False
lia.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: (user =? caller context) = false

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = true
Case: user <> caller context

get_default 0 user (set (caller context) (let (intval, _) := callvalue context in intval) (Crowdfunding_backers (contract_state prevSt))) > 0
rewrite get_default_so; assumption.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True
a: unit
H3: negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = true
a1: unit
H7: ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) >=? 0) = true
Heqb: Int256.ltu (Crowdfunding_max_block (contract_state prevSt)) (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) = false
Heqb0: (get_default 0 (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (Crowdfunding_backers (contract_state prevSt)) =? 0)%Z = false
H21: false = true

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
match goal with H : false = true |- _ => inversion H end.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_getFunds_prf: runStateT (Crowdfunding_getFunds_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_getFunds_prf: runStateT (Crowdfunding_getFunds_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_getFunds_prf: runStateT ((v <- ret (negb (me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)));; guard v);; (v <- ret ((let (intval, _) := me_callvalue (make_machine_env contract_address prevSt context address_accepts_funds_assumption) in intval) =? 0)%Z;; guard v);; spec1 <- gets Crowdfunding_owner;; (if me_caller (make_machine_env contract_address prevSt context address_accepts_funds_assumption) =? spec1 then spec2 <- ret (me_number (make_machine_env contract_address prevSt context address_accepts_funds_assumption));; spec3 <- ret (let (intval, _) := me_balance (make_machine_env contract_address prevSt context address_accepts_funds_assumption) (me_address (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) in intval);; spec4 <- gets Crowdfunding_max_block;; (if Int256.ltu spec4 spec2 then spec5 <- gets Crowdfunding_goal;; (if spec5 <=? spec3 then MonadState.modify (update_Crowdfunding_funded true);; ret tt;; d <- MonadState.get;; (let (success, d') := me_transfer (...) spec1 (...) d in if success =? Int256.one then put d' else mzero) else ret tt) else ret tt) else ret tt)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
ds_inv; subst; simpl; try lia.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
context: CallContext
callvalue_prf: noOverflowOrUnderflowInTransfer (caller context) contract_address (callvalue context) (balance prevSt) = true
r: unit
contract_state_after: global_abstract_data_type
case_claim_prf: runStateT (Crowdfunding_claim_opt (make_machine_env contract_address prevSt context address_accepts_funds_assumption)) (contract_state prevSt) = Some (r, contract_state_after)
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: False

get_default 0 user (Crowdfunding_backers contract_state_after) > 0
contradiction.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
sender, recipient: addr
amount0: wei
prf: sender <> contract_address /\ noOverflowOrUnderflowInTransfer sender recipient amount0 (balance prevSt) && address_accepts_funds_assumption None sender recipient amount0 = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
assumption.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
block_count, time_passing: int256
prf: validTimeChange block_count time_passing (block_number prevSt) (timestamp prevSt) = true
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
assumption.
snapshot_timestamp, snapshot_number: int256
snapshot_blockhash: int256 -> int256
snapshot_balances: addr -> wei
HmemOps, memModelOps: MemoryModelOps mem
contract_address: addr
address_accepts_funds: option ContractState -> addr -> addr -> wei -> bool
user: addr
amount: Z
start, prevSt: BlockchainState
prevList: list Step
H2: get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
H0: True

get_default 0 user (Crowdfunding_backers (contract_state prevSt)) > 0
assumption. Qed.

If showing a part of this, show the very last Transparent and unfold of getFunds_opt. This shows something familiar that looks complex but is resolved via automation, because getFunds is what is called by the owner, so it has no bearing on the user donation record which is the focus of this lemma.

Also can show the first section, in particular after "Proof."

Paper overviews

References

Thank you!

I would like to thank my supervisor Professor Steve Reeves at the University of Waikato and Vilhelm Sjöberg at CertiK for their valuable insights and input.

I would also like to thank Associate Professor Jing Sun and the University of Auckland for kindly hosting me during this research.

Additional Slides

Example: a property of a list membership function

Inductive list (A : Type) : Type :=
| nil : list A
| cons : A -> list A -> list A.

Fixpoint contains (n:nat) (l:list nat) : bool :=
  match l with
  | [] => false
  | h :: tl => (n =? h) || contains n tl
end.

forall (n : nat) (list1 : list nat), contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true

forall (n : nat) (list1 : list nat), contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
n: nat

forall list1 : list nat, contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
n: nat

contains n [] = true -> forall list2 : list nat, contains n ([] ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
contains n (a :: list1) = true -> forall list2 : list nat, contains n ((a :: list1) ++ list2) = true
n: nat

contains n [] = true -> forall list2 : list nat, contains n ([] ++ list2) = true
n: nat

false = true -> forall list2 : list nat, contains n list2 = true
n: nat
H: false = true
list2: list nat

contains n list2 = true
discriminate.
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true

contains n (a :: list1) = true -> forall list2 : list nat, contains n ((a :: list1) ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: contains n (a :: list1) = true
list2: list nat

contains n ((a :: list1) ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) || contains n list1 = true
list2: list nat

(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) = true \/ contains n list1 = true
list2: list nat

(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) = true
list2: list nat

(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: contains n list1 = true
list2: list nat
(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) = true
list2: list nat

(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) = true
list2: list nat

(n =? a) = true \/ contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: (n =? a) = true
list2: list nat

(n =? a) = true
assumption.
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: contains n list1 = true
list2: list nat

(n =? a) || contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: contains n list1 = true
list2: list nat

(n =? a) = true \/ contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
H: contains n list1 = true
list2: list nat

contains n (list1 ++ list2) = true
n, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = true
list2: list nat
H: contains n (list1 ++ ?list2) = true

contains n (list1 ++ list2) = true
eassumption. Qed.

forall (n : nat) (l : list nat), contains n l = true <-> In n l

forall (n : nat) (l : list nat), contains n l = true <-> In n l
In = fun A : Type => fix In (a : A) (l : list A) {struct l} : Prop := match l with | [] => False | b :: m => b = a \/ In a m end : forall A : Type, A -> list A -> Prop Arguments In [A]%type_scope _ _%list_scope

forall (n : nat) (l : list nat), contains n l = true <-> In n l
n: nat
l: list nat

contains n l = true -> In n l
n: nat
l: list nat
In n l -> contains n l = true
n: nat
l: list nat

contains n l = true -> In n l
n: nat

contains n [] = true -> In n []
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
contains n (l' :: l) = true -> In n (l' :: l)
n: nat

contains n [] = true -> In n []
n: nat

false = true -> False
discriminate.
n, l': nat
l: list nat
IHl: contains n l = true -> In n l

contains n (l' :: l) = true -> In n (l' :: l)
n, l': nat
l: list nat
IHl: contains n l = true -> In n l

(n =? l') || contains n l = true -> l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') || contains n l = true

l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = true \/ contains n l = true

l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = true

l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = true
l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = true

l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = true

l' = n
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: n = l'

l' = n
auto.
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = true

l' = n \/ In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = true

In n l
n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: In n l

In n l
assumption.
n: nat
l: list nat

In n l -> contains n l = true
n: nat

In n [] -> contains n [] = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
In n (l' :: l) -> contains n (l' :: l) = true
n: nat

In n [] -> contains n [] = true
n: nat

False -> false = true
contradiction.
n, l': nat
l: list nat
IHl: In n l -> contains n l = true

In n (l' :: l) -> contains n (l' :: l) = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true

l' = n \/ In n l -> (n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n \/ In n l

(n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n

(n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l
(n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n

(n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n

(n =? l') = true \/ contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n

(n =? l') = true
n: nat
l: list nat
IHl: In n l -> contains n l = true

(n =? n) = true
apply Nat.eqb_refl.
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l

(n =? l') || contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l

(n =? l') = true \/ contains n l = true
n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l

contains n l = true
auto. Qed.

Example: Simple state machine

example state machine diagram
Inductive State :=
  | initial
  | middle
  | extra
  | final
.

Inductive Transition (before : State) :=
  | advance (prf : before <> final)
  | sidetrack (prf : before = initial).
Program Definition step (s : State) (t : Transition s) :=
  match t with
  | advance _ =>
    match s with
    | initial => middle
    | middle => final
    | extra => middle
    | final => _
    end
  | sidetrack _ =>
    match s with
    | initial => extra
    | _ => _
    end
end.

forall (s : State) (t : Transition s) (wildcard' : s <> final), advance s wildcard' = t -> final = s -> State
s: State
t: Transition s
wildcard': s <> final
Heq_t: advance s wildcard' = t
Heq_s: final = s

State
s: State
t: Transition s
wildcard': s <> final
Heq_t: advance s wildcard' = t
Heq_s: final = s

False
wildcard': final <> final

False
contradiction. Defined.

forall (s : State) (t : Transition s) (wildcard'0 : s = initial), sidetrack s wildcard'0 = t -> forall wildcard' : State, initial <> wildcard' -> wildcard' = s -> State
s: State
t: Transition s
wildcard'0: s = initial
Heq_t: sidetrack s wildcard'0 = t
wildcard': State
H: initial <> wildcard'
Heq_s: wildcard' = s

State
s: State
t: Transition s
wildcard'0: s = initial
Heq_t: sidetrack s wildcard'0 = t
wildcard': State
H: initial <> wildcard'
Heq_s: wildcard' = s

False
H: initial <> initial

False
contradiction. Defined.
Local Obligation Tactic := try discriminate. (* Used for the above. *)

forall (t1 : Transition initial) (t2 : Transition (step initial t1)) (t3 : Transition (step (step initial t1) t2)), let s1 := step initial t1 in let s2 := step s1 t2 in step s2 t3 = final

forall (t1 : Transition initial) (t2 : Transition (step initial t1)) (t3 : Transition (step (step initial t1) t2)), let s1 := step initial t1 in let s2 := step s1 t2 in step s2 t3 = final
t1: Transition initial
t2: Transition (step initial t1)
t3: Transition (step (step initial t1) t2)
s1:= step initial t1: State
s2:= step s1 t2: State

step s2 t3 = final
prf: initial <> final
t2: Transition (step initial (advance initial prf))
t3: Transition (step (step initial (advance initial prf)) t2)
s1:= step initial (advance initial prf): State
s2:= step s1 t2: State

step s2 t3 = final
prf: initial = initial
t2: Transition (step initial (sidetrack initial prf))
t3: Transition (step (step initial (sidetrack initial prf)) t2)
s1:= step initial (sidetrack initial prf): State
s2:= step s1 t2: State
step s2 t3 = final
prf: initial <> final
t2: Transition middle
t3: Transition (step middle t2)
s1:= middle: State
s2:= step s1 t2: State

step s2 t3 = final
prf: initial = initial
t2: Transition (step initial (sidetrack initial prf))
t3: Transition (step (step initial (sidetrack initial prf)) t2)
s1:= step initial (sidetrack initial prf): State
s2:= step s1 t2: State
step s2 t3 = final
prf: initial <> final
t2: Transition middle
t3: Transition (step middle t2)
s1:= middle: State
s2:= step s1 t2: State

step s2 t3 = final
prf: initial <> final
prf0: middle <> final
t3: Transition (step middle (advance middle prf0))
s1:= middle: State
s2:= step s1 (advance middle prf0): State

step s2 t3 = final
prf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): State
step s2 t3 = final
prf: initial <> final
prf0: middle <> final
t3: Transition final
s1:= middle: State
s2:= final: State

step s2 t3 = final
prf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): State
step s2 t3 = final
prf: initial <> final
prf0: middle <> final
t3: Transition final
s1:= middle: State
s2:= final: State

step s2 t3 = final
prf: initial <> final
prf0: middle <> final
prf1: final <> final
s1:= middle: State
s2:= final: State

step s2 (advance final prf1) = final
prf: initial <> final
prf0: middle <> final
prf1: final = initial
s1:= middle: State
s2:= final: State
step s2 (sidetrack final prf1) = final
prf: initial <> final
prf0: middle <> final
prf1: final <> final
s1:= middle: State
s2:= final: State

step s2 (advance final prf1) = final
contradiction.
prf: initial <> final
prf0: middle <> final
prf1: final = initial
s1:= middle: State
s2:= final: State

step s2 (sidetrack final prf1) = final
discriminate.
prf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): State

step s2 t3 = final
discriminate.
prf: initial = initial
t2: Transition (step initial (sidetrack initial prf))
t3: Transition (step (step initial (sidetrack initial prf)) t2)
s1:= step initial (sidetrack initial prf): State
s2:= step s1 t2: State

step s2 t3 = final
prf: initial = initial
prf0: step initial (sidetrack initial prf) <> final
t3: Transition (step (step initial (sidetrack initial prf)) (advance (step initial (sidetrack initial prf)) prf0))
s1:= step initial (sidetrack initial prf): State
s2:= step s1 (advance (step initial (sidetrack initial prf)) prf0): State

step s2 t3 = final
prf: initial = initial
prf0: step initial (sidetrack initial prf) = initial
t3: Transition (step (step initial (sidetrack initial prf)) (sidetrack (step initial (sidetrack initial prf)) prf0))
s1:= step initial (sidetrack initial prf): State
s2:= step s1 (sidetrack (step initial (sidetrack initial prf)) prf0): State
step s2 t3 = final
prf: initial = initial
prf0: extra <> final
t3: Transition middle
s1:= extra: State
s2:= middle: State

step s2 t3 = final
prf: initial = initial
prf0: step initial (sidetrack initial prf) = initial
t3: Transition (step (step initial (sidetrack initial prf)) (sidetrack (step initial (sidetrack initial prf)) prf0))
s1:= step initial (sidetrack initial prf): State
s2:= step s1 (sidetrack (step initial (sidetrack initial prf)) prf0): State
step s2 t3 = final
prf: initial = initial
prf0: extra <> final
t3: Transition middle
s1:= extra: State
s2:= middle: State

step s2 t3 = final
prf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: State

step s2 (advance middle prf1) = final
prf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: State
step s2 (sidetrack middle prf1) = final
prf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: State

final = final
prf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: State
step s2 (sidetrack middle prf1) = final
prf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: State

final = final
reflexivity.
prf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: State

step s2 (sidetrack middle prf1) = final
discriminate.
prf: initial = initial
prf0: step initial (sidetrack initial prf) = initial
t3: Transition (step (step initial (sidetrack initial prf)) (sidetrack (step initial (sidetrack initial prf)) prf0))
s1:= step initial (sidetrack initial prf): State
s2:= step s1 (sidetrack (step initial (sidetrack initial prf)) prf0): State

step s2 t3 = final
discriminate. Qed.
1