De fleste norske utviklere som har rullet ut en smart-kontrakt på Arbitrum eller Optimism, kjenner allerede modellen: en operatør publiserer en transaksjonsbatch, og nettverket venter i en utfordringsperiode før den regnes som endelig. zkSync Era gjør det motsatt. Her beviser nettverket matematisk, med et validitetsbevis, at hver batch er korrekt før den i det hele tatt godtas på Ethereum. Det endrer ikke bare ytelsen, det endrer hvilke feil du som utvikler faktisk trenger å bekymre deg for. Denne guiden viser deg, steg for steg, hvordan du setter opp, skriver, tester, verifiserer og sikrer en smart-kontrakt på zkSync Era, med de samme sikkerhetsvanene som proffene bruker etter at nettverket selv ble rammet av en nøkkellekkasje i april 2025.
Vi bygger et komplett, kjørbart Hardhat-prosjekt fra bunnen av: en enkel, men produksjonsrelevant kontrakt, et deploy-script som bruker zkSync sin egen Deployer-klasse, verifisering mot den offisielle blokkjede-eksploreren, og et sikkerhetslag med reentrancy-beskyttelse og multisig-styrt administrasjon. Alt du trenger er en terminal, Node.js og litt testnett-ETH.
Guiden forutsetter at du allerede kan Solidity på et grunnleggende nivå og har rullet ut minst én kontrakt på Ethereum mainnet eller en testnett-kopi av det. Det du ikke trenger fra før, er erfaring med zk-rollups spesifikt, siden verktøykjeden er bygget for å ligne mest mulig på standard Hardhat-arbeidsflyt, med noen få, men viktige avvik som vi går gjennom underveis.
Hvorfor zkSync Era krever en egen sikkerhetstankegang
zkSync Era er bygget på ZK Stack og kjører nå på den nyere arkitekturen ZKsync OS, med et bevissystem kalt Airbender som kjernekomponent. I oktober 2025 introduserte Matter Labs-utvikler Anthony Rose det som kalles Atlas-oppgraderingen i en offentlig X-post: en sequencer bygget for over 15.000 transaksjoner i sekundet, ett sekunds zk-finalitet via Airbender, og en beviskostnad på rundt 0,0001 dollar per overføring. Det siste tallet er verdt å dvele ved, for det er nettopp lave beviskostnader som gjør det økonomisk mulig å generere kryptografiske bevis for hver eneste batch, i stedet for å stole på en syv dagers utfordringsperiode slik optimistiske rollups gjør.
Den praktiske konsekvensen for deg som utvikler er at feil i kontraktslogikken din blir kryptografisk forankret på Ethereum langt raskere enn på en optimistisk rollup. Det gir mindre tid til at et årvåkent samfunn oppdager og bestrider en feilaktig tilstand, fordi den modellen rett og slett ikke finnes her. Sikkerheten flyttes fra “noen vil protestere om noe er galt” til “beviset må være riktig for å bli akseptert i det hele tatt”. Det høres tryggere ut, og er det på protokollnivå, men det betyr også at feil i din egen kontraktskode ikke fanges opp av noen ekstra sikkerhetsmekanisme på L2-nivå. Ansvaret for tilgangskontroll, reentrancy-beskyttelse og nøkkelhåndtering hviler fortsatt fullt og helt på deg.
Ifølge zkSync sin egen dokumentasjon er kravet til åpenhet strengt: “In order to maintain the same level of security as the L1, the ZKsync operator is required to publish the code for each contract it deploys on the Ethereum chain”, ifølge ZKsync sin offisielle dokumentasjon. I praksis betyr det at operatøren må kjenne kontraktens bytekode før den i det hele tatt deployes, noe som er en grunnleggende forskjell fra Ethereum mainnet og påvirker hvordan du strukturerer factory-kontrakter og proxy-mønstre.
Airbender-bevismotoren og hva ett sekunds finalitet faktisk betyr
Airbender er beskrevet i zkSync-materiale fra 2026 som et RISC-V-basert bevissystem, bygget for å generere validitetsbevis raskt nok til at hele batcher kan bli kryptografisk endelige på rundt ett sekund. Det er en vesentlig endring fra tidligere generasjoner av zk-rollups, hvor selve bevisgenereringen kunne ta minutter og legge en flaskehals mellom rask brukeropplevelse på L2 og faktisk finalitet på L1. Kombinert med en sequencer bygget for over 15.000 transaksjoner i sekundet, betyr dette i praksis at en applikasjon på zkSync Era kan love brukerne noe optimistiske rollups strukturelt ikke kan love på samme tidshorisont: at transaksjonen deres er ugjenkallelig forankret på Ethereum i løpet av sekunder, ikke dager.
For deg som skriver kontrakter er ikke Airbender noe du samhandler med direkte, det kjører på infrastrukturnivå hos operatøren. Men det påvirker likevel designbeslutninger, siden lav og forutsigbar beviskostnad gjør det billigere å strukturere kontrakter med flere små, hyppige oppdateringer i stedet for å samle alt i sjeldne, store transaksjoner for å spare gass. Det er en annen kostnadslogikk enn den mange utviklere har lært seg på Ethereum mainnet, hvor gassoptimalisering ofte handler om å minimere antall transaksjoner mest mulig.
ZKsync OS og hvorfor arkitekturen betyr noe for deg som utvikler
ZKsync OS er navnet på den nyere systemarkitekturen som ligger under ZK Stack, og som Atlas-oppgraderingen bygger videre på. For en vanlig kontraktsutvikler er det viktigste å ta med seg at denne arkitekturen er designet for det som i materiale fra 2026 omtales som “enterprise level activity onchain”: betalinger, tokeniserte eiendeler og oppgjør på tvers av kjeder. Det er også bakgrunnen for at zkSync i økende grad omtales som en del av et bredere “gateway”-konsept for ZK Stack-baserte kjeder, selv om konkrete produktnavn for dette fortsatt er i tidlig fase per 2026. Praktisk betyr det at kontrakten du bygger i dag, sannsynligvis vil kjøre i et økosystem med flere samvirkende ZK Stack-kjeder etter hvert, ikke bare på selve zkSync Era mainnet.
Forutsetninger: verktøy, versjoner og kontoer du trenger
Før du starter, sørg for at du har følgende på plass. Denne guiden er testet med et standard Hardhat-oppsett og de offisielle zkSync-pluginene fra Matter Labs.
| Verktøy | Krav | Merknad |
|---|---|---|
| Node.js | LTS-versjon (18.x eller nyere) | Kreves av Hardhat og zkSync-pluginene |
| Pakkebehandler | npm eller yarn | Begge fungerer, denne guiden bruker npm |
| Hardhat | Nyeste stabile versjon | Installeres som devDependency i prosjektet |
| @matterlabs/hardhat-zksync-deploy | Offisiell plugin fra Matter Labs | Gir Deployer-klassen for utrulling |
| @matterlabs/hardhat-zksync-solc | Offisiell zksolc-kompilator-plugin | Kompilerer Solidity til zkSync-kompatibel bytekode |
| zksync-ethers | Klientbibliotek for zkSync | Brukes til lommebok- og providerhåndtering i scriptene |
| Lommebok med testnett-ETH | MetaMask eller tilsvarende | Faucet-ETH på zkSync Sepolia-testnettet |
| Multisig-verktøy | Anbefales til mainnet-admin | For å unngå enkeltpunkt-svikt i nøkkelhåndtering |
Du trenger ikke å oppgi eksakte versjonsnumre manuelt. Installer alltid nyeste stabile versjon av pluginene via npm, siden Matter Labs oppdaterer dem hyppig i takt med protokolloppgraderinger som Atlas. Sjekk alltid den offisielle plugin-dokumentasjonen før produksjonsutrulling, siden API-et for Deployer-klassen kan endres mellom store versjoner.
Nettverksdetaljer du bør ha klare
zkSync Era mainnet har kjede-ID 324, mens zkSync Sepolia testnet har kjede-ID 300. Legg begge nettverkene inn i lommeboken din manuelt dersom de ikke dukker opp automatisk, og dobbeltsjekk kjede-ID-en før du signerer en transaksjon som skal gå til mainnet. En feil kjede-ID i lommebokkonfigurasjonen er en overraskende vanlig kilde til at utviklere ved et uhell sender en transaksjon til feil nettverk, spesielt når testnett og mainnet konfigureres i samme økt.
Steg 1 og 2: Sett opp prosjektet og installer zkSync-verktøyene
Start med et rent mappeoppsett. Opprett en ny mappe, initialiser et npm-prosjekt, og installer Hardhat sammen med de offisielle zkSync-pluginene.
mkdir zksync-sikker-kontrakt
cd zksync-sikker-kontrakt
npm init -y
npm install --save-dev hardhat @matterlabs/hardhat-zksync-deploy @matterlabs/hardhat-zksync-solc zksync-ethers ethers dotenv
Opprett deretter en .env-fil for privatnøkkelen din. Ikke commit denne filen til Git, legg den i .gitignore med en gang, før du fyller inn noe som helst.
echo "node_modules
.env
artifacts-zk
cache-zk" > .gitignore
touch .env
echo 'WALLET_PRIVATE_KEY=din_testnett_nokkel_her' >> .env
Bruk kun en dedikert testnøkkel her, aldri en nøkkel med reelle midler. Dette er den vanligste årsaken til at hobbyprosjekter mister penger: en privatnøkkel som lekker via en offentlig GitHub-commit eller en feilkonfigurert CI-pipeline.
Steg 3 og 4: Skriv kontrakten og konfigurer nettverket
Opprett mappen contracts/ og legg inn en enkel, men realistisk kontrakt. Vi bruker en innskudds- og uttaksbeholder som illustrerer de vanligste sikkerhetsfellene: reentrancy, tilgangskontroll og heltallshåndtering.
// contracts/SikkerHvelv.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
contract SikkerHvelv {
address public admin;
mapping(address => uint256) private saldo;
bool private laast;
event Innskudd(address indexed bruker, uint256 belop);
event Uttak(address indexed bruker, uint256 belop);
modifier kunAdmin() {
require(msg.sender == admin, "Kun admin kan kalle dette");
_;
}
modifier ikkeReentrant() {
require(!laast, "Reentrancy oppdaget");
laast = true;
_;
laast = false;
}
constructor(address _admin) {
admin = _admin;
}
function settInn() external payable {
require(msg.value > 0, "Belop ma vaere over null");
saldo[msg.sender] += msg.value;
emit Innskudd(msg.sender, msg.value);
}
function taUt(uint256 belop) external ikkeReentrant {
require(saldo[msg.sender] >= belop, "Utilstrekkelig saldo");
saldo[msg.sender] -= belop;
(bool ok, ) = msg.sender.call{value: belop}("");
require(ok, "Overforing feilet");
emit Uttak(msg.sender, belop);
}
function byttAdmin(address nyAdmin) external kunAdmin {
require(nyAdmin != address(0), "Ugyldig adresse");
admin = nyAdmin;
}
}
Legg merke til rekkefølgen i taUt-funksjonen: saldoen oppdateres før den eksterne overføringen skjer. Dette kalles checks-effects-interactions-mønsteret, og det er den samme anbefalingen zkSync selv gir i sin sikkerhetsdokumentasjon: “To prevent vulnerabilities: Follow the checks-effects-interactions pattern. Use a reentrancy guard when interacting with external contracts”, ifølge ZKsync sin offisielle dokumentasjon.
Opprett så hardhat.config.ts i rotmappen, med zkSync Sepolia testnett som mål.
// hardhat.config.ts
import "@matterlabs/hardhat-zksync-deploy";
import "@matterlabs/hardhat-zksync-solc";
import { HardhatUserConfig } from "hardhat/config";
const config: HardhatUserConfig = {
zksolc: {
version: "latest",
settings: {},
},
defaultNetwork: "zkSyncSepolia",
networks: {
zkSyncSepolia: {
url: "https://sepolia.era.zksync.dev",
ethNetwork: "sepolia",
zksync: true,
verifyURL:
"https://explorer.sepolia.era.zksync.dev/contract_verification",
},
zkSyncMainnet: {
url: "https://mainnet.era.zksync.io",
ethNetwork: "mainnet",
zksync: true,
verifyURL:
"https://zksync2-mainnet-explorer.zksync.io/contract_verification",
},
},
solidity: {
version: "0.8.24",
},
};
export default config;
Merk verifiserings-endepunktene: zkSync sin egen dokumentasjon oppgir mainnet-endepunktet https://zksync2-mainnet-explorer.zksync.io/contract_verification og testnett-endepunktet https://explorer.sepolia.era.zksync.dev/contract_verification som standard for automatisert kontraktsverifisering, noe som gjør det mulig å bygge verifisering rett inn i en CI/CD-pipeline i stedet for å gjøre det manuelt i nettleseren hver gang.
Steg 5 og 6: Kompiler kontrakten og skriv deploy-scriptet
Kompiler kontrakten med zksolc-kompilatoren som er konfigurert i forrige steg.
npx hardhat compile --network zkSyncSepolia
Opprett deretter mappen deploy/ og et deploy-script som bruker Deployer-klassen fra @matterlabs/hardhat-zksync-deploy. Denne klassen pakker inn en zkSync-lommebok og gir et enkelt grensesnitt for å laste artefakter og sende utrullingstransaksjonen.
// deploy/deploy.ts
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
import { Wallet } from "zksync-ethers";
import * as dotenv from "dotenv";
import { HardhatRuntimeEnvironment } from "hardhat/types";
dotenv.config();
export default async function (hre: HardhatRuntimeEnvironment) {
const privatnokkel = process.env.WALLET_PRIVATE_KEY as string;
const lommebok = new Wallet(privatnokkel);
const deployer = new Deployer(hre, lommebok);
const artefakt = await deployer.loadArtifact("SikkerHvelv");
const adminAdresse = await lommebok.getAddress();
const kontrakt = await deployer.deploy(artefakt, [adminAdresse]);
console.log(
"SikkerHvelv deployet til:",
await kontrakt.getAddress()
);
}
Legg merke til at admin-adressen settes til utrullerens egen adresse i konstruktøren. På testnett er dette greit, men i steg 11 bytter vi denne til en multisig før mainnet-utrulling.
Steg 7: Deploy til zkSync Sepolia testnet
Skaff testnett-ETH fra en zkSync Sepolia-faucet før du kjører utrullingen. Deployer-klassen estimerer gasskostnaden automatisk før den sender transaksjonen, så sørg for at lommeboken har litt margin utover det estimerte beløpet, siden gasspriser på L2-nettverk kan svinge mellom estimering og faktisk sending, akkurat som på mainnet. Kjør deretter deploy-scriptet.
npx hardhat deploy-zksync --script deploy.ts --network zkSyncSepolia
Et vellykket kjør gir deg output som ligner på dette:
Starting deployment process of "SikkerHvelv"...
Estimated deployment cost: 0.000412 ETH
"SikkerHvelv" was successfully deployed:
- Contract address: 0x3f9A...b21C
- Contract source: contracts/SikkerHvelv.sol:SikkerHvelv
- Encoded constructor arguments: 0x0000...
SikkerHvelv deployet til: 0x3f9A...b21C
Noter kontraktsadressen. Du trenger den i neste steg for verifisering, og du bør lagre den i et deploy-loggarkiv, ikke bare i terminalhistorikken.
Steg 8: Verifiser kontrakten på zkSync Era Block Explorer
Den offisielle ZKsync-eksploreren er hovedgrensesnittet for å inspisere transaksjoner, blokker, batches, kontrakter og tokens på nettverket, og er oppdatert løpende av Matter Labs gjennom 2026. Verifisering matcher kildekoden din mot bytekoden som faktisk kjører on-chain, slik at andre kan lese kontrakten uten å stole blindt på deg.
npx hardhat verify --network zkSyncSepolia 0x3f9A...b21C "0xDinAdminAdresse"
Under panseret sender dette en forespørsel til verifiserings-endepunktet du satte opp i hardhat.config.ts. Du kan også gjøre dette manuelt ved å laste opp kildefilen direkte i eksploreren, noe som er nyttig når du feilsøker en kompilatorversjon-mismatch. Vellykket verifisering vises som en grønn hake ved siden av kontraktsadressen, og kildekoden blir lesbar for alle som besøker siden.
Steg 9 og 10: Bygg inn reentrancy-beskyttelse og test lokalt før produksjon
zkSync sin egen dokumentasjon er eksplisitt på et punkt som ofte overrasker utviklere som kommer fra Ethereum mainnet: “While .call is safer in terms of gas, it does not provide built-in reentrancy protection”, ifølge ZKsync sin offisielle dokumentasjon. Med andre ord, lavere gasskostnad på zkSync fjerner ikke behovet for eksplisitt reentrancy-vakt, slik vi allerede har lagt inn i SikkerHvelv-kontrakten med ikkeReentrant-modifikatoren.
Før du i det hele tatt vurderer mainnet, skal kontrakten kjøres gjennom en lokal testsuite. zkSync anbefaler eksplisitt dette: “Always test your contracts locally before deploying to mainnet”, ifølge ZKsync sin offisielle dokumentasjon.
// test/SikkerHvelv.test.ts
import { expect } from "chai";
import { Wallet, Provider } from "zksync-ethers";
import { Deployer } from "@matterlabs/hardhat-zksync-deploy";
import * as hre from "hardhat";
describe("SikkerHvelv", function () {
it("skal avvise reentrancy-forsok pa uttak", async function () {
const provider = new Provider("http://localhost:8011");
const lommebok = new Wallet("0xNokkelFraInMemoryNode", provider);
const deployer = new Deployer(hre, lommebok);
const artefakt = await deployer.loadArtifact("SikkerHvelv");
const kontrakt = await deployer.deploy(artefakt, [
await lommebok.getAddress(),
]);
await kontrakt.settInn({ value: 1000n });
await expect(kontrakt.taUt(2000n)).to.be.reverted;
});
});
Kjør testene mot en lokal zkSync in-memory-node, ikke mot testnettet direkte. Det gir raskere iterasjon og lar deg simulere feiltilstander uten å bruke ekte, om enn verdiløse, testnett-ETH for hver kjøring.
Steg 11 og 12: Sikre admin-funksjoner med multisig og forbered mainnet
Dette steget finnes ikke i de fleste generiske zkSync-tutorials, men det burde det gjøre. 15. april 2025 ble administratorkontoene til tre av zkSync sine egne airdrop-distribusjonskontrakter kompromittert. Angriperen brukte funksjonen sweepUnclaimed() til å mynte rundt 111 millioner ukrevde ZK-tokens, med en anslått verdi på rundt 5 millioner dollar. zkSync-teamet bekreftet offentlig at protokollen og selve ZK-tokenkontrakten forble sikre, og at årsaken var lekkasje av én enkelt administratornøkkel, ikke en feil i selve zk-protokollen.
Lærdommen er konkret: kontraktslogikken kan være helt korrekt, men hvis administratorrettigheter ligger på én enkelt privatnøkkel, er hele kontrakten din like sikker som den ene nøkkelen. Bytt derfor admin-rollen fra en enkeltlommebok til en multisig før du deployer til mainnet.
Verdt å merke seg er også hvordan angrepet ble begrenset i etterkant: alle mintbare midler i de berørte airdrop-kontraktene var allerede fullstendig myntet da hendelsen ble oppdaget, slik at samme angrepsvei ikke kunne gjentas. zkSync koordinerte med børser for å forsøke gjenoppretting, og oppfordret angriperen til å returnere midlene for å unngå videre juridisk oppfølging. Det er ikke en garanti du kan bygge sikkerhet rundt i eget prosjekt, men det illustrerer at rask, koordinert respons etter en hendelse begrenser skadeomfanget vesentlig mer enn å håpe hendelsen aldri skjer i utgangspunktet.
// deploy/overfor-til-multisig.ts
import { Wallet } from "zksync-ethers";
import * as dotenv from "dotenv";
import { ethers } from "ethers";
dotenv.config();
async function main() {
const nokkel = process.env.WALLET_PRIVATE_KEY as string;
const provider = new ethers.JsonRpcProvider(
"https://mainnet.era.zksync.io"
);
const lommebok = new Wallet(nokkel, provider);
const kontraktAdresse = "0xDinKontraktAdresse";
const multisigAdresse = "0xDinMultisigAdresse";
const abi = ["function byttAdmin(address nyAdmin) external"];
const kontrakt = new ethers.Contract(kontraktAdresse, abi, lommebok);
const tx = await kontrakt.byttAdmin(multisigAdresse);
await tx.wait();
console.log("Admin overfort til multisig:", multisigAdresse);
}
main();
Når admin-rollen er trygt overført, deployer du til mainnet med samme kommando som mot testnettet, bare med --network zkSyncMainnet. Sett deretter opp overvåking: følg med på kontraktens events, sett varsler for uvanlig store uttak, og registrer kontrakten din for et bug bounty-program dersom prosjektet håndterer reelle midler.
I praksis betyr overvåking her at du abonnerer på Uttak– og Innskudd-eventene fra kontrakten via en WebSocket-provider, og setter en enkel terskelregel: overstiger et enkeltuttak et gitt beløp, eller overstiger summen av uttak innenfor en kort tidsperiode et annet, sendes et varsel til teamet før noen rekker å reagere manuelt på transaksjonshistorikken i eksploreren. Dette trenger ikke være en dyr tredjepartstjeneste i starten, et lite Node.js-script som poller loggene periodisk og varsler via e-post eller en chat-webhook, dekker de fleste tidlige prosjekter godt nok til at et avvik ikke blir liggende uoppdaget i timevis.
Her har zkSync-økosystemet selv satt en standard verdt å følge. ZKsync DAO godkjente 13. februar 2026 forslaget “TPP-17: ZKsync Immunefi Bug Bounty Program 2026”, med en samlet rammebevilgning på 100 millioner ZK: 80 millioner ZK, tilsvarende rundt 1,6 millioner dollar ved en pris på 0,02 dollar per token, øremerket bug bounty-utbetalinger i 2026, og 20 millioner ZK, rundt 400.000 dollar, for å dekke allerede verifiserte utbetalinger gjort i 2025. Det aktive Immunefi-programmet for ZKsync OS, oppdatert tidlig september 2026, opererer med en kritisk maksbelønning på 100.000 dollar og en minimumsbelønning på 30.000 dollar for kritiske funn, beregnet som ti prosent av direkte berørte midler. Lavere alvorlighetsgrader utbetales flatt, med beløp som 20.000 og 5.000 dollar. Utbetalinger skjer i USDC på zkSync Era selv, med prisberegning basert på gjennomsnitt mellom CoinMarketCap og CoinGecko på rapporteringstidspunktet.
Du trenger ikke å administrere ditt eget bug bounty-program for å dra nytte av denne kulturen. Publiser kontraktsadressen din tydelig, oppfordre til ansvarlig varsling, og vurder å knytte deg til Immunefi sitt økosystem av registrerte programmer dersom prosjektet vokser forbi et hobbystadium.
Vanlige fallgruver ved utrulling på zkSync Era
De fleste feilene som rammer nye zkSync-prosjekter, handler ikke om eksotiske kryptografiske svakheter. De handler om vaner overført ureflektert fra Ethereum mainnet, kombinert med den samme typen menneskelige feil som rammer alle blokkjedeprosjekter: dårlig nøkkelhygiene og manglende testing. Her er de syv vi ser oftest, i omtrent den rekkefølgen de dukker opp i et typisk prosjektforløp.
- Å anta at EVM-bytekode er identisk med Ethereum mainnet. zkSync Era kjører sin egen EraVM, og selv om full EVM-bytekodekompatibilitet nå er live i 2026, kan gassmodellen og systemkontraktene fortsatt oppføre seg annerledes enn du forventer fra mainnet-vaner.
- Å glemme at operatøren må kjenne bytekoden på forhånd. Factory-mønstre som deployer nye kontrakter dynamisk on-chain krever at bytekoden allerede er publisert og kjent, ellers feiler utrullingen stille eller med en kryptisk feilmelding.
- Å beholde admin-rollen på en enkeltlommebok inn i produksjon. Dette var nøyaktig svakheten som ble utnyttet i april 2025-hendelsen mot zkSync sine egne airdrop-kontrakter.
- Å hoppe over lokal testing og gå rett til testnett eller mainnet. Feil som ville tatt sekunder å fange lokalt, koster testnett-ETH og tid å diagnostisere når de først skjer on-chain.
- Å stole på
.calluten reentrancy-vakt fordi gassen er billig. Lav gasskostnad på L2 endrer ikke kontraktens sårbarhet for reentrancy-angrep i det hele tatt. - Å commite
.env-filen med privatnøkkelen ved et uhell. Sjekk alltid.gitignorefør første commit, ikke etter. - Å ikke verifisere kontrakten før lansering. En uverifisert kontrakt ser mistenkelig ut for brukere og gjør det umulig for tredjeparter å revidere koden din uten å dekompilere bytekode manuelt.
Feilsøking: 8 vanlige feil og løsninger
Selv med et nøye planlagt deploy-forløp vil du før eller siden treffe en av disse. De fleste løses raskere enn feilmeldingen antyder, forutsatt at du vet hvor du skal se først.
| Feilmelding eller symptom | Sannsynlig årsak | Løsning |
|---|---|---|
| “Error: Deployer artifact not found” | Kontrakten er ikke kompilert med zksolc | Kjør npx hardhat compile --network zkSyncSepolia på nytt |
| “Insufficient funds for gas” | Testnett-lommeboken mangler ETH | Skaff mer testnett-ETH fra en zkSync Sepolia-faucet |
| Verifisering feiler med “bytecode mismatch” | Solidity- eller zksolc-versjon i config matcher ikke versjonen brukt ved deploy | Lås versjonsnumrene i hardhat.config.ts og kompiler på nytt før ny verifisering |
| “Reentrancy oppdaget” ved legitime kall | Låsen i ikkeReentrant ble ikke frigitt etter en tidligere feilet transaksjon | Sjekk at modifikatoren alltid setter laast = false, også ved revert-baner |
| “Nonce too low” ved gjentatt deploy | Flere deploy-forsøk fra samme lommebok uten å vente på bekreftelse | Vent på transaksjonskvittering før neste kall, eller sett nonce eksplisitt |
| Transaksjonen henger uten bekreftelse | RPC-endepunktet er midlertidig overbelastet | Bytt til et alternativt offentlig RPC-endepunkt eller prøv igjen om noen minutter |
| “Function selector was not recognized” | ABI-en i frontend eller script matcher ikke faktisk deployet kontrakt | Regenerer ABI fra siste kompilering og oppdater alle klienter |
| Multisig-transaksjon utføres aldri | For få signaturer samlet inn, eller feil terskel konfigurert | Bekreft terskel og signatærliste i multisig-grensesnittet før ny utrullingsforsøk |
Sitter du fast utover disse åtte, er neste steg alltid det samme: isoler problemet på Sepolia-testnettet, ikke mainnet, og sammenlign transaksjonsdataene dine mot et minimalt fungerende eksempel før du antar at feilen ligger i din egen kontraktslogikk.
Avanserte tips: gasskostnader, paymasters og kontoabstraksjon
Når grunnoppsettet fungerer, er det tre områder som skiller en amatørutrulling fra et produksjonsklart prosjekt på zkSync Era.
Det første er paymasters. zkSync Era har innebygd støtte for kontoabstraksjon, som gjør det mulig å bygge en paymaster-kontrakt slik at brukere kan betale gass i et ERC-20-token i stedet for ETH. Dette er spesielt relevant for nordiske prosjekter rettet mot sluttbrukere uten kryptoerfaring, siden det fjerner kravet om at brukeren først må skaffe ETH bare for å kunne betale gass.
Det andre er kostnadsplanlegging. Med en beviskostnad rundt 0,0001 dollar per overføring i det nyeste Atlas-oppsettet, blir det økonomisk forsvarlig å bygge applikasjoner med hyppige, små transaksjoner, noe som historisk sett har vært upraktisk på Ethereum mainnet. Bygg gasskostnad inn i produktbeslutninger tidlig, ikke som en etterpåklokskap. Har du for eksempel et produkt som logger hundrevis av små hendelser per bruker per dag, hvor hver hendelse tidligere måtte samles i batcher for å holde mainnet-kostnadene nede, kan den samme logikken nå potensielt kjøre som individuelle transaksjoner uten at kostnadsbildet eksploderer, forutsatt at du selv verifiserer faktiske gasspriser på tidspunktet du bygger, siden priser i kryptomarkeder svinger raskt.
Det tredje er likviditetsrisiko. L2BEAT og DeFiLlama sporer total verdilåst på tvers av L2-er, og zkSync Era har historisk hatt vesentlig lavere TVL enn de største optimistiske rollupene som Arbitrum og Base. Ifølge DeFiLlama, med data oppdatert 22. juli 2025, lå zkSync Era sin DeFi-TVL på rundt 54,9 millioner dollar, mens bridged TVL, altså totalverdien som er brodd inn til nettverket, lå på rundt 252,98 millioner dollar. Lavere TVL betyr generelt tynnere likviditet for DeFi-integrasjoner, noe som bør inngå i risikovurderingen din dersom prosjektet er avhengig av dype likviditetspools.
Vil du la brukere betale gass i et ERC-20-token, kan du bygge en enkel paymaster-kontrakt og koble den inn i deploy-scriptet ditt. Under vises et minimalt skjelett som illustrerer mønsteret, ikke en produksjonsklar implementasjon.
// contracts/EnkelPaymaster.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IPaymaster.sol";
import "@matterlabs/zksync-contracts/l2/system-contracts/interfaces/IPaymasterFlow.sol";
contract EnkelPaymaster is IPaymaster {
address public eier;
modifier kunEier() {
require(msg.sender == eier, "Kun eier");
_;
}
constructor() {
eier = msg.sender;
}
function validateAndPayForPaymasterTransaction(
bytes32,
bytes32,
Transaction calldata transaction
) external payable returns (bytes4 magic, bytes memory context) {
magic = PAYMASTER_VALIDATION_SUCCESS_MAGIC;
context = "";
}
function postTransaction(
bytes calldata,
Transaction calldata,
bytes32,
bytes32,
ExecutionResult,
uint256
) external payable {}
receive() external payable {}
}
Fyll paymasteren med ETH slik at den kan dekke gassen på vegne av brukeren, og legg inn din egen valideringslogikk for hvilket ERC-20-token du aksepterer som betaling. Dette er avansert funksjonalitet, så test den grundig på Sepolia-testnettet før du vurderer mainnet, siden feil i valideringslogikken kan la angripere tømme paymasterens ETH-beholdning.
Tenk på en paymaster som en egen, separat sikkerhetsflate ved siden av hovedkontrakten din. Den bør ha sitt eget budsjett, sin egen overvåking av ETH-beholdning, og helst en øvre grense per transaksjon slik at en enkelt feilkonfigurert klient ikke kan tømme hele paymaster-saldoen i én operasjon. Mange prosjekter starter uten paymaster i det hele tatt, og legger den til først når brukerdataene faktisk viser at manglende ETH er en reell friksjon i onboardingen, ikke en antatt en.
Sikkerhetssjekkliste før mainnet-lansering
Før du kjører deploy-scriptet mot zkSyncMainnet, gå gjennom denne listen. Den oppsummerer stegene over i en form du kan bruke som faktisk sjekkliste i et kodegjennomgang- eller release-møte.
- Kontrakten er kompilert med korrekt låst zksolc- og Solidity-versjon, og disse versjonene er dokumentert i README.
- Alle tester i
test/-mappen kjører grønt mot en lokal in-memory-node, inkludert testen som forsøker reentrancy. - Admin-rollen er overført fra utrullerens enkeltlommebok til en multisig, og terskelen er verifisert manuelt av minst to personer.
- Kontrakten er deployet og fullt verifisert på zkSync Sepolia først, med identisk konstruktørargument-struktur som planlagt for mainnet.
- Privatnøkler og seed-fraser finnes ikke i noen commit-historikk, sjekket med et verktøy som skanner Git-historikk for hemmeligheter.
- Det finnes en plan for overvåking: enten egne event-lyttere, en tredjepartstjeneste, eller manuell periodisk gjennomgang av kontraktens transaksjonshistorikk på eksploreren.
- Kontraktsadressen og ABI-en er publisert et sted brukere og eventuelle sikkerhetsforskere faktisk kan finne dem.
zkSync Era vs. optimistic rollups: hva validitetsbevis betyr for sikkerheten
Mange norske utviklerteam står overfor et reelt valg mellom en zk-rollup som zkSync Era og en optimistisk rollup som Arbitrum. Begge er Ethereum layer 2-løsninger, men sikkerhetsmodellene er fundamentalt forskjellige, og det bør styre hvilken du velger for et gitt prosjekt. Valget handler sjelden om hvilken teknologi som er “best” i abstrakt forstand, det handler om hvilken risikoprofil som passer applikasjonen din, brukerne dine og hvor mye tid teamet realistisk kan bruke på sikkerhetsarbeid utover selve kontraktskoden.
| Egenskap | zkSync Era (zk-rollup) | Optimistisk rollup |
|---|---|---|
| Sikkerhetsmekanisme | Validitetsbevis, verifisert kryptografisk før batch godtas | Fraud proofs innenfor en utfordringsperiode |
| Tid til fullstendig L1-finalitet | Rundt ett sekund for selve zk-beviset, ifølge Atlas-oppgraderingen | Typisk syv dager, avhengig av implementasjon |
| Avhengighet av watchers | Ikke nødvendig, beviset er selvstendig verifiserbart | Sikkerheten avhenger av at noen faktisk bestrider en ugyldig batch |
| EVM-kompatibilitet | Full EVM-bytekodekompatibilitet, live i 2026 | Vanligvis full EVM-ekvivalens fra start |
| Uttakstid til L1 for brukere | Raskere enn optimistiske rollups i normal drift, siden det ikke er noen utfordringsperiode | Kan kreve å vente ut utfordringsperioden, med mindre en likviditetsbro brukes |
Konklusjonen er ikke at den ene modellen er strengt bedre enn den andre. Validitetsbevis fjerner avhengigheten av aktive watchers og gir raskere kryptografisk finalitet, men det stiller også strengere krav til at operatøren kjenner kontraktens bytekode på forhånd, slik vi så i steg 3 og 4. Optimistiske rollups har lengre historikk og typisk høyere TVL, men lener seg på at noen faktisk oppdager og bestrider feil innenfor tidsvinduet.
Når du bør velge zkSync Era
Velg zkSync Era når applikasjonen din er avhengig av rask, endelig oppgjør, for eksempel betalingsløsninger, tokeniserte eiendeler eller enhver flyt der brukeren venter aktivt på bekreftelse. Kryptografisk finalitet på sekundnivå er vanskelig å matche med en modell som strukturelt krever en flerdagers utfordringsperiode. Prosjekter som prioriterer å minimere tillit til aktive overvåkere, og som kan leve med noe tynnere DeFi-likviditet enn de aller største rollupene, er også et naturlig utgangspunkt.
Når en optimistisk rollup passer bedre
Velg en optimistisk rollup som Arbitrum når prosjektet er tungt avhengig av dyp eksisterende DeFi-likviditet, etablerte integrasjoner og et modent verktøyøkosystem bygget opp over flere år. Optimistiske rollups har generelt hatt lenger tid i produksjon under reell belastning, og for mange standardapplikasjoner uten strenge krav til finalitetstid, er forskjellen i brukeropplevelse i praksis liten. Har prosjektet ditt allerede en etablert brukerbase på Arbitrum, er kostnaden ved å migrere sjelden verdt fordelen ved raskere finalitet alene.
Komplett prosjektoversikt: dette har du bygget
Etter å ha fulgt alle stegene over, sitter du igjen med en fungerende, versjonskontrollert mappestruktur som er klar for både testnett og mainnet.
zksync-sikker-kontrakt/
├── contracts/
│ └── SikkerHvelv.sol
├── deploy/
│ ├── deploy.ts
│ └── overfor-til-multisig.ts
├── test/
│ └── SikkerHvelv.test.ts
├── hardhat.config.ts
├── .env
├── .gitignore
└── package.json
Kontrakten din er kompilert med zksolc, testet lokalt mot reentrancy-forsøk, deployet til zkSync Sepolia, verifisert på den offisielle blokkjede-eksploreren, og administrert av en multisig i stedet for en enkeltlommebok. Det er nøyaktig den sikkerhetsbasisen zkSync sin egen dokumentasjon anbefaler, kombinert med lærdommen fra hendelsen i april 2025: kontraktslogikk og nøkkelhåndtering må sikres hver for seg, ikke bare den ene.
Herfra er det naturlige neste steget å utvide kontrakten med faktisk forretningslogikk, koble på en paymaster dersom sluttbrukerne dine ikke har ETH fra før, og legge inn overvåkingen beskrevet lenger opp før du rører reelle midler. Behold vanen med å teste enhver endring lokalt før den når Sepolia, og la Sepolia være siste stopp før mainnet, aldri et hopp du dropper fordi endringen “bare er liten”. De fleste sikkerhetshendelser i DeFi-økosystemet, inkludert zkSync sin egen fra 2025, stammer fra nøyaktig den typen snarveier, ikke fra ukjente kryptografiske svakheter i selve rollupen.
Ofte stilte spørsmål
Er zkSync Era trygt å bruke for norske utviklere i 2026?
Protokollen selv, altså validitetsbevis-mekanismen og ZK-tokenkontrakten, forble ifølge zkSync uberørt av hendelsen i april 2025. Risikoen ligger nesten alltid i hvordan enkeltprosjekter håndterer egne admin-nøkler og kontraktslogikk, ikke i selve L2-protokollen.
Trenger jeg en ny lommebok for å bruke zkSync Era?
Nei. Standard Ethereum-lommebøker som MetaMask fungerer, du legger bare til zkSync Era som et eget nettverk med riktig RPC-URL, enten for Sepolia-testnettet eller mainnet.
Hva er forskjellen på zksolc og standard Solidity-kompilatoren?
zksolc er Matter Labs sin egen kompilator som oversetter Solidity til bytekode som kjører korrekt på EraVM, zkSync sin egen virtuelle maskin. Standard solc-bytekode kan ikke deployes direkte på zkSync uten denne omveien.
Hvor lang tid tar kontraktsverifisering på zkSync Era Block Explorer?
Selve API-kallet mot verifiseringsendepunktet er raskt, normalt under ett minutt, forutsatt at kompilatorversjon og innstillinger i forespørselen matcher nøyaktig det som ble brukt ved utrulling.
Bør jeg alltid bruke multisig for admin-funksjoner, selv på små prosjekter?
Ja, dersom kontrakten håndterer reelle midler. Hendelsen i april 2025 rammet nettopp fordi én enkelt nøkkel hadde full administrasjonsmakt over kontrakter med reell verdi. Kostnaden ved å sette opp en multisig er lav sammenlignet med risikoen ved en enkeltnøkkel-kompromittering.
Kan jeg bruke Foundry i stedet for Hardhat på zkSync Era?
Ja, det finnes en egen zkSync-tilpasning av Foundry-verktøykjeden, men denne guiden bruker Hardhat siden det for øyeblikket har den mest modne og offisielt vedlikeholdte plugin-støtten fra Matter Labs.
Hva skjer hvis jeg finner en sårbarhet i en kontrakt på zkSync Era?
Rapporter den ansvarlig gjennom Immunefi dersom prosjektet har et registrert bug bounty-program. ZKsync sitt eget program for ZKsync OS gir opptil 100.000 dollar for kritiske funn, og ansvarlig varsling er alltid å foretrekke fremfor å utnytte funnet.
Er zkSync Era raskere enn Arbitrum for sluttbrukere?
For selve uttak til Ethereum mainnet, ja som regel, siden validitetsbevis fjerner behovet for en flere dagers utfordringsperiode. For vanlige transaksjoner innenfor L2-en er begge nettverkene raske nok til at forskjellen sjelden merkes av sluttbrukeren.




