Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/rare-shirts-unite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'openzeppelin-solidity': minor
---

`Arrays`: Add `unsafeSetLength` for `bytes[]` and `string[]`.
22 changes: 22 additions & 0 deletions contracts/utils/Arrays.sol
Original file line number Diff line number Diff line change
Expand Up @@ -479,4 +479,26 @@ library Arrays {
sstore(array.slot, len)
}
}

/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(bytes[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}

/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(string[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
}
3 changes: 3 additions & 0 deletions scripts/generate/templates/Arrays.js
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,9 @@ module.exports = format(
TYPES.map(unsafeAccessStorage),
TYPES.map(unsafeAccessMemory),
TYPES.map(unsafeSetLength),
// arrays of non-value types
unsafeSetLength('bytes'),
unsafeSetLength('string'),
),
).trimEnd(),
'}',
Expand Down
9 changes: 7 additions & 2 deletions test/helpers/random.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@ const generators = {
bytes32: () => ethers.hexlify(ethers.randomBytes(32)),
uint256: () => ethers.toBigInt(ethers.randomBytes(32)),
int256: () => ethers.toBigInt(ethers.randomBytes(32)) + ethers.MinInt256,
hexBytes: length => ethers.hexlify(ethers.randomBytes(length)),
bytes: (length = 32) => ethers.hexlify(ethers.randomBytes(length)),
string: () => ethers.uuidV4(ethers.randomBytes(32)),
};

generators.address.zero = ethers.ZeroAddress;
generators.bytes32.zero = ethers.ZeroHash;
generators.uint256.zero = 0n;
generators.int256.zero = 0n;
generators.hexBytes.zero = '0x';
generators.bytes.zero = '0x';
generators.string.zero = '';

// alias hexBytes -> bytes
generators.hexBytes = generators.bytes;

module.exports = {
generators,
Expand Down
Loading