Deployer
The deployer plans and executes intent-based contract deployments with idempotency guarantees. It handles both plain contract creation and CREATE2 deterministic deployments, wit...
Source file: internal/deployer/deployer.go
The deployer plans and executes intent-based contract deployments with idempotency guarantees. It handles both plain contract creation and CREATE2 deterministic deployments, with on-chain confirmation and registry write-back.
Design decisions
Idempotency by key, not by state
Deployments are keyed by idempotency_key + chain_id. Before broadcasting, the deployer checks the registry for an existing record. If found and confirmed on-chain (bytecode > 0 at the address), it returns the existing deployment with Existing: true. This makes retries safe: the same key always returns the same address.
CREATE2 support
CREATE2 deployments use a deterministic factory pattern. The deployer:
- Computes the deterministic address from
deployer(factory),salt(32 bytes), andkeccak256(initCode) - Checks if code already exists at that address
- If not, builds a factory call:
to = deployer,data = salt ++ initCode - After broadcast, uses the precomputed
create2Addras the deployment address (not the receipt'sContractAddress, which is the factory call's receipt)
func computeCreate2(deployerHex, saltHex string, initCode []byte) (common.Address, error)
On-chain confirmation
Before returning an existing deployment, the deployer verifies the contract is actually on-chain:
func (d *Deployer) confirmOnChain(ctx context.Context, chainID, address string) (bool, error)
This calls eth_getCode and checks len(code) > 0. This prevents returning stale registry entries from reverted deployments or chain resets.
Constructor arg packing
Constructor arguments are ABI-encoded and appended to the creation bytecode:
func packConstructor(art registry.ArtifactRecord, args json.RawMessage) ([]byte, error)
- Decodes bytecode from hex
- If args present and not
null: callsabienc.PackConstructorArgs(art.ABI, args) - Returns
bytecode ++ packedArgs
Wallet integration
The deployer delegates signing and broadcasting to the wallet gate:
Wallet.Authorize(capabilityToken, spendCap, chainID)— policy checkWallet.Sign(ctx, client, intent, policy)— sign or delegate- If
RawTxreturned:client.SendRawTransaction(ctx, res.RawTx)— broadcast - If
TxHashreturned: signer already broadcast (embedded wallet mode) client.WaitReceipt(ctx, txHash)— poll for confirmation
Registry write-back
After successful deployment, the record is written to the registry:
registry.DeploymentRecord{
IdempotencyKey: key,
ChainID: chainKey,
Contract: contract,
Address: address,
TxHash: txHash,
Confirmed: txHash != "" || existing,
ProjectID: projectID,
}
Deployment flow
DeployRequest{idempotency_key, chain_id, contract, constructor_args, create2?}
│
▼
Check registry for existing deployment by key+chain
│
├── Found + confirmed on-chain → return Existing: true
│
└── Not found / not confirmed
│
▼
Resolve artifact from registry (projectID:contract)
│
▼
Resolve chain profile
│
▼
Pack constructor args + bytecode
│
▼
Build TxIntent (plain or CREATE2)
│
▼
Authorize via wallet policy gate
│
▼
Sign + broadcast
│
▼
Wait for receipt
│
▼
Record in registry
│
▼
Return DeployResponse
Error codes
| Code | Retry | Meaning |
|---|---|---|
DEPLOY_FAILED | varies | Deployment planning or broadcast failed |
ARTIFACT_NOT_FOUND | no | Compile first or wrong project_id |
WALLET_NOT_CONFIGURED | no | No signer configured |
WALLET_POLICY_DENIED | no | Spend cap or allow-list rejected |
CHAIN_NOT_FOUND | no | Unknown chain_id |
CHAIN_RPC_FAILED | yes | RPC dial or transport error |
Modifying the deployer
| What to change | Where |
|---|---|
| Add deployment metadata | pkg/types/deploy.go — DeployRequest/DeployResponse |
| Change CREATE2 formula | internal/deployer/deployer.go — computeCreate2 |
| Add proxy deployment | New method — UUPS/transparent proxy pattern |
| Change confirmation logic | internal/deployer/deployer.go — confirmOnChain |
| Add multi-chain deploy | internal/deployer/deployer.go — loop over chain IDs |
