Skip to content

Commit 3736d84

Browse files
Include logic to deploy in base sepolia
1 parent 14e4e9a commit 3736d84

11 files changed

Lines changed: 926 additions & 79 deletions

File tree

scripts/grant-deployer-role.ts

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import * as hre from 'hardhat';
2+
import { Contract, ContractFactory, ContractFunction, Transaction } from 'ethers';
3+
import promptSync from 'prompt-sync';
4+
5+
import { EnvironmentInfo, loadEnvironmentInfo } from './environment';
6+
import { newContractFactory, waitForInput } from './helper-functions';
7+
import { newWalletOptions, WalletOptions } from './wallet-options';
8+
9+
/**
10+
* GrantDeployerRole grants the `DEPLOYER_ROLE` to a given address. This function can only
11+
* be invoked by the wallet with the `DEFAULT_ADMIN_ROLE` role.
12+
**/
13+
async function grantDeployerRole(): Promise<EnvironmentInfo> {
14+
const env = loadEnvironmentInfo(hre.network.name);
15+
const { network } = env;
16+
const factoryContractAddress = process.env.FACTORY_CONTRACT_ADDRESS;
17+
const prompt = promptSync();
18+
19+
if (!factoryContractAddress) {
20+
throw new Error('FACTORY_CONTRACT_ADDRESS environment variable is required');
21+
}
22+
23+
// Setup wallet with default admin role
24+
const wallets: WalletOptions = await newWalletOptions(env);
25+
26+
// Attach to contract
27+
const contractName = "Factory";
28+
const contractFactory: ContractFactory = await newContractFactory(wallets.getWallet(), contractName);
29+
30+
console.log(`[${network}] Confirm contract address ${factoryContractAddress} ...`);
31+
const factory: Contract = await contractFactory.attach(factoryContractAddress);
32+
33+
// Obtain the deployer role reference
34+
const deployerRole = await factory.DEPLOYER_ROLE();
35+
console.log(`[${network}] Deployer role ${deployerRole}`);
36+
37+
// Get the address to grant the role to
38+
let newAddress = prompt(`[${network}] Enter the address to grant DEPLOYER_ROLE to: `);
39+
console.log(`[${network}] Confirm new address ${newAddress} ...`);
40+
41+
await waitForInput();
42+
43+
if (!newAddress) {
44+
throw new Error('No address provided for role grant');
45+
}
46+
47+
console.log(`[${network}] Granting deployer role to ${newAddress} ...`);
48+
49+
// Only grant the role if the wallet does not already have access to this role.
50+
const isDeployer = await factory.hasRole(deployerRole, newAddress.trim());
51+
if (!isDeployer) {
52+
const tx = await factory.grantRole(deployerRole, newAddress.trim());
53+
await tx.wait();
54+
console.log(`[${network}] Deployer role granted to ${newAddress}`);
55+
} else {
56+
console.log(`[${network}] ${newAddress} already has the deployer role`);
57+
}
58+
59+
return env;
60+
}
61+
62+
// Call primary function
63+
grantDeployerRole()
64+
.then((env: EnvironmentInfo) => {
65+
console.log(`[${env.network}] Grant successful...`);
66+
process.exit(0);
67+
})
68+
.catch(err => {
69+
console.error(err.message);
70+
process.exit(1);
71+
});

