Deploy
Locally#
With your local network still running (from Getting Started):
npm run deployIt writes packages/app/src/deployments/local.json (address, election, candidates) that the frontend reads.
With my local network running, run npm run deploy, then explain what an Aztec deploy does (publish the contract class, deploy an instance at a deterministic address, run its public initializer) and why re-running the script is idempotent. Open scripts/deploy.ts in my editor and walk me through the declarative deploy graph.
deploy.ts doesn't issue raw transactions — it's a declarative spec for a tiny deploy framework. You describe the contracts that must end up on-chain and the txs to send; the engine resolves deterministic addresses, takes an on-chain inventory, and runs only what's still missing, in dependency order:
steps: {
// The voting contract is published on-chain; its initializer takes the admin address.
voting: {
kind: "contract",
contract: PrivateVotingContract,
deployer: (resolve) => resolve.account("admin"),
initializerArgs: (resolve) => [resolve.account("admin")],
mode: "publish",
},
// The private fpc used on testnet. No public deployment, just wallet registration.
...(network === "local"
? {}
: {
fpc: {
kind: "contract" as const,
contract: PrivateFeeJuiceContract,
deployer: (resolve) => resolve.account("admin"),
salt: FPC_SALT,
mode: "register" as const,
},
}),
// Open the demo election so the frontend can cast votes immediately. `vote_active`
// is the idempotency gate — `start_vote` reverts if called twice.
startVote: {
kind: "action",
from: (resolve) => resolve.account("admin"),
dependsOn: ["voting"],
call: (ctx) => ctx.instance("voting").methods.start_vote(ELECTION),
done: async (ctx) => {
const { result } = await ctx
.instance("voting")
.methods.vote_active(ELECTION)
.simulate({ from: ctx.account("admin") });
return Boolean(result);
},
},
},Each contract address is a deterministic function of (class, deployer, salt, args), so the run is idempotent — re-running only does what's missing (here, start_vote is gated behind its own vote_active check). On local, fees are paid by the SponsoredFPC; the JSON the frontend reads is written to packages/app/src/deployments/local.json.
Ready to go beyond local? Deploy to testnet is a side quest from here.