Serverless claim flow for Kanaria Founder/Super Founder NFT owners to claim a physical metal/plexi plate.
- Frontend: single-page static site in
src/index.html(no backend) - Contract:
solidity/KinzokuV2.sol(Base mainnet, chainId 8453) - Ops scripts:
scripts/(Bun) for deploys + decrypting claims + marking shipped
src/: frontend source (single HTML file)dist/: generated build output (dist/index.html) for ENS/IPFS deploymentsolidity/: Solidity contract sources (Foundrysrc)script/: Foundry scripts (deploy)test/: Foundry tests (fork tests)scripts/: Bun scripts (deploy frontend, deploy contract, decrypt claims, mark shipped)deployments/: deployment metadata written by scripts (e.g.deployments/8453.json)
Prereqs:
- Foundry (
forge,cast,anvil) - Bun
Install Bun deps:
cd scripts
bun installPut your secrets in scripts/.env (it’s gitignored). Copy from env.example.
PRIVATE_KEY:0x...hex private key.- Used for contract deployment (deployer becomes contract
owner) - Used for ENS contenthash update (must be the ENS owner of
kinzoku.rmrk.eth)
- Used for contract deployment (deployer becomes contract
BASE_RPC_URL: reliable Base RPC (used for writes and as the upstream for local forks)
BASESCAN_API_KEY: enablesforge script ... --verifyon Basescan duringcontract:deploy
Used by bun run frontend:deploy:
FILEBASE_BUCKETFILEBASE_BUCKET_KEY(prefix/path inside the bucket)FILEBASE_ROOT_KEYFILEBASE_ROOT_SECRETFILEBASE_ENDPOINT(optional; defaults tohttps://s3.filebase.com)
ENS_NAME(optional; defaultkinzoku.rmrk.eth)ETH_RPC_URL(optional; defaulthttps://eth.llamarpc.com)SKIP_ENS=1(optional; upload to IPFS but don’t touch ENS)DRY_RUN=1(optional; build only)
PUBLIC_BASE_RPC_URL(optional; defaults tohttps://mainnet.base.org)
KINZOKU_ADDRESS: if set, overrides readingdeployments/8453.jsonfor scripts/buildENCRYPTION_PUBKEY: if set, overrides readingscripts/kinzoku-keys.jsonfor frontend build
From kinzoku-v2/scripts/:
bun run contract:deployThis runs a CREATE2 deploy script (script/Deploy.s.sol) and writes deployment metadata to:
deployments/8453.json
Verification:
- If
BASESCAN_API_KEYis present, the deploy includes--verifyautomatically.
This starts an Anvil fork of Base and runs fork-tests using the address derived from PRIVATE_KEY (so you can exercise onlyTokenOwner against real Kanaria ownership on the fork):
cd scripts
bun run testNotes:
- If you run
forge testdirectly, these fork tests are skipped unless you setRUN_FORK_TESTS=1+FORK_URL=....
Claims store an encrypted payload on-chain (shipping address + contact + type).
Generate a keypair once:
cd scripts
bun run keygenOutputs:
scripts/kinzoku-keys.json(gitignored)publicKey: injected into the frontend buildsecretKey: used bybun run fetchto decrypt claims
Public key is auto hardcoded into frontend on build if it exists in the folder.
The frontend loads only local assets from src/assets/ (no CDN dependencies).
From scripts/:
bun run anvilThis starts an Anvil fork of Base at http://127.0.0.1:8545 (chainId 31337) and deploys KinzokuV2 to the fork.
On localhost, the frontend uses a hardcoded local contract address (so you don’t need to rebuild just to test):
KinzokuV2(local):0xC5273AbFb36550090095B1EDec019216AD21BE6c
If you want the local fork to reflect already-claimed birds from the old v1 contract, run:
cd scripts
bun run migrate:v1To reflect the same “already shipped in v1” status on Base mainnet, run:
cd scripts
bun run migrate:v1:basecd scripts
bun run frontend:buildThis writes dist/index.html + dist/assets/ and injects:
KINZOKU_ADDRESS(fromdeployments/8453.json, or env override)ENCRYPTION_PUBKEY(fromkinzoku-keys.json, or env override)
cd scripts
bun run frontend:deployFlow:
- Builds
dist/index.html+dist/assets/ - Uploads
dist/assets/to Filebase (IPFS) and rewritesdist/index.htmlto point at the pinned asset CIDs (viaFILEBASE_IPFS_GATEWAY) - Uploads the rewritten
dist/index.htmlto Filebase (IPFS) - Sets ENS contenthash on mainnet for
kinzoku.rmrk.eth(pointing at theindex.htmlCID)
- If the site is served from localhost (
localhost/127.0.0.1), it reads from Anvil (http://127.0.0.1:8545, chainId31337) - Otherwise it reads from public Base RPCs and prompts the wallet to switch to Base mainnet (
8453)
Wallet UX:
- If you have multiple injected wallets installed (e.g. MetaMask + Rabby), the UI uses EIP-6963 discovery and shows a small wallet picker so you can choose which wallet to connect.
cd scripts
bun run fetchReads from PUBLIC_BASE_RPC_URL (default https://mainnet.base.org) and decrypts with kinzoku-keys.json.
cd scripts
bun run fetch:localReads from local Anvil (LOCAL_RPC_URL, default http://127.0.0.1:8545) and decrypts with kinzoku-keys.json.
cd scripts
bun run ship 1 5 23Uses:
- public RPC for reads (
PUBLIC_BASE_RPC_URL) - paid RPC for writes (
BASE_RPC_URL)