') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); fix(envelope): split abi.encode to avoid viaIR, add deploy+verify scripts by aliXsed · Pull Request #117 · NodleCode/rollup · GitHub
Skip to content

fix(envelope): split abi.encode to avoid viaIR, add deploy+verify scripts - #117

Merged
aliXsed merged 1 commit into
mainfrom
aliX/envelope-deploy-verify
May 22, 2026
Merged

fix(envelope): split abi.encode to avoid viaIR, add deploy+verify scripts#117
aliXsed merged 1 commit into
mainfrom
aliX/envelope-deploy-verify

Conversation

@aliXsed

Copy link
Copy Markdown
Collaborator

Summary

Fixes ZkSync source verification for EnvelopeLinks by eliminating the need for viaIR compilation, and adds reproducible deploy+verify scripts.

Problem

EnvelopeLinks._feeAuthorizationDigest had 15 parameters in a single abi.encode() call, exceeding solc's stack limit without viaIR. The ZkSync verifier cannot handle viaIR contracts:

  • zksolc ≤1.5.1: ignores viaIR flag → stack-too-deep error
  • zksolc ≥1.5.13: passes viaIR through → internal error (verifier crashes)

Solution

Split the abi.encode into two parts joined by abi.encodePacked:

// abi.encodePacked(abi.encode(a..h), abi.encode(i..n)) == abi.encode(a..n)// because abi.encode pads each value to 32 bytes

This produces byte-identical output and preserves EIP-712 signature compatibility while compiling without viaIR.

Changes

FileChange
src/envelope/EnvelopeLinks.solSplit _feeAuthorizationDigest abi.encode (8+7 params)
ops/verify_hardhat_zksync.pyNew: verification script for Hardhat builds (BFS imports, filtered standard JSON, API submission)
ops/deploy_envelope_zksync.shNew: one-command Hardhat deploy + verify workflow
hardhat-deploy/DeployEnvelope.tsAuto-select .env-prod on mainnet
src/envelope/doc/EnvelopeLinks.mdDocument fee-on-transfer token restriction
.github/copilot-instructions.mdDocument Hardhat path, split trick, and verification workflow

Deployed & Verified (ZkSync Era Mainnet)

ContractAddressStatus
EnvelopeLinks0xff735c70f33ca4eF1768F527B5f230b76A61A89b✅ Fully verified
EnvelopePaymaster0x5396e4F349D863C0AD577bd9E752293524460C36✅ Fully verified

Paymaster is not funded — will be funded separately after review.

Testing

  • All 8 EnvelopeLinks unit tests pass
  • All 19 EIP712 tests pass (18 pass, 1 pre-existing fuzz issue unrelated to this change)
  • All 7 integration tests pass
  • yarn spellcheck: 0 issues

…ipts
EnvelopeLinks._feeAuthorizationDigest had 15 parameters in a single
abi.encode() call, which exceeds solc's stack limit without viaIR.
The ZkSync verifier cannot handle viaIR contracts (crashes with
'internal error' on zksolc >=1.5.13, ignores viaIR on <=1.5.1).
Fix: split into abi.encodePacked(abi.encode(8), abi.encode(7)) which
produces byte-identical output (abi.encode pads to 32 bytes) and
compiles without viaIR.
Also adds:
- ops/verify_hardhat_zksync.py: verification script for Hardhat builds
(BFS import graph, filtered standard JSON, API submission)
- ops/deploy_envelope_zksync.sh: one-command deploy+verify workflow
- hardhat-deploy/DeployEnvelope.ts: auto-select .env-prod on mainnet
- .github/copilot-instructions.md: document Hardhat path and split trick
Deployed & verified on ZkSync Era mainnet:
- EnvelopeLinks: 0xff735c70f33ca4eF1768F527B5f230b76A61A89b
- EnvelopePaymaster: 0x5396e4F349D863C0AD577bd9E752293524460C36
@github-actions

Copy link
Copy Markdown

LCOV of commit fee57f3 during checks #713

Summary coverage rate:
lines......: 25.7% (771 of 3001 lines)
functions..: 22.3% (105 of 470 functions)
branches...: 27.5% (140 of 509 branches)
Files changed coverage rate:
|Lines |Functions |Branches Filename |Rate Num|Rate Num|Rate Num
======================================================================================
src/envelope/EnvelopeLinks.sol | 0.0% 355| 0.0% 53| 0.0% 96

@aliXsed
aliXsed merged commit 5f63dd6 into mainMay 22, 2026
3 checks passed
@aliXsed
aliXsed deleted the aliX/envelope-deploy-verify branch May 22, 2026 01:14
Sign up for freeto 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

@aliXsed