Skip to content

Commit 0e49b51

Browse files
authored
feat(cli): save deployed contracts info (#3816)
1 parent feeadcd commit 0e49b51

File tree

6 files changed

+61
-24
lines changed

6 files changed

+61
-24
lines changed

.changeset/twelve-melons-relate.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
"@latticexyz/cli": patch
3+
"@latticexyz/common": patch
4+
---
5+
6+
The `mud deploy` command now includes the addresses of all deployed contracts and libraries in the deployment file. Previously, it only included the world address.
7+
8+
The `mud test` command now includes an optional 'saveDeployment' flag to enable the deployment info from the test run to be saved to a file.

packages/cli/src/commands/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ const testOptions = {
1414
"Address of an existing world contract. If provided, deployment is skipped and the RPC provided in the foundry.toml is used for fork testing.",
1515
},
1616
forgeOptions: { type: "string", description: "Options to pass to forge test" },
17+
saveDeployment: { type: "boolean", desc: "Save the deployment info to a file", default: false },
1718
} as const satisfies Record<string, Options>;
1819

1920
type TestOptions = InferredOptionTypes<typeof testOptions>;
@@ -45,7 +46,6 @@ const commandModule: CommandModule<typeof testOptions, TestOptions> = {
4546
(
4647
await runDeploy({
4748
...opts,
48-
saveDeployment: false,
4949
rpc: forkRpc,
5050
})
5151
).address;

packages/cli/src/deploy/deploy.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,15 @@ export async function deploy({
7171
deployerAddress: initialDeployerAddress,
7272
indexerUrl,
7373
chainId,
74-
}: DeployOptions): Promise<WorldDeploy> {
74+
}: DeployOptions): Promise<
75+
WorldDeploy & {
76+
/** Addresses of the deployed contracts */
77+
readonly contracts: readonly {
78+
readonly label: string;
79+
readonly address: Address;
80+
}[];
81+
}
82+
> {
7583
const deployerAddress = initialDeployerAddress ?? (await ensureDeployer(client));
7684

7785
const worldDeploy = existingWorldAddress
@@ -105,7 +113,7 @@ export async function deploy({
105113
}
106114

107115
const libraryMap = getLibraryMap(libraries);
108-
await ensureContractsDeployed({
116+
const deployedContracts = await ensureContractsDeployed({
109117
...commonDeployOptions,
110118
deployerAddress,
111119
contracts: [
@@ -203,5 +211,11 @@ export async function deploy({
203211
});
204212

205213
debug("deploy complete");
206-
return worldDeploy;
214+
return {
215+
...worldDeploy,
216+
contracts: deployedContracts.map(({ contract, deployedAddress }) => ({
217+
label: contract.debugLabel ?? "unknown",
218+
address: deployedAddress,
219+
})),
220+
};
207221
}

packages/cli/src/runDeploy.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
158158
const automine = await enableAutomine(client);
159159

160160
const startTime = Date.now();
161-
const worldDeploy = await deploy({
161+
const deployResult = await deploy({
162162
config,
163163
deployerAddress: opts.deployerAddress as Hex | undefined,
164164
salt,
@@ -176,7 +176,7 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
176176
if (opts.worldAddress == null || opts.alwaysRunPostDeploy) {
177177
await postDeploy(
178178
config.deploy.postDeployScript,
179-
worldDeploy.address,
179+
deployResult.address,
180180
rpc,
181181
profile,
182182
opts.forgeScriptOptions,
@@ -190,8 +190,9 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
190190
console.log(chalk.green("Deployment completed in", (Date.now() - startTime) / 1000, "seconds"));
191191

192192
const deploymentInfo = {
193-
worldAddress: worldDeploy.address,
194-
blockNumber: Number(worldDeploy.deployBlock),
193+
worldAddress: deployResult.address,
194+
blockNumber: Number(deployResult.deployBlock),
195+
contracts: deployResult.contracts,
195196
};
196197

197198
if (opts.saveDeployment) {
@@ -219,9 +220,9 @@ export async function runDeploy(opts: DeployOptions): Promise<WorldDeploy> {
219220
);
220221
}
221222

222-
console.log(deploymentInfo);
223+
console.log({ worldAddress: deploymentInfo.worldAddress, blockNumber: deploymentInfo.blockNumber });
223224

224-
return worldDeploy;
225+
return deployResult;
225226
}
226227

227228
function getWorldDeployBlock({

packages/common/src/deploy/ensureContract.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ export type Contract = {
1111
salt?: Hex;
1212
};
1313

14+
export type EnsureContractResult = {
15+
contract: Contract;
16+
deployedAddress: Hex;
17+
txHash: readonly Hex[];
18+
};
19+
1420
export async function ensureContract({
1521
client,
1622
deployerAddress,
@@ -21,7 +27,7 @@ export async function ensureContract({
2127
}: {
2228
readonly client: Client<Transport, Chain | undefined, Account>;
2329
readonly deployerAddress: Hex;
24-
} & Contract): Promise<readonly Hex[]> {
30+
} & Contract): Promise<EnsureContractResult> {
2531
if (bytecode.includes("__$")) {
2632
throw new Error(`Found unlinked public library in ${debugLabel} bytecode`);
2733
}
@@ -31,7 +37,11 @@ export async function ensureContract({
3137
const contractCode = await getCode(client, { address, blockTag: "pending" });
3238
if (contractCode) {
3339
debug("found", debugLabel, "at", address);
34-
return [];
40+
return {
41+
contract: { bytecode, deployedBytecodeSize, debugLabel, salt },
42+
deployedAddress: address,
43+
txHash: [],
44+
};
3545
}
3646

3747
if (deployedBytecodeSize != null) {
@@ -52,11 +62,15 @@ export async function ensureContract({
5262
}
5363

5464
debug("deploying", debugLabel, "at", address);
55-
return [
56-
await sendTransaction(client, {
57-
chain: client.chain ?? null,
58-
to: deployerAddress,
59-
data: concatHex([salt, bytecode]),
60-
}),
61-
];
65+
return {
66+
contract: { bytecode, deployedBytecodeSize, debugLabel, salt },
67+
deployedAddress: address,
68+
txHash: [
69+
await sendTransaction(client, {
70+
chain: client.chain ?? null,
71+
to: deployerAddress,
72+
data: concatHex([salt, bytecode]),
73+
}),
74+
],
75+
};
6276
}
Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { Client, Transport, Chain, Account, Hex } from "viem";
2-
import { Contract, ensureContract } from "./ensureContract";
2+
import { Contract, ensureContract, EnsureContractResult } from "./ensureContract";
33
import { waitForTransactions } from "../waitForTransactions";
44
import { uniqueBy } from "../utils/uniqueBy";
55

@@ -11,19 +11,19 @@ export async function ensureContractsDeployed({
1111
readonly client: Client<Transport, Chain | undefined, Account>;
1212
readonly deployerAddress: Hex;
1313
readonly contracts: readonly Contract[];
14-
}): Promise<readonly Hex[]> {
14+
}): Promise<EnsureContractResult[]> {
1515
// Deployments assume a deterministic deployer, so we only need to deploy the unique bytecode
1616
const uniqueContracts = uniqueBy(contracts, (contract) => contract.bytecode);
1717

18-
const txs = (
18+
const deployedContracts = (
1919
await Promise.all(uniqueContracts.map((contract) => ensureContract({ client, deployerAddress, ...contract })))
2020
).flat();
2121

2222
await waitForTransactions({
2323
client,
24-
hashes: txs,
24+
hashes: deployedContracts.map(({ txHash }) => txHash).flat(),
2525
debugLabel: "contract deploys",
2626
});
2727

28-
return txs;
28+
return deployedContracts;
2929
}

0 commit comments

Comments
 (0)