Skip to content

Commit d2ec5b2

Browse files
authored
Script for deployment with new flow (#406)
* script for deployment with new flow * update * remove unused * fix, rename * correct sdk version
1 parent 4ded490 commit d2ec5b2

9 files changed

+637
-1426
lines changed

Diff for: .env.example

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
TEST_PRIVATE_KEY=
1+
PRIVATE_KEY=
22

33
ALCHEMY_KEY=
44

Diff for: hardhat.config.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const chainIds = {
3636
};
3737

3838
// Ensure that we have all the environment variables we need.
39-
const testPrivateKey: string = process.env.TEST_PRIVATE_KEY || "";
39+
const testPrivateKey: string = process.env.PRIVATE_KEY || "";
4040
const alchemyKey: string = process.env.ALCHEMY_KEY || "";
4141
const explorerScanKey: string = process.env.SCAN_API_KEY || "";
4242

Diff for: package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"@openzeppelin/contracts": "4.7.3",
1616
"@openzeppelin/contracts-upgradeable": "4.7.3",
1717
"@primitivefi/hardhat-dodoc": "^0.2.0",
18-
"@thirdweb-dev/sdk": "^3.6.9",
18+
"@thirdweb-dev/sdk": "3.10.20",
1919
"@typechain/ethers-v5": "^10.0.0",
2020
"@typechain/hardhat": "^4.0.0",
2121
"@types/fs-extra": "^9.0.13",

Diff for: scripts/deploy-prebuilt-deterministic/constants.ts

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { ChainId } from "@thirdweb-dev/sdk";
2+
import dotenv from "dotenv";
3+
4+
dotenv.config();
5+
6+
export const chainIdToName: Record<number, string> = {
7+
[ChainId.Mumbai]: "mumbai",
8+
[ChainId.Goerli]: "goerli",
9+
[ChainId.Polygon]: "polygon",
10+
[ChainId.Mainnet]: "mainnet",
11+
[ChainId.Optimism]: "optimism",
12+
[ChainId.OptimismGoerli]: "optimism-goerli",
13+
[ChainId.Arbitrum]: "arbitrum",
14+
[ChainId.ArbitrumGoerli]: "arbitrum-goerli",
15+
[ChainId.Fantom]: "fantom",
16+
[ChainId.FantomTestnet]: "fantom-testnet",
17+
[ChainId.Avalanche]: "avalanche",
18+
[ChainId.AvalancheFujiTestnet]: "avalanche-testnet",
19+
[ChainId.BinanceSmartChainMainnet]: "binance",
20+
[ChainId.BinanceSmartChainTestnet]: "binance-testnet",
21+
};
22+
23+
export const chainIdApiKey: Record<number, string | undefined> = {
24+
[ChainId.Mumbai]: process.env.POLYGONSCAN_API_KEY || process.env.SCAN_API_KEY,
25+
[ChainId.Goerli]: process.env.ETHERSCAN_API_KEY || process.env.SCAN_API_KEY,
26+
[ChainId.Polygon]: process.env.POLYGONSCAN_API_KEY || process.env.SCAN_API_KEY,
27+
[ChainId.Mainnet]: process.env.ETHERSCAN_API_KEY || process.env.SCAN_API_KEY,
28+
[ChainId.Optimism]: process.env.OPTIMISM_SCAN_API_KEY || process.env.SCAN_API_KEY,
29+
[ChainId.OptimismGoerli]: process.env.OPTIMISM_SCAN_API_KEY || process.env.SCAN_API_KEY,
30+
[ChainId.Arbitrum]: process.env.ARBITRUM_SCAN_API_KEY || process.env.SCAN_API_KEY,
31+
[ChainId.ArbitrumGoerli]: process.env.ARBITRUM_SCAN_API_KEY || process.env.SCAN_API_KEY,
32+
[ChainId.Fantom]: process.env.FANTOMSCAN_API_KEY || process.env.SCAN_API_KEY,
33+
[ChainId.FantomTestnet]: process.env.FANTOMSCAN_API_KEY || process.env.SCAN_API_KEY,
34+
[ChainId.Avalanche]: process.env.SNOWTRACE_API_KEY || process.env.SCAN_API_KEY,
35+
[ChainId.AvalancheFujiTestnet]: process.env.SNOWTRACE_API_KEY || process.env.SCAN_API_KEY,
36+
[ChainId.BinanceSmartChainMainnet]: process.env.BINANCE_SCAN_API_KEY || process.env.SCAN_API_KEY,
37+
[ChainId.BinanceSmartChainTestnet]: process.env.BINANCE_SCAN_API_KEY || process.env.SCAN_API_KEY,
38+
};
39+
40+
export const apiMap: Record<number, string> = {
41+
1: "https://api.etherscan.io/api",
42+
5: "https://api-goerli.etherscan.io/api",
43+
10: "https://api-optimistic.etherscan.io/api",
44+
56: "https://api.bscscan.com/api",
45+
97: "https://api-testnet.bscscan.com/api",
46+
137: "https://api.polygonscan.com/api",
47+
250: "https://api.ftmscan.com/api",
48+
420: "https://api-goerli-optimistic.etherscan.io/api",
49+
4002: "https://api-testnet.ftmscan.com/api",
50+
42161: "https://api.arbiscan.io/api",
51+
43113: "https://api-testnet.snowtrace.io/api",
52+
43114: "https://api.snowtrace.io/api",
53+
421613: "https://api-goerli.arbiscan.io/api",
54+
80001: "https://api-testnet.polygonscan.com/api",
55+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
import "dotenv/config";
2+
import {
3+
ThirdwebSDK,
4+
computeCloneFactoryAddress,
5+
deployContractDeterministic,
6+
deployCreate2Factory,
7+
deployWithThrowawayDeployer,
8+
getCreate2FactoryAddress,
9+
getDeploymentInfo,
10+
getThirdwebContractAddress,
11+
isContractDeployed,
12+
resolveAddress,
13+
} from "@thirdweb-dev/sdk";
14+
import { Signer } from "ethers";
15+
import { apiMap, chainIdApiKey, chainIdToName } from "./constants";
16+
17+
////// To run this script: `npx ts-node scripts/deploy-prebuilt-deterministic/deploy-deterministic-std-chains.ts` //////
18+
///// MAKE SURE TO PUT IN THE RIGHT CONTRACT NAME HERE AFTER PUBLISHING IT /////
19+
//// THE CONTRACT SHOULD BE PUBLISHED WITH THE NEW PUBLISH FLOW ////
20+
const publishedContractName = "Split";
21+
const publisherKey: string = process.env.THIRDWEB_PUBLISHER_PRIVATE_KEY as string;
22+
const deployerKey: string = process.env.PRIVATE_KEY as string;
23+
24+
const polygonSDK = ThirdwebSDK.fromPrivateKey(publisherKey, "polygon");
25+
26+
async function main() {
27+
const publisher = await polygonSDK.wallet.getAddress();
28+
const latest = await polygonSDK.getPublisher().getLatest(publisher, publishedContractName);
29+
30+
if (latest && latest.metadataUri) {
31+
for (const [chainId, networkName] of Object.entries(chainIdToName)) {
32+
console.log(`Deploying ${publishedContractName} on ${networkName}`);
33+
const sdk = ThirdwebSDK.fromPrivateKey(deployerKey, chainId); // can also hardcode the chain here
34+
const signer = sdk.getSigner() as Signer;
35+
// const chainId = (await sdk.getProvider().getNetwork()).chainId;
36+
37+
try {
38+
const implAddr = await getThirdwebContractAddress(publishedContractName, parseInt(chainId), sdk.storage);
39+
if (implAddr) {
40+
console.log(`implementation ${implAddr} already deployed on chainId: ${chainId}`);
41+
console.log();
42+
continue;
43+
}
44+
} catch (error) {}
45+
46+
try {
47+
console.log("Deploying as", await signer?.getAddress());
48+
// any evm deployment flow
49+
50+
// Deploy CREATE2 factory (if not already exists)
51+
const create2FactoryAddress = await getCreate2FactoryAddress(sdk.getProvider());
52+
if (await isContractDeployed(create2FactoryAddress, sdk.getProvider())) {
53+
console.log(`-- Create2 factory already present at ${create2FactoryAddress}`);
54+
} else {
55+
console.log(`-- Deploying Create2 factory at ${create2FactoryAddress}`);
56+
await deployCreate2Factory(signer, {});
57+
}
58+
59+
// TWStatelessFactory (Clone factory)
60+
const cloneFactoryAddress = await computeCloneFactoryAddress(
61+
sdk.getProvider(),
62+
sdk.storage,
63+
create2FactoryAddress,
64+
);
65+
if (await isContractDeployed(cloneFactoryAddress, sdk.getProvider())) {
66+
console.log(`-- TWCloneFactory already present at ${cloneFactoryAddress}`);
67+
}
68+
69+
// get deployment info for any evm
70+
const deploymentInfo = await getDeploymentInfo(
71+
latest.metadataUri,
72+
sdk.storage,
73+
sdk.getProvider(),
74+
create2FactoryAddress,
75+
);
76+
77+
const implementationAddress = deploymentInfo.find(i => i.type === "implementation")?.transaction
78+
.predictedAddress as string;
79+
80+
// filter out already deployed contracts (data is empty)
81+
const transactionsToSend = deploymentInfo.filter(i => i.transaction.data && i.transaction.data.length > 0);
82+
const transactionsforDirectDeploy = transactionsToSend
83+
.filter(i => {
84+
return i.type !== "infra";
85+
})
86+
.map(i => i.transaction);
87+
const transactionsForThrowawayDeployer = transactionsToSend
88+
.filter(i => {
89+
return i.type === "infra";
90+
})
91+
.map(i => i.transaction);
92+
93+
// deploy via throwaway deployer, multiple infra contracts in one transaction
94+
if (transactionsForThrowawayDeployer.length > 0) {
95+
console.log("-- Deploying Infra");
96+
await deployWithThrowawayDeployer(signer, transactionsForThrowawayDeployer, {});
97+
}
98+
99+
const resolvedImplementationAddress = await resolveAddress(implementationAddress);
100+
101+
console.log(`-- Deploying ${publishedContractName} at ${resolvedImplementationAddress}`);
102+
// send each transaction directly to Create2 factory
103+
await Promise.all(
104+
transactionsforDirectDeploy.map(tx => {
105+
return deployContractDeterministic(signer, tx, {});
106+
}),
107+
);
108+
} catch (e) {
109+
console.log("Error while deploying: ", e);
110+
console.log();
111+
continue;
112+
}
113+
}
114+
115+
console.log("Deployments done.");
116+
console.log();
117+
console.log("---------- Verification ---------");
118+
console.log();
119+
for (const [chainId, networkName] of Object.entries(chainIdToName)) {
120+
const sdk = new ThirdwebSDK(chainId);
121+
console.log("Network: ", networkName);
122+
try {
123+
await sdk.verifier.verifyThirdwebContract(
124+
publishedContractName,
125+
apiMap[parseInt(chainId)],
126+
chainIdApiKey[parseInt(chainId)] as string,
127+
);
128+
console.log();
129+
} catch (error) {
130+
console.log(error);
131+
console.log();
132+
}
133+
}
134+
} else {
135+
console.log("No previous release found");
136+
return;
137+
}
138+
139+
console.log("All done.");
140+
}
141+
142+
main()
143+
.then(() => process.exit(0))
144+
.catch(e => {
145+
console.error(e);
146+
process.exit(1);
147+
});

Diff for: scripts/deploy-prebuilt-deterministic/verify.ts

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { ThirdwebSDK } from "@thirdweb-dev/sdk";
2+
3+
import { apiMap, chainIdApiKey, chainIdToName } from "./constants";
4+
5+
////// To run this script: `npx ts-node scripts/deploy-new-flow/verify.ts` //////
6+
const deployedContractName = "VoteERC20";
7+
8+
async function main() {
9+
console.log("---------- Verification ---------");
10+
console.log();
11+
for (const [chainId, networkName] of Object.entries(chainIdToName)) {
12+
const sdk = new ThirdwebSDK(chainId);
13+
console.log("Network: ", networkName);
14+
try {
15+
await sdk.verifier.verifyThirdwebContract(
16+
deployedContractName,
17+
apiMap[parseInt(chainId)],
18+
chainIdApiKey[parseInt(chainId)] as string,
19+
);
20+
console.log();
21+
} catch (error) {
22+
console.log(error);
23+
console.log();
24+
}
25+
}
26+
27+
console.log("All done.");
28+
}
29+
30+
main()
31+
.then(() => process.exit(0))
32+
.catch(e => {
33+
console.error(e);
34+
process.exit(1);
35+
});

Diff for: scripts/release/add_implementations_from_release.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { chainIdToName } from "./constants";
77
///// MAKE SURE TO PUT IN THE RIGHT CONTRACT NAME HERE AFTER CREATING A RELEASE FOR IT /////
88
//// THE RELEASE SHOULD HAVE THE IMPLEMENTATIONS ALREADY DEPLOYED AND RECORDED (via dashboard) ////
99
const releasedContractName = "Multiwrap";
10-
const privateKey: string = process.env.DEPLOYER_KEY as string; // should be the correct deployer key
10+
const privateKey: string = process.env.THIRDWEB_PUBLISHER_PRIVATE_KEY as string;
1111

1212
const polygonSDK = ThirdwebSDK.fromPrivateKey(privateKey, "polygon");
1313

@@ -37,11 +37,11 @@ async function main() {
3737
for (const [chainId, implementation] of Object.entries(implementations)) {
3838
const chainName = chainIdToName[parseInt(chainId) as SUPPORTED_CHAIN_ID];
3939

40-
if(!chainName) {
40+
if (!chainName) {
4141
console.log("No chainName found for chain: ", chainId);
4242
continue;
4343
}
44-
44+
4545
const chainSDK = ThirdwebSDK.fromPrivateKey(privateKey, chainName);
4646
const factoryAddr = prevReleaseMetadata?.factoryDeploymentData?.factoryAddresses?.[chainId];
4747
if (implementation && factoryAddr) {

Diff for: scripts/release/approve_implementations_from_release.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { chainIdToName } from "./constants";
77
///// MAKE SURE TO PUT IN THE RIGHT CONTRACT NAME HERE AFTER CREATING A RELEASE FOR IT /////
88
//// THE RELEASE SHOULD HAVE THE IMPLEMENTATIONS ALREADY DEPLOYED AND RECORDED (via dashboard) ////
99
const releasedContractName = "TokenERC721";
10-
const privateKey: string = process.env.DEPLOYER_KEY as string; // should be the correct deployer key
10+
const privateKey: string = process.env.THIRDWEB_PUBLISHER_PRIVATE_KEY as string;
1111

1212
const polygonSDK = ThirdwebSDK.fromPrivateKey(privateKey, "polygon");
1313

0 commit comments

Comments
 (0)