text‹
In the following we use our calculus to verify a contract implementing a simple token.
The contract is defined by definition *bank* and consist of one state variable and two methods:
▪ The state variable "balance" is a mapping which assigns a balance to each address.
▪ Method "deposit" allows to send money to the contract which is then added to the sender's balance.
▪ Method "withdraw" allows to withdraw the callers balance. ›
text‹
We then verify that the following invariant (defined by *BANK*) is preserved by both methods:
The difference between
▪ the contracts own account-balance and
▪ the sum of all the balances kept in the contracts state variable
is larger than a certain threshold. ›
text‹
There are two things to note here:
First, Solidity implicitly triggers the call of a so-called fallback method whenever we transfer money to a contract.
In particular if another contract calls "withdraw", this triggers an implicit call to the callee's fallback method.
This functionality was exploited in the infamous DAO attack which we demonstrate it in terms of an example later on.
Since we do not know all potential contracts which call "withdraw", we need to verify our invariant for all possible Solidity programs. ›
text‹
The second thing to note is that we were not able to verify that the difference is indeed constant.
During verification it turned out that this is not the case since in the fallback method a contract could just send us additional money without calling "deposit".
In such a case the difference would change. In particular it would grow. However, we were able to verify that the difference does never shrink which is what we actually want to ensure. ›
theory Reentrancy imports Weakest_Precondition Solidity_Evaluator "HOL-Eisbach.Eisbach_Tools" begin
global_interpretation reentrancy: statement_with_gas costs_ex example_env costs_min defines stmt = "reentrancy.stmt" and lexp = reentrancy.lexp and expr = reentrancy.expr and ssel = reentrancy.ssel and rexp = reentrancy.rexp and msel = reentrancy.msel and load = reentrancy.load and eval = reentrancy.eval by unfold_locales auto
locale Reentrancy = Calculus + assumes r0: "cname = STR ''Bank''" and r1: "members = bank" and r2: "fb = SKIP" and r3: "const = ([], SKIP)" begin
subsubsection‹Method lemmas› text‹
These lemmas are required by @{term vcg_external}. ›
lemma mwithdraw[mcontract]: "members $$ STR ''withdraw'' = Some (Method ([], True, keep))" using r1 unfolding bank_def by simp
lemma mdeposit[mcontract]: "members $$ STR ''deposit'' = Some (Method ([], True, deposit))" using r1 unfolding bank_def by simp
subsubsection‹Variable lemma›
lemma balance: "members $$ (STR ''balance'') = Some (Var (STMap TAddr (STValue (TUInt 256))))" using r1 bank_def fmlookup_of_list[of "[(STR ''balance'', Var (STMap TAddr (STValue (TUInt 256)))), (STR ''deposit'', Method ([], True, ASSIGN myrexp (PLUS mylval VALUE))), (STR ''withdraw'', Method ([], True, BLOCK ((STR ''bal'', Value (TUInt 256)), Some mylval) (COMP (ASSIGN myrexp (UINT 256 0)) Reentrancy.transfer)))]"] by simp
subsubsection‹Case lemmas› text‹
These lemmas are required by @{term vcg_transfer}. › lemma cases_ext: assumes"members $$ mid = Some (Method (fp,True,f))" and"fp = [] ==> P deposit" and"fp = [] ==> P keep" shows"P f" proof - from assms(1) r1 consider (withdraw) "mid = STR ''withdraw''" | (deposit) "mid = STR ''deposit''"using bank_def fmap_of_list_SomeD[of "[(STR ''balance'', Var (STMap TAddr (STValue (TUInt 256)))), (STR ''deposit'', Method ([], True, deposit)), (STR ''withdraw'', Method ([], True, keep))]"] by auto thenshow ?thesis proof (cases) case withdraw thenhave"f = keep"and"fp = []"using assms(1) bank_def r1 fmlookup_of_list[of banklist] by simp+ thenshow ?thesis using assms(3) by simp next case deposit thenhave"f = deposit"and"fp = []"using assms(1) bank_def r1 fmlookup_of_list[of banklist] by simp+ thenshow ?thesis using assms(2) by simp qed qed
lemma cases_int: assumes"members $$ mid = Some (Method (fp,False,f))" shows"P fp f" using assms r1 bank_def fmap_of_list_SomeD[of "[(STR ''balance'', Var (STMap TAddr (STValue (TUInt 256)))), (STR ''deposit'', Method ([], True, deposit)), (STR ''withdraw'', Method ([], True, keep))]"] by auto
lemma cases_fb: assumes"P SKIP" shows"P fb" using assms bank_def r2 by simp
lemma cases_cons: assumes"fst const = [] ==> P (fst const, SKIP)" shows"P const" using assms bank_def r3 by simp
subsubsection‹Definition of Invariant›
abbreviation"SUMM s ≡∑(ad,x)|fmlookup s (ad + (STR ''.'' + STR ''balance'')) = Some x. ReadLint x"
abbreviation"POS s ≡∀ad x. fmlookup s (ad + (STR ''.'' + STR ''balance'')) = Some x ⟶ ReadLint x ≥ 0"
definition"iv s a ≡ a ≥ SUMM s ∧ POS s"
lemma weaken: assumes"iv (storage st ad) (ReadLint (bal (acc ad)) - ReadLint v)" and"ReadLint v ≥0" shows"iv (storage st ad) (ReadLint (bal (acc ad)))" using assms unfolding iv_def by simp
subsubsection‹Additional lemmas›
lemma expr_0: assumes"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" and"decl STR ''bal'' (Value (TUInt 256)) (Some (lv, lt)) False cdl ml s (cdl, ml, kl, el) = Some (cd', mem', sck', e')" and"expr (UINT 256 0) ev0 cd0 st0 g0 = Normal ((rv, rt),g''a)" shows"rv= KValue (ShowLint 0)"and"rt=Value (TUInt 256)" using assms(3) by (simp add:expr.simps createUInt_def split:if_split_asm)+
lemma load_empty_par: assumes"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" shows"load True [] [] (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" proof - have"xe=[]" proof (rule ccontr) assume"¬ xe=[]" thenobtain x and xa where"xe=x # xa"by (meson list.exhaust) thenhave"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = throw Err g1"by (simp add:load.simps) with assms show False by simp qed thenshow ?thesis using assms(1) by simp qed
lemma lexp_myrexp_decl: assumes"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" and"decl STR ''bal'' (Value (TUInt 256)) (Some (lv, lt)) False cdl ml s (cdl, ml, kl, el) = Some (cd', mem', sck', e')" and"lexp myrexp e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := g'a)) g'a = Normal ((rv,rt), g''a)" shows"rv= LStoreloc (address env + (STR ''.'' + STR ''balance''))"and"rt=Storage (STValue (TUInt 256))" proof - have"fmlookup (denvalue (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"unfolding emptyEnv_def using ffold_init_fmdom balance by simp moreoverhave el_def: "el = (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))"using load_empty_par[OF assms(1)] by (simp add:load.simps) ultimatelyhave"fmlookup (denvalue el) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"using assms by auto thenhave *: "fmlookup (denvalue e') (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"using decl_env[OF assms(2)] by simp
moreoverobtain g'' where"ssel (STMap TAddr (STValue (TUInt 256))) (STR ''balance'') [SENDER] e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := g'a)) g'a = Normal (((address env) + (STR ''.'' + STR ''balance''), STValue (TUInt 256)), g'')" proof - have"g'a > costse SENDER e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := g'a))"using assms(3) * by (simp add:expr.simps ssel.simps lexp.simps split:if_split_asm) thenobtain g'' where"expr SENDER e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := g'a)) g'a = Normal ((KValue (sender e'), Value TAddr), g'')"by (simp add:expr.simps) moreoverhave"sender el = address env"using el_def ffold_init_ad_same[of members "(emptyEnv ad cname (address env) v)""fmdom members" el] unfolding emptyEnv_def by simp thenhave"sender e' = address env"using decl_env[OF assms(2)] by simp ultimatelyshow ?thesis using that hash_def by (simp add:ssel.simps) qed ultimatelyshow"rv= LStoreloc (address env + (STR ''.'' + STR ''balance''))"and"rt=Storage (STValue (TUInt 256))"using assms(3) by (simp add:lexp.simps)+ qed
lemma expr_bal: assumes"expr (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g'')) g'' = Normal ((KValue lv, Value t), g''')" and"(sck', e') = astack STR ''bal'' (Value (TUInt 256)) (KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s')) (kl, el)" shows"(⌈accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'⌉::int) = ReadLint lv" (is ?G1) and"t = TUInt 256" proof - from assms(1) have"expr (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g'')) g'' = rexp ((L.Id STR ''bal'')) e' cd' ((st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g''))) (g'' - costse (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g'')))"by (simp add:expr.simps split:if_split_asm) moreoverhave"rexp ((L.Id STR ''bal'')) e' cd' ((st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g''))) (g'' - costse (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g''))) = Normal ((KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'), (Value (TUInt 256))),(g'' - costse (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g''))) )" proof - from assms(2) have"fmlookup (denvalue e') (STR ''bal'') = Some (Value (TUInt 256), Stackloc ⌊toploc kl⌋)"by (simp add:push_def allocate_def updateStore_def ) moreoverhave"accessStore (⌊toploc kl⌋) sck' = Some (KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'))"using assms(2) by (simp add:push_def allocate_def updateStore_def accessStore_def) ultimatelyshow ?thesis by (simp add:rexp.simps) qed ultimatelyhave"expr (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g'')) g'' = Normal ((KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'), (Value (TUInt 256))),(g'' - costse (LVAL (L.Id STR ''bal'')) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := fmupd l v' s'), gas := g''))))"and"t = TUInt 256"using assms(1) by simp+ thenhave"lv = accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'"using assms(1) by (auto) with `t = TUInt 256` show ?G1 and"t = TUInt 256"by simp+ qed
lemma lexp_myrexp: assumes"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" and"lexp myrexp el cdl (st'(gas := g2)) g2 = Normal ((rv,rt), g2')" shows"rv= LStoreloc (address env + (STR ''.'' + STR ''balance''))"and"rt=Storage (STValue (TUInt 256))" proof - have"fmlookup (denvalue (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"unfolding emptyEnv_def using ffold_init_fmdom balance by simp moreoverhave el_def: "el = (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))"using load_empty_par[OF assms(1)] by (simp add:load.simps) ultimatelyhave *: "fmlookup (denvalue el) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"using assms by auto
moreoverobtain g'' where"ssel (STMap TAddr (STValue (TUInt 256))) (STR ''balance'') [SENDER] el cdl (st'(gas := g2)) g2 = Normal (((address env) + (STR ''.'' + STR ''balance''), STValue (TUInt 256)), g'')" proof - have"g2 > costse SENDER el cdl (st'(gas := g2))"using assms(2) * by (simp add:expr.simps ssel.simps lexp.simps split:if_split_asm) thenobtain g'' where"expr SENDER el cdl (st'(gas := g2)) g2 = Normal ((KValue (sender el), Value TAddr), g'')"by (simp add: expr.simps) moreoverhave"sender el = address env"using el_def ffold_init_ad_same[of members "(emptyEnv ad cname (address env) v)""fmdom members" el] unfolding emptyEnv_def by simp ultimatelyshow ?thesis using that hash_def by (simp add:ssel.simps) qed ultimatelyshow"rv= LStoreloc (address env + (STR ''.'' + STR ''balance''))"and"rt=Storage (STValue (TUInt 256))"using assms(2) by (simp add: lexp.simps)+ qed
lemma expr_balance: assumes"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g1)) g1 = Normal ((el, cdl, kl, ml), g1')" and"expr (LVAL (Ref (STR ''balance'') [SENDER])) el cdl (st(accounts := acc, stack := kl, memory := ml, gas := g2)) g2 = Normal ((va, ta), g'a)" shows"va= KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) (storage st ad))" and"ta = Value (TUInt 256)" proof - have"fmlookup (denvalue (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"unfolding emptyEnv_def using ffold_init_fmdom balance by simp moreoverhave el_def: "el = (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))"using load_empty_par[OF assms(1)] by (simp add:load.simps) ultimatelyhave *: "fmlookup (denvalue el) (STR ''balance'') = Some (Storage (STMap TAddr (STValue (TUInt 256))), Storeloc (STR ''balance''))"using assms by auto
moreoverobtain g'' where"ssel (STMap TAddr (STValue (TUInt 256))) (STR ''balance'') [SENDER] el cdl (st(accounts := acc, stack := kl, memory := ml, gas := g2)) g2 = Normal (((address env) + (STR ''.'' + STR ''balance''), STValue (TUInt 256)), g'')" proof - have"g2 > costse SENDER el cdl (st(accounts := acc, stack := kl, memory := ml, gas := g2))"using assms(2) * by (simp add: expr.simps ssel.simps rexp.simps split:if_split_asm) thenobtain g'' where"expr SENDER el cdl (st(accounts := acc, stack := kl, memory := ml, gas := g2)) g2 = Normal ((KValue (sender el), Value TAddr), g'')"by (simp add:expr.simps ssel.simps rexp.simps) moreoverhave"sender el = address env"using el_def ffold_init_ad_same[of members "(emptyEnv ad cname (address env) v)""fmdom members" el] unfolding emptyEnv_def by simp ultimatelyshow ?thesis using that hash_def by (simp add:expr.simps ssel.simps rexp.simps) qed moreoverhave"ad = address el"using el_def ffold_init_ad_same[of members "(emptyEnv ad cname (address env) v)""fmdom members" el] unfolding emptyEnv_def by simp ultimatelyshow"va= KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) (storage st ad))"and"ta = Value (TUInt 256)"using assms(2) by (simp add:expr.simps ssel.simps rexp.simps split:if_split_asm)+ qed
lemma balance_inj: "inj_on (λ(ad, x). (ad + (STR ''.'' + STR ''balance''),x)) {(ad, x). (fmlookup y ∘ f) ad = Some x}" proof fix v v' assume asm1: "v ∈ {(ad, x). (fmlookup y ∘ f) ad = Some x}"and asm2: "v' ∈ {(ad, x). (fmlookup y ∘ f) ad = Some x}" and *:"(case v of (ad, x) ==> (ad + (STR ''.'' + STR ''balance''),x)) = (case v' of (ad, x) ==> (ad + (STR ''.'' + STR ''balance''),x))" thenobtain ad ad' x x' where **: "v = (ad,x)"and ***: "v'=(ad',x')"by auto moreoverfrom * ** *** have"ad + (STR ''.'' + STR ''balance'') = ad' + (STR ''.'' + STR ''balance'')"by simp with * ** have"ad = ad'"using String_Cancel[of ad "STR ''.'' + STR ''balance''" ad' ] by simp moreoverfrom asm1 asm2 ** *** have"(fmlookup y ∘ f) ad = Some x"and"(fmlookup y ∘ f) ad' = Some x'"by auto with calculation(3) have"x=x'"by simp ultimatelyshow"v=v'"by simp qed
lemma fmfinite: "finite ({(ad, x). fmlookup y ad = Some x})" proof - have"{(ad, x). fmlookup y ad = Some x} ⊆ dom (fmlookup y) × ran (fmlookup y)" proof fix x assume"x ∈ {(ad, x). fmlookup y ad = Some x}" thenhave"fmlookup y (fst x) = Some (snd x)"by auto thenhave"fst x ∈ dom (fmlookup y)"and"snd x ∈ ran (fmlookup y)"using Map.ranI by (blast,metis) thenshow"x ∈ dom (fmlookup y) × ran (fmlookup y)"by (simp add: mem_Times_iff) qed thus ?thesis by (simp add: finite_ran finite_subset) qed
lemma fmlookup_finite: fixes f :: "'a ==> 'a" and y :: "('a, 'b) fmap" assumes"inj_on (λ(ad, x). (f ad, x)) {(ad, x). (fmlookup y ∘ f) ad = Some x}" shows"finite {(ad, x). (fmlookup y ∘ f) ad = Some x}" proof (cases rule: inj_on_finite[OF assms(1), of "{(ad, x)|ad x. (fmlookup y) ad = Some x}"]) case1 thenshow ?caseby auto next case2 thenhave *: "finite {(ad, x) |ad x. fmlookup y ad = Some x}"using fmfinite[of y] by simp show ?caseusing finite_image_set[OF *, of "λ(ad, x). (ad, x)"] by simp qed
lemma summ_eq_sum: "SUMM s' = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ad ≠ adr. ReadLint x) + ReadLint (accessStorage (TUInt 256) (adr + (STR ''.'' + STR ''balance'')) s')" proof (cases "fmlookup s' (adr + (STR ''.'' + STR ''balance'')) = None") case True thenhave"accessStorage (TUInt 256) (adr + (STR ''.'' + STR ''balance'')) s' = ShowLint 0"unfolding accessStorage_def by simp moreoverhave"{(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x} = {(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" proof show"{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x} ⊆ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" proof fix x assume"x ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}" thenshow"x ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x∧ ad ≠ adr}"using True by auto qed next show"{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠adr} ⊆ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x }" proof fix x assume"x ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" thenshow"x ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}"using True by auto qed qed thenhave"SUMM s' = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr. ReadLint x)"by simp ultimatelyshow ?thesis using Read_ShowL_id by simp next case False thenobtain val where val_def: "fmlookup s' (adr + (STR ''.'' + STR ''balance'')) = Some val"by auto
have"inj_on (λ(ad, x). (ad + (STR ''.'' + STR ''balance''), x)) {(ad, x). (fmlookup s' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using balance_inj bysimp thenhave"finite {(ad, x). (fmlookup s' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using fmlookup_finite[of "λad. (ad + (STR ''.'' + STR ''balance''))"s'] by simp thenhave sum1: "finite ({(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr})"using finite_subset[of "{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}""{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}"] by auto moreoverhave sum2: "(adr,val) ∉ {(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}"by simp moreoverfrom sum1 val_def have"insert (adr,val) {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr} = {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}"by auto ultimatelyshow ?thesis using sum.insert[OF sum1 sum2, of "λ(ad,x). ReadLint x"] val_def unfolding accessStorage_def by simp qed
lemma sum_eq_update: assumes s''_def: "s'' = fmupd (adr + (STR ''.'' + STR ''balance'')) v' s'" shows"(∑(ad,x)|fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr. ReadLint x) =(∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr. ReadLint x)" proof - have"{(ad,x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠adr} = {(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠adr}" proof show"{(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr} ⊆ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" proof fix xx assume"xx ∈ {(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x∧ ad ≠ adr}" thenobtain ad x where"xx = (ad,x)"and"fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x"and"ad ≠ adr"by auto thenhave"fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x"using String_Cancel[of ad "(STR ''.'' + STR ''balance'')""adr"] s''_defby (simp split:if_split_asm) with `ad ≠ adr` `xx = (ad,x)` show"xx ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}"by simp qed next show"{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠adr} ⊆ {(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" proof fix xx assume"xx ∈ {(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}" thenobtain ad x where"xx = (ad,x)"and"fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x"and"ad ≠ adr"by auto thenhave"fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x"using String_Cancel[of ad "(STR ''.'' + STR ''balance'')""adr"] s''_defby (auto split:if_split_asm) with `ad ≠ adr` `xx = (ad,x)` show"xx ∈ {(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ adr}"by simp qed qed thus ?thesis by simp qed
lemma adapt_deposit: assumes"address env ≠ ad" and"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st0(gas := g3)) g3 = Normal ((el, cdl, kl, ml), g3')" and"Accounts.transfer (address env) ad v a = Some acc" and"iv (storage st0 ad) (ReadLint (bal (acc ad)) - ReadLint v)" and"lexp myrexp el cdl (st0(gas := g'', accounts := acc, stack := kl, memory := ml, gas := g')) g' = Normal ((LStoreloc l, Storage (STValue t')), g''a)" and"expr (PLUS mylval VALUE) el cdl (st0(gas := g'', accounts := acc, stack := kl, memory := ml, gas := g)) g = Normal ((KValue va, Value ta), g')" and"Valuetypes.convert ta t' va = Some v'" shows"(ad = address el⟶ iv (storage st0 (address el)(l $$:= v')) ⌈bal (acc (address el))⌉) ∧ (ad ≠ address el⟶ iv (storage st0 ad) (ReadLint (bal (acc ad))))" proof (rule conjI; rule impI) assume"ad = address el"
define s' s'' where"s' = storage st0 (address el)"and"s'' = storage st0 (address el)(l $$:= v')" thenhave"s'' = fmupd l v' s'"by simp moreoverfrom lexp_myrexp[OF assms(2) assms(5)] have"l = address env + (STR ''.'' + STR ''balance'')"and"t'=TUInt 256"by simp+ ultimatelyhave s''_s': "s'' = s' (address env + (STR ''.'' + STR ''balance'') $$:= v')"by simp
have"svalue el = v"and"sender el = address env"and"address el = ad"using ffold_init_ad_same msel_ssel_expr_load_rexp_gas(4)[OF assms(2)] unfolding emptyEnv_def by simp+ thenhave a_frame: "iv s' (ReadLint (bal (acc ad)) - ReadLint v)"using assms(4) unfolding s'_defby simp
from assms(1) have"ReadLint (bal (a ad)) + ReadLint v < 2^256"using transfer_val2[OF assms(3)] by simp moreoverfrom `address env ≠ ad` have"ReadLint (bal (acc ad)) = ReadLint (bal (a ad)) + ReadLint v"using transfer_add[OF assms(3)] by simp ultimatelyhave a_bal: "ReadLint (bal (acc ad)) < 2^256"by simp
moreoverhave a_bounds: "ReadLint (accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') + ⌈svalue el⌉ < 2 ^ 256 ∧ ReadLint (accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') + ⌈svalue el⌉≥ 0" proof (cases "fmlookup s' (sender el + (STR ''.'' + STR ''balance'')) = None") case True hence"(accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') = ShowLint 0"unfolding accessStorage_def by simp moreoverhave"(⌈svalue el⌉::int) < 2 ^ 256" proof - from a_frame have"⌈svalue el⌉ + SUMM s' ≤ ReadLint (bal (acc ad))"unfolding iv_def using `svalue el = v` by simp moreoverhave"0 ≤ SUMM s'" using a_frame sum_nonneg[of "{(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}""λ(ad,x). ReadLint x"] unfolding iv_def by auto ultimatelyhave"⌈svalue el⌉≤ ReadLint (bal (acc ad))"by simp thenshow"(⌈svalue el⌉::int) < 2 ^ 256"using a_bal by simp qed moreoverhave"ReadLint v ≥ 0"using transfer_val1[OF assms(3)] by simp with `svalue el = v` have"(⌈svalue el⌉::int) ≥ 0"by simp ultimatelyshow ?thesis using Read_ShowL_id by simp next case False thenobtain x where x_def: "fmlookup s' (sender el + (STR ''.'' + STR ''balance'')) = Some x"by auto moreoverfrom a_frame have"⌈svalue el⌉ + SUMM s' ≤ ReadLint (bal (acc ad))"unfolding iv_def using `svalue el = v` by simp moreoverhave"(case (sender el, x) of (ad, x) ==>⌈x⌉) ≤ (∑(ad, x)∈{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}. ReadLint x)" proof (cases rule: member_le_sum[of "(sender el,x)""{(ad,x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}""λ(ad,x). ReadLint x"]) case1 thenshow ?caseusing x_def by simp next case (2 x) with a_frame show ?caseunfolding iv_def by auto next case3 have"inj_on (λ(ad, x). (ad + (STR ''.'' + STR ''balance''), x)) {(ad, x). (fmlookup s' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using balance_inj bysimp thenhave"finite {(ad, x). (fmlookup s' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using fmlookup_finite[of "λad. (ad + (STR ''.'' + STR ''balance''))"s'] by simp thenshow ?caseusing finite_subset[of "{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}""{(ad, x). fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x}"] by auto qed thenhave"ReadLint x ≤ SUMM s'"by simp ultimatelyhave"⌈svalue el⌉ + ReadLint x ≤ ReadLint (bal (acc ad))"by simp thenhave"⌈svalue el⌉ + ReadLint x ≤ ReadLint (bal (acc ad))"by simp with a_bal have"⌈svalue el⌉ + ReadLint x < 2^256"by simp thenhave"⌈svalue el⌉≤⌈bal (acc ad)⌉ - SUMM s'"and lck: "fmlookup s' (sender el + (STR ''.'' + STR ''balance'')) = Some x"and"ReadLint x + ⌈svalue el⌉ < 2 ^ 256"using a_frame x_def `svalue el = v` unfolding iv_def by auto moreoverfrom lck have"(accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') = x"unfolding accessStorage_def by simp moreoverhave"⌈svalue el⌉ + ReadLint x ≥ 0" proof - have"ReadLint v ≥ 0"using transfer_val1[OF assms(3)] by simp with `svalue el = v` have"(⌈svalue el⌉::int) ≥ 0"by simp moreoverfrom a_frame have"ReadLint x ≥ 0"unfolding iv_def using x_def by simp ultimatelyshow ?thesis by simp qed ultimatelyshow ?thesis using Read_ShowL_id by simp qed ultimatelyhave"va = ShowLint (ReadLint (accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') + ReadLint (svalue el))"using createUInt_id[where ?v="ReadLint (accessStorage (TUInt 256) (sender el + (STR ''.'' + STR ''balance'')) s') + ReadLint (svalue el)"] va_def by simp thenhave v'_def: "v' = ShowLint (ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v)"using `sender el = address env` `svalue el = v` `t'=TUInt 256` `ta = (TUInt 256)` using assms(7) by auto
have"SUMM s'' ≤⌈bal (acc ad)⌉" proof - have"SUMM s' ≤ ReadLint (bal (acc ad)) - ReadLint v"using a_frame unfolding iv_def by simp moreoverhave"SUMM s'' = SUMM s' + ReadLint v" proof - from summ_eq_sum have s1: "SUMM s' = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x) + ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s')"by simp have s2: "SUMM s'' = (∑(ad,x)|fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x) + ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v" proof - have"inj_on (λ(ad, x). (ad + (STR ''.'' + STR ''balance''), x)) {(ad, x). (fmlookup s'' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using balance_inj by simp thenhave"finite {(ad, x). (fmlookup s'' ∘ (λad. ad + (STR ''.'' + STR ''balance''))) ad = Some x}"using fmlookup_finite[of "λad. (ad + (STR ''.'' + STR ''balance''))" s''] by simp thenhave sum1: "finite ({(ad,x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env})"using finite_subset[of "{(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env}""{(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x}"] by auto moreoverhave sum2: "(address env, ShowLint (ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v)) ∉ {(ad,x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env}"by simp moreoverfrom v'_def s''_s' have"insert (address env, ShowLint (ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v)) {(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env} = {(ad, x). fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x}"by auto thenshow ?thesis using sum.insert[OF sum1 sum2, of "λ(ad,x). ReadLint x"] Read_ShowL_id bysimp qed from sum_eq_update[OF s''_s'] have s3: "(∑(ad,x)|fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x) =(∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x)"by simp moreoverfrom s''_s' v'_defhave"ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s'') = ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v"using Read_ShowL_id unfolding accessStorage_def by simp ultimatelyhave"SUMM s''= SUMM s' + ReadLint v" proof - from s2 have"SUMM s'' = (∑(ad,x)|fmlookup s'' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x) + ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v"by simp alsofrom s3 have"… = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ address env. ReadLint x) + ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v"by simp alsofrom s1 have"… = SUMM s' - ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') + ReadLint v"by simp finallyshow ?thesis by simp qed thenshow ?thesis by simp qed ultimatelyshow ?thesis by simp qed moreoverhave"POS s''" proof (rule allI[OF allI]) fix x xa show"fmlookup s'' (x + (STR ''.'' + STR ''balance'')) = Some xa ⟶ 0 ≤ (⌈xa⌉::int)" proof assume a_lookup: "fmlookup s'' (x + (STR ''.'' + STR ''balance'')) = Some xa" show"0 ≤ (⌈xa⌉::int)" proof (cases "x = address env") case True thenshow ?thesis using s''_s' a_lookup using Read_ShowL_id v'_def a_bounds `sender el = address env` `svalue el = v` by auto next case False thenhave"fmlookup s' (x + (STR ''.'' + STR ''balance'')) = Some xa"using s''_s' a_lookup String_Cancel[of "address env""(STR ''.'' + STR ''balance'')" x] by (simp split:if_split_asm) thenshow ?thesis using a_frame unfolding iv_def by simp qed qed qed ultimatelyshow"iv (storage st0 (address el)(l $$:= v')) ⌈bal (acc (address el))⌉"unfolding iv_def s''_defusing `ad = address el` by simp next assume"ad ≠ address el" moreoverhave"ad = address el"using ffold_init_ad_same msel_ssel_expr_load_rexp_gas(4)[OF assms(2)] unfolding emptyEnv_def by simp ultimatelyshow"iv (storage st0 ad) ⌈bal (acc ad)⌉"by simp qed
lemma adapt_withdraw: fixes st acc sck' mem' g''a e' l v' xe defines"st' ≡ st(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st) (address e' := (storage st (address e')) (l $$:= v')))" assumes"iv (storage st ad) (ReadLint (bal (acc ad)) - ReadLint v)" and"load True [] xe (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members)) emptyStore emptyStore emptyStore env cd (st(gas := g')) g' = Normal ((el, cdl, kl, ml), g'')" and"decl STR ''bal'' (Value (TUInt 256)) (Some (va, ta)) False cdl ml (storage st) (cdl, ml, kl, el) = Some (cd', mem', sck', e')" and"expr (UINT 256 0) e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := ga)) ga = Normal ((KValue vb, Value tb), g'b)" and"Valuetypes.convert tb t' vb = Some v'" and"lexp myrexp e' cd' (st(accounts := acc, stack := sck', memory := mem', gas := g'b)) g'b = Normal ((LStoreloc l, Storage (STValue t')), g''a)" and"expr mylval el cdl (st(accounts := acc, stack := kl, memory := ml, gas := g'' - costs keep el cdl (st(gas := g'', accounts := acc, stack := kl, memory := ml)))) (g'' - costs keep el cdl (st(gas := g'', accounts := acc, stack := kl, memory := ml))) = Normal ((va, ta), g'a)" and"Accounts.transfer (address env) ad v (accounts st) = Some acc" and"expr SENDER e' cd' (st' (gas := g)) g = Normal ((KValue adv, Value TAddr), g'x)" and adv_def: "adv ≠ ad" and bal: "expr (LVAL (L.Id STR ''bal'')) e' cd' (st'(gas := g''b)) g''b = Normal ((KValue lv, Value t), g''')" and con: "Valuetypes.convert t (TUInt 256) lv = Some lv'" shows"iv (storage st' ad) (ReadLint (bal (accounts st' ad)) - (ReadLint lv'))" proof -
define acca where"acca = accounts st' ad"
define s' where"s' = storage st (address e')"
define s'a where"s'a = storage st' ad" moreoverhave"address e' = ad" proof - have"address e' = address el"using decl_env[OF assms(4)] by simp alsohave"address el = address (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))"using msel_ssel_expr_load_rexp_gas(4)[OF assms(3)] by simp alsohave"… = ad"unfolding emptyEnv_def using ffold_init_ad_same by simp finallyshow ?thesis . qed ultimatelyhave s'a_def: "s'a = fmupd l v' s'"unfolding s'_def st'_defby simp
have"sender e' = address env" proof - have"sender e' = sender el"using decl_env[OF assms(4)] by simp alsohave"sender el = sender (ffold (init members) (emptyEnv ad cname (address env) v) (fmdom members))"using msel_ssel_expr_load_rexp_gas(4)[OF assms(3)] by simp alsohave"… = address env"unfolding emptyEnv_def using ffold_init_ad_same by simp finallyshow ?thesis . qed
have"iv s'a (⌈bal acca⌉ - ⌈lv'⌉)"unfolding iv_def proofintros have"SUMM s' ≤⌈bal acca⌉" proof - from `address e' = ad` have"iv s' (ReadLint (bal acca) - ReadLint v)"using assms(2,5) unfolding s'_def st'_def acca_def by simp thenhave"SUMM s' ≤⌈bal (acca)⌉ - ⌈v⌉"unfolding iv_def by simp moreoverhave"ReadLint v ≥ 0"using transfer_val1[OF assms(9)] by simp ultimatelyshow ?thesis by simp qed moreoverhave"SUMM s'a = SUMM s' - ReadLint lv'" proof - from summ_eq_sum have"SUMM s'a = (∑(ad,x)|fmlookup s'a (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ sender e'. ReadLint x) + ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s'a)"by simp moreoverfrom summ_eq_sum have"SUMM s' = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ sender e'. ReadLint x) + ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s')"by simp moreoverfrom s'a_def lexp_myrexp_decl(1)[OF assms(3,4) assms(7)] have" s'a = s'((sender e' + (STR ''.'' + STR ''balance''))$$:= v')"using `sender e' = address env` by simp with sum_eq_update have"(∑(ad,x)|fmlookup s'a (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ sender e'. ReadLint x) = (∑(ad,x)|fmlookup s' (ad + (STR ''.'' + STR ''balance'')) = Some x ∧ ad ≠ sender e'. ReadLint x)"by simp moreoverhave"ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s'a) = ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s') - ReadLint lv'" proof - have"ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s') = ReadLint lv'" proof - from expr_balance[OF assms(3) assms(8)] have"va= KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s')"and"ta = Value (TUInt 256)"using`address e' = ad` unfolding s'_defby simp+ thenhave"(sck',e') = astack STR ''bal'' (Value (TUInt 256)) (KValue (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s')) (kl, el)"usingdecl.simps(2) assms(4) by simp thenhave"ReadLint (accessStorage (TUInt 256) (address env + (STR ''.'' + STR ''balance'')) s') = ReadLint lv"and"t = TUInt 256"using expr_bal bal unfolding s'_def st'_defby auto moreoverfrom `t = TUInt 256` have"lv = lv'"using con by simp ultimatelyshow ?thesis using `sender e' = address env` by simp qed moreoverhave"ReadLint (accessStorage (TUInt 256) (sender e' + (STR ''.'' + STR ''balance'')) s'a) = ReadLint (ShowLint 0)" proof - have"v' = ShowLint 0" proof - have"vb = createUInt 256 0"and"tb=TUInt 256"using assms(5) by (simp add: expr.simps load.simps split:if_split_asm)+ moreoverhave"t'=TUInt 256"using lexp_myrexp_decl(2)[OF assms(3,4) assms(7)] by simp ultimatelyshow ?thesis using assms(6) by (simp add: createUInt_id) qed moreoverhave"l= (sender e' + (STR ''.'' + STR ''balance''))"using lexp_myrexp_decl(1)[OF assms(3,4) assms(7)] `sender e' = address env` by simp ultimatelyshow ?thesis using s'a_def accessStorage_def by simp qed ultimatelyshow ?thesis using Read_ShowL_id by simp qed ultimatelyshow ?thesis by simp qed ultimatelyshow"SUMM s'a ≤⌈bal acca⌉ - ⌈lv'⌉"by simp next fix ad' x assume *: "fmlookup s'a (ad' + (STR ''.'' + STR ''balance'')) = Some x" show"0 ≤ ReadLint x" proof (cases "ad' = sender e'") case True moreoverhave"v' = ShowLint 0" proof - have"vb = createUInt 256 0"and"tb=TUInt 256"using assms(5) by (simp add:expr.simps split:if_split_asm)+ moreoverhave"t'=TUInt 256"using lexp_myrexp_decl(2)[OF assms(3,4) assms(7)] by simp ultimatelyshow ?thesis using assms(6) by (simp add: createUInt_id) qed moreoverhave"l= (sender e' + (STR ''.'' + STR ''balance''))"using lexp_myrexp_decl(1)[OF assms(3,4) assms(7)] `sender e' = address env` by simp ultimatelyshow ?thesis using Read_ShowL_id s'a_def * by auto next case False moreoverfrom `address e' = ad` have"iv s' (ReadLint (bal (acc ad)) - ReadLint v)"using assms(2) unfolding s'_defby simp thenhave"POS s'"unfolding iv_def by simp moreoverhave"l= (sender e' + (STR ''.'' + STR ''balance''))"using lexp_myrexp_decl(1)[OF assms(3,4) assms(7)] `sender e' = address env` by simp ultimatelyshow ?thesis using s'a_def * String_Cancel by (auto split:if_split_asm) qed qed thenshow ?thesis unfolding s'a_def s'_def acca_def st'_def `address e' = ad` by simp qed
lemma wp_deposit[external]: assumes"address ev ≠ ad" and"expr adex ev cd (st(gas := gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0)) (gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0) = Normal ((KValue ad, Value TAddr), g)" and"expr val ev cd (st0(gas := g)) g = Normal ((KValue v, Value t), g')" and"Valuetypes.convert t (TUInt 256) v = Some v'" and"load True [] xe (ffold (init members) (emptyEnv ad cname (address ev) v') (fmdom members)) emptyStore emptyStore emptyStore ev cd (st0(gas := g')) g' = Normal ((el, cdl, kl, ml), g'')" and"Accounts.transfer (address ev) ad v' (accounts st0) = Some acc" and"iv (storage st0 ad) (ReadLint (bal (acc ad)) - ReadLint v')" shows"wpS (stmt (ASSIGN myrexp (PLUS mylval VALUE)) el cdl) (λst. (iv (storage st ad) (ReadLint (bal (accounts st ad))))) (λe. e = Gas ∨ e = Err) (st0(gas := g'', accounts := acc, stack := kl, memory := ml))" apply (vcg_assign expr_rule: expr_plus[OF assms(5)] lexp_rule: lexp_myrexp(1)[OF assms(5)]) by (simp add: adapt_deposit[OF assms(1,5,6,7)])
lemma wptransfer: fixes st0 acc sck' mem' g''a e' l v' defines"st' ≡ st0(accounts := acc, stack := sck', memory := mem', gas := g''a, storage := (storage st0)(address e' := storage st0 (address e')(l $$:= v')))" assumes"Pfe ad iv st'" and"address ev ≠ ad" and"g'' ≤ gas st" and"type (acc ad) = Some (Contract cname)" and"expr adex ev cd (st0(gas := gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0)) (gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0) = Normal ((KValue ad, Value TAddr), g)" and"expr val ev cd (st0(gas := g)) g = Normal ((KValue gv, Value gt), g')" and"Valuetypes.convert gt (TUInt 256) gv = Some gv'" and"load True [] xe (ffold (init members) (emptyEnv ad cname (address ev) gv') (fmdom members)) emptyStore emptyStore emptyStore ev cd (st0(gas := g')) g' = Normal ((el, cdl, kl, ml), g'')" and"Accounts.transfer (address ev) ad gv' (accounts st0) = Some acc" and"iv (storage st0 ad) (ReadLint (bal (acc ad)) - ReadLint gv')" and"decl STR ''bal'' (Value (TUInt 256)) (Some (v, t)) False cdl ml (storage st0) (cdl, ml, kl, el) = Some (cd', mem', sck', e')" and"Valuetypes.convert ta t' va = Some v'" and"lexp myrexp e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := g'a)) g'a = Normal ((LStoreloc l, Storage (STValue t')), g''a)" and"expr mylval el cdl (st0(accounts := acc, stack := kl, memory := ml, gas := g'' - costs (BLOCK ((STR ''bal'', Value (TUInt 256)), Some mylval) (COMP (ASSIGN myrexp (UINT 256 0)) Reentrancy.transfer)) el cdl (st0(gas := g'', accounts := acc, stack := kl, memory := ml)))) (g'' - costs (BLOCK ((STR ''bal'', Value (TUInt 256)), Some mylval) (COMP (ASSIGN myrexp (UINT 256 0)) Reentrancy.transfer)) el cdl (st0(gas := g'', accounts := acc, stack := kl, memory := ml))) = Normal ((v, t), g''')" and"expr (UINT 256 0) e' cd' (st0(accounts := acc, stack := sck', memory := mem', gas := ga)) ga = Normal ((KValue va, Value ta), g'a)" shows"wpS (stmt Reentrancy.transfer e' cd') (λst. iv (storage st ad) (ReadLint (bal (accounts st ad)))) (λe. e = Gas ∨ e = Err) st'" proof (rule meta_eq_to_obj_eq[THEN iffD1, OF Pfe_def assms(2),rule_format], (rule conjI; (rule conjI)?)) show"address e' = ad" proof - have"address e' = address el"using decl_env[OF assms(12)] by simp alsohave"address el = address (ffold (init members) (emptyEnv ad cname (address ev) gv') (fmdom members))"using msel_ssel_expr_load_rexp_gas(4)[OF assms(9)] by simp alsohave"… = ad"unfolding emptyEnv_def using ffold_init_ad_same by simp finallyshow ?thesis . qed next show"∀adv g. expr SENDER e' cd' (st'(gas := gas st' - costs Reentrancy.transfer e' cd' st')) (gas st' - costs Reentrancy.transfer e' cd' st') = Normal ((KValue adv, Value TAddr), g) ⟶ adv ≠ ad" proof (intros) fix adv g assume"expr SENDER e' cd' (st'(gas := gas st' - costs Reentrancy.transfer e' cd' st')) (gas st' - costs Reentrancy.transfer e' cd' st') = Normal ((KValue adv, Value TAddr), g)" moreoverhave"sender e' ≠ ad" proof - have"sender e' = sender el"using decl_env[OF assms(12)] by simp alsohave"sender el = sender (ffold (init members) (emptyEnv ad cname (address ev) gv') (fmdom members))"using msel_ssel_expr_load_rexp_gas(4)[OF assms(9)] by simp alsohave"… = address ev"unfolding emptyEnv_def using ffold_init_ad_same by simp finallyshow ?thesis using assms(3) by simp qed ultimatelyshow"adv ≠ ad"by (simp add:expr.simps split:result.split_asm if_split_asm prod.split_asm) qed next show"∀adv g v t g' v'. local.expr SENDER e' cd' (st'(gas := gas st' - costs Reentrancy.transfer e' cd' st')) (gas st' - costs Reentrancy.transfer e' cd' st') = Normal ((KValue adv, Value TAddr), g) ∧ adv ≠ ad ∧ local.expr (LVAL (L.Id STR ''bal'')) e' cd' (st'(gas := g)) g = Normal ((KValue v, Value t), g') ∧ Valuetypes.convert t (TUInt 256) v = Some v' ⟶ iv (storage st' ad) (⌈bal (accounts st' ad)⌉ - ReadLint v')" proof elims fix adv lg lv lt lg' lv' assume a1:"expr SENDER e' cd' (st'(gas := gas st' - costs Reentrancy.transfer e' cd' st')) (gas st' - costs Reentrancy.transfer e' cd' st') = Normal ((KValue adv, Value TAddr), lg)" and adv_def: "adv ≠ ad" and bal: "expr (LVAL (L.Id STR ''bal'')) e' cd' (st'(gas := lg)) lg = Normal ((KValue lv, Value lt), lg')" and con: "Valuetypes.convert lt (TUInt 256) lv = Some lv'" show"iv (storage st' ad) (⌈bal (accounts st' ad)⌉ - ReadLint lv')" using adapt_withdraw[where ?acc=acc, OF assms(11) load_empty_par[OF assms(9)] assms(12,16,13,14,15,10) _ adv_def _] a1 bal con unfolding st'_defby simp qed qed
lemma wp_withdraw[external]: assumes"∧st'. gas st' ≤ gas st ∧ type (accounts st' ad) = Some (Contract cname) ==> Pe ad iv st' ∧ Pi ad (λ_ _. True) (λ_ _. True) st' ∧ Pfi ad (λ_. True) (λ_. True) st' ∧ Pfe ad iv st'" and"address ev ≠ ad" and"g'' ≤ gas st" and"type (acc ad) = Some (Contract cname)" and"expr adex ev cd (st0(gas := gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0)) (gas st0 - costs (EXTERNAL adex mid xe val) ev cd st0) = Normal ((KValue ad, Value TAddr), g)" and"expr val ev cd (st0(gas := g)) g = Normal ((KValue v, Value t), g')" and"Valuetypes.convert t (TUInt 256) v = Some v'" and"load True [] xe (ffold (init members) (emptyEnv ad cname (address ev) v') (fmdom members)) emptyStore emptyStore emptyStore ev cd (st0(gas := g')) g' = Normal ((el, cdl, kl, ml), g'')" and"Accounts.transfer (address ev) ad v' (accounts st0) = Some acc" and"iv (storage st0 ad) (ReadLint (bal (acc ad)) - ReadLint v')" shows"wpS (stmt keep el cdl) (λst. iv (storage st ad) (ReadLint (bal (accounts st ad)))) (λe. e = Gas ∨ e = Err) (st0(gas := g'', accounts := acc, stack := kl, memory := ml))" apply vcg_block_some apply vcg_comp apply (vcg_assign expr_rule: expr_0[OF assms(8)] lexp_rule: lexp_myrexp_decl[OF assms(8)]) apply (rule wptransfer[OF _ assms(2-10)]) apply (rule_tac assms(1)[THEN conjunct2,THEN conjunct2,THEN conjunct2]) using assms(3,4) by simp
lemma wp_fallback: assumes"Accounts.transfer (address ev) ad v (accounts st0) = Some acca" and"iv (storage st0 ad) (ReadLint (bal (acca ad)) - ReadLint v)" shows"wpS (stmt SKIP (ffold (init members) (emptyEnv ad cname (address ev) vc) (fmdom members)) emptyStore) (λst. iv (storage st ad) (ReadLint (bal (accounts st ad)))) (λe. e = Gas ∨ e = Err) (st0(gas := g'c, accounts := acca, stack := emptyStore, memory := emptyStore))" apply vcg_skip using weaken[where ?acc=acca, OF assms(2) transfer_val1[OF assms(1)]] by auto
lemma wp_construct: assumes"Accounts.transfer (address ev) (hash (address ev) ⌊contracts (accounts st (address ev))⌋) v ((accounts st) (hash (address ev) ⌊contracts (accounts st (address ev))⌋ := (bal = ShowLint 0, type = Some (Contract i), contracts = 0))) = Some acc" shows"iv fmempty ⌈bal (acc (hash (address ev) ⌊contracts (accounts st (address ev))⌋))⌉" proof -
define adv where"adv = (hash (address ev) ⌊contracts (accounts st (address ev))⌋)" moreoverhave"ReadLint (bal (((accounts st) (adv := (bal = ShowLint 0, type = Some (Contract i), contracts = 0))) adv)) = 0"using Read_ShowL_id[of 0] by simp ultimatelyhave"ReadLint (bal (acc (hash (address ev) ⌊contracts (accounts st (address ev))⌋))) ≥ 0"using transfer_mono[OF assms(1)] by simp thenshow ?thesis unfolding iv_def by simp qed
lemma wp_true[external]: assumes"E Gas" and"E Err" shows"wpS (stmt f e cd) (λst. True) E st" unfolding wpS_def wp_def proof ((split result.split, (split prod.split)?); rule conjI; (rule allI)+; (rule impI)+) fix x1 x1a s assume"x1 = (x1a, s)"and"stmt f e cd st = Normal x1" thenshow"gas s ≤ gas st ∧ True"using stmt_gas by simp next fix x2 assume"stmt f e cd st = Exception x2" show"E x2"using assms Ex.nchotomy by metis qed
subsubsection‹Final results›
interpretation vcg:VCG costse ep costs cname members const fb "λ_. True""λ_. True""λ_ _. True""λ_ _. True" by (simp add: VCG.intro Calculus_axioms)
theorem safe: assumes"∀ad. address ev ≠ ad ∧ type (accounts st ad) = Some (Contract cname) ⟶ iv (storage st ad) (ReadLint (bal (accounts st ad)))" shows"∀(st'::State) ad. stmt f ev cd st = Normal ((), st') ∧ type (accounts st' ad) = Some (Contract cname) ∧ address ev ≠ ad ⟶ iv (storage st' ad) (ReadLint (bal (accounts st' ad)))" apply (rule invariant) using assms safe_external safe_fallback safe_constructor by auto
end
end
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.23 Sekunden
(vorverarbeitet am 2026-06-10)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.