It's great to be here...
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 nOdd (n + 1)n: nat
H: exists k : nat, n = 2 * kOdd (n + 1)n, k: nat
H: n = 2 * kOdd (n + 1)n, k: nat
H: n = 2 * kexists l : nat, n + 1 = 2 * l + 1n, k: nat
H: n = 2 * kn + 1 = 2 * k + 1reflexivity. Qed.n, k: nat
H: n = 2 * kn + 1 = n + 1
Introduction to creating a DeepSEA smart contract
Example: Trivial contract converting bool to int
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 } object Trivial : trivial { let boolToInt b = if b then 1 else 0 } layer CONTRACT = { o = Trivial }
Refinement and the Lem EVM model
References
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) = trueforall (n : nat) (list1 : list nat), contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = truen: natforall list1 : list nat, contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = truen: natcontains n [] = true -> forall list2 : list nat, contains n ([] ++ list2) = truen, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = truecontains n (a :: list1) = true -> forall list2 : list nat, contains n ((a :: list1) ++ list2) = truen: natcontains n [] = true -> forall list2 : list nat, contains n ([] ++ list2) = truen: natfalse = true -> forall list2 : list nat, contains n list2 = truediscriminate.n: nat
H: false = true
list2: list natcontains n list2 = truen, a: nat
list1: list nat
IHlist1: contains n list1 = true -> forall list2 : list nat, contains n (list1 ++ list2) = truecontains n (a :: list1) = true -> forall list2 : list nat, contains n ((a :: list1) ++ list2) = truen, 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 natcontains n ((a :: list1) ++ list2) = truen, 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) = truen, 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) = truen, 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) = truen, 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) = truen, 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) = truen, 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) = trueassumption.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) = truen, 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) = truen, 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) = truen, 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 natcontains n (list1 ++ list2) = trueeassumption. Qed.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) = truecontains n (list1 ++ list2) = true
forall (n : nat) (l : list nat), contains n l = true <-> In n lforall (n : nat) (l : list nat), contains n l = true <-> In n lforall (n : nat) (l : list nat), contains n l = true <-> In n ln: nat
l: list natcontains n l = true -> In n ln: nat
l: list natIn n l -> contains n l = truen: nat
l: list natcontains n l = true -> In n ln: natcontains n [] = true -> In n []n, l': nat
l: list nat
IHl: contains n l = true -> In n lcontains n (l' :: l) = true -> In n (l' :: l)n: natcontains n [] = true -> In n []discriminate.n: natfalse = true -> Falsen, l': nat
l: list nat
IHl: contains n l = true -> In n lcontains 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 ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') || contains n l = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = true \/ contains n l = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: (n =? l') = truel' = nauto.n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: n = l'l' = nn, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = truel' = n \/ In n ln, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: contains n l = trueIn n lassumption.n, l': nat
l: list nat
IHl: contains n l = true -> In n l
H: In n lIn n ln: nat
l: list natIn n l -> contains n l = truen: natIn n [] -> contains n [] = truen, l': nat
l: list nat
IHl: In n l -> contains n l = trueIn n (l' :: l) -> contains n (l' :: l) = truen: natIn n [] -> contains n [] = truecontradiction.n: natFalse -> false = truen, l': nat
l: list nat
IHl: In n l -> contains n l = trueIn n (l' :: l) -> contains n (l' :: l) = truen, l': nat
l: list nat
IHl: In n l -> contains n l = truel' = n \/ In n l -> (n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n \/ In n l(n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n(n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l(n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n(n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n(n =? l') = true \/ contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: l' = n(n =? l') = trueapply Nat.eqb_refl.n: nat
l: list nat
IHl: In n l -> contains n l = true(n =? n) = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l(n =? l') || contains n l = truen, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n l(n =? l') = true \/ contains n l = trueauto. Qed.n, l': nat
l: list nat
IHl: In n l -> contains n l = true
H: In n lcontains n l = true

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 -> States: State
t: Transition s
wildcard': s <> final
Heq_t: advance s wildcard' = t
Heq_s: final = sStates: State
t: Transition s
wildcard': s <> final
Heq_t: advance s wildcard' = t
Heq_s: final = sFalsecontradiction. Defined.wildcard': final <> finalFalseforall (s : State) (t : Transition s) (wildcard'0 : s = initial), sidetrack s wildcard'0 = t -> forall wildcard' : State, initial <> wildcard' -> wildcard' = s -> States: State
t: Transition s
wildcard'0: s = initial
Heq_t: sidetrack s wildcard'0 = t
wildcard': State
H: initial <> wildcard'
Heq_s: wildcard' = sStates: State
t: Transition s
wildcard'0: s = initial
Heq_t: sidetrack s wildcard'0 = t
wildcard': State
H: initial <> wildcard'
Heq_s: wildcard' = sFalsecontradiction. Defined.H: initial <> initialFalse
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 = finalforall (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 = finalt1: Transition initial
t2: Transition (step initial t1)
t3: Transition (step (step initial t1) t2)
s1:= step initial t1: State
s2:= step s1 t2: Statestep s2 t3 = finalprf: 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: Statestep s2 t3 = finalprf: 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: Statestep s2 t3 = finalprf: initial <> final
t2: Transition middle
t3: Transition (step middle t2)
s1:= middle: State
s2:= step s1 t2: Statestep s2 t3 = finalprf: 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: Statestep s2 t3 = finalprf: initial <> final
t2: Transition middle
t3: Transition (step middle t2)
s1:= middle: State
s2:= step s1 t2: Statestep s2 t3 = finalprf: initial <> final
prf0: middle <> final
t3: Transition (step middle (advance middle prf0))
s1:= middle: State
s2:= step s1 (advance middle prf0): Statestep s2 t3 = finalprf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): Statestep s2 t3 = finalprf: initial <> final
prf0: middle <> final
t3: Transition final
s1:= middle: State
s2:= final: Statestep s2 t3 = finalprf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): Statestep s2 t3 = finalprf: initial <> final
prf0: middle <> final
t3: Transition final
s1:= middle: State
s2:= final: Statestep s2 t3 = finalprf: initial <> final
prf0: middle <> final
prf1: final <> final
s1:= middle: State
s2:= final: Statestep s2 (advance final prf1) = finalprf: initial <> final
prf0: middle <> final
prf1: final = initial
s1:= middle: State
s2:= final: Statestep s2 (sidetrack final prf1) = finalcontradiction.prf: initial <> final
prf0: middle <> final
prf1: final <> final
s1:= middle: State
s2:= final: Statestep s2 (advance final prf1) = finaldiscriminate.prf: initial <> final
prf0: middle <> final
prf1: final = initial
s1:= middle: State
s2:= final: Statestep s2 (sidetrack final prf1) = finaldiscriminate.prf: initial <> final
prf0: middle = initial
t3: Transition (step middle (sidetrack middle prf0))
s1:= middle: State
s2:= step s1 (sidetrack middle prf0): Statestep s2 t3 = finalprf: 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: Statestep s2 t3 = finalprf: 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): Statestep s2 t3 = finalprf: 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): Statestep s2 t3 = finalprf: initial = initial
prf0: extra <> final
t3: Transition middle
s1:= extra: State
s2:= middle: Statestep s2 t3 = finalprf: 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): Statestep s2 t3 = finalprf: initial = initial
prf0: extra <> final
t3: Transition middle
s1:= extra: State
s2:= middle: Statestep s2 t3 = finalprf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: Statestep s2 (advance middle prf1) = finalprf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: Statestep s2 (sidetrack middle prf1) = finalprf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: Statefinal = finalprf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: Statestep s2 (sidetrack middle prf1) = finalreflexivity.prf: initial = initial
prf0: extra <> final
prf1: middle <> final
s1:= extra: State
s2:= middle: Statefinal = finaldiscriminate.prf: initial = initial
prf0: extra <> final
prf1: middle = initial
s1:= extra: State
s2:= middle: Statestep s2 (sidetrack middle prf1) = finaldiscriminate. Qed.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): Statestep s2 t3 = final