Skip to content

Commit 13c0727

Browse files
authoredFeb 8, 2023
Improve detection of storage gap usage (#731)

File tree

4 files changed

+76
-2
lines changed

4 files changed

+76
-2
lines changed
 

‎packages/core/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## Unreleased
44

55
- Support storage gaps named with `__gap_*`. ([#732](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/732))
6+
- Improve detection of storage gap usage. ([#731](https://github.com/OpenZeppelin/openzeppelin-upgrades/pull/731))
67

78
## 1.22.0 (2023-01-31)
89

‎packages/core/contracts/test/Storage.sol

+41
Original file line numberDiff line numberDiff line change
@@ -858,4 +858,45 @@ contract StorageUpgrade_CustomGap_V2_Bad_Changed_Gap_Name {
858858
uint256 c;
859859
uint256[23] __gap_part2; // name stayed the same
860860
uint256 z;
861+
}
862+
863+
contract Parent1 {
864+
string[5] s;
865+
uint256[45] private __gap;
866+
}
867+
868+
contract Parent2 {
869+
bool b;
870+
uint256[49] private __gap;
871+
}
872+
873+
contract StorageUpgrade_ConsumeAndAddGap_V1 is Parent1 {
874+
uint256[50] private __gap;
875+
}
876+
877+
contract StorageUpgrade_ConsumeAndAddGap_V2 is Parent1, Parent2 {
878+
}
879+
880+
contract StorageUpgrade_ConsumeAndAddGap_V3 is Parent1, Parent2 {
881+
uint256 a;
882+
uint256[49] private __gap;
883+
}
884+
885+
contract StorageUpgrade_ConsumeAndAddGap_V3b is Parent1, Parent2 {
886+
uint256[50] private __gap;
887+
}
888+
889+
contract V1Storage {
890+
uint256[50] private __gap;
891+
}
892+
893+
contract StorageUpgrade_ConsumeAndAddGap_Storage_V1 is V1Storage, Parent1 {
894+
}
895+
896+
contract V2Storage {
897+
uint256 abc;
898+
uint256[49] private __gap;
899+
}
900+
901+
contract StorageUpgrade_ConsumeAndAddGap_Storage_V2 is V2Storage, Parent1, Parent2 {
861902
}

‎packages/core/src/storage/compare.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -91,10 +91,10 @@ export function storageFieldEnd(field: StorageField): bigint | undefined {
9191
return begin + BigInt(numberOfBytes);
9292
}
9393

94-
const LAYOUTCHANGE_COST = 0;
94+
const LAYOUTCHANGE_COST = 1;
9595
const FINISHGAP_COST = 1;
9696
const SHRINKGAP_COST = 0;
97-
const TYPECHANGE_COST = 0;
97+
const TYPECHANGE_COST = 1;
9898

9999
export class StorageLayoutComparator {
100100
hasAllowedUncheckedCustomTypes = false;

‎packages/core/src/storage/report-gap.test.ts

+32
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,12 @@ const testContracts = [
3131
'contracts/test/Storage.sol:StorageUpgrade_CustomGap_V2_Ok_Switched_Gaps',
3232
'contracts/test/Storage.sol:StorageUpgrade_CustomGap_V2_Bad_Switched_Gaps',
3333
'contracts/test/Storage.sol:StorageUpgrade_CustomGap_V2_Bad_Changed_Gap_Name',
34+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_V1',
35+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_V2',
36+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_V3',
37+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_V3b',
38+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_Storage_V1',
39+
'contracts/test/Storage.sol:StorageUpgrade_ConsumeAndAddGap_Storage_V2',
3440
];
3541

3642
test.before(async t => {
@@ -172,3 +178,29 @@ test('custom gap - insert var, did not shrink gaps, changed first gap name', t =
172178
t.false(report.ok);
173179
t.snapshot(report.explain());
174180
});
181+
182+
test('consume entire gap and add new gap of different size', t => {
183+
const v1 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V1');
184+
const v2 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V2');
185+
const v3 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V3');
186+
187+
t.true(getReport(v1, v2).ok);
188+
t.true(getReport(v2, v3).ok);
189+
t.true(getReport(v1, v3).ok);
190+
});
191+
192+
test('consume entire gap and add new gap of same size', t => {
193+
const v1 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V1');
194+
const v2 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V2');
195+
const v3b = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_V3b');
196+
197+
t.true(getReport(v2, v3b).ok);
198+
t.true(getReport(v1, v3b).ok);
199+
});
200+
201+
test('consume partial gap and add new gap, storage contract pattern', t => {
202+
const v1 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_Storage_V1');
203+
const v2 = t.context.extractStorageLayout('StorageUpgrade_ConsumeAndAddGap_Storage_V2');
204+
205+
t.true(getReport(v1, v2).ok);
206+
});

0 commit comments

Comments
 (0)
Please sign in to comment.