Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/fruity-suits-relax.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"thirdweb": patch
---

Fix module deployment with refs and zk
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
import { THIRDWEB_DEPLOYER_ADDRESS } from "constants/addresses";
import type { ThirdwebClient, ThirdwebContract } from "thirdweb";
import { fetchPublishedContract } from "thirdweb/contract";
import {
getContractPublisher,
getPublishedUriFromCompilerUri,
} from "thirdweb/extensions/thirdweb";
import { extractIPFSUri, resolveImplementation } from "thirdweb/utils";
import { download } from "thirdweb/storage";
import {
extractIPFSUri,
isZkSyncChain,
resolveImplementation,
} from "thirdweb/utils";
import { fetchDeployMetadata } from "./fetchDeployMetadata";

type ZkSolcMetadata = {
source_metadata: { settings: { compilationTarget: Record<string, string> } };
};

export async function fetchPublishedContractsFromDeploy(options: {
contract: ThirdwebContract;
client: ThirdwebClient;
Expand All @@ -17,11 +28,37 @@ export async function fetchPublishedContractsFromDeploy(options: {
throw new Error("No IPFS URI found in bytecode");
}

const publishURIs = await getPublishedUriFromCompilerUri({
let publishURIs = await getPublishedUriFromCompilerUri({
contract: getContractPublisher(client),
compilerMetadataUri: contractUri,
});

// Try fetching using contract name from compiler metadata for zksolc variants
// TODO: ContractPublisher should handle multiple metadata uri for a published version
if (publishURIs.length === 0 && (await isZkSyncChain(contract.chain))) {
try {
const res = await download({
uri: contractUri,
client,
});

const deployMetadata = (await res.json()) as ZkSolcMetadata;

const contractId = Object.values(
deployMetadata.source_metadata.settings.compilationTarget,
);

if (contractId[0]) {
const published = await fetchPublishedContract({
client,
contractId: contractId[0],
publisherAddress: THIRDWEB_DEPLOYER_ADDRESS,
});
publishURIs = [published.publishMetadataUri];
}
} catch {}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we want to log an error here?

also what happens if this fails, but the code continues? is it just gonna fail down the line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah this is a fallback, but we don't need to throw here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's something I added in case there's a contract-id we can search on thirdweb published contracts. Else, continue as before.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to update ContractPublisher contract to map multiple metadata-uris (if present) for a single publish version. That's the best way to handle it. Added this in comments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it

}

return await Promise.all(
publishURIs.map((uri) => fetchDeployMetadata(uri, client)),
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ export async function getOrDeployInfraContract(
});
}

export async function getOrDeployInfraContractFromMetadata(
async function getOrDeployInfraContractFromMetadata(
options: ClientAndChainAndAccount & {
contractMetadata: FetchDeployMetadataResult;
constructorParams?: Record<string, unknown>;
Expand Down
14 changes: 8 additions & 6 deletions packages/thirdweb/src/extensions/prebuilts/deploy-published.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { Chain } from "../../chains/types.js";
import type { ThirdwebClient } from "../../client/client.js";
import { type ThirdwebContract, getContract } from "../../contract/contract.js";
import { fetchPublishedContractMetadata } from "../../contract/deployment/publisher.js";
import { getOrDeployInfraContractFromMetadata } from "../../contract/deployment/utils/bootstrap.js";
import { sendAndConfirmTransaction } from "../../transaction/actions/send-and-confirm-transaction.js";
import { simulateTransaction } from "../../transaction/actions/simulate.js";
import { prepareContractCall } from "../../transaction/prepare-contract-call.js";
Expand Down Expand Up @@ -435,18 +434,21 @@ export async function getInitializeTransaction(options: {
const moduleInstallData: Hex[] = [];
for (const module of modules) {
// deploy the module if not already deployed
const contract = await getOrDeployInfraContractFromMetadata({
client,
chain,
const contractAddress = await deployContractfromDeployMetadata({
account,
contractMetadata: module.deployMetadata,
chain,
client,
deployMetadata: module.deployMetadata,
implementationConstructorParams:
module.deployMetadata.implConstructorParams,
salt: "",
});

const installFunction = module.deployMetadata.abi.find(
(i) => i.type === "function" && i.name === "encodeBytesOnInstall",
) as AbiFunction | undefined;

moduleAddresses.push(getAddress(contract.address));
moduleAddresses.push(getAddress(contractAddress));
moduleInstallData.push(
installFunction
? encodeAbiParameters(
Expand Down
Loading