1
1
2
+ // TODO: Add shifts to `castsAndShiftsFlows`!!!!!!!!!
3
+ // Maybe they are not there for a reason?
4
+ // Example: 4b053890c3ceb6c77358d624bd0c10bb: 0x6a
2
5
.init castsAndShiftsFlows = LocalFlowAnalysis
3
6
castsAndShiftsFlows.TransferStmt(stmt):-
4
7
Statement_Opcode(stmt, "OR").
@@ -190,18 +193,34 @@ DEBUG_OUTPUT(SuccessfulMergedStorageModeling)
190
193
AnyLoadStoreStorVarBytes(stmt, storVar, low, high):-
191
194
VarHoldsBytesOfStorVarFinal(_, stmt, storVar, low, high);
192
195
VarWrittenToBytesOfStorVar(_, stmt, storVar, low, high);
193
- // Will need to handle these differently because in optimized code a single constant can initialize many vars
194
- ConstWrittenToBytesOfStorVar(_, _, stmt, _, storVar, low, high).
196
+ ConstWrittenToUnreadBytesOfStorVar(_, stmt, _, storVar, low, high).
197
+
198
+ // rare case, a variable is never read directly, but only stored
199
+ // try to capture it with 2 simple rules
200
+ VarWrittenToBytesOfStorVar(var, store, construct, 0, 31):-
201
+ SSTOREToConstruct(store, construct, var),
202
+ !Variable_Value(var, _),
203
+ !LowBytesMaskOp(_, var, _),
204
+ !SLOADOfConstruct(_, construct, _).
195
205
196
- AnyLoadStoreStorVarBytes(store, construct, 0, 31):-
197
- SSTOREToConstruct(store, construct, _),
206
+ // This pattern will be used when an array is shortened (replaced with a smaller one)
207
+ // in via-ir code
208
+ VarWrittenToBytesOfStorVar(var, store, construct, 0, numOfBytes - 1):-
209
+ SSTOREToConstruct(store, construct, var),
210
+ LowBytesMaskOp(_, var, numOfBytes),
211
+ !Variable_Value(var, _),
212
+ !SLOADOfConstruct(_, construct, _).
213
+
214
+ // Added for completeness to revisit
215
+ ConstWrittenToBytesOfStorVar(var, val, store, store, construct, 0, 31):-
216
+ SSTOREToConstruct(store, construct, var),
217
+ Variable_Value(var, val),
198
218
!SLOADOfConstruct(_, construct, _).
199
219
200
220
FailedMergedStorageModelingReason(storVar, stmt, stmt2, [low, high], [otherLow, otherHigh]),
201
221
FailedMergedStorageModeling(storVar):-
202
222
AnyLoadStoreStorVarBytes(stmt, storVar, low, high),
203
223
AnyLoadStoreStorVarBytes(stmt2, storVar, otherLow, otherHigh), otherLow = otherLow, otherHigh = otherHigh, // NOWARN
204
- !ArrayIdToStorageIndex(as(storVar, Value), _),
205
224
(low != otherLow ; high != otherHigh),
206
225
( (low < otherLow , otherLow < high) ; (low < otherHigh, otherHigh < high) ).
207
226
@@ -215,14 +234,14 @@ FailedMergedStorageModeling(storVar):-
215
234
!UselessSLOAD(stmt),
216
235
!AnyLoadStoreStorVarBytes(stmt, storVar, _, _),
217
236
!BytesOfStorVarKept(_, stmt, storVar, _, _),
218
- !ConstWrittenToBytesOfStorVar(_, _, _, stmt, storVar, _, _),
219
- !ArrayIdToStorageIndex(as(storVar, Value), _).
237
+ !DeleteOfStructSlot(stmt, storVar),
238
+ !ConstWrittenToBytesOfStorVar(_, _, stmt, _, storVar, _, _),
239
+ !ConstWrittenToBytesOfStorVar(_, _, _, stmt, storVar, _, _).
220
240
221
241
222
242
SuccessfulMergedStorageModeling(storVar):-
223
243
AnyLoadStoreStorVarBytes(_, storVar, _, _),
224
- !FailedMergedStorageModeling(storVar),
225
- !ArrayIdToStorageIndex(as(storVar, Value), _).
244
+ !FailedMergedStorageModeling(storVar).
226
245
227
246
/**
228
247
Models complex expressions of many shifted and masked vars to update a single storage slot.
@@ -262,6 +281,12 @@ DEBUG_OUTPUT(VarWrittenToBytesOfStorVar)
262
281
.decl ConstWrittenToBytesOfStorVar(constVar:Variable, const:Value, store:Statement, load:Statement, storVar:StorageConstruct, byteLow:number, byteHigh:number)
263
282
DEBUG_OUTPUT(ConstWrittenToBytesOfStorVar)
264
283
284
+ /**
285
+ Results of ConstWrittenToBytesOfStorVar processed after identifying the variables
286
+ */
287
+ .decl ConstWrittenToBytesOfStorVarProcessed(constVar:Variable, const:Value, store:Statement, load:Statement, storVar:StorageConstruct, byteLow:number, byteHigh:number)
288
+ DEBUG_OUTPUT(ConstWrittenToBytesOfStorVarProcessed)
289
+
265
290
ProbablyPartialStorageUpdatePattern(fromVar, toVar, "VAR", writtenVar, byteLow, byteLow + castedTo - 1):-
266
291
CastedAndShiftedVar(writtenVar, castedNShifted, byteLow, castedTo),
267
292
(OR(_, castedNShifted, fromVar, toVar) ; OR(_, fromVar, castedNShifted, toVar)),
@@ -378,6 +403,16 @@ ConstWrittenToBytesOfStorVar("0xlala", as(writtenConst, Value), store, "lolo", c
378
403
ProbablyPartialStorageUpdateSequenceWrite(storedVar, "CONST", writtenConst, byteLow, byteHigh),
379
404
!ProbablyPartialStorageUpdateSequenceWrite(storedVar, "VAR", _, byteLow, _). // prefer var inference if they start from the same byte
380
405
406
+ /**
407
+ Needs special handling because in via-ir deleted storage structs have all their bytes zeroed out.
408
+ Before the unused bytes would be kept.
409
+ */
410
+ .decl DeleteOfStructSlot(store: Statement, construct: StorageConstruct)
411
+ DEBUG_OUTPUT(DeleteOfStructSlot)
412
+ DeleteOfStructSlot(store, construct):-
413
+ SSTOREToConstruct(store, construct, storedVar),
414
+ Variable_Value(storedVar, "0x0").
415
+
381
416
.decl BytesOfStorVarKept(store: Statement, load: Statement, construct: StorageConstruct, keepByteLow: number, keepByteHigh: number)
382
417
383
418
BytesOfStorVarKept(store, load, construct, keepByteLow, keepByteHigh):-
@@ -451,6 +486,43 @@ ConstWrittenToBytesOfStorVar("0xNoVar", "0x0", store, load, construct, maskByteL
451
486
ByteMaskOpMaskRange(originVar, storedVar, [maskByteLow, maskByteHigh]),
452
487
SSTOREToConstruct(store, construct, storedVar).
453
488
489
+ /**
490
+ byte of storage variable is never read ConstWrittenToByteOfStorVar that write to bytes that are never read
491
+ */
492
+ .decl ConstWrittenToUnreadByteOfStorVar(const: Value, store: Statement, load: Statement, storVar: StorageConstruct, byteLow: number, writeByte: number)
493
+ DEBUG_OUTPUT(ConstWrittenToUnreadByteOfStorVar)
494
+
495
+ /**
496
+ Subset of ConstWrittenToBytesOfStorVar that write to bytes that are never read
497
+ Will first identify individual bytes and then group them together
498
+ */
499
+ .decl ConstWrittenToUnreadBytesOfStorVar(const: Value, store: Statement, load: Statement, storVar: StorageConstruct, byteLow: number, byteHigh: number)
500
+ DEBUG_OUTPUT(ConstWrittenToUnreadBytesOfStorVar)
501
+
502
+ ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, byteLow, writeByte):-
503
+ ConstWrittenToBytesOfStorVar(_, const, store, load, storVar, byteLow, byteHigh),
504
+ writeByte = range(byteLow, byteHigh + 1, 1),
505
+ !ByteOfStorVarReadOfWritten(storVar, writeByte).
506
+
507
+ ConstWrittenToUnreadBytesOfStorVar(newVal, store, load, storVar, byteLow, byteHigh):-
508
+ ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, originalByteLow, byteLow),
509
+ !ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, originalByteLow, byteLow - 1),
510
+ ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, originalByteLow, byteHigh),
511
+ !ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, originalByteLow, byteHigh + 1),
512
+ 1 + byteHigh - byteLow = count : {ConstWrittenToUnreadByteOfStorVar(const, store, load, storVar, originalByteLow, k), byteLow <= k, k <= byteHigh},
513
+ excessRightBytes = byteLow - originalByteLow,
514
+ Mask_Length(mask, byteHigh - byteLow + 1),
515
+ ValueIsByteMask(mask),
516
+ newVal = as(@and_256(@shr_256(@number_to_hex(excessRightBytes*8), const), mask), Value).
517
+
518
+
519
+ // Helper
520
+ .decl ByteOfStorVarReadOfWritten(storVar: StorageConstruct, byte: number)
521
+ ByteOfStorVarReadOfWritten(storVar, byte):-
522
+ (VarHoldsBytesOfStorVarFinal(_, _, storVar, varByteLow, varByteHigh);
523
+ VarWrittenToBytesOfStorVar(_, _, storVar, varByteLow, varByteHigh)),
524
+ byte = range(varByteLow, varByteHigh + 1, 1).
525
+
454
526
/**
455
527
HACK (?) HACK (?) HACK (?)
456
528
If the variable that is being stored on the update of a merged storage var
@@ -545,7 +617,7 @@ StoreGlobalVariable(store, v, writtenVar):-
545
617
StoreGlobalVariable(store, v, constVar):-
546
618
SuccessfulMergedStorageModeling($Variable($Constant(storVar))),
547
619
SSTOREToConst(_, storVar, _), // ensure it's a global variable
548
- ConstWrittenToBytesOfStorVar (constVar, _, store, _, $Variable($Constant(storVar)), byteLow, byteHigh),
620
+ ConstWrittenToBytesOfStorVarProcessed (constVar, _, store, _, $Variable($Constant(storVar)), byteLow, byteHigh),
549
621
v = MERGED_STORAGE_VAR(storVar, byteLow, byteHigh).
550
622
551
623
@@ -562,7 +634,7 @@ ProcessedStorageVariable(storageVar, storageVar):-
562
634
ProcessedStorageVariable(construct, construct):-
563
635
SuccessfulMergedStorageModeling(construct),
564
636
(
565
- ConstWrittenToBytesOfStorVar(_, _, _, _, construct, 0, 31);
637
+ // ConstWrittenToBytesOfStorVar(_, _, _, _, construct, 0, 31);
566
638
VarWrittenToBytesOfStorVarFinal(_, _, construct, 0, 31);
567
639
VarHoldsBytesOfStorVarFinal(_, _, construct, 0, 31)
568
640
).
@@ -571,7 +643,7 @@ ProcessedStorageVariable(storageVar, $TightlyPackedVariable(parentCons, byteLow,
571
643
SuccessfulMergedStorageModeling(storageVar),
572
644
storageVar = $Variable(parentCons),
573
645
(
574
- ConstWrittenToBytesOfStorVar(_, _, _, _, storageVar, byteLow, byteHigh);
646
+ ConstWrittenToUnreadBytesOfStorVar( _, _, _, storageVar, byteLow, byteHigh);
575
647
VarWrittenToBytesOfStorVarFinal(_, _, storageVar, byteLow, byteHigh);
576
648
VarHoldsBytesOfStorVarFinal(_, _, storageVar, byteLow, byteHigh)
577
649
),
@@ -588,6 +660,32 @@ StorageVariablePacksNVars(storageVar, numberOfVars):-
588
660
numberOfVars = count : ProcessedStorageVariable(storageVar, _),
589
661
numberOfVars > 1.
590
662
663
+ ConstWrittenToBytesOfStorVarProcessed(constVar, const, store, load, $Variable(parentCons), byteLow, byteHigh):-
664
+ ConstWrittenToBytesOfStorVar(constVar, const, store, load, $Variable(parentCons), byteLow, byteHigh),
665
+ ProcessedStorageVariable($Variable(parentCons), $TightlyPackedVariable(parentCons, byteLow, byteHigh)).
666
+
667
+ ConstWrittenToBytesOfStorVarProcessed(constVar, const, store, load, $Variable(parentCons), byteLow, actualByteHigh):-
668
+ ConstWrittenToBytesOfStorVar(constVar, const, store, load, $Variable(parentCons), byteLow, byteHigh),
669
+ ProcessedStorageVariable($Variable(parentCons), $TightlyPackedVariable(parentCons, byteLow, actualByteHigh)),
670
+ actualByteHigh > byteHigh.
671
+
672
+ ConstWrittenToBytesOfStorVarProcessed("0xNoVar", as(@and_256(const, mask), Value), store, load, $Variable(parentCons), byteLow, actualByteHigh):-
673
+ ConstWrittenToBytesOfStorVar(_, const, store, load, $Variable(parentCons), byteLow, byteHigh),
674
+ ProcessedStorageVariable($Variable(parentCons), $TightlyPackedVariable(parentCons, byteLow, actualByteHigh)),
675
+ actualByteHigh < byteHigh,
676
+ Mask_Length(mask, byteHigh - actualByteHigh),
677
+ ValueIsByteMask(mask).
678
+
679
+ ConstWrittenToBytesOfStorVarProcessed("0xNoVar", newVal, store, load, $Variable(parentCons), actualByteLow, actualByteHigh):-
680
+ ConstWrittenToBytesOfStorVar(_, const, store, load, $Variable(parentCons), writeByteLow, writeByteHigh),
681
+ ProcessedStorageVariable($Variable(parentCons), $TightlyPackedVariable(parentCons, actualByteLow, actualByteHigh)),
682
+ writeByteLow <= actualByteLow,
683
+ actualByteHigh <= writeByteHigh,
684
+ excessRightBytes = actualByteLow - writeByteLow,
685
+ Mask_Length(mask, actualByteHigh - actualByteLow + 1),
686
+ ValueIsByteMask(mask),
687
+ newVal = as(@and_256(@shr_256(@number_to_hex(excessRightBytes*8), const), mask), Value).
688
+
591
689
/**
592
690
Basic type inference
593
691
Hacky for now just to print the correct uintX or address if nessesary.
0 commit comments