@@ -4,6 +4,22 @@ pragma solidity ^0.8.4;
44import "./utils/SoladyTest.sol " ;
55import {LibBytes} from "../src/utils/LibBytes.sol " ;
66
7+ contract BytesStore {
8+ LibBytes.BytesStorage internal value;
9+
10+ function set (bytes calldata newValue ) external {
11+ LibBytes.setCalldata (value, newValue);
12+ }
13+
14+ function length () external view returns (uint256 ) {
15+ return LibBytes.length (value);
16+ }
17+
18+ function at_ (uint256 index ) external view returns (uint8 ) {
19+ return LibBytes.uint8At (value, index);
20+ }
21+ }
22+
723contract LibBytesTest is SoladyTest {
824 function testLoad (bytes memory a ) public {
925 if (a.length < 32 ) a = abi.encodePacked (a, new bytes (32 ));
@@ -414,4 +430,55 @@ contract LibBytesTest is SoladyTest {
414430 require (keccak256 (expectedChildren[i]) == keccak256 (children[i]));
415431 }
416432 }
433+
434+ function testUint8AtStaleByteAfterShrink () public {
435+ BytesStore store = new BytesStore ();
436+ bytes memory previous = new bytes (32 );
437+ previous[31 ] = 0xbb ;
438+
439+ store.set (previous);
440+ store.set (new bytes (31 ));
441+
442+ assertEq (store.length (), 31 );
443+ assertEq (store.at_ (31 ), 0 );
444+ }
445+
446+ function testUint8AtPaddingAfterShortValue () public {
447+ BytesStore store = _storeWithDirtyPadding (5 );
448+ assertEq (store.length (), 5 );
449+ assertEq (store.at_ (4 ), 0x11 );
450+ assertEq (store.at_ (5 ), 0 );
451+ assertEq (store.at_ (30 ), 0 );
452+ }
453+
454+ function testUint8AtPaddingAfterSpilledValue () public {
455+ BytesStore store = _storeWithDirtyPadding (40 );
456+ assertEq (store.length (), 40 );
457+ assertEq (store.at_ (39 ), 0x11 );
458+ assertEq (store.at_ (40 ), 0 );
459+ }
460+
461+ function testUint8AtPaddingAfterTaggedLongValue () public {
462+ BytesStore store = _storeWithDirtyPadding (255 );
463+ assertEq (store.length (), 255 );
464+ assertEq (store.at_ (254 ), 0x11 );
465+ assertEq (store.at_ (255 ), 0 );
466+ assertEq (store.at_ (256 ), 0 );
467+ }
468+
469+ function _storeWithDirtyPadding (uint256 n ) internal returns (BytesStore store ) {
470+ store = new BytesStore ();
471+
472+ bytes memory value = new bytes (n);
473+ for (uint256 i; i < n; ++ i) {
474+ value[i] = 0x11 ;
475+ }
476+
477+ bytes memory data = abi.encodeWithSelector (BytesStore.set.selector , value);
478+ for (uint256 i = 4 + 32 + 32 + n; i < data.length ; ++ i) {
479+ data[i] = 0xaa ;
480+ }
481+ (bool success ,) = address (store).call (data);
482+ require (success);
483+ }
417484}
0 commit comments