@@ -39,6 +39,7 @@ import {IRewardDistributor} from "@aztec/governance/interfaces/IRewardDistributo
39
39
import {OracleInput} from "@aztec/core/libraries/FeeMath.sol " ;
40
40
import {ProposeArgs, OracleInput, ProposeLib} from "@aztec/core/libraries/ProposeLib.sol " ;
41
41
import {IERC20 } from "@oz/token/ERC20/IERC20.sol " ;
42
+ import {FeeMath} from "@aztec/core/libraries/FeeMath.sol " ;
42
43
43
44
import {
44
45
FeeHeader as FeeHeaderModel,
@@ -80,6 +81,8 @@ contract FakeCanonical {
80
81
contract FeeRollupTest is FeeModelTestPoints , DecoderBase {
81
82
using SlotLib for Slot;
82
83
using EpochLib for Epoch;
84
+ using FeeMath for uint256 ;
85
+ using FeeMath for ManaBaseFeeComponents;
83
86
// We need to build a block that we can submit. We will be using some values from
84
87
// the empty blocks, but otherwise populate using the fee model test points.
85
88
@@ -171,7 +174,11 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase {
171
174
+ point.outputs.mana_base_fee_components_in_fee_asset.congestion_cost
172
175
);
173
176
174
- assertEq (manaBaseFee, rollup.getManaBaseFee (true ), "mana base fee mismatch " );
177
+ assertEq (
178
+ manaBaseFee,
179
+ rollup.getManaBaseFeeAt (Timestamp.wrap (block .timestamp ), true ),
180
+ "mana base fee mismatch "
181
+ );
175
182
176
183
uint256 manaSpent = point.block_header.mana_spent;
177
184
@@ -212,12 +219,92 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase {
212
219
});
213
220
}
214
221
222
+ function test__FeeModelPrune () public {
223
+ // Submit a few blocks, then compute what the fees would be with/without a potential prune
224
+ // and ensure that they match what happens.
225
+ Slot nextSlot = Slot.wrap (1 );
226
+ for (uint256 i = 0 ; i < SLOT_DURATION / 12 * 5 ; i++ ) {
227
+ _loadL1Metadata (i);
228
+
229
+ if (rollup.getCurrentSlot () == nextSlot) {
230
+ TestPoint memory point = points[nextSlot.unwrap () - 1 ];
231
+ Block memory b = getBlock ();
232
+
233
+ rollup.propose (
234
+ ProposeArgs ({
235
+ header: b.header,
236
+ archive: b.archive,
237
+ blockHash: b.blockHash,
238
+ oracleInput: OracleInput ({
239
+ provingCostModifier: point.oracle_input.proving_cost_modifier,
240
+ feeAssetPriceModifier: point.oracle_input.fee_asset_price_modifier
241
+ }),
242
+ txHashes: b.txHashes
243
+ }),
244
+ b.signatures,
245
+ b.body
246
+ );
247
+ nextSlot = nextSlot + Slot.wrap (1 );
248
+ }
249
+ }
250
+
251
+ FeeHeader memory parentFeeHeaderNoPrune =
252
+ rollup.getBlock (rollup.getPendingBlockNumber ()).feeHeader;
253
+ uint256 excessManaNoPrune = (
254
+ parentFeeHeaderNoPrune.excessMana + parentFeeHeaderNoPrune.manaUsed
255
+ ).clampedAdd (- int256 (FeeMath.MANA_TARGET));
256
+
257
+ FeeHeader memory parentFeeHeaderPrune = rollup.getBlock (rollup.getProvenBlockNumber ()).feeHeader;
258
+ uint256 excessManaPrune = (parentFeeHeaderPrune.excessMana + parentFeeHeaderPrune.manaUsed)
259
+ .clampedAdd (- int256 (FeeMath.MANA_TARGET));
260
+
261
+ assertGt (excessManaNoPrune, excessManaPrune, "excess mana should be lower if we prune " );
262
+
263
+ // Find the point in time where we can prune. We can be smarter, but I'm not trying to be smart here
264
+ // trying to be foolproof, for I am a fool.
265
+ uint256 timeOfPrune = block .timestamp ;
266
+ while (! rollup.canPruneAtTime (Timestamp.wrap (timeOfPrune))) {
267
+ timeOfPrune += SLOT_DURATION;
268
+ }
269
+
270
+ ManaBaseFeeComponents memory componentsPrune =
271
+ rollup.getManaBaseFeeComponentsAt (Timestamp.wrap (timeOfPrune), true );
272
+
273
+ // If we assume that everything is proven, we will see what the fee would be if we did not prune.
274
+ rollup.setAssumeProvenThroughBlockNumber (10000 );
275
+ ManaBaseFeeComponents memory componentsNoPrune =
276
+ rollup.getManaBaseFeeComponentsAt (Timestamp.wrap (timeOfPrune), true );
277
+
278
+ // The congestion multipliers should be different, with the no-prune being higher
279
+ // as it is based on the accumulated excess mana.
280
+ assertGt (
281
+ componentsNoPrune.congestionMultiplier,
282
+ componentsPrune.congestionMultiplier,
283
+ "congestion multiplier should be higher if we do not prune "
284
+ );
285
+
286
+ assertEq (
287
+ componentsPrune.congestionMultiplier,
288
+ FeeMath.congestionMultiplier (excessManaPrune),
289
+ "congestion multiplier mismatch for prune "
290
+ );
291
+ assertEq (
292
+ componentsNoPrune.congestionMultiplier,
293
+ FeeMath.congestionMultiplier (excessManaNoPrune),
294
+ "congestion multiplier mismatch for no-prune "
295
+ );
296
+ }
297
+
215
298
function test_FeeModelEquivalence () public {
216
299
Slot nextSlot = Slot.wrap (1 );
217
300
Epoch nextEpoch = Epoch.wrap (1 );
218
301
219
302
// Loop through all of the L1 metadata
220
303
for (uint256 i = 0 ; i < l1Metadata.length ; i++ ) {
304
+ // Predict what the fee will be before we jump in time!
305
+ uint256 baseFeePrediction =
306
+ rollup.getManaBaseFeeAt (Timestamp.wrap (l1Metadata[i].timestamp), true );
307
+
221
308
_loadL1Metadata (i);
222
309
223
310
// For every "new" slot we encounter, we construct a block using current L1 Data
@@ -226,11 +313,13 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase {
226
313
if (rollup.getCurrentSlot () == nextSlot) {
227
314
TestPoint memory point = points[nextSlot.unwrap () - 1 ];
228
315
229
- L1FeeData memory fees = rollup.getCurrentL1Fees ( );
316
+ L1FeeData memory fees = rollup.getL1FeesAt (Timestamp. wrap ( block . timestamp ) );
230
317
uint256 feeAssetPrice = rollup.getFeeAssetPrice ();
231
318
232
- ManaBaseFeeComponents memory components = rollup.getManaBaseFeeComponents (false );
233
- ManaBaseFeeComponents memory componentsFeeAsset = rollup.getManaBaseFeeComponents (true );
319
+ ManaBaseFeeComponents memory components =
320
+ rollup.getManaBaseFeeComponentsAt (Timestamp.wrap (block .timestamp ), false );
321
+ ManaBaseFeeComponents memory componentsFeeAsset =
322
+ rollup.getManaBaseFeeComponentsAt (Timestamp.wrap (block .timestamp ), true );
234
323
BlockLog memory parentBlockLog = rollup.getBlock (nextSlot.unwrap () - 1 );
235
324
236
325
Block memory b = getBlock ();
@@ -252,6 +341,10 @@ contract FeeRollupTest is FeeModelTestPoints, DecoderBase {
252
341
253
342
BlockLog memory blockLog = rollup.getBlock (nextSlot.unwrap ());
254
343
344
+ assertEq (
345
+ baseFeePrediction, componentsFeeAsset.summedBaseFee (), "base fee prediction mismatch "
346
+ );
347
+
255
348
assertEq (
256
349
componentsFeeAsset.congestionCost,
257
350
blockLog.feeHeader.congestionCost,
0 commit comments