@@ -156,4 +156,55 @@ contract TrimmingTest is Test {
156
156
157
157
assertEq (expectedRoundTrip, amountRoundTrip);
158
158
}
159
+
160
+ // invariant: forall (x: uint256, y: uint8, z: uint8),
161
+ // (x <= type(uint64).max, y <= z)
162
+ // => (x.trim(x, 8).untrim(y) == x)
163
+ function testFuzz_trimIsLeftInverse (
164
+ uint256 amount ,
165
+ uint8 fromDecimals ,
166
+ uint8 toDecimals
167
+ ) public {
168
+ // this is guaranteed by trimming
169
+ uint256 amt = bound (amount, 1 , type (uint64 ).max);
170
+ vm.assume (fromDecimals <= 18 );
171
+ vm.assume (toDecimals <= 18 );
172
+
173
+ // trimming
174
+ uint8 initialDecimals = 0 ;
175
+ TrimmedAmount memory trimmedAmount = TrimmedAmount (uint64 (amt), initialDecimals);
176
+ console.log ("trimmedAmount %s " , trimmedAmount.amount);
177
+ console.log ("trimmedDecimals %s " , trimmedAmount.decimals);
178
+
179
+ // trimming is left inverse of trimming
180
+ uint256 amountUntrimmed = trimmedAmount.untrim (fromDecimals);
181
+ TrimmedAmount memory amountRoundTrip = amountUntrimmed.trim (fromDecimals, initialDecimals);
182
+
183
+ assertEq (trimmedAmount.amount, amountRoundTrip.amount);
184
+ }
185
+
186
+ // invariant: forall (TrimmedAmount a, TrimmedAmount b) a.saturatingAdd(b).amount <= type(uint64).max
187
+ function testFuzz_saturatingAddDoesNotOverflow (
188
+ TrimmedAmount memory a ,
189
+ TrimmedAmount memory b
190
+ ) public {
191
+ vm.assume (a.decimals == b.decimals);
192
+
193
+ // this is guaranteed by trimming
194
+ a.amount = uint64 (bound (a.amount, 0 , type (uint64 ).max));
195
+ a.decimals = uint8 (bound (a.decimals, 0 , 8 ));
196
+
197
+ b.amount = uint64 (bound (b.amount, 0 , type (uint64 ).max));
198
+ b.decimals = uint8 (bound (b.decimals, 0 , 8 ));
199
+
200
+ TrimmedAmount memory c = a.saturatingAdd (b);
201
+
202
+ // decimals should always be the same, else revert
203
+ assertEq (c.decimals, a.decimals);
204
+
205
+ // amount should never overflow
206
+ assertLe (c.amount, type (uint64 ).max);
207
+ // amount should never underflow
208
+ assertGe (c.amount, 0 );
209
+ }
159
210
}
0 commit comments