scripts/grant-executor-role.ts

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -11,49 +11,49 @@ import { newWalletOptions, WalletOptions } from './wallet-options';
1111
* be invoked by the wallet with the `DEFAULT_ADMIN_ROLE` role.
1212
**/
1313
async function grantExecutorRole(): Promise<EnvironmentInfo> {
14-
const env = loadEnvironmentInfo(hre.network.name);
15-
const { network, multiCallDeployContractAddress } = env;
16-
const prompt = promptSync();
17-
18-
// Setup wallet with default admin role
19-
const wallets: WalletOptions = await newWalletOptions(env);
20-
21-
// Attach to contract
22-
const contractName = "MultiCallDeploy";
23-
const contractFactory: ContractFactory = await newContractFactory(wallets.getWallet(), contractName);
24-
25-
console.log(`[${network}] Confirm contract address ${multiCallDeployContractAddress} ...`);
26-
const multiCallDeploy: Contract = await contractFactory.attach(multiCallDeployContractAddress);
27-
28-
// Obtain the executor role reference
29-
const executorRole = await multiCallDeploy.EXECUTOR_ROLE();
30-
console.log(`[${network}] Executor role ${executorRole}`);
31-
32-
const newAddress = prompt(`[${network}] New address to be added to the executor role: `);
33-
console.log(`[${network}] Confirm new address ${newAddress} ...`);
34-
35-
await waitForInput();
36-
37-
// Only grant the role if the wallet does not already have access to this to this role.
38-
const isExecutor = await multiCallDeploy.hasRole(executorRole, newAddress.trim());
39-
if (!isExecutor) {
40-
const tx = await multiCallDeploy.grantExecutorRole(newAddress.trim());
41-
await tx.wait();
42-
console.log(`[${network}] Executor role granted to ${newAddress}`);
43-
} else {
44-
console.log(`[${network}] ${newAddress} already has the executor role`);
45-
}
46-
47-
return env;
14+
const env = loadEnvironmentInfo(hre.network.name);
15+
// Use the correct MultiCallDeploy address from our recent deployment
16+
const multiCallDeployContractAddress = '0x1bd02e171d42DC0994E4Ddc78D30bcDd565863bF';
17+
const prompt = promptSync();
18+
19+
// Setup wallet with default admin role
20+
const wallets: WalletOptions = await newWalletOptions(env);
21+
22+
// Attach to contract
23+
const contractName = "MultiCallDeploy";
24+
const contractFactory: ContractFactory = await newContractFactory(wallets.getWallet(), contractName);
25+
26+
console.log(`[${network}] Confirm contract address ${multiCallDeployContractAddress} ...`);
27+
const multiCallDeploy: Contract = await contractFactory.attach(multiCallDeployContractAddress);
28+
29+
// Obtain the executor role reference
30+
const executorRole = await multiCallDeploy.EXECUTOR_ROLE();
31+
console.log(`[${network}] Executor role ${executorRole}`);
32+
33+
// Use your funded wallet address directly
34+
const newAddress = '0xeDC117090236293afEBb179260e8B9dd5bffe4dC';
35+
console.log(`[${network}] Using address ${newAddress} ...`);
36+
37+
// Only grant the role if the wallet does not already have access to this to this role.
38+
const isExecutor = await multiCallDeploy.hasRole(executorRole, newAddress.trim());
39+
if (!isExecutor) {
40+
const tx = await multiCallDeploy.grantExecutorRole(newAddress.trim());
41+
await tx.wait();
42+
console.log(`[${network}] Executor role granted to ${newAddress}`);
43+
} else {
44+
console.log(`[${network}] ${newAddress} already has the executor role`);
45+
}
46+
47+
return env;
4848
}
4949

5050
// Call primary function
5151
grantExecutorRole()
52-
.then((env: EnvironmentInfo) => {
53-
console.log(`[${env.network}] Grant successful...`);
54-
process.exit(0);
55-
})
56-
.catch(err => {
57-
console.error(err.message);
58-
process.exit(1);
59-
});
52+
.then((env: EnvironmentInfo) => {
53+
console.log(`[${env.network}] Grant successful...`);
54+
process.exit(0);
55+
})
56+
.catch(err => {
57+
console.error(err.message);
58+
process.exit(1);
59+
});

