D3ploy
A censorship-resistant deployment platform
Created on 15th March 2026
•
D3ploy
A censorship-resistant deployment platform
The problem D3ploy solves
The Problem
Every DeFi frontend today has a dirty secret: it's centralized.
The smart contracts are on-chain. The tokens are yours. But the website
you use to interact with them? It runs on AWS, Vercel, or Cloudflare
servers controlled by a company that can be hacked, subpoenaed, or simply
decide to pull the plug.
This has already caused real damage:
- Curve Finance, Uniswap, Balancer frontends hijacked via DNS attacks
to drain user wallets - Tornado Cash OFAC pressured the frontend offline within hours
- Compound, dYdX geo-blocked entire regions via their hosting provider
- Hundreds of smaller protocols taken offline the moment their Vercel
free tier expired or their domain registrar received a complaint
The smart contract is trustless. The frontend is not. That gap kills people.
What Deploy.eth Solves
Deploy.eth makes your entire stack trustless — not just the contracts.
🌐 For DeFi Protocol Teams
Ship a frontend that cannot be taken down.
web3deploy push # ✓ Site live on IPFS (content-addressed, immutable) # ✓ myprotocol.eth now resolves to your new build # ✓ No Vercel. No AWS. No domain registrar. No kill switch.
Your site lives on IPFS a global peer-to-peer network where files are
addressed by their content hash, not a server location. Nobody can redirect
it, modify it silently, or take it offline. Even if your entire team
disappears, the frontend keeps serving users.
Store your protocol config on-chain, not in a dashboard.
Every deploy writes your configuration to ENS text records publicly
auditable, immutable history, readable by your smart contracts:
swap.slippage → 0.5 fee.recipient → 0x... fee.bps → 30 access.policy → public monitor.riskLevel → medium
Users can verify exactly what your frontend is configured to do before
they connect their wallet. No more "trust us."
Require multi-sig approval before any frontend update goes live.
Malicious frontend updates are one of DeFi's biggest attack vectors.
Deploy.eth lets you require 3-of-5 team signatures before the ENS
contenthash changes making a frontend attack as hard as a smart
contract exploit.
📊 For DeFi Users
A live, intelligent frontend powered by Elsa x402 with no backend.
Because there's no server, there are no API keys to steal, no database
to breach, and no company to subpoena for your transaction history.
Every data call is a direct pay-per-use request:
| What you get | How | Cost |
|---|---|---|
| Portfolio across 15+ chains | elsa_get_portfolio | $0.01 |
| Live yield suggestions | elsa_get_yield_suggestions | $0.02 |
| Best swap quote across 20+ DEXs | elsa_get_swap_quote | $0.01 |
| P&L report | elsa_get_pnl_report | $0.015 |
Your ENS domain becomes your personal DeFi config — store your risk
tolerance, preferred chains, slippage limits, and the site respects them
automatically, every time, on any device, without logging in.
Your site watches your portfolio even when you're not looking.
ENS monitor records tell the site what to watch for:
monitor.alertThreshold → 0.15 (alert if 15% drawdown) monitor.autoRebalance → true monitor.preferredYield → 0.08 (suggest moves if APY < 8%)
When conditions are met, your ungoverned frontend surfaces the action.
You confirm. Elsa executes. No email. No notification from a company
that knows your wallet address.
🔒 For DAOs and Governance-Heavy Protocols
Make frontend deployments a governance action.
Right now, a DAO can vote on treasury decisions, parameter changes, and
contract upgrades — but a single developer can push a malicious frontend
unilaterally. Deploy.eth closes that gap.
Every frontend update is a proposal. Signers review the CID diff. The
ENS contenthash only changes when the threshold is met. The full deploy
history — who proposed what, when, with which CID — lives on-chain forever.
Environment routing without a backend.
myprotocol.eth → production (CID: bafybeig3...) staging.myprotocol.eth → staging (CID: bafybeia7...) v2.myprotocol.eth → beta (CID: bafybeif2...)
Each subname is independently owned. Staging can move fast. Production
requires governance. All of it lives in ENS — no DevOps, no infra bill.
🛠 For Developers
One command. Everything decentralized.
npx web3deploy init # scaffold config web3deploy push # build → IPFS → ENS → done web3deploy rollback # one command back to any previous deploy web3deploy env set swap.slippage 0.3 # update on-chain config
No accounts to create. No credit card. No vendor lock-in. If Deploy.eth
shuts down tomorrow, your site keeps running — the files are on IPFS,
the domain is in ENS, the history is on-chain. The platform is optional
infrastructure, not a dependency.
The Core Insight
A truly trustless DeFi app needs every layer to be trustless
not just
Challenges we ran into
Challenges I Ran Into
1. ENS
contenthash
encoding is not what you think it isThe first wall I hit. ENS doesn't store a raw IPFS CID string in the
contenthash
field — it stores a binary-encoded value following aspecific multicodec spec. Passing a raw CIDv1 string to the resolver
contract just reverts silently.
The CID has to be encoded as:
0xe3010170 + varint(cid-length) + cid-bytes
The
0xe3010170
prefix encodes the namespace (IPFS), the version, andthe codec. Miss any byte and the ENS gateway refuses to resolve it —
with no error message, just a blank page.
Fix: Used
@ensdomains/content-hash
library which handles theencoding correctly. But it took hours to diagnose because the ENS
resolver accepts the malformed transaction — it only fails silently
at resolution time, not at write time.
import { encode } from '@ensdomains/content-hash'; const encoded = encode('ipfs', cid); // '0xe301017012...'
2. IPFS CIDs change every build even when nothing changes
The second major hurdle. Vite's build output includes chunk hashes in
filenames —
index-BvXk3a91.js
— so every build produces a differentdist/
tree even if the source hasn't changed. Every different treeproduces a different root CID. This meant every
git push
, even aREADME typo fix, produced a new CID, a new ENS transaction, and ~$5-15
in gas fees on mainnet.
Fix 1: Switched to deterministic chunk naming in
vite.config.ts
:build: { rollupOptions: { output: { entryFileNames: 'assets/[name].js', chunkFileNames: 'assets/[name].js', assetFileNames: 'assets/[name].[ext]', } } }
Fix 2: Added a CID comparison step in the deploy script — reads the
current ENS
contenthash
, decodes it, compares with the new CID, andskips the ENS transaction entirely if they match:
const currentCid = await getCurrentEnsCid(domain); if (currentCid === newCid) { console.log('CID unchanged, skipping ENS update'); process.exit(0); }
Gas saved. Sanity restored.
3. Elsa x402 payment tokens expire mid-pipeline
The x402 payment flow generates a short-lived JWT-style payment token
before each API call. In a multi-step pipeline —
get_portfolio
→get_yield_suggestions
→execute_swap_dry_run
—if any step takes longer than expected (slow IPFS pin, RPC congestion),
the token for the next step has already expired by the time you use it.
This caused the swap dry-run to fail silently, returning a
402 Payment Required
response that I initially mistook for a broken endpoint.Fix: Generate payment tokens lazily — immediately before each
individual API call rather than upfront for the whole pipeline:
// ❌ Wrong — tokens generated upfront, may expire const tokens = await generateTokens(['portfolio', 'yield', 'swap']); await getPortfolio(tokens[0]); await sleep(3000); // tokens[1] may already be stale await getYield(tokens[1]); // ✅ Correct — token generated fresh per call await getPortfolio(await generateToken('portfolio')); await getYield(await generateToken('yield')); await executeDryRun(await generateToken('swap'));
4. ENS text record updates require a separate resolver transaction
I assumed updating the
contenthash
and updating text records couldbe batched into one transaction. They can't — at least not on the
standard public resolver. Each
setText
call is a separate transaction,and with 8 text records to update per deploy (CID, timestamp, framework,
env, tx hash, version, build command, node version), the deploy script
was firing 9 transactions sequentially.
At ~15 seconds per transaction confirmation and gas for each, a full
deploy was taking 3+ minutes and costing more in gas than the hosting
was worth.
Fix: Used ENS's
multicall
on the resolver contract, which batchesmultiple
setText
andsetContenthash
calls into a single transaction:const resolver = await provider.getResolver(domain); await resolver.multicall([ resolver.interface.encodeFunctionData('setContenthash', [node, encoded]), resolver.interface.encodeFunctionData('setText', [node, 'deploy.cid', cid]), resolver.interface.encodeFunctionData('setText', [node, 'deploy.timestamp', ts]), // ... all 8 records ]);
One transaction. One gas fee. Deploy time dropped from 3 minutes to
under 30 seconds.
5. IPFS gateway resolution lag breaks the "instant deploy" experience
After updating the ENS contenthash to a new CID, there's a propagation
delay before IPFS gateways (ipfs.io, cloudflare-ipfs.com, eth.limo)
actually serve the new content. The CID is correct in ENS immediately,
but visiting
myapp.eth.limo
still shows the old version for anywherefrom 30 seconds to 5 minutes.
Users opening the site right after a deploy would see the old version
with no indication that a new one exists — confusing and undermining
trust in the platform.
Fix: Two-part. First, added a deploy banner comp
Tracks Applied (4)
Privacy
AI
Best creative use of ENS
Ethereum Name Service
Best Use of Elsa x402 and Elsa OpenClaw skills
HeyElsa
Technologies used
Cheer Project
Cheering for a project means supporting a project you like with as little as 0.0025 ETH. Right now, you can Cheer using ETH on Arbitrum, Optimism and Base.