feat(deploy): optional contract deploy for foundry, hardhat, cdm#38
Merged
charlesHetterich merged 9 commits intomainfrom Apr 22, 2026
Merged
feat(deploy): optional contract deploy for foundry, hardhat, cdm#38charlesHetterich merged 9 commits intomainfrom
charlesHetterich merged 9 commits intomainfrom
Conversation
… and cdm projects
Detects a contract project at the deploy root via three signals:
- `foundry.toml` → foundry path
- `hardhat.config.{ts,js,...}` → hardhat path
- `Cargo.toml` w/ pvm_contract → cdm path
When detected, the TUI prompts "deploy contracts?" (default no) between
the playground prompt and confirm; non-interactive callers pass `--contracts`.
A new `contracts` phase runs after `build` and before `storage-and-dotns`.
When the user picks "no", or no project is detected, the phase emits
`phase-skipped` so the TUI collapses the row instead of leaving it pending.
All three paths converge on the same Substrate-extrinsic deploy: each one
compiles locally to PolkaVM bytecode, writes the bytes to a tmp `.polkavm`
file, then hands every file to `@dotdm/contracts` `ContractDeployer.deployBatch`,
which weight-aware-chunks them into one or more `Utility.batch_all` calls
on Asset Hub. This means the existing signer plumbing (`//Alice` in
`--signer dev`, the user's session signer in `--signer phone`) signs the
contract instantiations directly — no ECDSA private key, no hardhat-ethers
wallet, no foundry keystore.
Per-language compile:
- foundry → `forge build --resolc` (the polkadot fork's PolkaVM codegen;
`--resolc` is forced rather than relying on `foundry.toml`
config so a plain forge-init project Just Works). Reads
`out/<C>.sol/<C>.json:bytecode.object`. Skips `.t.sol` and
`.s.sol` directories.
- hardhat → `npx hardhat compile`. Reads
`artifacts/contracts/<C>.sol/<C>.json:bytecode`.
- cdm → `@dotdm/contracts` `buildContracts({ rootDir })`, which uses
cargo metadata for layered detection and pvmContractBuildAsync
for per-crate compilation.
Solidity output is validated against the `0x50564d00` ("PVM\0") magic
header before deploy, so a foundry user who skipped `--resolc` (or a
hardhat user who forgot to load `@parity/hardhat-polkadot`) gets a
targeted error instead of a cryptic pallet revert later.
Contributor
|
Dev build ready — try this branch: |
…logged in user during init
- `runDeploy` runs the contracts phase and the frontend build+upload concurrently via `Promise.all`; playground publish stays sequential after both.
- `RunningStage` rewritten: vertical `contracts` / `frontend` sections, per-contract rows showing a spinner → checkmark + full on-chain address (truncate-middle on narrow terminals, 1-char right pad), playground as a single line below. Stays mounted through `done` / `error` so `FinalResult` renders below the sections the way `dot init` keeps its dep list.
- `deploy-chunk` event now carries `{ contracts: [{ name, address }] }` so rows flip to complete + populate the address incrementally as each chunk lands, instead of all at once at `deploy-done`. All rows spin from `compile-detected` onward so cdm's 10–20 s pre-submit silence stops looking like a freeze.
- `runStreamed` consolidated into `src/utils/process.ts`; `build/runner.ts`, `deploy/contracts.ts`, and `toolchain.ts` import from there (−130 duplicated lines).
- `StepRunner` gets coalesced log updates (ref + 100 ms timer, 160-char cap) so firehose sources can't re-trigger the 20 GB reconciler bug.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contracts in
dot deploySummary
dot deploycan now compile and deploy the project's contracts alongsidethe frontend. Supports foundry, hardhat, and cdm projects — detected at the
project root from
foundry.toml,hardhat.config.*, or aCargo.tomlwitha
pvm_contractdep. Off by default: the TUI asks "deploy contracts?" whena contract project is detected; headless runs opt in with
--contracts.Contracts and the frontend build+upload run concurrently; the running-stage
TUI gains a
contractssection alongsidefrontend, with per-contract rowsshowing deployed addresses as each chunk lands.
Contract extrinsics are signed by a persistent on-disk session key at
~/.polkadot/accounts.json, not the mobile signer — today's mobile flowcan't handle the encoded size of a batched contract deploy, and the failure
is miscategorised as a user-cancel. The session key is funded by the user's
signer on first deploy (one phone tap) or by Alice in pure dev mode;
subsequent runs skip funding when balance is above threshold.
No constructor args, no registry publish, no on-chain metadata in this
first cut — follow-up work.
What's in the PR
dot deploy --contractsflag + interactive "deploy contracts?" promptrunDeployforge build --resolc,npx hardhat compile,or
@dotdm/contractsbuildContractsContractDeployer.deployBatch(weight-awareUtility.batch_all)src/utils/deploy/session-account.ts) with first-runRevive.map_accountbootstrap and session-key top-up flowcontracts+frontendsections with purereducer in
src/commands/deploy/runningState.tsdot initgains afoundry (polkadot)check that installsfoundryup-polkadotPeripheral
runStreamed/runShellconsolidated insrc/utils/process.ts(previously duplicated across build, contracts, and toolchain paths)
checkBalance/ensureFundedtake optional min-balance andfund-amount overrides
StepRunnerlog output now throttled to ≤10 Hz (samereconciler-backpressure mitigation as the deploy TUI)
extractFoundryBytecode,extractHardhatBytecode,hexToBytes) exported for unit testsrunningState,contractshelpers,session-account,signerModematrix,process,run(contracts-phase orchestration),detect.detectContractsType,summary(contracts row),deploy/indexhelpersTest plan
dot deployon a foundry project with--contracts→ forge compiles,contracts deploy, addresses shown in TUI, app still publishes
@parity/hardhat-polkadotloaded)no contracts → prompt skipped
Revive.map_accountsubmitted--contractson a non-contract project errors fastdot initoffers + installs foundry (polkadot)