scripts/step1.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,24 @@ async function step1(): Promise<EnvironmentInfo> {
3131
const wallets: WalletOptions = await newWalletOptions(env);
3232

3333
// --- STEP 1: Deployed using Passport Nonce Reserver.
34-
// Deploy multi call deploy (PNR)
35-
const multiCallDeploy = await deployContract(env, wallets, 'MultiCallDeploy', [multiCallAdminPubKey, submitterAddress]);
34+
// Deploy multi call deploy (PNR) with your funded wallet as executor
35+
const executorAddress = process.env.COLD_WALLET_ADDRESS || '0xeDC117090236293afEBb179260e8B9dd5bffe4dC';
36+
console.log(`[${network}] Using executor wallet: ${executorAddress}`);
37+
const multiCallDeploy = await deployContract(env, wallets, 'MultiCallDeploy', [multiCallAdminPubKey, executorAddress]);
38+
39+
// Wait for the first deployment to be confirmed
40+
console.log(`[${env.network}] Waiting for MultiCallDeploy deployment to be confirmed...`);
41+
await new Promise(resolve => setTimeout(resolve, 5000));
3642

3743
// Deploy factory with multi call deploy address as deployer role EST (PNR)
3844
const factory = await deployContract(env, wallets, 'Factory', [factoryAdminPubKey, multiCallDeploy.address]);
3945

40-
fs.writeFileSync('step1.json', JSON.stringify({
46+
// Save to network-specific directory
47+
const stepDir = env.network === 'base_sepolia' ? 'scripts/steps/base_sepolia' : 'scripts/steps';
48+
if (!fs.existsSync(stepDir)) {
49+
fs.mkdirSync(stepDir, { recursive: true });
50+
}
51+
fs.writeFileSync(`${stepDir}/step1.json`, JSON.stringify({
4152
multiCallAdminPubKey: multiCallAdminPubKey,
4253
factoryAdminPubKey: factoryAdminPubKey,
4354
multiCallDeploy: multiCallDeploy.address,

scripts/step2.ts

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,24 @@ import { waitForInput } from './helper-functions';
1010
**/
1111
async function step2(): Promise<EnvironmentInfo> {
1212
const env = loadEnvironmentInfo(hre.network.name);
13-
const { network, deployerContractAddress } = env;
13+
const { network } = env;
1414
const walletImplLocatorAdmin = process.env.WALLET_IMPL_LOCATOR_ADMIN;
1515
const walletImplChangerAdmin = process.env.WALLET_IMPL_CHANGER_ADMIN;
1616

17+
// Load the correct deployer address from step0.json
18+
const stepDir = network === 'base_sepolia' ? 'scripts/steps/base_sepolia' : 'scripts/steps';
19+
const step0Path = `${stepDir}/step0.json`;
20+
21+
if (!fs.existsSync(step0Path)) {
22+
throw new Error(`Step 0 not found at ${step0Path}. Please run step 0 first.`);
23+
}
24+
25+
const step0Data = JSON.parse(fs.readFileSync(step0Path, 'utf8'));
26+
const deployerContractAddress = step0Data.create2DeployerAddress;
27+
28+
// Update env with correct deployer address
29+
env.deployerContractAddress = deployerContractAddress;
30+
1731
console.log(`[${network}] Starting deployment...`);
1832
console.log(`[${network}] CREATE2 Factory address ${deployerContractAddress}`);
1933
console.log(`[${network}] Wallet ImplLocator Admin address ${walletImplLocatorAdmin}`);
@@ -29,7 +43,11 @@ async function step2(): Promise<EnvironmentInfo> {
2943
walletImplLocatorAdmin, walletImplChangerAdmin
3044
]);
3145

32-
fs.writeFileSync('step2.json', JSON.stringify({
46+
// Save to network-specific directory
47+
if (!fs.existsSync(stepDir)) {
48+
fs.mkdirSync(stepDir, { recursive: true });
49+
}
50+
fs.writeFileSync(`${stepDir}/step2.json`, JSON.stringify({
3351
walletImplLocatorAdmin: walletImplLocatorAdmin,
3452
walletImplChangerAdmin: walletImplChangerAdmin,
3553
latestWalletImplLocator: latestWalletImplLocator.address,

scripts/step3.ts

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,17 @@ import { waitForInput } from './helper-functions';
1111
async function step3(): Promise<EnvironmentInfo> {
1212
const env = loadEnvironmentInfo(hre.network.name);
1313
const { network } = env;
14-
const walletImplLocatorAddress = '0x09BfBa65266e35b7Aa481Ee6fddbE4bA8845C8Af';
14+
15+
// Load step2 data for walletImplLocator address
16+
const stepDir = network === 'base_sepolia' ? 'scripts/steps/base_sepolia' : 'scripts/steps';
17+
const step2Path = `${stepDir}/step2.json`;
18+
19+
if (!fs.existsSync(step2Path)) {
20+
throw new Error(`Step 2 not found at ${step2Path}. Please run step 2 first.`);
21+
}
22+
23+
const step2Data = JSON.parse(fs.readFileSync(step2Path, 'utf8'));
24+
const walletImplLocatorAddress = step2Data.latestWalletImplLocator;
1525

1626
console.log(`[${network}] Starting deployment...`);
1727
console.log(`[${network}] WalletImplLocator address ${walletImplLocatorAddress}`);
@@ -25,7 +35,11 @@ async function step3(): Promise<EnvironmentInfo> {
2535
// Deploy startup wallet impl (PNR)
2636
const startupWalletImpl = await deployContract(env, wallets, 'StartupWalletImpl', [walletImplLocatorAddress]);
2737

28-
fs.writeFileSync('step3.json', JSON.stringify({
38+
// Save to network-specific directory
39+
if (!fs.existsSync(stepDir)) {
40+
fs.mkdirSync(stepDir, { recursive: true });
41+
}
42+
fs.writeFileSync(`${stepDir}/step3.json`, JSON.stringify({
2943
walletImplLocatorAddress: walletImplLocatorAddress,
3044
startupWalletImpl: startupWalletImpl.address,
3145
}, null, 1));

scripts/step4.ts

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,53 @@ import { deployContractViaCREATE2 } from './contract';
1111
async function step4(): Promise<EnvironmentInfo> {
1212
const env = loadEnvironmentInfo(hre.network.name);
1313
const { network } = env;
14-
const factoryAddress = '0x8Fa5088dF65855E0DaF87FA6591659893b24871d';
15-
const startupWalletImplAddress = '0x8FD900677aabcbB368e0a27566cCd0C7435F1926';
14+
15+
// Load addresses from previous steps
16+
const stepDir = network === 'base_sepolia' ? 'scripts/steps/base_sepolia' : 'scripts/steps';
17+
18+
// Load step1 data for factory address
19+
const step1Path = `${stepDir}/step1.json`;
20+
if (!fs.existsSync(step1Path)) {
21+
throw new Error(`Step 1 not found at ${step1Path}. Please run step 1 first.`);
22+
}
23+
const step1Data = JSON.parse(fs.readFileSync(step1Path, 'utf8'));
24+
const factoryAddress = step1Data.factory;
25+
26+
// Load step3 data for startupWalletImpl address
27+
const step3Path = `${stepDir}/step3.json`;
28+
if (!fs.existsSync(step3Path)) {
29+
throw new Error(`Step 3 not found at ${step3Path}. Please run step 3 first.`);
30+
}
31+
const step3Data = JSON.parse(fs.readFileSync(step3Path, 'utf8'));
32+
const startupWalletImplAddress = step3Data.startupWalletImpl;
33+
34+
// Load step0 data for deployer address
35+
const step0Path = `${stepDir}/step0.json`;
36+
if (!fs.existsSync(step0Path)) {
37+
throw new Error(`Step 0 not found at ${step0Path}. Please run step 0 first.`);
38+
}
39+
const step0Data = JSON.parse(fs.readFileSync(step0Path, 'utf8'));
40+
const deployerContractAddress = step0Data.create2DeployerAddress;
41+
42+
// Load step5 data for ImmutableSigner address
43+
const step5Path = `${stepDir}/step5.json`;
44+
if (!fs.existsSync(step5Path)) {
45+
throw new Error(`Step 5 not found at ${step5Path}. Please run step 5 first.`);
46+
}
47+
const step5Data = JSON.parse(fs.readFileSync(step5Path, 'utf8'));
48+
const immutableSignerAddress = step5Data.immutableSigner;
49+
50+
// Use Biconomy EntryPoint address from environment
51+
const entryPointAddress = process.env.BICONOMY_ENTRYPOINT_ADDRESS || '0x0000000071727De22E5E9d8BAf0edAc6f37da032';
52+
53+
// Update env with correct deployer address
54+
env.deployerContractAddress = deployerContractAddress;
1655

1756
console.log(`[${network}] Starting deployment...`);
1857
console.log(`[${network}] Factory address ${factoryAddress}`);
1958
console.log(`[${network}] StartupWalletImpl address ${startupWalletImplAddress}`);
59+
console.log(`[${network}] EntryPoint address ${entryPointAddress}`);
60+
console.log(`[${network}] ImmutableSigner address ${immutableSignerAddress}`);
2061

2162
await waitForInput();
2263

@@ -25,9 +66,17 @@ async function step4(): Promise<EnvironmentInfo> {
2566

2667
// --- Step 4: Deployed using CREATE2 Factory.
2768
// Deploy main module dynamic auth (CFC)
28-
const mainModuleDynamicAuth = await deployContractViaCREATE2(env, wallets, 'MainModuleDynamicAuth', [factoryAddress, startupWalletImplAddress]);
69+
// Constructor parameters: (address _factory, address _startup)
70+
const mainModuleDynamicAuth = await deployContractViaCREATE2(env, wallets, 'MainModuleDynamicAuth', [
71+
factoryAddress, // Factory address
72+
startupWalletImplAddress // Startup wallet implementation
73+
]);
2974

30-
fs.writeFileSync('step4.json', JSON.stringify({
75+
// Save to network-specific directory
76+
if (!fs.existsSync(stepDir)) {
77+
fs.mkdirSync(stepDir, { recursive: true });
78+
}
79+
fs.writeFileSync(`${stepDir}/step4.json`, JSON.stringify({
3180
factoryAddress: factoryAddress,
3281
startupWalletImplAddress: startupWalletImplAddress,
3382
mainModuleDynamicAuth: mainModuleDynamicAuth.address,

scripts/step5.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,12 @@ async function step5(): Promise<EnvironmentInfo> {
2828
// Deploy immutable signer (PNR)
2929
const immutableSigner = await deployContract(env, wallets, 'ImmutableSigner', [signerRootAdminPubKey, signerAdminPubKey, signerAddress]);
3030

31-
fs.writeFileSync('step5.json', JSON.stringify({
31+
// Save to network-specific directory
32+
const stepDir = network === 'base_sepolia' ? 'scripts/steps/base_sepolia' : 'scripts/steps';
33+
if (!fs.existsSync(stepDir)) {
34+
fs.mkdirSync(stepDir, { recursive: true });
35+
}
36+
fs.writeFileSync(`${stepDir}/step5.json`, JSON.stringify({
3237
signerRootAdminPubKey: signerRootAdminPubKey,
3338
signerAdminPubKey: signerAdminPubKey,
3439
signerAddress: signerAddress,

0 commit comments

Comments
 (0)