1
1
// SPDX-License-Identifier: MIT
2
2
3
- pragma solidity ^ 0.8.0 ;
3
+ pragma solidity ^ 0.8.24 ; // tload/tstore are available since 0.8.24
4
4
5
+ import { Math } from "@openzeppelin/contracts/utils/math/Math.sol " ;
5
6
import { TransientLib, tuint256, taddress, tbytes32 } from "./Transient.sol " ;
6
7
7
8
/// @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";
23
24
/// }
24
25
/// ```
25
26
library TransientArray {
27
+ using Math for uint256 ;
26
28
using TransientLib for tuint256;
27
29
using TransientLib for taddress;
28
30
using TransientLib for tbytes32;
@@ -60,21 +62,32 @@ library TransientArray {
60
62
return self._items[index].tload ();
61
63
}
62
64
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 ) {
64
79
uint256 nextElementIndex = self._length.tload ();
65
80
self._items[nextElementIndex].tstore (value);
66
81
unchecked {
67
- self._length.tstore (nextElementIndex + 1 );
82
+ newLength = nextElementIndex + 1 ;
83
+ self._length.tstore (newLength);
68
84
}
69
85
}
70
86
71
87
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
+
78
91
ret = self._items[newLength].tload ();
79
92
delete self._items[newLength];
80
93
self._length.tstore (newLength);
@@ -95,21 +108,32 @@ library TransientArray {
95
108
return self._items[index].tload ();
96
109
}
97
110
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 ) {
99
125
uint256 nextElementIndex = self._length.tload ();
100
126
self._items[nextElementIndex].tstore (value);
101
127
unchecked {
102
- self._length.tstore (nextElementIndex + 1 );
128
+ newLength = nextElementIndex + 1 ;
129
+ self._length.tstore (newLength);
103
130
}
104
131
}
105
132
106
133
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
+
113
137
ret = self._items[newLength].tload ();
114
138
delete self._items[newLength];
115
139
self._length.tstore (newLength);
@@ -130,21 +154,32 @@ library TransientArray {
130
154
return self._items[index].tload ();
131
155
}
132
156
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 ) {
134
171
uint256 nextElementIndex = self._length.tload ();
135
172
self._items[nextElementIndex].tstore (value);
136
173
unchecked {
137
- self._length.tstore (nextElementIndex + 1 );
174
+ newLength = nextElementIndex + 1 ;
175
+ self._length.tstore (newLength);
138
176
}
139
177
}
140
178
141
179
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
+
148
183
ret = self._items[newLength].tload ();
149
184
delete self._items[newLength];
150
185
self._length.tstore (newLength);
0 commit comments