-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathTrustSurface.lean
More file actions
1415 lines (1309 loc) · 63.3 KB
/
TrustSurface.lean
File metadata and controls
1415 lines (1309 loc) · 63.3 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import Compiler.CompilationModel.Types
import Compiler.CompilationModel.EcmAxiomCollection
import Compiler.Json
import Compiler.ProofStatus
namespace Compiler.CompilationModel
open Compiler.Json
private def dedupPreserve (items : List String) : List String :=
items.foldl (fun acc item => if acc.contains item then acc else acc ++ [item]) []
private def dedupExternalFunctions (items : List ExternalFunction) : List ExternalFunction :=
items.foldl
(fun acc item => if acc.any (fun prev => prev.name = item.name) then acc else acc ++ [item])
[]
private def dedupLocalObligations (items : List LocalObligation) : List LocalObligation :=
items.foldl
(fun acc item => if acc.any (fun prev => prev.name = item.name) then acc else acc ++ [item])
[]
private def dedupEcmModules (items : List ECM.ExternalCallModule) : List ECM.ExternalCallModule :=
items.foldl (fun acc item => if acc.contains item then acc else acc ++ [item]) []
private partial def collectLowLevelExprMechanics : Expr → List String
| .intrinsic _ (.builtin "create2") _ args =>
["create2"] ++ args.flatMap collectLowLevelExprMechanics
| .intrinsic _ (.builtin "extcodecopy") _ args =>
["extcodecopy"] ++ args.flatMap collectLowLevelExprMechanics
| .intrinsic _ (.builtin "codecopy") _ args =>
["codecopy"] ++ args.flatMap collectLowLevelExprMechanics
| .intrinsic _ _ _ args =>
args.flatMap collectLowLevelExprMechanics
| .call gas target value inOffset inSize outOffset outSize =>
["call"] ++ collectLowLevelExprMechanics gas ++ collectLowLevelExprMechanics target ++
collectLowLevelExprMechanics value ++ collectLowLevelExprMechanics inOffset ++
collectLowLevelExprMechanics inSize ++ collectLowLevelExprMechanics outOffset ++
collectLowLevelExprMechanics outSize
| .staticcall gas target inOffset inSize outOffset outSize =>
["staticcall"] ++ collectLowLevelExprMechanics gas ++ collectLowLevelExprMechanics target ++
collectLowLevelExprMechanics inOffset ++ collectLowLevelExprMechanics inSize ++
collectLowLevelExprMechanics outOffset ++ collectLowLevelExprMechanics outSize
| .delegatecall gas target inOffset inSize outOffset outSize =>
["delegatecall"] ++ collectLowLevelExprMechanics gas ++ collectLowLevelExprMechanics target ++
collectLowLevelExprMechanics inOffset ++ collectLowLevelExprMechanics inSize ++
collectLowLevelExprMechanics outOffset ++ collectLowLevelExprMechanics outSize
| .returndataSize =>
["returndataSize"]
| .blobbasefee =>
["blobbasefee"]
| .tload offset =>
["tload"] ++ collectLowLevelExprMechanics offset
| .returndataOptionalBoolAt outOffset =>
["returndataOptionalBoolAt"] ++ collectLowLevelExprMechanics outOffset
| .mapping _ key
| .mappingWord _ key _
| .mappingPackedWord _ key _ _
| .structMember _ key _ =>
collectLowLevelExprMechanics key
| .mappingChain _ keys =>
keys.flatMap collectLowLevelExprMechanics
| .mapping2 _ key1 key2
| .mapping2Word _ key1 key2 _
| .structMember2 _ key1 key2 _ =>
collectLowLevelExprMechanics key1 ++ collectLowLevelExprMechanics key2
| .mappingUint _ key
| .storageArrayElement _ key
| .arrayElement _ key
| .memoryArrayElement _ key
| .arrayElementWord _ key _ _
| .arrayElementDynamicWord _ key _
| .arrayElementDynamicMemberLength _ key _ =>
collectLowLevelExprMechanics key
| .arrayElementDynamicMemberElement _ key _ innerKey =>
collectLowLevelExprMechanics key ++ collectLowLevelExprMechanics innerKey
| .mload key =>
["mload"] ++ collectLowLevelExprMechanics key
| .calldataload key =>
["calldataload"] ++ collectLowLevelExprMechanics key
| .extcodesize key =>
["extcodesize"] ++ collectLowLevelExprMechanics key
| .keccak256 offset size =>
collectLowLevelExprMechanics offset ++ collectLowLevelExprMechanics size
| .externalCall _ args
| .internalCall _ args =>
args.flatMap collectLowLevelExprMechanics
| .add a b | .sub a b | .mul a b | .div a b | .sdiv a b | .mod a b | .smod a b
| .bitAnd a b | .bitOr a b | .bitXor a b | .shl a b | .shr a b | .sar a b | .byte a b | .signextend a b
| .eq a b | .gt a b | .sgt a b | .lt a b | .slt a b | .ge a b | .le a b
| .logicalAnd a b | .logicalOr a b
| .wMulDown a b | .wDivUp a b | .min a b | .max a b | .ceilDiv a b =>
collectLowLevelExprMechanics a ++ collectLowLevelExprMechanics b
| .mulDivDown a b c | .mulDivUp a b c
| .mulDiv512Down a b c | .mulDiv512Up a b c =>
collectLowLevelExprMechanics a ++ collectLowLevelExprMechanics b ++ collectLowLevelExprMechanics c
| .bitNot a | .logicalNot a =>
collectLowLevelExprMechanics a
| .ite cond thenVal elseVal =>
collectLowLevelExprMechanics cond ++ collectLowLevelExprMechanics thenVal ++ collectLowLevelExprMechanics elseVal
| _ =>
[]
private partial def collectAxiomatizedExprPrimitives : Expr → List String
| .intrinsic _ _ _ args =>
args.flatMap collectAxiomatizedExprPrimitives
| .keccak256 offset size =>
["keccak256"] ++ collectAxiomatizedExprPrimitives offset ++ collectAxiomatizedExprPrimitives size
| .call gas target value inOffset inSize outOffset outSize =>
collectAxiomatizedExprPrimitives gas ++ collectAxiomatizedExprPrimitives target ++
collectAxiomatizedExprPrimitives value ++ collectAxiomatizedExprPrimitives inOffset ++
collectAxiomatizedExprPrimitives inSize ++ collectAxiomatizedExprPrimitives outOffset ++
collectAxiomatizedExprPrimitives outSize
| .staticcall gas target inOffset inSize outOffset outSize =>
collectAxiomatizedExprPrimitives gas ++ collectAxiomatizedExprPrimitives target ++
collectAxiomatizedExprPrimitives inOffset ++ collectAxiomatizedExprPrimitives inSize ++
collectAxiomatizedExprPrimitives outOffset ++ collectAxiomatizedExprPrimitives outSize
| .delegatecall gas target inOffset inSize outOffset outSize =>
collectAxiomatizedExprPrimitives gas ++ collectAxiomatizedExprPrimitives target ++
collectAxiomatizedExprPrimitives inOffset ++ collectAxiomatizedExprPrimitives inSize ++
collectAxiomatizedExprPrimitives outOffset ++ collectAxiomatizedExprPrimitives outSize
| .returndataOptionalBoolAt outOffset
| .mload outOffset
| .tload outOffset
| .calldataload outOffset
| .extcodesize outOffset =>
collectAxiomatizedExprPrimitives outOffset
| .mapping _ key
| .mappingWord _ key _
| .mappingPackedWord _ key _ _
| .structMember _ key _ =>
collectAxiomatizedExprPrimitives key
| .mappingChain _ keys =>
keys.flatMap collectAxiomatizedExprPrimitives
| .mapping2 _ key1 key2
| .mapping2Word _ key1 key2 _
| .structMember2 _ key1 key2 _ =>
collectAxiomatizedExprPrimitives key1 ++ collectAxiomatizedExprPrimitives key2
| .mappingUint _ key
| .storageArrayElement _ key
| .arrayElement _ key
| .memoryArrayElement _ key
| .arrayElementWord _ key _ _
| .arrayElementDynamicWord _ key _
| .arrayElementDynamicMemberLength _ key _ =>
collectAxiomatizedExprPrimitives key
| .arrayElementDynamicMemberElement _ key _ innerKey =>
collectAxiomatizedExprPrimitives key ++ collectAxiomatizedExprPrimitives innerKey
| .externalCall _ args
| .internalCall _ args =>
args.flatMap collectAxiomatizedExprPrimitives
| .add a b | .sub a b | .mul a b | .div a b | .sdiv a b | .mod a b | .smod a b
| .bitAnd a b | .bitOr a b | .bitXor a b | .shl a b | .shr a b | .sar a b | .byte a b | .signextend a b
| .eq a b | .gt a b | .sgt a b | .lt a b | .slt a b | .ge a b | .le a b
| .logicalAnd a b | .logicalOr a b
| .wMulDown a b | .wDivUp a b | .min a b | .max a b | .ceilDiv a b =>
collectAxiomatizedExprPrimitives a ++ collectAxiomatizedExprPrimitives b
| .mulDivDown a b c | .mulDivUp a b c
| .mulDiv512Down a b c | .mulDiv512Up a b c =>
collectAxiomatizedExprPrimitives a ++ collectAxiomatizedExprPrimitives b ++ collectAxiomatizedExprPrimitives c
| .bitNot a | .logicalNot a =>
collectAxiomatizedExprPrimitives a
| .ite cond thenVal elseVal =>
collectAxiomatizedExprPrimitives cond ++ collectAxiomatizedExprPrimitives thenVal ++
collectAxiomatizedExprPrimitives elseVal
| _ =>
[]
private def collectLowLevelMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve <|
Stmt.foldList
(fun acc _ md =>
acc ++ md.lowLevelMechanics.map LowLevelMechanic.toReportString ++
md.subexpressions.flatMap collectLowLevelExprMechanics)
[]
stmts
private def collectAxiomatizedPrimitivesFromStmts (stmts : List Stmt) : List String :=
dedupPreserve <|
Stmt.foldList
(fun acc _ md => acc ++ md.subexpressions.flatMap collectAxiomatizedExprPrimitives)
[]
stmts
private def isUnsafeBoundaryMechanic (mechanic : String) : Bool :=
match mechanic with
| "call" | "staticcall" | "delegatecall"
| "returndataSize" | "returndataCopy" | "revertReturndata" | "returndataOptionalBoolAt"
| "mload" | "mstore" | "calldataload" | "calldatacopy" | "codecopy"
| "extcodesize" | "extcodecopy" | "create2" | "tload" | "tstore" => true
| _ => false
/-- Collect assembly-shaped low-level mechanics that require an explicit local obligation. -/
def collectUnsafeBoundaryMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve ((collectLowLevelMechanicsFromStmts stmts).filter isUnsafeBoundaryMechanic)
/-- Like `collectLowLevelMechanicsFromStmts` but skips `unsafeBlock` bodies —
returns only mechanics that appear *outside* any `unsafe` wrapper. -/
private partial def collectUnguardedLowLevelStmtMechanics : Stmt → List String
| .letVar _ value
| .assignVar _ value
| .setStorage _ value
| .setStorageAddr _ value
| .setStorageWord _ _ value
| .storageArrayPush _ value
| .return value
| .require value _ =>
collectLowLevelExprMechanics value
| .setStorageArrayElement _ index value =>
collectLowLevelExprMechanics index ++ collectLowLevelExprMechanics value
| .storageArrayPop _ =>
[]
| .requireError cond _ args =>
collectLowLevelExprMechanics cond ++ args.flatMap collectLowLevelExprMechanics
| .revertError _ args =>
args.flatMap collectLowLevelExprMechanics
| .mstore offset value =>
["mstore"] ++ collectLowLevelExprMechanics offset ++ collectLowLevelExprMechanics value
| .tstore offset value =>
["tstore"] ++ collectLowLevelExprMechanics offset ++ collectLowLevelExprMechanics value
| .calldatacopy destOffset sourceOffset size =>
["calldatacopy"] ++ collectLowLevelExprMechanics destOffset ++
collectLowLevelExprMechanics sourceOffset ++ collectLowLevelExprMechanics size
| .returndataCopy destOffset sourceOffset size =>
["returndataCopy"] ++ collectLowLevelExprMechanics destOffset ++ collectLowLevelExprMechanics sourceOffset ++ collectLowLevelExprMechanics size
| .revertReturndata =>
["revertReturndata"]
| .setMapping _ key value
| .setMappingWord _ key _ value
| .setMappingPackedWord _ key _ _ value
| .setMappingUint _ key value
| .setStructMember _ key _ value =>
collectLowLevelExprMechanics key ++ collectLowLevelExprMechanics value
| .setMappingChain _ keys value =>
keys.flatMap collectLowLevelExprMechanics ++ collectLowLevelExprMechanics value
| .setMapping2 _ key1 key2 value
| .setMapping2Word _ key1 key2 _ value
| .setStructMember2 _ key1 key2 _ value =>
collectLowLevelExprMechanics key1 ++ collectLowLevelExprMechanics key2 ++ collectLowLevelExprMechanics value
| .ite cond thenBr elseBr =>
collectLowLevelExprMechanics cond ++ thenBr.flatMap collectUnguardedLowLevelStmtMechanics ++ elseBr.flatMap collectUnguardedLowLevelStmtMechanics
| .forEach _ count body =>
collectLowLevelExprMechanics count ++ body.flatMap collectUnguardedLowLevelStmtMechanics
| .unsafeBlock _ _ =>
[]
| .matchAdt _ scrutinee branches =>
collectLowLevelExprMechanics scrutinee ++
branches.flatMap fun (_, _, body) => body.flatMap collectUnguardedLowLevelStmtMechanics
| .emit _ args
| .internalCall _ args
| .externalCallBind _ _ args | .tryExternalCallBind _ _ _ args
| .returnValues args
| .ecm _ args
| .internalCallAssign _ _ args =>
args.flatMap collectLowLevelExprMechanics
| .rawLog topics dataOffset dataSize =>
topics.flatMap collectLowLevelExprMechanics ++ collectLowLevelExprMechanics dataOffset ++ collectLowLevelExprMechanics dataSize
| .unsafeYul _ =>
[]
| .returnArray _
| .returnBytes _
| .returnStorageWords _
| .stop =>
[]
private def collectUnguardedLowLevelMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve (stmts.flatMap collectUnguardedLowLevelStmtMechanics)
/-- Collect unsafe boundary mechanics that appear *outside* any `unsafe "reason" do` block.
Operations inside `unsafe` blocks are considered documented and do not require
`local_obligations`. -/
def collectUnguardedUnsafeBoundaryMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve ((collectUnguardedLowLevelMechanicsFromStmts stmts).filter isUnsafeBoundaryMechanic)
private def collectUnsafeBlockReasonsFromStmts (stmts : List Stmt) : List String :=
Stmt.foldList (fun acc _ md => acc ++ md.unsafeReasons) [] stmts
/-- Collect all `unsafe "reason" do` block reasons used by a spec. -/
def collectUnsafeBlockReasons (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectUnsafeBlockReasonsFromStmts allStmts
private def isLinearMemoryMechanic (mechanic : String) : Bool :=
match mechanic with
| "mload" | "mstore" | "calldatacopy" | "codecopy" | "extcodecopy"
| "returndataCopy" | "returndataOptionalBoolAt" => true
| _ => false
private def collectLinearMemoryMechanicsFromMechanics (mechanics : List String) : List String :=
dedupPreserve (mechanics.filter isLinearMemoryMechanic)
private def isProxyUpgradeabilityMechanic (mechanic : String) : Bool :=
match mechanic with
| "delegatecall" => true
| _ => false
private def collectProxyUpgradeabilityMechanicsFromMechanics (mechanics : List String) : List String :=
dedupPreserve (mechanics.filter isProxyUpgradeabilityMechanic)
private partial def collectEventEmissionExprMechanics : Expr → List String
| .externalCall _ args
| .internalCall _ args =>
args.flatMap collectEventEmissionExprMechanics
| .call gas target value inOffset inSize outOffset outSize =>
collectEventEmissionExprMechanics gas ++ collectEventEmissionExprMechanics target ++
collectEventEmissionExprMechanics value ++ collectEventEmissionExprMechanics inOffset ++
collectEventEmissionExprMechanics inSize ++ collectEventEmissionExprMechanics outOffset ++
collectEventEmissionExprMechanics outSize
| .staticcall gas target inOffset inSize outOffset outSize
| .delegatecall gas target inOffset inSize outOffset outSize =>
collectEventEmissionExprMechanics gas ++ collectEventEmissionExprMechanics target ++
collectEventEmissionExprMechanics inOffset ++ collectEventEmissionExprMechanics inSize ++
collectEventEmissionExprMechanics outOffset ++ collectEventEmissionExprMechanics outSize
| .returndataOptionalBoolAt outOffset
| .mload outOffset
| .tload outOffset
| .calldataload outOffset
| .extcodesize outOffset =>
collectEventEmissionExprMechanics outOffset
| .keccak256 offset size =>
collectEventEmissionExprMechanics offset ++ collectEventEmissionExprMechanics size
| .mapping _ key
| .mappingWord _ key _
| .mappingPackedWord _ key _ _
| .structMember _ key _ =>
collectEventEmissionExprMechanics key
| .mapping2 _ key1 key2
| .mapping2Word _ key1 key2 _
| .structMember2 _ key1 key2 _ =>
collectEventEmissionExprMechanics key1 ++ collectEventEmissionExprMechanics key2
| .mappingChain _ keys =>
keys.flatMap collectEventEmissionExprMechanics
| .mappingUint _ key
| .arrayElement _ key
| .memoryArrayElement _ key
| .arrayElementWord _ key _ _
| .arrayElementDynamicWord _ key _
| .arrayElementDynamicMemberLength _ key _ =>
collectEventEmissionExprMechanics key
| .arrayElementDynamicMemberElement _ key _ innerKey =>
collectEventEmissionExprMechanics key ++ collectEventEmissionExprMechanics innerKey
| .add a b | .sub a b | .mul a b | .div a b | .sdiv a b | .mod a b | .smod a b
| .bitAnd a b | .bitOr a b | .bitXor a b | .shl a b | .shr a b | .sar a b | .byte a b | .signextend a b
| .eq a b | .gt a b | .sgt a b | .lt a b | .slt a b | .ge a b | .le a b
| .logicalAnd a b | .logicalOr a b
| .wMulDown a b | .wDivUp a b | .min a b | .max a b | .ceilDiv a b =>
collectEventEmissionExprMechanics a ++ collectEventEmissionExprMechanics b
| .mulDivDown a b c | .mulDivUp a b c
| .mulDiv512Down a b c | .mulDiv512Up a b c =>
collectEventEmissionExprMechanics a ++ collectEventEmissionExprMechanics b ++
collectEventEmissionExprMechanics c
| .bitNot a | .logicalNot a =>
collectEventEmissionExprMechanics a
| .ite cond thenVal elseVal =>
collectEventEmissionExprMechanics cond ++ collectEventEmissionExprMechanics thenVal ++
collectEventEmissionExprMechanics elseVal
| _ =>
[]
private def collectEventEmissionMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve <|
Stmt.foldList
(fun acc stmt md =>
let direct :=
match stmt with
| .rawLog _ _ _ => ["rawLog"]
| .unsafeYul fragment => if fragment.mechanics.contains .rawLog then ["rawLog"] else []
| _ => []
acc ++ direct ++ md.subexpressions.flatMap collectEventEmissionExprMechanics)
[]
stmts
/-- Collect not-modeled raw event-emission mechanics used by a spec. -/
def collectEventEmissionMechanics (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectEventEmissionMechanicsFromStmts allStmts
private def isDeniedLowLevelMechanic (mechanic : String) : Bool :=
match mechanic with
| "call" | "staticcall" | "delegatecall" | "create2" | "returndataSize" | "returndataCopy"
| "revertReturndata" | "rawRevert" | "returndataOptionalBoolAt" | "blobbasefee" => true
| _ => false
private def collectDeniedLowLevelMechanicsFromMechanics (mechanics : List String) : List String :=
dedupPreserve (mechanics.filter isDeniedLowLevelMechanic)
/-- Collect unique low-level call and returndata mechanics used by a spec. -/
def collectLowLevelMechanics (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectLowLevelMechanicsFromStmts allStmts
/-- Collect partially modeled linear-memory mechanics used by a spec. -/
def collectLinearMemoryMechanics (spec : CompilationModel) : List String :=
collectLinearMemoryMechanicsFromMechanics (collectLowLevelMechanics spec)
/-- Collect not-modeled proxy / upgradeability mechanics used by a spec. -/
def collectProxyUpgradeabilityMechanics (spec : CompilationModel) : List String :=
collectProxyUpgradeabilityMechanicsFromMechanics (collectLowLevelMechanics spec)
private partial def collectRuntimeIntrospectionExprMechanics : Expr → List String
| .contractAddress => ["contractAddress"]
| .chainid => ["chainid"]
| .selfBalance => ["selfBalance"]
| .blockNumber => ["blockNumber"]
| .blobbasefee => ["blobbasefee"]
| .externalCall _ args
| .internalCall _ args =>
args.flatMap collectRuntimeIntrospectionExprMechanics
| .call gas target value inOffset inSize outOffset outSize =>
collectRuntimeIntrospectionExprMechanics gas ++ collectRuntimeIntrospectionExprMechanics target ++
collectRuntimeIntrospectionExprMechanics value ++ collectRuntimeIntrospectionExprMechanics inOffset ++
collectRuntimeIntrospectionExprMechanics inSize ++ collectRuntimeIntrospectionExprMechanics outOffset ++
collectRuntimeIntrospectionExprMechanics outSize
| .staticcall gas target inOffset inSize outOffset outSize
| .delegatecall gas target inOffset inSize outOffset outSize =>
collectRuntimeIntrospectionExprMechanics gas ++ collectRuntimeIntrospectionExprMechanics target ++
collectRuntimeIntrospectionExprMechanics inOffset ++ collectRuntimeIntrospectionExprMechanics inSize ++
collectRuntimeIntrospectionExprMechanics outOffset ++ collectRuntimeIntrospectionExprMechanics outSize
| .returndataOptionalBoolAt outOffset
| .mload outOffset
| .tload outOffset
| .calldataload outOffset
| .extcodesize outOffset =>
collectRuntimeIntrospectionExprMechanics outOffset
| .keccak256 offset size =>
collectRuntimeIntrospectionExprMechanics offset ++ collectRuntimeIntrospectionExprMechanics size
| .mapping _ key
| .mappingWord _ key _
| .mappingPackedWord _ key _ _
| .structMember _ key _ =>
collectRuntimeIntrospectionExprMechanics key
| .mapping2 _ key1 key2
| .mapping2Word _ key1 key2 _
| .structMember2 _ key1 key2 _ =>
collectRuntimeIntrospectionExprMechanics key1 ++ collectRuntimeIntrospectionExprMechanics key2
| .mappingChain _ keys =>
keys.flatMap collectRuntimeIntrospectionExprMechanics
| .mappingUint _ key
| .arrayElement _ key
| .memoryArrayElement _ key
| .arrayElementWord _ key _ _
| .arrayElementDynamicWord _ key _
| .arrayElementDynamicMemberLength _ key _ =>
collectRuntimeIntrospectionExprMechanics key
| .arrayElementDynamicMemberElement _ key _ innerKey =>
collectRuntimeIntrospectionExprMechanics key ++ collectRuntimeIntrospectionExprMechanics innerKey
| .add a b | .sub a b | .mul a b | .div a b | .sdiv a b | .mod a b | .smod a b
| .bitAnd a b | .bitOr a b | .bitXor a b | .shl a b | .shr a b | .sar a b | .byte a b | .signextend a b
| .eq a b | .gt a b | .sgt a b | .lt a b | .slt a b | .ge a b | .le a b
| .logicalAnd a b | .logicalOr a b
| .wMulDown a b | .wDivUp a b | .min a b | .max a b | .ceilDiv a b =>
collectRuntimeIntrospectionExprMechanics a ++ collectRuntimeIntrospectionExprMechanics b
| .mulDivDown a b c | .mulDivUp a b c
| .mulDiv512Down a b c | .mulDiv512Up a b c =>
collectRuntimeIntrospectionExprMechanics a ++ collectRuntimeIntrospectionExprMechanics b ++
collectRuntimeIntrospectionExprMechanics c
| .bitNot a | .logicalNot a =>
collectRuntimeIntrospectionExprMechanics a
| .ite cond thenVal elseVal =>
collectRuntimeIntrospectionExprMechanics cond ++ collectRuntimeIntrospectionExprMechanics thenVal ++
collectRuntimeIntrospectionExprMechanics elseVal
| _ =>
[]
private def collectRuntimeIntrospectionMechanicsFromStmts (stmts : List Stmt) : List String :=
dedupPreserve <|
Stmt.foldList
(fun acc stmt md =>
let direct :=
match stmt with
| .unsafeYul fragment =>
fragment.mechanics.filterMap (fun mechanic =>
if mechanic == .contractAddress || mechanic == .chainid ||
mechanic == .selfBalance || mechanic == .blockNumber ||
mechanic == .blobbasefee then
some mechanic.toReportString
else
none)
| _ => []
acc ++ direct ++ md.subexpressions.flatMap collectRuntimeIntrospectionExprMechanics)
[]
stmts
/-- Collect partially modeled runtime-introspection mechanics used by a spec. -/
def collectRuntimeIntrospectionMechanics (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectRuntimeIntrospectionMechanicsFromStmts allStmts
/-- Collect unique axiomatized primitives used directly by a spec. -/
def collectAxiomatizedPrimitives (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectAxiomatizedPrimitivesFromStmts allStmts
private def collectAxiomatizedPrimitivesByStatus
(spec : CompilationModel)
(status : Compiler.ProofStatus) : List String :=
match status with
| .proved => []
| .assumed => collectAxiomatizedPrimitives spec
| .unchecked => []
private partial def collectExternalExprNames : Expr → List String
| .externalCall name args =>
if name == builtinExpName then
args.flatMap collectExternalExprNames
else
name :: args.flatMap collectExternalExprNames
| .call gas target value inOffset inSize outOffset outSize =>
collectExternalExprNames gas ++ collectExternalExprNames target ++ collectExternalExprNames value ++
collectExternalExprNames inOffset ++ collectExternalExprNames inSize ++
collectExternalExprNames outOffset ++ collectExternalExprNames outSize
| .staticcall gas target inOffset inSize outOffset outSize
| .delegatecall gas target inOffset inSize outOffset outSize =>
collectExternalExprNames gas ++ collectExternalExprNames target ++ collectExternalExprNames inOffset ++
collectExternalExprNames inSize ++ collectExternalExprNames outOffset ++ collectExternalExprNames outSize
| .returndataOptionalBoolAt outOffset
| .mload outOffset
| .tload outOffset
| .calldataload outOffset
| .extcodesize outOffset =>
collectExternalExprNames outOffset
| .keccak256 offset size =>
collectExternalExprNames offset ++ collectExternalExprNames size
| .mapping _ key
| .mappingWord _ key _
| .mappingPackedWord _ key _ _
| .structMember _ key _ =>
collectExternalExprNames key
| .mapping2 _ key1 key2
| .mapping2Word _ key1 key2 _
| .structMember2 _ key1 key2 _ =>
collectExternalExprNames key1 ++ collectExternalExprNames key2
| .mappingChain _ keys =>
keys.flatMap collectExternalExprNames
| .mappingUint _ key
| .arrayElement _ key
| .memoryArrayElement _ key
| .arrayElementWord _ key _ _
| .arrayElementDynamicWord _ key _
| .arrayElementDynamicMemberLength _ key _ =>
collectExternalExprNames key
| .arrayElementDynamicMemberElement _ key _ innerKey =>
collectExternalExprNames key ++ collectExternalExprNames innerKey
| .internalCall _ args =>
args.flatMap collectExternalExprNames
| .add a b | .sub a b | .mul a b | .div a b | .sdiv a b | .mod a b | .smod a b
| .bitAnd a b | .bitOr a b | .bitXor a b | .shl a b | .shr a b | .sar a b | .byte a b | .signextend a b
| .eq a b | .gt a b | .sgt a b | .lt a b | .slt a b | .ge a b | .le a b
| .logicalAnd a b | .logicalOr a b
| .wMulDown a b | .wDivUp a b | .min a b | .max a b | .ceilDiv a b =>
collectExternalExprNames a ++ collectExternalExprNames b
| .mulDivDown a b c | .mulDivUp a b c
| .mulDiv512Down a b c | .mulDiv512Up a b c =>
collectExternalExprNames a ++ collectExternalExprNames b ++ collectExternalExprNames c
| .bitNot a | .logicalNot a =>
collectExternalExprNames a
| .ite cond thenVal elseVal =>
collectExternalExprNames cond ++ collectExternalExprNames thenVal ++ collectExternalExprNames elseVal
| _ =>
[]
private def arrayElementWordLowLevelIndexSmoke : Expr :=
Expr.arrayElementWord "cuts"
(Expr.call (Expr.literal 5000) (Expr.literal 1) (Expr.literal 0)
(Expr.literal 0) (Expr.literal 0) (Expr.literal 0) (Expr.literal 32))
3 1
private def arrayElementWordAxiomatizedIndexSmoke : Expr :=
Expr.arrayElementWord "cuts" (Expr.keccak256 (Expr.literal 0) (Expr.literal 64)) 3 1
private def arrayElementWordRuntimeIndexSmoke : Expr :=
Expr.arrayElementWord "cuts" Expr.blockNumber 3 1
private def arrayElementWordExternalIndexSmoke : Expr :=
Expr.arrayElementWord "cuts" (Expr.externalCall "oracle" []) 3 1
example : collectLowLevelExprMechanics arrayElementWordLowLevelIndexSmoke = ["call"] := by
native_decide
example : collectAxiomatizedExprPrimitives arrayElementWordAxiomatizedIndexSmoke = ["keccak256"] := by
native_decide
example : collectRuntimeIntrospectionExprMechanics arrayElementWordRuntimeIndexSmoke = ["blockNumber"] := by
native_decide
example : collectExternalExprNames arrayElementWordExternalIndexSmoke = ["oracle"] := by
native_decide
private def stmtAxiomatizedArgSmoke : Stmt :=
Stmt.mstore (Expr.keccak256 (Expr.literal 0) (Expr.literal 64)) (Expr.literal 32)
private def stmtRuntimeArgSmoke : Stmt :=
Stmt.mstore Expr.blockNumber (Expr.literal 32)
private def stmtExternalArgSmoke : Stmt :=
Stmt.mstore (Expr.externalCall "oracle" []) (Expr.literal 32)
example : collectAxiomatizedPrimitivesFromStmts [stmtAxiomatizedArgSmoke] = ["keccak256"] := by
native_decide
example : collectRuntimeIntrospectionMechanicsFromStmts [stmtRuntimeArgSmoke] = ["blockNumber"] := by
native_decide
private def collectUsedExternalNamesFromStmts (stmts : List Stmt) : List String :=
dedupPreserve <|
Stmt.foldList
(fun acc stmt md =>
let direct :=
match stmt with
| .externalCallBind _ externalName _ => [externalName]
| .tryExternalCallBind _ _ externalName _ => [externalName]
| _ => []
acc ++ direct ++ md.subexpressions.flatMap collectExternalExprNames)
[]
stmts
private def collectUsedExternalAssumptionsFromStmts
(externals : List ExternalFunction)
(stmts : List Stmt) : List ExternalFunction :=
let usedNames := collectUsedExternalNamesFromStmts stmts
dedupExternalFunctions (externals.filter (fun ext => usedNames.contains ext.name))
private def collectUsedExternalNames (spec : CompilationModel) : List String :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectUsedExternalNamesFromStmts allStmts
/-- Collect linked external declarations that are actually referenced by the spec. -/
def collectUsedExternalAssumptions (spec : CompilationModel) : List ExternalFunction :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectUsedExternalAssumptionsFromStmts spec.externals allStmts
private def collectUsedExternalNamesByStatus
(spec : CompilationModel)
(status : Compiler.ProofStatus) : List String :=
(collectUsedExternalAssumptions spec).foldl
(fun acc ext => if ext.proofStatus == status then acc ++ [ext.name] else acc)
[]
example : collectUsedExternalNamesFromStmts [stmtExternalArgSmoke] = ["oracle"] := by
native_decide
private def collectUsedEcmModulesFromStmts (stmts : List Stmt) : List ECM.ExternalCallModule :=
dedupEcmModules <|
Stmt.foldList
(fun acc stmt _ =>
match stmt with
| .ecm mod _ => acc ++ [mod]
| _ => acc)
[]
stmts
/-- Collect ECM modules that are actually referenced by the spec, including
constructor bodies. This shared view keeps machine-readable reports and
compiler summaries aligned. -/
def collectUsedEcmModules (spec : CompilationModel) : List ECM.ExternalCallModule :=
let stmtsFromFn (fn : FunctionSpec) := fn.body
let stmtsFromCtor : List Stmt := match spec.constructor with
| some ctor => ctor.body
| none => []
let allStmts := stmtsFromCtor ++ spec.functions.flatMap stmtsFromFn
collectUsedEcmModulesFromStmts allStmts
private def collectUsedEcmModuleNamesByStatus
(spec : CompilationModel)
(status : Compiler.ProofStatus) : List String :=
(collectUsedEcmModules spec).foldl
(fun acc mod => if mod.proofStatus == status then acc ++ [mod.name] else acc)
[]
private def collectLocalObligationsFromStmts
(obligations : List LocalObligation)
(stmts : List Stmt) : List LocalObligation :=
dedupLocalObligations
(obligations ++ Stmt.foldList (fun acc _ md => acc ++ md.localObligations) [] stmts)
private def collectConstructorLocalObligations (spec : CompilationModel) : List LocalObligation :=
match spec.constructor with
| some ctor => ctor.localObligations
| none => []
/-- Collect local proof obligations attached to functions/constructors. -/
def collectLocalObligations (spec : CompilationModel) : List LocalObligation :=
let ctorObligations :=
match spec.constructor with
| some ctor => collectLocalObligationsFromStmts ctor.localObligations ctor.body
| none => []
let functionObligations :=
spec.functions.flatMap fun fn => collectLocalObligationsFromStmts fn.localObligations fn.body
dedupLocalObligations (ctorObligations ++ functionObligations)
private def collectUnsafeYulContractsFromStmts (stmts : List Stmt) : List UnsafeYulContract :=
Stmt.foldList (fun acc _ md => acc ++ md.unsafeYulContracts) [] stmts
private def collectLocalObligationNamesByStatus
(spec : CompilationModel)
(status : Compiler.ProofStatus) : List String :=
(collectLocalObligations spec).foldl
(fun acc obligation =>
if obligation.proofStatus == status then acc ++ [obligation.name] else acc)
[]
private def proofStatusString (status : Compiler.ProofStatus) : String :=
jsonString status.toJsonString
private def assumptionJson (entry : ExternalFunction) : String :=
jsonObject [
("name", jsonString entry.name),
("status", proofStatusString entry.proofStatus),
("linkMode", jsonString entry.linkMode.toJsonString),
("axioms", jsonArray (entry.axiomNames.map jsonString))
]
/-- Stable machine-readable assumption name for a trusted primitive boundary. -/
def primitiveAssumptionName (primitive : String) : String :=
match primitive with
| "keccak256" => "keccak256_memory_slice_matches_evm"
| other => s!"{other}_assumed"
private def primitiveAssumptionJson (primitive : String) : String :=
jsonObject [
("primitive", jsonString primitive),
("status", proofStatusString .assumed),
("assumption", jsonString (primitiveAssumptionName primitive))
]
private def ecmJson (entry : String × String) : String :=
jsonObject [
("module", jsonString entry.1),
("assumption", jsonString entry.2)
]
private def ecmModuleJson (entry : ECM.ExternalCallModule) : String :=
jsonObject [
("module", jsonString entry.name),
("status", proofStatusString entry.proofStatus),
("axioms", jsonArray (entry.axioms.map jsonString))
]
private def frameSpecJson (frame : FrameSpec) : String :=
jsonObject [
("localReads", jsonArray (frame.localReads.map jsonString)),
("localWrites", jsonArray (frame.localWrites.map jsonString)),
("memoryReads", jsonArray (frame.memoryReads.map jsonString)),
("memoryWrites", jsonArray (frame.memoryWrites.map jsonString)),
("storageReads", jsonArray (frame.storageReads.map jsonString)),
("storageWrites", jsonArray (frame.storageWrites.map jsonString)),
("transientReads", jsonArray (frame.transientReads.map jsonString)),
("transientWrites", jsonArray (frame.transientWrites.map jsonString))
]
private def unsafeYulContractJson (contract : UnsafeYulContract) : String :=
jsonObject [
("name", jsonString contract.name),
("summary", jsonString contract.summary),
("frame", frameSpecJson contract.frame)
]
private def localObligationJson (entry : LocalObligation) : String :=
jsonObject [
("name", jsonString entry.name),
("status", proofStatusString entry.proofStatus),
("obligation", jsonString entry.obligation)
]
private structure AssumptionReportEntry where
category : String
siteKind : String
siteName : String
name : String
status : ProofStatus
detail : String := ""
assumption : String := ""
linkMode : String := ""
moduleName : String := ""
axioms : List String := []
private def assumptionReportEntryJson (entry : AssumptionReportEntry) : String :=
jsonObject [
("category", jsonString entry.category),
("siteKind", jsonString entry.siteKind),
("siteName", jsonString entry.siteName),
("name", jsonString entry.name),
("status", proofStatusString entry.status),
("detail", jsonString entry.detail),
("assumption", jsonString entry.assumption),
("linkMode", jsonString entry.linkMode),
("module", jsonString entry.moduleName),
("axioms", jsonArray (entry.axioms.map jsonString))
]
private def proofStatusBucketJson
(primitives externals modules localObligations : List String) : String :=
jsonObject [
("axiomatizedPrimitives", jsonArray (primitives.map jsonString)),
("linkedExternals", jsonArray (externals.map jsonString)),
("ecmModules", jsonArray (modules.map jsonString)),
("localObligations", jsonArray (localObligations.map jsonString))
]
private def proofStatusJson (spec : CompilationModel) : String :=
jsonObject [
("proved", proofStatusBucketJson
(collectAxiomatizedPrimitivesByStatus spec .proved)
(collectUsedExternalNamesByStatus spec .proved)
(collectUsedEcmModuleNamesByStatus spec .proved)
(collectLocalObligationNamesByStatus spec .proved)),
("assumed", proofStatusBucketJson
(collectAxiomatizedPrimitivesByStatus spec .assumed)
(collectUsedExternalNamesByStatus spec .assumed)
(collectUsedEcmModuleNamesByStatus spec .assumed)
(collectLocalObligationNamesByStatus spec .assumed)),
("unchecked", proofStatusBucketJson
(collectAxiomatizedPrimitivesByStatus spec .unchecked)
(collectUsedExternalNamesByStatus spec .unchecked)
(collectUsedEcmModuleNamesByStatus spec .unchecked)
(collectLocalObligationNamesByStatus spec .unchecked))
]
private def proofStatusBucketJsonForSite
(primitives : List String)
(externals : List ExternalFunction)
(modules : List ECM.ExternalCallModule)
(localObligations : List LocalObligation)
(status : Compiler.ProofStatus) : String :=
let primitiveBucket :=
if status == .assumed then primitives.map jsonString else []
let externalBucket :=
(externals.filter (fun ext => ext.proofStatus == status)).map (fun ext => jsonString ext.name)
let moduleBucket :=
(modules.filter (fun mod => mod.proofStatus == status)).map (fun mod => jsonString mod.name)
let localObligationBucket :=
(localObligations.filter (fun obligation => obligation.proofStatus == status)).map
(fun obligation => jsonString obligation.name)
proofStatusBucketJson primitiveBucket externalBucket moduleBucket localObligationBucket
private def proofStatusJsonForSite
(primitives : List String)
(externals : List ExternalFunction)
(modules : List ECM.ExternalCallModule)
(localObligations : List LocalObligation) : String :=
jsonObject [
("proved", proofStatusBucketJsonForSite primitives externals modules localObligations .proved),
("assumed", proofStatusBucketJsonForSite primitives externals modules localObligations .assumed),
("unchecked", proofStatusBucketJsonForSite primitives externals modules localObligations .unchecked)
]
private def hasUncheckedDependenciesForSite
(externals : List ExternalFunction)
(modules : List ECM.ExternalCallModule) : Bool :=
externals.any (fun ext => ext.proofStatus == .unchecked) ||
modules.any (fun mod => mod.proofStatus == .unchecked)
private def hasDependenciesForStatusesForSite
(statuses : List Compiler.ProofStatus)
(externals : List ExternalFunction)
(modules : List ECM.ExternalCallModule) : Bool :=
externals.any (fun ext => statuses.contains ext.proofStatus) ||
modules.any (fun mod => statuses.contains mod.proofStatus)
private structure UsageSiteSummary where
kind : String
name : String
mechanics : List String
eventEmission : List String
proxyUpgradeability : List String
runtimeIntrospection : List String
primitives : List String
externals : List ExternalFunction
modules : List ECM.ExternalCallModule
localObligations : List LocalObligation
unsafeYulContracts : List UnsafeYulContract
unsafeBlocks : List String
private def ecmAxiomsFromModules (modules : List ECM.ExternalCallModule) : List (String × String) :=
modules.flatMap (fun mod => mod.axioms.map (fun assumption => (mod.name, assumption)))
private def siteHasTrustSurface
(externals : List ExternalFunction)
(localObligations : List LocalObligation)
(stmts : List Stmt) : Bool :=
!(collectLowLevelMechanicsFromStmts stmts).isEmpty ||
!(collectEventEmissionMechanicsFromStmts stmts).isEmpty ||
!(collectProxyUpgradeabilityMechanicsFromMechanics (collectLowLevelMechanicsFromStmts stmts)).isEmpty ||
!(collectRuntimeIntrospectionMechanicsFromStmts stmts).isEmpty ||
!(collectAxiomatizedPrimitivesFromStmts stmts).isEmpty ||
!(collectUsedExternalAssumptionsFromStmts externals stmts).isEmpty ||
!(collectUsedEcmModulesFromStmts stmts).isEmpty ||
!(collectLocalObligationsFromStmts localObligations stmts).isEmpty ||
!(collectUnsafeYulContractsFromStmts stmts).isEmpty ||
!(collectUnsafeBlockReasonsFromStmts stmts).isEmpty
private def usageSiteSummary
(spec : CompilationModel)
(kind name : String)
(localObligations : List LocalObligation)
(stmts : List Stmt) :
UsageSiteSummary :=
let mechanics := collectLowLevelMechanicsFromStmts stmts
let eventEmission := collectEventEmissionMechanicsFromStmts stmts
let proxyUpgradeability := collectProxyUpgradeabilityMechanicsFromMechanics mechanics
let runtimeIntrospection := collectRuntimeIntrospectionMechanicsFromStmts stmts
let primitives := collectAxiomatizedPrimitivesFromStmts stmts
let siteExternals := collectUsedExternalAssumptionsFromStmts spec.externals stmts
let siteModules := collectUsedEcmModulesFromStmts stmts
let siteLocalObligations := collectLocalObligationsFromStmts localObligations stmts
let siteUnsafeYulContracts := collectUnsafeYulContractsFromStmts stmts
let siteUnsafeBlocks := collectUnsafeBlockReasonsFromStmts stmts
{ kind := kind
name := name
mechanics := mechanics
eventEmission := eventEmission
proxyUpgradeability := proxyUpgradeability
runtimeIntrospection := runtimeIntrospection
primitives := primitives
externals := siteExternals
modules := siteModules
localObligations := siteLocalObligations
unsafeYulContracts := siteUnsafeYulContracts
unsafeBlocks := siteUnsafeBlocks }
private def collectUsageSiteSummaries (spec : CompilationModel) : List UsageSiteSummary :=
let constructorSites :=
match spec.constructor with
| some ctor =>
if siteHasTrustSurface spec.externals ctor.localObligations ctor.body then
[usageSiteSummary spec "constructor" "constructor" ctor.localObligations ctor.body]
else
[]
| none => []
let functionSites :=
spec.functions.foldl
(fun acc fn =>
if siteHasTrustSurface spec.externals fn.localObligations fn.body then
acc ++ [usageSiteSummary spec "function" fn.name fn.localObligations fn.body]
else
acc)
[]
constructorSites ++ functionSites
private def usageSitesJson (spec : CompilationModel) : String :=
let siteJson (site : UsageSiteSummary) : String :=
let linearMemoryMechanics := collectLinearMemoryMechanicsFromMechanics site.mechanics
jsonObject [
("kind", jsonString site.kind),
("name", jsonString site.name),
("modeledLowLevelMechanics", jsonArray (site.mechanics.map jsonString)),
("notModeledEventEmission", jsonArray (site.eventEmission.map jsonString)),
("notModeledProxyUpgradeability", jsonArray (site.proxyUpgradeability.map jsonString)),
("partiallyModeledLinearMemoryMechanics", jsonArray (linearMemoryMechanics.map jsonString)),
("partiallyModeledRuntimeIntrospection", jsonArray (site.runtimeIntrospection.map jsonString)),
("axiomatizedPrimitives", jsonArray (site.primitives.map jsonString)),
("proofStatus", proofStatusJsonForSite site.primitives site.externals site.modules site.localObligations),
("localObligations", jsonArray (site.localObligations.map localObligationJson)),
("unsafeYulContracts", jsonArray (site.unsafeYulContracts.map unsafeYulContractJson)),
("unsafeBlocks", jsonArray (site.unsafeBlocks.map jsonString)),
("hasUncheckedDependencies",
if hasUncheckedDependenciesForSite site.externals site.modules then "true" else "false"),
("externalAssumptions", jsonObject [
("axiomatizedPrimitives", jsonArray (site.primitives.map primitiveAssumptionJson)),
("linkedExternals", jsonArray (site.externals.map assumptionJson)),
("ecmAxioms", jsonArray ((ecmAxiomsFromModules site.modules).map ecmJson)),
("ecmModules", jsonArray (site.modules.map ecmModuleJson))
])
]
jsonArray ((collectUsageSiteSummaries spec).map siteJson)
private def assumptionReportEntriesForSite (site : UsageSiteSummary) : List AssumptionReportEntry :=
let primitiveEntries :=
site.primitives.map (fun primitive =>
{ category := "axiomatizedPrimitive"
siteKind := site.kind
siteName := site.name