Skip to content

Commit 3b550ae

Browse files
committed
Infra deployment updated
1 parent 7855c3e commit 3b550ae

File tree

8 files changed

+262
-6
lines changed

8 files changed

+262
-6
lines changed

apps/dashboard/src/components/contract-components/contract-deploy-form/custom-contract.tsx

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {
3737
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
3838
import { upload } from "thirdweb/storage";
3939
import { FormHelperText, FormLabel, Heading, Text } from "tw-components";
40-
import { useCustomFactoryAbi, useFunctionParamsFromABI } from "../hooks";
40+
import { useCustomFactoryAbi, useFunctionParamsFromABI, useMintfeeManager, useMultisig } from "../hooks";
4141
import { addContractToMultiChainRegistry } from "../utils";
4242
import { Fieldset } from "./common";
4343
import { ContractMetadataFieldset } from "./contract-metadata-fieldset";
@@ -149,6 +149,9 @@ export const CustomContractForm: React.FC<CustomContractFormProps> = ({
149149

150150
const isTWPublisher = checkTwPublisher(metadata?.publisher);
151151

152+
const multisig = useMultisig(walletChain?.id);
153+
const mintfeeManager = useMintfeeManager(walletChain?.id);
154+
152155
const initializerParams = useFunctionParamsFromABI(
153156
metadata?.deployType === "customFactory" && customFactoryAbi?.data
154157
? customFactoryAbi.data
@@ -193,6 +196,8 @@ export const CustomContractForm: React.FC<CustomContractFormProps> = ({
193196
{
194197
connectedWallet: activeAccount?.address,
195198
chainId: walletChain?.id,
199+
multisig: multisig.data?.multisig,
200+
mintFeeManager: mintfeeManager.data?.mintfeeManager
196201
},
197202
);
198203

apps/dashboard/src/components/contract-components/hooks.ts

Lines changed: 70 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import type { Abi } from "abitype";
66
import { isEnsName, resolveEns } from "lib/ens";
77
import { useV5DashboardChain } from "lib/v5-adapter";
88
import { useMemo } from "react";
9-
import { type ThirdwebContract, getContract } from "thirdweb";
9+
import { type ThirdwebContract, ZERO_ADDRESS, getContract } from "thirdweb";
1010
import { resolveContractAbi } from "thirdweb/contract";
1111
import { isAddress } from "thirdweb/utils";
1212
import {
@@ -18,6 +18,7 @@ import { fetchDeployMetadata } from "./fetchDeployMetadata";
1818
import { fetchPublishedContracts } from "./fetchPublishedContracts";
1919
import { fetchPublishedContractsFromDeploy } from "./fetchPublishedContractsFromDeploy";
2020
import type { ContractId } from "./types";
21+
import { getPredictedMintFeeManagerAddress, getPredictedMultisigAddress } from "thirdweb/deploys";
2122

2223
export function useFetchDeployMetadata(contractId: ContractId) {
2324
return useQuery({
@@ -150,6 +151,66 @@ export function usePublishedContractsQuery(address?: string) {
150151
});
151152
}
152153

154+
function multisigQuery(chainId: number | undefined) {
155+
if(!chainId) {
156+
chainId = 1;
157+
}
158+
159+
return queryOptions({
160+
queryKey: ["multisig", chainId],
161+
queryFn: async() => {
162+
const chain = useV5DashboardChain(chainId);
163+
const client = useThirdwebClient();
164+
165+
const multisig = await getPredictedMultisigAddress({client, chain});
166+
167+
return {
168+
multisig
169+
}
170+
171+
},
172+
enabled:
173+
!!chainId,
174+
// 24h
175+
gcTime: 60 * 60 * 24 * 1000,
176+
// 1h
177+
staleTime: 60 * 60 * 1000,
178+
// default to zero address
179+
placeholderData: { multisig: ZERO_ADDRESS },
180+
retry: false,
181+
})
182+
}
183+
184+
function mintfeeManagerQuery(chainId: number | undefined) {
185+
if(!chainId) {
186+
chainId = 1;
187+
}
188+
189+
return queryOptions({
190+
queryKey: ["mintfee-manager", chainId],
191+
queryFn: async() => {
192+
const chain = useV5DashboardChain(chainId);
193+
const client = useThirdwebClient();
194+
195+
const mintfeeManager = await getPredictedMintFeeManagerAddress({client, chain});
196+
197+
return {
198+
mintfeeManager
199+
}
200+
201+
},
202+
enabled:
203+
!!chainId,
204+
// 24h
205+
gcTime: 60 * 60 * 24 * 1000,
206+
// 1h
207+
staleTime: 60 * 60 * 1000,
208+
// default to zero address
209+
placeholderData: { mintfeeManager: ZERO_ADDRESS },
210+
retry: false,
211+
})
212+
}
213+
153214
function ensQuery(addressOrEnsName?: string) {
154215
// if the address is `thirdweb.eth` we actually want `deployer.thirdweb.eth` here...
155216
if (addressOrEnsName === "thirdweb.eth") {
@@ -208,6 +269,14 @@ export function useEns(addressOrEnsName?: string) {
208269
return useQuery(ensQuery(addressOrEnsName));
209270
}
210271

272+
export function useMultisig(chainId: number | undefined) {
273+
return useQuery(multisigQuery(chainId));
274+
}
275+
276+
export function useMintfeeManager(chainId: number | undefined) {
277+
return useQuery(mintfeeManagerQuery(chainId));
278+
}
279+
211280
export function useContractEvents(abi: Abi) {
212281
return abi.filter((a) => a.type === "event");
213282
}

apps/dashboard/src/lib/deployment/template-values.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import type { SolidityType } from "lib/solidity-types";
33
interface ReplacementProps {
44
connectedWallet?: string;
55
chainId?: number;
6+
mintFeeManager?: string;
7+
multisig?: string;
68
}
79

810
interface TemplateValue {
@@ -25,6 +27,26 @@ const ADDRESS_TEMPLATE_VALUES: TemplateValue[] = [
2527
);
2628
},
2729
},
30+
{
31+
value: "{{tw_mintfee_manager}}",
32+
helperText: "Replaced with the address of the thirdweb mint fee manager.",
33+
replacerFunction: (searchValue, replacers) => {
34+
return searchValue.replaceAll(
35+
"{{tw_mintfee_manager}}",
36+
replacers.mintFeeManager || "",
37+
);
38+
},
39+
},
40+
{
41+
value: "{{tw_multisig}}",
42+
helperText: "Replaced with the address of the thirdweb multisig.",
43+
replacerFunction: (searchValue, replacers) => {
44+
return searchValue.replaceAll(
45+
"{{tw_multisig}}",
46+
replacers.multisig || "",
47+
);
48+
},
49+
},
2850
];
2951

3052
const ADDRESS_ARRAY_TEMPLATE_VALUES: TemplateValue[] = [

packages/thirdweb/src/contract/deployment/utils/bootstrap.ts

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { ZERO_ADDRESS } from "../../../constants/addresses.js";
12
import { sendAndConfirmTransaction } from "../../../transaction/actions/send-and-confirm-transaction.js";
23
import {
34
type FetchDeployMetadataResult,
@@ -20,6 +21,7 @@ import {
2021
getDeployedInfraContractFromMetadata,
2122
prepareInfraContractDeployTransactionFromMetadata,
2223
} from "./infra.js";
24+
import { getDeployedMintFeeManagerContract } from "./mintfee-manager.js";
2325

2426
/**
2527
* @internal
@@ -34,6 +36,7 @@ export async function getOrDeployInfraForPublishedContract(
3436
): Promise<{
3537
cloneFactoryContract: ThirdwebContract;
3638
implementationContract: ThirdwebContract;
39+
mintfeeManagerContract?: ThirdwebContract;
3740
}> {
3841
const {
3942
chain,
@@ -83,11 +86,15 @@ export async function getOrDeployInfraForPublishedContract(
8386
};
8487
}
8588

86-
let [cloneFactoryContract, implementationContract] = await Promise.all([
89+
let [cloneFactoryContract, mintfeeManagerContract, implementationContract] = await Promise.all([
8790
getDeployedCloneFactoryContract({
8891
chain,
8992
client,
9093
}),
94+
getDeployedMintFeeManagerContract({
95+
chain,
96+
client,
97+
}),
9198
getDeployedInfraContract({
9299
chain,
93100
client,
@@ -98,13 +105,18 @@ export async function getOrDeployInfraForPublishedContract(
98105
}),
99106
]);
100107

101-
if (!implementationContract || !cloneFactoryContract) {
108+
if (!implementationContract || !cloneFactoryContract || !mintfeeManagerContract) {
102109
// deploy the infra and implementation contracts if not found
103110
cloneFactoryContract = await deployCloneFactory({
104111
client,
105112
chain,
106113
account,
107114
});
115+
mintfeeManagerContract = await deployMintFeeManager({
116+
client,
117+
chain,
118+
account,
119+
});
108120
implementationContract = await deployImplementation({
109121
client,
110122
chain,
@@ -115,7 +127,7 @@ export async function getOrDeployInfraForPublishedContract(
115127
version,
116128
});
117129
}
118-
return { cloneFactoryContract, implementationContract };
130+
return { cloneFactoryContract, mintfeeManagerContract, implementationContract };
119131
}
120132

121133
/**
@@ -143,6 +155,52 @@ export async function deployCloneFactory(options: ClientAndChainAndAccount) {
143155
});
144156
}
145157

158+
/**
159+
* @internal
160+
* @returns the deployed mint fee manager contract
161+
*/
162+
export async function deployMintFeeManager(options: ClientAndChainAndAccount) {
163+
// create2 factory
164+
const create2Factory = await getDeployedCreate2Factory(options);
165+
if (!create2Factory) {
166+
await deployCreate2Factory(options);
167+
}
168+
169+
// Multisig
170+
const multisig = await deployMultisig(options);
171+
172+
// clone factory
173+
return getOrDeployInfraContract({
174+
...options,
175+
contractId: "MintFeeManagerCore",
176+
constructorParams: { _owner: multisig, _modules: [], _moduleInstallData: [] },
177+
});
178+
}
179+
180+
/**
181+
* @internal
182+
* @returns the deployed multisig contract
183+
*/
184+
export async function deployMultisig(options: ClientAndChainAndAccount) {
185+
// create2 factory
186+
const create2Factory = await getDeployedCreate2Factory(options);
187+
if (!create2Factory) {
188+
await deployCreate2Factory(options);
189+
}
190+
191+
return getOrDeployInfraContract({
192+
...options,
193+
contractId: "Multisig",
194+
constructorParams: { _signers: [TW_SIGNER_1, TW_SIGNER_2, TW_SIGNER_3], _requiredApprovals: MULTISIG_REQUIRED_APPROVALS },
195+
});
196+
}
197+
198+
export const TW_SIGNER_1 = ZERO_ADDRESS;
199+
export const TW_SIGNER_2 = ZERO_ADDRESS;
200+
export const TW_SIGNER_3 = ZERO_ADDRESS;
201+
202+
export const MULTISIG_REQUIRED_APPROVALS = 2;
203+
146204
/**
147205
* @internal
148206
* @returns the deployed infra contract

packages/thirdweb/src/contract/deployment/utils/infra.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ export type InfraContractId =
1616
| "Forwarder"
1717
| "ForwarderEOAOnly"
1818
| "TWCloneFactory"
19+
| "MintFeeManagerCore"
20+
| "Multisig"
1921
| (string & {});
2022

2123
type GetDeployedInfraParams = Prettify<
@@ -27,6 +29,26 @@ type GetDeployedInfraParams = Prettify<
2729
}
2830
>;
2931

32+
/**
33+
* @internal
34+
*/
35+
export async function getPredictedInfraContractAddress(
36+
options: GetDeployedInfraParams,
37+
): Promise<string> {
38+
const contractMetadata = await fetchPublishedContractMetadata({
39+
client: options.client,
40+
contractId: options.contractId,
41+
publisher: options.publisher,
42+
version: options.version,
43+
});
44+
return await computeContractAddress({
45+
client: options.client,
46+
chain: options.chain,
47+
contractMetadata,
48+
constructorParams: options.constructorParams,
49+
})
50+
}
51+
3052
/**
3153
* @internal
3254
*/
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import type { ClientAndChain } from "../../../utils/types.js";
2+
import { TW_SIGNER_1, TW_SIGNER_2, TW_SIGNER_3, MULTISIG_REQUIRED_APPROVALS } from "./bootstrap.js";
3+
import { getDeployedInfraContract, getPredictedInfraContractAddress } from "./infra.js";
4+
5+
/**
6+
* @internal
7+
*/
8+
export async function getDeployedMintFeeManagerContract(args: ClientAndChain) {
9+
// check if Multisig is deployed
10+
const multisig = await getDeployedInfraContract({
11+
...args,
12+
contractId: "Multisig",
13+
constructorParams: { _signers: [TW_SIGNER_1, TW_SIGNER_2, TW_SIGNER_3], _requiredApprovals: MULTISIG_REQUIRED_APPROVALS },
14+
publisher: "0x6453a486d52e0EB6E79Ec4491038E2522a926936", // TODO: remove before merging
15+
});
16+
if (!multisig) {
17+
return null;
18+
}
19+
20+
// check if MintFeeManager is deployed
21+
const mintfeeManager = await getDeployedInfraContract({
22+
...args,
23+
contractId: "MintFeeManagerCore",
24+
constructorParams: { _owner: multisig, _modules: [], _moduleInstallData: [] },
25+
publisher: "0x6453a486d52e0EB6E79Ec4491038E2522a926936", // TODO: remove before merging
26+
});
27+
if (!mintfeeManager) {
28+
return null;
29+
}
30+
return mintfeeManager;
31+
}
32+
33+
/**
34+
* @internal
35+
*/
36+
export async function getPredictedMintFeeManagerAddress(args: ClientAndChain) {
37+
// compute multisig address
38+
const multisig = await getPredictedInfraContractAddress({
39+
...args,
40+
contractId: "Multisig",
41+
constructorParams: { _signers: [TW_SIGNER_1, TW_SIGNER_2, TW_SIGNER_3], _requiredApprovals: MULTISIG_REQUIRED_APPROVALS },
42+
publisher: "0x6453a486d52e0EB6E79Ec4491038E2522a926936", // TODO: remove before merging
43+
});
44+
45+
// compute mintfee manager address
46+
const mintfeeManager = await getPredictedInfraContractAddress({
47+
...args,
48+
contractId: "MintFeeManagerCore",
49+
constructorParams: { _owner: multisig, _modules: [], _moduleInstallData: [] },
50+
publisher: "0x6453a486d52e0EB6E79Ec4491038E2522a926936", // TODO: remove before merging
51+
});
52+
53+
return mintfeeManager;
54+
}
55+
56+
/**
57+
* @internal
58+
*/
59+
export async function getPredictedMultisigAddress(args: ClientAndChain) {
60+
// compute multisig address
61+
const multisig = await getPredictedInfraContractAddress({
62+
...args,
63+
contractId: "Multisig",
64+
constructorParams: { _signers: [TW_SIGNER_1, TW_SIGNER_2, TW_SIGNER_3], _requiredApprovals: MULTISIG_REQUIRED_APPROVALS },
65+
publisher: "0x6453a486d52e0EB6E79Ec4491038E2522a926936", // TODO: remove before merging
66+
});
67+
68+
return multisig;
69+
}

packages/thirdweb/src/exports/deploys.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,8 @@ export {
5454
type DeployPackContractOptions,
5555
deployPackContract,
5656
} from "../extensions/prebuilts/deploy-pack.js";
57+
export {
58+
getDeployedMintFeeManagerContract,
59+
getPredictedMintFeeManagerAddress,
60+
getPredictedMultisigAddress
61+
} from "../contract/deployment/utils/mintfee-manager.js";

0 commit comments

Comments
 (0)