Remix Bounties Split v20
A music & sound tool that turns remix bounties into a one-click, gas-sponsored EVVM payment.
Split payment· evvm
Section · Onchain
full primer →The primitive.
One signed message from songwriters pays every remix bounties recipient atomically via EVVM's split primitive; the fisher settles the whole payout for zero user gas.
Why this primitiveOne signed message pays many recipients atomically via Core.split.
Kernel
One signed message pays many recipients atomically via Core.split.
Drives the UI as
Enter a payee list with shares; one sponsored click settles everyone.
Required keys.
METAMASK_PRIVATE_KEY
Sepolia deployer + fisher wallet (single-EOA model). Fund via the Google Cloud faucet.
open ↗PRIVY_APP_ID
Enables Google sign-in and sponsored transactions. Toggle Gas sponsorship → Sepolia in the dashboard.
open ↗Add these in your Lovable project under Settings → Secrets before pasting the prompt below.
Appendix · Mega-prompt
The build prompt.
budget · 1 message
Paste into a fresh Lovable project. Make sure all five secrets above are set first. read the build strategy →
Build "Remix Bounties Split v20" in ONE Lovable message. Single-page demo on Ethereum Sepolia.
CONCEPT
A music & sound tool that turns remix bounties into a one-click, gas-sponsored EVVM payment.
Discipline: Music & Sound (remix bounties).
EVVM primitive: Split payment. Why: One signed message pays many recipients atomically via Core.split.
EVVM STANDING ORDERS (self-contained — do NOT rely on any external skill)
Chain: Ethereum Sepolia (chainId 11155111). Auth: Privy (Google/email/wallet), embedded wallet.
Gas: Native Privy sponsorship — enable in Privy dashboard → Gas sponsorship → App pays → Sepolia →
"Allow transactions from the client".
Signing rule: EVVM messages are EIP-191 personal_sign of a CSV STRING (not abi-encoded):
"{evvmId},{senderExecutor},{hashPayload},{originExecutor},{nonce},{isAsyncExec}"
Addresses lowercase, booleans literal "true"/"false".
hashPayload rule: hashPayload = keccak256(abi.encode("<functionName>", ...on-chain hash args ONLY))
Include ONLY the fields the on-chain hashDataForX view hashes — nothing else. Do NOT include
evvmId, nonce, or isAsyncExec in the hash; they live in the outer CSV. Example for Core.pay
it is 5 args exactly:
keccak256(abi.encode("pay", to, identity, token, amount, priorityFee))
A wrong shape reverts InvalidSignature (selector 0x8baa579f) with no useful message. Always
cross-check locally against the hashDataForX view before shipping.
Sender rules (multi-leg flows):
- Single-leg op: senderExecutor = 0x0
- Two-leg (MNS reveal, staking, swap, split):
op leg → senderExecutor = 0x0
pay leg → senderExecutor = address of the CALLING contract (NameService / Staking / Swap / Core)
Nonces: random uint256 from 32 bytes of crypto.getRandomValues; isAsyncExec = true.
Browser-signing rule: any op that binds a user 'from' address (deposit, withdraw, split, MNS, staking,
swap) MUST be signed by the connected Privy wallet. The fisher route re-derives the expected message,
runs verifyMessage against the user's address, then broadcasts with its own EOA paying gas.
Privy mount rule: NEVER import @privy-io/react-auth at module scope of a route file.
Wrap in <ClientOnly><Suspense><LazyPrivyEntry/></Suspense></ClientOnly>. PrivyProvider config:
{ loginMethods:["google","email","wallet"],
embeddedWallets:{ ethereum:{ createOnLogin:"users-without-wallets" } },
defaultChain: sepolia, supportedChains:[sepolia] }
DO NOT pass uiOptions:{ showWalletUIs:false } — aborts with "signal is aborted without reason".
DO NOT wire ZeroDev/paymaster URLs — native Privy sponsorship handles it.
Sponsored host-chain sends (Fund-EVVM, any host-chain user tx):
await sendTransaction(
{ to, data, chainId: 11155111 },
{ sponsor: true, address: embedded.address }
);
Both fields (sponsor + address) are required or Privy silently falls back to a user-paid path.
Fund-EVVM is a TWO-STEP host-chain flow (both via the sponsored send above):
1. USDC.approve(Treasury, amount) // atomic USDC units, uint256
2. Treasury.deposit(USDC, amount) // pulls the approved amount into EVVM
Refetch Core.getBalance(user, USDC) after settle. Show approve+deposit as two buttons.
Decimal USDC UX (non-negotiable):
- Inputs: <input inputMode="decimal" defaultValue="0.01" /> — never "USDC (micro)" labels.
- Parse: parseUnits(str.trim(), 6) // → bigint atomic
- Format: `${formatUnits(wei, 6)} USDC`
- Never render raw atomic values like "10000" in the UI. Contracts still receive the atomic bigint.
Balance preflight (mandatory before ANY user-signed op that spends inside EVVM — pay, split, MNS
pay leg, staking, swap, x402 settle, shielded deposit): read Core.getBalance(user, token) on mount
and after every settle. Gate the submit button when balance < required and render an amber
"Insufficient EVVM USDC — top up first" notice pointing at the Fund-EVVM card. Skipping this
produces InsufficientBalance (selector 0xf4d678b8) reverts the user can't self-diagnose.
Deployment (in a Lovable Linux sandbox — participants deploy from THEIR project, not locally):
1. bash scripts/install-foundry.sh # installs foundry via Nix into the sandbox
2. node scripts/deploy-evvm.mjs # deploys the 6-contract EVVM stack + registers evvmId
Uses METAMASK_PRIVATE_KEY as deployer AND admin AND goldenFisher AND activator (single-EOA model).
Writes src/evvm/deployment.json { evvmId, core, staking, nameService, swap, treasury, usdc, chainId }.
3. node scripts/set-evvm-id.mjs # CRITICAL — Registry.register assigns the id but Core still
reports evvmId=0 until an admin calls Core.setEvvmID(assignedId). Every user signature (built
with the Registry id) reverts InvalidSignature (0x8baa579f) until this runs. Re-run whenever
Core is redeployed. The script reads evvmId from src/evvm/deployment.json and signs with
METAMASK_PRIVATE_KEY (the single-EOA admin).
Fisher: server-side viem wallet at src/lib/fisher.server.ts, uses METAMASK_PRIVATE_KEY.
Fisher routes: src/routes/api/public/fisher/*.ts (the /api/public/* prefix bypasses site auth on
published builds — verify signatures inside every handler).
Fisher response contract (every fisher route returns this exact shape):
{ ok: boolean, txHash?: `0x${string}`, explorer?: string, revert?: string, error?: string }
Build `explorer` server-side: `${evvmCfg.explorer}/tx/${txHash}`. On success the UI renders
a clickable "↗ View on Etherscan · <txHash slice>". On failure surface `revert` (decoded
selector) or `error` verbatim in the step log — do NOT swallow it.
Common revert selectors — decode and show human strings, do NOT show raw 0x-selectors:
InvalidSignature 0x8baa579f → wrong hashPayload shape, or Core.setEvvmID never ran
InsufficientBalance 0xf4d678b8 → payer EVVM balance too low; preflight must have caught this
ProofLengthWrongWithLogN 0x59895a53 → zkVault verifier ↔ bb.js version mismatch
REQUIRED SECRETS:
- PRIVY_APP_ID — Privy dashboard → App settings
- METAMASK_PRIVATE_KEY — Sepolia EOA that deploys + fishes; fund via https://cloud.google.com/application/web3/faucet/ethereum/sepolia
- SEPOLIA_RPC_URL — Alchemy Sepolia HTTPS URL (public RPCs throttle under load)
- ETHERSCAN_API_KEY — for verification via forge verify-contract
CREDIT LINE (must appear in UI footer AND as a NatSpec @notice on any deployed contract):
Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14.
MINIMUM VIABLE FLOW
1. Landing page. "Sign in with Google" via Privy — embedded wallet is auto-provisioned.
2. Show the user their EVVM USDC balance. If zero, render the fund-EVVM empty-state (address + copy
button + Circle faucet link + refresh).
3. Primary action: "Remix Bounties Split v20" — collect the inputs relevant to remix bounties.
4. On submit:
a. Client builds hashPayload = keccak256(abi.encode("<functionName>", ...typedArgs)) exactly per
the on-chain hashDataForX view for this flow.
b. Client builds the CSV message with the sender rules above (single-leg or two-leg as required
by "Split payment") and calls personal_sign via Privy.
c. Client POSTs { user, signature, args } to /api/public/fisher/<flow>.
d. Fisher route re-derives the expected message, verifyMessage's the user signature, then submits
the tx with METAMASK_PRIVATE_KEY (see src/lib/fisher.server.ts). Return the tx hash.
5. UI shows a Sepolia Etherscan link for the tx and a receipt tuned to "remix bounties".
CONTRACTS: reuse the deployed EVVM stack — see src/evvm/deployment.json. Do NOT redeploy per-idea.
If deployment.json.deployed is false, run: node scripts/deploy-evvm.mjs (from a Lovable sandbox
terminal, NOT from a user's laptop).
TAILORING NOTES for "remix bounties":
- Copy, iconography, and success states should read as Music & Sound content, not generic web3.
- Use the discipline vocabulary the audience already knows (songwriters, producers, indie labels, session musicians).
- Keep the whole build to ONE index route + ONE fisher route.
CREDIT (footer + on-chain @notice):
Built during the Creative AI & Quantum Hackathon organised by StreetKode Fam during Indian Krump Festival 14.
Market sizing.
TAM
the recorded-music market (~$28B) plus $10B in live royalties
SAM
A gas-sponsored payments slice of Music & Sound
estimate 10% of TAM.
SOM
The songwriters early-adopter segment
estimate 1% of TAM in year one.
Indicative figures for hackathon pitches — refine with your own research before raising.
Adjacent entries.
beat marketplace
Beat Marketplace Split
A music & sound tool that turns beat marketplace into a one-click, gas-sponsored EVVM payment.
remix bountiesRemix Bounties Split v2
A music & sound tool that turns remix bounties into a one-click, gas-sponsored EVVM payment.
beat marketplaceBeat Marketplace Split v3
A music & sound tool that turns beat marketplace into a one-click, gas-sponsored EVVM payment.
remix bountiesRemix Bounties Split v4
A music & sound tool that turns remix bounties into a one-click, gas-sponsored EVVM payment.