diff --git a/.changeset/fruity-suits-relax.md b/.changeset/fruity-suits-relax.md new file mode 100644 index 00000000000..f4c3a9d938e --- /dev/null +++ b/.changeset/fruity-suits-relax.md @@ -0,0 +1,5 @@ +--- +"thirdweb": patch +--- + +Fix module deployment with refs and zk diff --git a/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts b/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts index 2cd3e9056cf..1814da9fd7c 100644 --- a/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts +++ b/apps/dashboard/src/components/contract-components/fetchPublishedContractsFromDeploy.ts @@ -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 } }; +}; + export async function fetchPublishedContractsFromDeploy(options: { contract: ThirdwebContract; client: ThirdwebClient; @@ -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 {} + } + return await Promise.all( publishURIs.map((uri) => fetchDeployMetadata(uri, client)), ); diff --git a/packages/thirdweb/src/contract/deployment/utils/bootstrap.ts b/packages/thirdweb/src/contract/deployment/utils/bootstrap.ts index 256392288f5..3aa9c7af5b2 100644 --- a/packages/thirdweb/src/contract/deployment/utils/bootstrap.ts +++ b/packages/thirdweb/src/contract/deployment/utils/bootstrap.ts @@ -236,7 +236,7 @@ export async function getOrDeployInfraContract( }); } -export async function getOrDeployInfraContractFromMetadata( +async function getOrDeployInfraContractFromMetadata( options: ClientAndChainAndAccount & { contractMetadata: FetchDeployMetadataResult; constructorParams?: Record; diff --git a/packages/thirdweb/src/extensions/prebuilts/deploy-published.ts b/packages/thirdweb/src/extensions/prebuilts/deploy-published.ts index 9151c9bed2d..9a714305700 100644 --- a/packages/thirdweb/src/extensions/prebuilts/deploy-published.ts +++ b/packages/thirdweb/src/extensions/prebuilts/deploy-published.ts @@ -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"; @@ -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(