Skip to content

Commit 3f90169

Browse files
cairoethAmxx
andauthored
Clean dirty addresses and booleans (#5195)
Co-authored-by: Hadrien Croubois <[email protected]>
1 parent 809ded8 commit 3f90169

File tree

7 files changed

+50
-7
lines changed

7 files changed

+50
-7
lines changed

contracts/utils/SlotDerivation.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ library SlotDerivation {
7070
*/
7171
function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
7272
assembly ("memory-safe") {
73-
mstore(0x00, key)
73+
mstore(0x00, and(key, shr(96, not(0))))
7474
mstore(0x20, slot)
7575
result := keccak256(0x00, 0x40)
7676
}
@@ -81,7 +81,7 @@ library SlotDerivation {
8181
*/
8282
function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
8383
assembly ("memory-safe") {
84-
mstore(0x00, key)
84+
mstore(0x00, iszero(iszero(key)))
8585
mstore(0x20, slot)
8686
result := keccak256(0x00, 0x40)
8787
}

scripts/generate/helpers/sanitize.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
address: expr => `and(${expr}, shr(96, not(0)))`,
3+
bool: expr => `iszero(iszero(${expr}))`,
4+
bytes: (expr, size) => `and(${expr}, shl(${256 - 8 * size}, not(0)))`,
5+
};

scripts/generate/templates/Packing.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const format = require('../format-lines');
2+
const sanitize = require('../helpers/sanitize');
23
const { product } = require('../../helpers');
34
const { SIZES } = require('./Packing.opts');
45

@@ -44,8 +45,8 @@ function pack_${left}_${right}(bytes${left} left, bytes${right} right) internal
4445
left + right
4546
} result) {
4647
assembly ("memory-safe") {
47-
left := and(left, shl(${256 - 8 * left}, not(0)))
48-
right := and(right, shl(${256 - 8 * right}, not(0)))
48+
left := ${sanitize.bytes('left', left)}
49+
right := ${sanitize.bytes('right', right)}
4950
result := or(left, shr(${8 * left}, right))
5051
}
5152
}
@@ -55,7 +56,7 @@ const extract = (outer, inner) => `\
5556
function extract_${outer}_${inner}(bytes${outer} self, uint8 offset) internal pure returns (bytes${inner} result) {
5657
if (offset > ${outer - inner}) revert OutOfRangeAccess();
5758
assembly ("memory-safe") {
58-
result := and(shl(mul(8, offset), self), shl(${256 - 8 * inner}, not(0)))
59+
result := ${sanitize.bytes('shl(mul(8, offset), self)', inner)}
5960
}
6061
}
6162
`;
@@ -64,7 +65,7 @@ const replace = (outer, inner) => `\
6465
function replace_${outer}_${inner}(bytes${outer} self, bytes${inner} value, uint8 offset) internal pure returns (bytes${outer} result) {
6566
bytes${inner} oldValue = extract_${outer}_${inner}(self, offset);
6667
assembly ("memory-safe") {
67-
value := and(value, shl(${256 - 8 * inner}, not(0)))
68+
value := ${sanitize.bytes('value', inner)}
6869
result := xor(self, shr(mul(8, offset), xor(oldValue, value)))
6970
}
7071
}

scripts/generate/templates/Slot.opts.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ const TYPES = [
1010
{ type: 'bytes', isValueType: false },
1111
].map(type => Object.assign(type, { name: type.name ?? capitalize(type.type) }));
1212

13+
Object.assign(TYPES, Object.fromEntries(TYPES.map(entry => [entry.type, entry])));
14+
1315
module.exports = { TYPES };

scripts/generate/templates/SlotDerivation.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
const format = require('../format-lines');
2+
const sanitize = require('../helpers/sanitize');
23
const { TYPES } = require('./Slot.opts');
34

45
const header = `\
@@ -77,7 +78,7 @@ const mapping = ({ type }) => `\
7778
*/
7879
function deriveMapping(bytes32 slot, ${type} key) internal pure returns (bytes32 result) {
7980
assembly ("memory-safe") {
80-
mstore(0x00, key)
81+
mstore(0x00, ${(sanitize[type] ?? (x => x))('key')})
8182
mstore(0x20, slot)
8283
result := keccak256(0x00, 0x40)
8384
}

scripts/generate/templates/SlotDerivation.t.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,18 @@ function testSymbolicDeriveMapping${name}(${type} key) public {
6161
}
6262
`;
6363

64+
const mappingDirty = ({ type, name }) => `\
65+
function testSymbolicDeriveMapping${name}Dirty(bytes32 dirtyKey) public {
66+
${type} key;
67+
assembly {
68+
key := dirtyKey
69+
}
70+
71+
// run the "normal" test using a potentially dirty value
72+
testSymbolicDeriveMapping${name}(key);
73+
}
74+
`;
75+
6476
const boundedMapping = ({ type, name }) => `\
6577
mapping(${type} => bytes) private _${type}Mapping;
6678
@@ -107,6 +119,8 @@ module.exports = format(
107119
})),
108120
),
109121
).map(type => (type.isValueType ? mapping(type) : boundedMapping(type))),
122+
mappingDirty(TYPES.bool),
123+
mappingDirty(TYPES.address),
110124
),
111125
).trimEnd(),
112126
'}',

test/utils/SlotDerivation.t.sol

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,4 +225,24 @@ contract SlotDerivationTest is Test, SymTest {
225225

226226
assertEq(baseSlot.deriveMapping(key), derivedSlot);
227227
}
228+
229+
function testSymbolicDeriveMappingBooleanDirty(bytes32 dirtyKey) public {
230+
bool key;
231+
assembly {
232+
key := dirtyKey
233+
}
234+
235+
// run the "normal" test using a potentially dirty value
236+
testSymbolicDeriveMappingBoolean(key);
237+
}
238+
239+
function testSymbolicDeriveMappingAddressDirty(bytes32 dirtyKey) public {
240+
address key;
241+
assembly {
242+
key := dirtyKey
243+
}
244+
245+
// run the "normal" test using a potentially dirty value
246+
testSymbolicDeriveMappingAddress(key);
247+
}
228248
}

0 commit comments

Comments
 (0)