11// SPDX-License-Identifier: MIT
22
3- pragma solidity ^ 0.8.0 ;
3+ pragma solidity ^ 0.8.24 ; // tload/tstore are available since 0.8.24
44
5+ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol " ;
56import { TransientLib, tuint256, taddress, tbytes32 } from "./Transient.sol " ;
67
78/// @dev Library for managing transient dynamic arrays (TSTORE, TLOAD) of different types (uint256, address, bytes32).
@@ -23,6 +24,7 @@ import { TransientLib, tuint256, taddress, tbytes32 } from "./Transient.sol";
2324/// }
2425/// ```
2526library TransientArray {
27+ using Math for uint256 ;
2628 using TransientLib for tuint256;
2729 using TransientLib for taddress;
2830 using TransientLib for tbytes32;
@@ -60,21 +62,32 @@ library TransientArray {
6062 return self._items[index].tload ();
6163 }
6264
63- function push (Uint256 storage self , uint256 value ) internal {
65+ function get (Uint256 storage self ) internal view returns (uint256 [] memory array ) {
66+ uint256 len = self._length.tload ();
67+ array = new uint256 [](len);
68+ for (uint256 i = 0 ; i < len; i++ ) {
69+ array[i] = self._items[i].tload ();
70+ }
71+ }
72+
73+ function set (Uint256 storage self , uint256 index , uint256 value ) internal {
74+ if (index >= self._length.tload ()) revert TransientArray_IndexOutOfBounds ();
75+ self._items[index].tstore (value);
76+ }
77+
78+ function push (Uint256 storage self , uint256 value ) internal returns (uint256 newLength ) {
6479 uint256 nextElementIndex = self._length.tload ();
6580 self._items[nextElementIndex].tstore (value);
6681 unchecked {
67- self._length.tstore (nextElementIndex + 1 );
82+ newLength = nextElementIndex + 1 ;
83+ self._length.tstore (newLength);
6884 }
6985 }
7086
7187 function pop (Uint256 storage self ) internal returns (uint256 ret ) {
72- uint256 currentLength = self._length.tload ();
73- if (currentLength == 0 ) revert TransientArray_EmptyArrayPop ();
74- uint256 newLength;
75- unchecked {
76- newLength = currentLength - 1 ;
77- }
88+ (bool success , uint256 newLength ) = self._length.tload ().trySub (1 );
89+ if (! success) revert TransientArray_EmptyArrayPop ();
90+
7891 ret = self._items[newLength].tload ();
7992 delete self._items[newLength];
8093 self._length.tstore (newLength);
@@ -95,21 +108,32 @@ library TransientArray {
95108 return self._items[index].tload ();
96109 }
97110
98- function push (Address storage self , address value ) internal {
111+ function get (Address storage self ) internal view returns (address [] memory array ) {
112+ uint256 len = self._length.tload ();
113+ array = new address [](len);
114+ for (uint256 i = 0 ; i < len; i++ ) {
115+ array[i] = self._items[i].tload ();
116+ }
117+ }
118+
119+ function set (Address storage self , uint256 index , address value ) internal {
120+ if (index >= self._length.tload ()) revert TransientArray_IndexOutOfBounds ();
121+ self._items[index].tstore (value);
122+ }
123+
124+ function push (Address storage self , address value ) internal returns (uint256 newLength ) {
99125 uint256 nextElementIndex = self._length.tload ();
100126 self._items[nextElementIndex].tstore (value);
101127 unchecked {
102- self._length.tstore (nextElementIndex + 1 );
128+ newLength = nextElementIndex + 1 ;
129+ self._length.tstore (newLength);
103130 }
104131 }
105132
106133 function pop (Address storage self ) internal returns (address ret ) {
107- uint256 currentLength = self._length.tload ();
108- if (currentLength == 0 ) revert TransientArray_EmptyArrayPop ();
109- uint256 newLength;
110- unchecked {
111- newLength = currentLength - 1 ;
112- }
134+ (bool success , uint256 newLength ) = self._length.tload ().trySub (1 );
135+ if (! success) revert TransientArray_EmptyArrayPop ();
136+
113137 ret = self._items[newLength].tload ();
114138 delete self._items[newLength];
115139 self._length.tstore (newLength);
@@ -130,21 +154,32 @@ library TransientArray {
130154 return self._items[index].tload ();
131155 }
132156
133- function push (Bytes32 storage self , bytes32 value ) internal {
157+ function get (Bytes32 storage self ) internal view returns (bytes32 [] memory array ) {
158+ uint256 len = self._length.tload ();
159+ array = new bytes32 [](len);
160+ for (uint256 i = 0 ; i < len; i++ ) {
161+ array[i] = self._items[i].tload ();
162+ }
163+ }
164+
165+ function set (Bytes32 storage self , uint256 index , bytes32 value ) internal {
166+ if (index >= self._length.tload ()) revert TransientArray_IndexOutOfBounds ();
167+ self._items[index].tstore (value);
168+ }
169+
170+ function push (Bytes32 storage self , bytes32 value ) internal returns (uint256 newLength ) {
134171 uint256 nextElementIndex = self._length.tload ();
135172 self._items[nextElementIndex].tstore (value);
136173 unchecked {
137- self._length.tstore (nextElementIndex + 1 );
174+ newLength = nextElementIndex + 1 ;
175+ self._length.tstore (newLength);
138176 }
139177 }
140178
141179 function pop (Bytes32 storage self ) internal returns (bytes32 ret ) {
142- uint256 currentLength = self._length.tload ();
143- if (currentLength == 0 ) revert TransientArray_EmptyArrayPop ();
144- uint256 newLength;
145- unchecked {
146- newLength = currentLength - 1 ;
147- }
180+ (bool success , uint256 newLength ) = self._length.tload ().trySub (1 );
181+ if (! success) revert TransientArray_EmptyArrayPop ();
182+
148183 ret = self._items[newLength].tload ();
149184 delete self._items[newLength];
150185 self._length.tstore (newLength);
0 commit comments