Skip to content

Commit

Permalink
fix(cli): fix verify with sourcify for dependencies (#2750)
Browse files Browse the repository at this point in the history
  • Loading branch information
yonadaa authored Apr 27, 2024
1 parent c3a2d59 commit b4eb795
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 88 deletions.
5 changes: 5 additions & 0 deletions .changeset/sour-otters-warn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@latticexyz/cli": patch
---

Patched `mud verify` to properly verify store, world, and world-modules contracts. Currently only `sourcify` is fully supported and is the default verifier.
3 changes: 1 addition & 2 deletions packages/cli/src/commands/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const verifyOptions = {
desc: "Enable batch processing of RPC requests in viem client (defaults to batch size of 100 and wait of 1s)",
},
srcDir: { type: "string", desc: "Source directory. Defaults to foundry src directory." },
verifier: { type: "string", desc: "The verifier to use" },
verifier: { type: "string", desc: "The verifier to use. Default to sourcify", default: "sourcify" },
verifierUrl: {
type: "string",
desc: "The verification provider.",
Expand Down Expand Up @@ -97,7 +97,6 @@ const commandModule: CommandModule<Options, Options> = {
await verify({
client,
rpc,
foundryProfile: profile,
systems,
modules,
deployerAddress: opts.deployerAddress as Hex | undefined,
Expand Down
172 changes: 91 additions & 81 deletions packages/cli/src/verify.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import { getDeployer } from "./deploy/getDeployer";
import { MUDError } from "@latticexyz/common/errors";
import { salt } from "./deploy/common";
import { getStorageAt } from "viem/actions";
import { execa } from "execa";

type VerifyOptions = {
client: Client<Transport, Chain | undefined>;
rpc: string;
foundryProfile?: string;
verifier?: string;
verifier: string;
verifierUrl?: string;
systems: { name: string; bytecode: Hex }[];
modules: { name: string; bytecode: Hex }[];
Expand All @@ -30,7 +30,6 @@ const ERC1967_IMPLEMENTATION_SLOT = "0x360894a13ba1a3210667c828492db98dca3e2076c
export async function verify({
client,
rpc,
foundryProfile = process.env.FOUNDRY_PROFILE,
systems,
modules,
worldAddress,
Expand All @@ -50,35 +49,46 @@ export async function verify({
});
const usesProxy = implementationStorage && implementationStorage !== zeroHash;

const verifyQueue = new PQueue({ concurrency: 1 });
const verifyQueue = new PQueue({ concurrency: 4 });

systems.map(({ name, bytecode }) =>
verifyQueue.add(() =>
verifyContract(
{
name,
rpc,
verifier,
verifierUrl,
address: getCreate2Address({
from: deployerAddress,
bytecode: bytecode,
salt,
}),
},
{ profile: foundryProfile },
).catch((error) => {
verifyContract({
name,
rpc,
verifier,
verifierUrl,
address: getCreate2Address({
from: deployerAddress,
bytecode: bytecode,
salt,
}),
}).catch((error) => {
console.error(`Error verifying system contract ${name}:`, error);
}),
),
);

Object.entries(
usesProxy ? getWorldProxyFactoryContracts(deployerAddress) : getWorldFactoryContracts(deployerAddress),
).map(([name, { bytecode }]) =>
verifyQueue.add(() =>
verifyContract(
{
// If the verifier is Sourcify, attempt to verify MUD core contracts
// There are path issues with verifying Blockscout and Etherscan
if (verifier === "sourcify") {
// Install subdependencies so contracts can compile
await execa("npm", ["install"], {
cwd: "node_modules/@latticexyz/store",
});
await execa("npm", ["install"], {
cwd: "node_modules/@latticexyz/world",
});
await execa("npm", ["install"], {
cwd: "node_modules/@latticexyz/world-modules",
});

Object.entries(
usesProxy ? getWorldProxyFactoryContracts(deployerAddress) : getWorldFactoryContracts(deployerAddress),
).map(([name, { bytecode }]) =>
verifyQueue.add(() =>
verifyContract({
cwd: "node_modules/@latticexyz/world",
name,
rpc,
verifier,
Expand All @@ -88,21 +98,16 @@ export async function verify({
bytecode: bytecode,
salt,
}),
},
{
profile: foundryProfile,
cwd: "node_modules/@latticexyz/world",
},
).catch((error) => {
console.error(`Error verifying world factory contract ${name}:`, error);
}),
),
);
}).catch((error) => {
console.error(`Error verifying world factory contract ${name}:`, error);
}),
),
);

modules.map(({ name, bytecode }) =>
verifyQueue.add(() =>
verifyContract(
{
modules.map(({ name, bytecode }) =>
verifyQueue.add(() =>
verifyContract({
cwd: "node_modules/@latticexyz/world-modules",
name: name,
rpc,
verifier,
Expand All @@ -112,55 +117,60 @@ export async function verify({
bytecode: bytecode,
salt,
}),
},
{
profile: foundryProfile,
cwd: "node_modules/@latticexyz/world-modules",
},
).catch((error) => {
console.error(`Error verifying module contract ${name}:`, error);
}),
),
);
}).catch((error) => {
console.error(`Error verifying module contract ${name}:`, error);
}),
),
);

// If the world was deployed as a Proxy, verify the proxy and implementation.
if (usesProxy) {
const implementationAddress = sliceHex(implementationStorage, -20);
// If the world was deployed as a Proxy, verify the proxy and implementation.
if (usesProxy) {
const implementationAddress = sliceHex(implementationStorage, -20);

verifyQueue.add(() =>
verifyContract(
{ name: "WorldProxy", rpc, verifier, verifierUrl, address: worldAddress },
{
profile: foundryProfile,
verifyQueue.add(() =>
verifyContract({
cwd: "node_modules/@latticexyz/world",
},
).catch((error) => {
console.error(`Error verifying WorldProxy contract:`, error);
}),
);
name: "WorldProxy",
rpc,
verifier,
verifierUrl,
address: worldAddress,
}).catch((error) => {
console.error(`Error verifying WorldProxy contract:`, error);
}),
);

verifyQueue.add(() =>
verifyContract(
{ name: "World", rpc, verifier, verifierUrl, address: implementationAddress },
{
profile: foundryProfile,
verifyQueue.add(() =>
verifyContract({
cwd: "node_modules/@latticexyz/world",
},
).catch((error) => {
console.error(`Error verifying World contract:`, error);
}),
);
} else {
verifyQueue.add(() =>
verifyContract(
{ name: "World", rpc, verifier, verifierUrl, address: worldAddress },
{
profile: foundryProfile,
name: "World",
rpc,
verifier,
verifierUrl,
address: implementationAddress,
}).catch((error) => {
console.error(`Error verifying World contract:`, error);
}),
);
} else {
verifyQueue.add(() =>
verifyContract({
cwd: "node_modules/@latticexyz/world",
},
).catch((error) => {
console.error(`Error verifying World contract:`, error);
}),
name: "World",
rpc,
verifier,
verifierUrl,
address: worldAddress,
}).catch((error) => {
console.error(`Error verifying World contract:`, error);
}),
);
}
} else {
console.log("");
console.log(
`Note: MUD is currently unable to verify store, world, and world-modules contracts with ${verifier}. We are planning to expand support in a future version.`,
);
console.log("");
}
}
7 changes: 3 additions & 4 deletions packages/cli/src/verify/verifyContract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,10 @@ type VerifyContractOptions = {
verifier?: string;
verifierUrl?: string;
address: Address;
cwd?: string;
};

type ForgeOptions = { profile?: string; silent?: boolean; env?: NodeJS.ProcessEnv; cwd?: string };

export async function verifyContract(options: VerifyContractOptions, forgeOptions?: ForgeOptions) {
export async function verifyContract(options: VerifyContractOptions) {
const args = ["verify-contract", options.address, options.name, "--rpc-url", options.rpc];

if (options.verifier) {
Expand All @@ -20,5 +19,5 @@ export async function verifyContract(options: VerifyContractOptions, forgeOption
if (options.verifierUrl) {
args.push("--verifier-url", options.verifierUrl);
}
await forge(args, forgeOptions);
await forge(args, { cwd: options.cwd });
}
8 changes: 7 additions & 1 deletion packages/schema-type/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,10 @@
!dist/**
!src/**
!package.json
!README.md
!README.md

!out/**/*.json
!out/**/*.abi.json
!out/**/*.abi.json.d.ts
!cache/solidity-files-cache.json
!foundry.toml
2 changes: 2 additions & 0 deletions packages/store/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
!out/**/*.json
!out/**/*.abi.json
!out/**/*.abi.json.d.ts
!cache/solidity-files-cache.json
!foundry.toml
!src/**
!ts/**
!mud.config.ts
Expand Down
2 changes: 2 additions & 0 deletions packages/world-modules/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
!out/**/*.json
!out/**/*.abi.json
!out/**/*.abi.json.d.ts
!cache/solidity-files-cache.json
!foundry.toml
!src/**
!ts/**
!package.json
Expand Down
2 changes: 2 additions & 0 deletions packages/world/.npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
!out/**/*.json
!out/**/*.abi.json
!out/**/*.abi.json.d.ts
!cache/solidity-files-cache.json
!foundry.toml
!src/**
!test/MudTest.t.sol
!ts/**
Expand Down

0 comments on commit b4eb795

Please sign in to comment.