Skip to content

fix(fees)!: canonical v0.6 ABI in harness/site/smoke; show the fee deposit in the snap - #45

Merged
MuncleUscles merged 5 commits into
v0.2-devfrom
fix/v06-fee-abi-and-display
Jun 10, 2026
Merged

MuncleUscles merged 5 commits into
v0.2-devfrom
fix/v06-fee-abi-and-display

Conversation

@MuncleUscles

@MuncleUscles MuncleUscles commented Jun 9, 2026

Copy link
Copy Markdown
Member

From the fee audit: the snap's parser was already canonical-correct, but the E2E scaffolding around it encoded a stale pre-CON-504 protocol — transactions built by the site couldn't be parsed by the snap's own fee-aware branch, so green wallet E2E proved nothing about v0.6.

  • Harness GenLayerFeeShim.sol, site prototype encoder, and smoke script now encode the canonical shapes (10-field FeesDistribution incl. the three price caps; MessageFeeAllocationNode with messageType/onAcceptance/callKey/bytes feeParams), byte-matching the snap parser and genlayer-js.
  • Site fee math replaced with the consensus round-0 formula; units fixed (time-unit allocations are integer seconds, not parseUnits(x, 18); realistic cap placeholders instead of '110'/'150').
  • Snap insight panel now shows Total / Fee deposit (= value − userValue) / userValue in GEN (raw wei secondary), and the bond being paid on appeal flows — previously the one number that matters was never displayed.
  • Integration test asserts a SITE-encoded transaction parses as fee-aware (fixture built by the site encoder, not the snap's own ABI constants — kills the self-referential fixture blind spot).
  • snap.manifest.json shasum updated from an actual build.

forge build, site+snap builds, lint, and snap test suite green.

Summary by CodeRabbit

  • New Features

    • GEN-denominated formatting for transaction values and richer fee/value display
    • UI inputs for storage/receipt gas price caps, leader/validator timeunit allocations, and per-round execution budget
    • Message call-key input and updated transaction payload encoding for submitted intents
  • Bug Fixes

    • More robust handling of malformed or unexpected transaction calldata
  • Refactor

    • Overhauled fee configuration and message allocation schema
  • Tests

    • Added integration test to decode fee-aware transactions
  • Chores

    • Updated package manifest checksum

…posit in the snap

- harness GenLayerFeeShim.sol, site prototype encoder, and smoke script were
  still encoding a stale pre-CON-504 protocol (8-field FeesDistribution with
  leaderTimeoutFee/validatorsTimeoutFee, bytes4 functionSelector allocation
  nodes) — transactions built by the E2E site could not even be parsed by the
  snap's own (correct) parser, so green wallet E2E proved nothing about v0.6.
  All three now encode the canonical shapes (10-field distribution incl. the
  three price caps; MessageFeeAllocationNode with messageType/onAcceptance/
  callKey/bytes feeParams) matching the snap parser and genlayer-js
- site fee math replaced with the consensus round-0 formula; units fixed
  (time-unit allocations are integer seconds, not parseUnits(x,18); realistic
  cap placeholders)
- snap insight panel now shows the numbers that matter: Total / Fee deposit
  (= value − userValue) / userValue in GEN with raw wei secondary, and the
  bond being paid on appeal flows
- integration test asserts a site-encoded transaction parses as fee-aware
  (fixture built by the SITE encoder, not the snap's own ABI constants)
- snap.manifest.json shasum updated from an actual reproducible build
@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@MuncleUscles, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 25 minutes and 57 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a74b9c1e-798b-498c-81f0-d2d56b978fff

📥 Commits

Reviewing files that changed from the base of the PR and between bbf5c95 and 51ab11d.

📒 Files selected for processing (4)
  • .github/workflows/main.yml
  • packages/site/src/pages/index.tsx
  • packages/snap/snap.manifest.json
  • packages/snap/src/components/TransactionConfig.tsx
📝 Walkthrough

Walkthrough

Migrate fee model to timeunit allocations and per-round execution budgeting; switch message allocation nodes to use callKey (bytes32) and encoded feeParams; update ABI/type bindings, encoders (RLP), UI forms/presets, smoke harness, Snap display/enrichment, and related tests.

Changes

Fee Schema and Core Implementation

Layer / File(s) Summary
Core Fee Schema Definition
packages/harness/src/GenLayerFeeShim.sol
FeesDistribution replaces timeout/rollup fields with leaderTimeunitsAllocation, validatorTimeunitsAllocation, executionBudgetPerRound, executionConsumed, storageFeeMaxGasPrice, receiptFeeMaxGasPrice. MessageFeeAllocationNode adds messageType/onAcceptance, replaces functionSelector (bytes4) with callKey (bytes32), and changes feeParams to raw bytes.
TypeScript Type Definitions and ABI Encoding
packages/site/src/prototype/transaction.ts
Type shapes and CONSENSUS_MAIN_WITH_FEES_ABI tuples updated to match the new Solidity schema, including new gas-price fields and message node callKey + encoded feeParams.
Fee Building and Hashing Functions
packages/site/src/prototype/transaction.ts
Helpers parse form inputs into the new fee schema: parseGwei, normalizeBytes32, buildFeesDistribution, buildMessageAllocations, RLP-encode tx calldata, and hashFeeConfig uses updated ABI type strings.
Default Form Initialization
packages/site/src/prototype/transaction.ts
makeDefaultForm() now populates new timeunit, executionBudgetPerRound, maxPriceGenPerTimeUnit, storage/receipt gas caps, and messageCallKey/messageExecutionBudget defaults.
UI Form Configuration and Fee Presets
packages/site/src/pages/index.tsx
PROFILE_PRESETS maps to new PrototypeForm fields; fee policy inputs replace timeout/rollup fields with leader/validator timeunits and execution budget; new storage and receipt gas cap inputs; message mode uses messageCallKey.
Smoke Test Harness Update
packages/harness/scripts/smoke.mjs
Smoke script adds encodeRlp/parseUnits, updates params.feesDistribution to new fields (including parseUnits('24','gwei')), RLP-encodes txCalldata, restructures messageAllocations (feeParams: '0x'), and lowers maxTotalFee.

MetaMask Snap Transaction Display and Enrichment

Layer / File(s) Summary
GEN Value Formatting and Display
packages/snap/src/components/TransactionConfig.tsx
Adds WEI_PER_GEN and formatWeiToGen to show GEN-denominated values with fractional trimming; computes totalValue, userValue, feeDeposit, and conditionally shows appeal-related bond/value rows.
Transaction Type Extension and Value Enrichment
packages/snap/src/transactions/transaction.ts, packages/snap/src/index.tsx
ParsedGenLayerTransaction gains optional totalValue and feeDeposit fields; onTransaction parses numeric transaction.value and enriches/persists the summary; calldata decoding is wrapped in try/catch returning 'unknown' on failure.
Snap Tests and Manifest Update
packages/snap/snap.manifest.json, packages/snap/src/index.test.tsx, packages/snap/src/transactions/transaction.integration.test.ts
Updated snap manifest source.shasum; tests extend mockTransactionSummary with totalValue/feeDeposit; new integration test decodes fee-aware addTransaction calldata and asserts feesDistribution and allocation callKey.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • cristiam86

"🐰 In code the rabbit hops and digs,
Timeunits grown from tiny gigs,
CallKeys replace the selector rigs,
GEN totals print with polished twigs."

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main objectives: canonical v0.6 ABI updates across harness/site/smoke and fee deposit display in snap, with a breaking change indicator.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/v06-fee-abi-and-display

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/snap/src/components/TransactionConfig.tsx`:
- Around line 22-47: The parse of BigInt in formatWeiToGen can throw on
malformed input; wrap the BigInt(value) call in a try-catch inside
formatWeiToGen, catch any error from BigInt parsing, log or silently handle it
and return 'unknown' (same as undefined case) so the component doesn't throw;
keep the rest of the conversion logic unchanged and only proceed when BigInt
parsing succeeds.
- Around line 109-120: The fee deposit line in TransactionConfig is misleading:
change the parenthetical that reads "(+ userValue {formatWeiToGen(userValue)})"
to a clearer label such as "(userValue: {formatWeiToGen(userValue)})" or remove
the parenthetical entirely so it doesn't imply addition to feeDeposit; update
the JSX where feeDeposit and userValue are rendered (refer to variables
feeDeposit and userValue and the formatter formatWeiToGen) to reflect the chosen
wording and keep the existing Total display unchanged.

In `@packages/snap/src/index.tsx`:
- Around line 44-62: The BigInt conversion in withTransactionValue can throw if
summary.userValue is malformed; wrap the BigInt(summary.userValue) conversion in
a try-catch (inside withTransactionValue), and on error log or record the error
and fall back to 0n for userValue so processing continues safely; ensure you
still compute feeDeposit using the recovered userValue and return the same shape
(totalValue and feeDeposit as strings) from withTransactionValue.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 37fe8a59-b1af-4fa2-b400-970b16192a78

📥 Commits

Reviewing files that changed from the base of the PR and between 37b8edd and 1e676e0.

📒 Files selected for processing (10)
  • packages/harness/scripts/smoke.mjs
  • packages/harness/src/GenLayerFeeShim.sol
  • packages/site/src/pages/index.tsx
  • packages/site/src/prototype/transaction.ts
  • packages/snap/snap.manifest.json
  • packages/snap/src/components/TransactionConfig.tsx
  • packages/snap/src/index.test.tsx
  • packages/snap/src/index.tsx
  • packages/snap/src/transactions/transaction.integration.test.ts
  • packages/snap/src/transactions/transaction.ts

Comment on lines +22 to +47
const formatWeiToGen = (value: string | undefined): string => {
if (value === undefined) {
return 'unknown';
}

const wei = BigInt(value);
const whole = wei / WEI_PER_GEN;
const fraction = wei % WEI_PER_GEN;
if (fraction === 0n) {
return `${whole.toString()} GEN`;
}

const fractionText = fraction.toString().padStart(18, '0');
const significantDigits =
whole > 0n
? 6
: Math.max(
6,
fractionText.search(/[1-9]/u) + 6,
);
const trimmedFraction = fractionText
.slice(0, Math.min(significantDigits, 18))
.replace(/0+$/u, '');

return `${whole.toString()}.${trimmedFraction} GEN`;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add defensive error handling for BigInt parsing.

While the upstream code should guarantee that value is a valid bigint string (from .toString() on bigints in withTransactionValue), the current implementation will throw an uncaught exception if an invalid string somehow reaches line 27. For defense in depth in a security-critical snap component, wrap the BigInt parsing in a try-catch block.

🛡️ Proposed fix to add error handling
 const formatWeiToGen = (value: string | undefined): string => {
   if (value === undefined) {
     return 'unknown';
   }
 
+  try {
     const wei = BigInt(value);
     const whole = wei / WEI_PER_GEN;
     const fraction = wei % WEI_PER_GEN;
     if (fraction === 0n) {
       return `${whole.toString()} GEN`;
     }
 
     const fractionText = fraction.toString().padStart(18, '0');
     const significantDigits =
       whole > 0n
         ? 6
         : Math.max(
             6,
             fractionText.search(/[1-9]/u) + 6,
           );
     const trimmedFraction = fractionText
       .slice(0, Math.min(significantDigits, 18))
       .replace(/0+$/u, '');
 
     return `${whole.toString()}.${trimmedFraction} GEN`;
+  } catch {
+    return 'unknown';
+  }
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/snap/src/components/TransactionConfig.tsx` around lines 22 - 47, The
parse of BigInt in formatWeiToGen can throw on malformed input; wrap the
BigInt(value) call in a try-catch inside formatWeiToGen, catch any error from
BigInt parsing, log or silently handle it and return 'unknown' (same as
undefined case) so the component doesn't throw; keep the rest of the conversion
logic unchanged and only proceed when BigInt parsing succeeds.

Comment on lines +109 to +120
<Box direction="horizontal" alignment={'space-between'}>
<Text>
<Bold>Fee deposit:</Bold>
</Text>
<Text>
{formatWeiToGen(feeDeposit)} (+ userValue{' '}
{formatWeiToGen(userValue)})
</Text>
</Box>
<Text>
<Italic>Raw fee deposit: {displayValue(feeDeposit)} wei</Italic>
</Text>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Clarify the fee deposit display text.

The text (+ userValue ...) on line 114 is misleading because it suggests that userValue is being added to feeDeposit, when in fact totalValue = feeDeposit + userValue (and Total is already displayed above). Consider revising the text to avoid confusion, such as (userValue: X GEN) or removing the parenthetical entirely since userValue is shown separately below.

✏️ Suggested clarification
         <Text>
           <Bold>Fee deposit:</Bold>
         </Text>
         <Text>
-          {formatWeiToGen(feeDeposit)} (+ userValue{' '}
-          {formatWeiToGen(userValue)})
+          {formatWeiToGen(feeDeposit)}
         </Text>

Or alternatively:

         <Text>
-          {formatWeiToGen(feeDeposit)} (+ userValue{' '}
-          {formatWeiToGen(userValue)})
+          {formatWeiToGen(feeDeposit)} (userValue: {formatWeiToGen(userValue)})
         </Text>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Box direction="horizontal" alignment={'space-between'}>
<Text>
<Bold>Fee deposit:</Bold>
</Text>
<Text>
{formatWeiToGen(feeDeposit)} (+ userValue{' '}
{formatWeiToGen(userValue)})
</Text>
</Box>
<Text>
<Italic>Raw fee deposit: {displayValue(feeDeposit)} wei</Italic>
</Text>
<Box direction="horizontal" alignment={'space-between'}>
<Text>
<Bold>Fee deposit:</Bold>
</Text>
<Text>
{formatWeiToGen(feeDeposit)} (userValue: {formatWeiToGen(userValue)})
</Text>
</Box>
<Text>
<Italic>Raw fee deposit: {displayValue(feeDeposit)} wei</Italic>
</Text>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/snap/src/components/TransactionConfig.tsx` around lines 109 - 120,
The fee deposit line in TransactionConfig is misleading: change the
parenthetical that reads "(+ userValue {formatWeiToGen(userValue)})" to a
clearer label such as "(userValue: {formatWeiToGen(userValue)})" or remove the
parenthetical entirely so it doesn't imply addition to feeDeposit; update the
JSX where feeDeposit and userValue are rendered (refer to variables feeDeposit
and userValue and the formatter formatWeiToGen) to reflect the chosen wording
and keep the existing Total display unchanged.

Comment on lines +44 to +62
const withTransactionValue = (
summary: ParsedGenLayerTransaction,
value: unknown,
): ParsedGenLayerTransaction => {
const totalValue = parseTransactionValue(value);
if (totalValue === undefined) {
return summary;
}

const userValue =
summary.userValue === undefined ? 0n : BigInt(summary.userValue);
const feeDeposit = totalValue > userValue ? totalValue - userValue : 0n;

return {
...summary,
totalValue: totalValue.toString(),
feeDeposit: feeDeposit.toString(),
};
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add defensive error handling for BigInt conversion of userValue.

Line 54 calls BigInt(summary.userValue) without error handling. While summary.userValue should always be a valid bigint string from upstream parsing (via stringifyUint), adding a try-catch here provides defense in depth for a transaction handler in a security-critical snap.

🛡️ Proposed fix to add error handling
 const withTransactionValue = (
   summary: ParsedGenLayerTransaction,
   value: unknown,
 ): ParsedGenLayerTransaction => {
   const totalValue = parseTransactionValue(value);
   if (totalValue === undefined) {
     return summary;
   }
 
+  try {
     const userValue =
       summary.userValue === undefined ? 0n : BigInt(summary.userValue);
     const feeDeposit = totalValue > userValue ? totalValue - userValue : 0n;
 
     return {
       ...summary,
       totalValue: totalValue.toString(),
       feeDeposit: feeDeposit.toString(),
     };
+  } catch {
+    return {
+      ...summary,
+      totalValue: totalValue.toString(),
+      feeDeposit: totalValue.toString(),
+    };
+  }
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/snap/src/index.tsx` around lines 44 - 62, The BigInt conversion in
withTransactionValue can throw if summary.userValue is malformed; wrap the
BigInt(summary.userValue) conversion in a try-catch (inside
withTransactionValue), and on error log or record the error and fall back to 0n
for userValue so processing continues safely; ensure you still compute
feeDeposit using the recovered userValue and return the same shape (totalValue
and feeDeposit as strings) from withTransactionValue.

- parseTransactionValue: validate with an explicit numeric pattern instead of
  a bare try/catch (the security scanner flags bare catch blocks as unhandled
  promise rejections; a regex guard is also more precise)
- eslint/prettier fixes from --fix
- snap.manifest.json shasum from rebuild
Local prettier disagrees with CI's pin on two sites; applied CI's exact
suggested output. Snap manifest shasum from local rebuild — if CI's bundle
still differs (build is environment-sensitive), the next commit adopts CI's
computed value verbatim.
Push trigger was main-only; merges to v0.2-dev got no post-merge CI.
Local snap builds produce a different bundle hash than CI (environment-
sensitive build — flagged for follow-up); CI is the gate, so its computed
value is canonical.
@MuncleUscles
MuncleUscles merged commit 87d9ef1 into v0.2-dev Jun 10, 2026
9 checks passed
@MuncleUscles
MuncleUscles deleted the fix/v06-fee-abi-and-display branch June 10, 2026 12:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant