@diamondslab/diamonds 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +618 -0
- package/diamonds/README.md +3 -0
- package/dist/core/CallbackManager.d.ts +13 -0
- package/dist/core/CallbackManager.d.ts.map +1 -0
- package/dist/core/CallbackManager.js +95 -0
- package/dist/core/CallbackManager.js.map +1 -0
- package/dist/core/DeploymentManager.d.ts +10 -0
- package/dist/core/DeploymentManager.d.ts.map +1 -0
- package/dist/core/DeploymentManager.js +50 -0
- package/dist/core/DeploymentManager.js.map +1 -0
- package/dist/core/Diamond.d.ts +58 -0
- package/dist/core/Diamond.d.ts.map +1 -0
- package/dist/core/Diamond.js +146 -0
- package/dist/core/Diamond.js.map +1 -0
- package/dist/core/DiamondDeployer.d.ts +10 -0
- package/dist/core/DiamondDeployer.d.ts.map +1 -0
- package/dist/core/DiamondDeployer.js +33 -0
- package/dist/core/DiamondDeployer.js.map +1 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts +1 -0
- package/dist/repositories/DBDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DBDeploymentRepository.js +20 -0
- package/dist/repositories/DBDeploymentRepository.js.map +1 -0
- package/dist/repositories/DeploymentRepository.d.ts +8 -0
- package/dist/repositories/DeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/DeploymentRepository.js +7 -0
- package/dist/repositories/DeploymentRepository.js.map +1 -0
- package/dist/repositories/FileDeploymentRepository.d.ts +18 -0
- package/dist/repositories/FileDeploymentRepository.d.ts.map +1 -0
- package/dist/repositories/FileDeploymentRepository.js +58 -0
- package/dist/repositories/FileDeploymentRepository.js.map +1 -0
- package/dist/repositories/databaseHandler.d.ts +1 -0
- package/dist/repositories/databaseHandler.d.ts.map +1 -0
- package/dist/repositories/databaseHandler.js +13 -0
- package/dist/repositories/databaseHandler.js.map +1 -0
- package/dist/repositories/index.d.ts +4 -0
- package/dist/repositories/index.d.ts.map +1 -0
- package/dist/repositories/index.js +20 -0
- package/dist/repositories/index.js.map +1 -0
- package/dist/repositories/jsonFileHandler.d.ts +81 -0
- package/dist/repositories/jsonFileHandler.d.ts.map +1 -0
- package/dist/repositories/jsonFileHandler.js +223 -0
- package/dist/repositories/jsonFileHandler.js.map +1 -0
- package/dist/repositories/prismaDBHandler.d.ts +1 -0
- package/dist/repositories/prismaDBHandler.d.ts.map +1 -0
- package/dist/repositories/prismaDBHandler.js +11 -0
- package/dist/repositories/prismaDBHandler.js.map +1 -0
- package/dist/schemas/DeploymentSchema.d.ts +309 -0
- package/dist/schemas/DeploymentSchema.d.ts.map +1 -0
- package/dist/schemas/DeploymentSchema.js +56 -0
- package/dist/schemas/DeploymentSchema.js.map +1 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +18 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts +41 -0
- package/dist/strategies/BaseDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/BaseDeploymentStrategy.js +545 -0
- package/dist/strategies/BaseDeploymentStrategy.js.map +1 -0
- package/dist/strategies/DeploymentStrategy.d.ts +19 -0
- package/dist/strategies/DeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/DeploymentStrategy.js +3 -0
- package/dist/strategies/DeploymentStrategy.js.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts +4 -0
- package/dist/strategies/LocalDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/LocalDeploymentStrategy.js +8 -0
- package/dist/strategies/LocalDeploymentStrategy.js.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts +62 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js +757 -0
- package/dist/strategies/OZDefenderDeploymentStrategy.js.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts +139 -0
- package/dist/strategies/RPCDeploymentStrategy.d.ts.map +1 -0
- package/dist/strategies/RPCDeploymentStrategy.js +710 -0
- package/dist/strategies/RPCDeploymentStrategy.js.map +1 -0
- package/dist/strategies/index.d.ts +6 -0
- package/dist/strategies/index.d.ts.map +1 -0
- package/dist/strategies/index.js +12 -0
- package/dist/strategies/index.js.map +1 -0
- package/dist/types/config.d.ts +26 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +3 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/defender.d.ts +22 -0
- package/dist/types/defender.d.ts.map +1 -0
- package/dist/types/defender.js +3 -0
- package/dist/types/defender.js.map +1 -0
- package/dist/types/deployments.d.ts +71 -0
- package/dist/types/deployments.d.ts.map +1 -0
- package/dist/types/deployments.js +20 -0
- package/dist/types/deployments.js.map +1 -0
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +21 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/rpc.d.ts +35 -0
- package/dist/types/rpc.d.ts.map +1 -0
- package/dist/types/rpc.js +3 -0
- package/dist/types/rpc.js.map +1 -0
- package/dist/utils/common.d.ts +20 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/common.js +45 -0
- package/dist/utils/common.js.map +1 -0
- package/dist/utils/configurationResolver.d.ts +30 -0
- package/dist/utils/configurationResolver.d.ts.map +1 -0
- package/dist/utils/configurationResolver.js +151 -0
- package/dist/utils/configurationResolver.js.map +1 -0
- package/dist/utils/contractMapping.d.ts +29 -0
- package/dist/utils/contractMapping.d.ts.map +1 -0
- package/dist/utils/contractMapping.js +224 -0
- package/dist/utils/contractMapping.js.map +1 -0
- package/dist/utils/defenderClients.d.ts +5 -0
- package/dist/utils/defenderClients.d.ts.map +1 -0
- package/dist/utils/defenderClients.js +21 -0
- package/dist/utils/defenderClients.js.map +1 -0
- package/dist/utils/defenderStore.d.ts +14 -0
- package/dist/utils/defenderStore.d.ts.map +1 -0
- package/dist/utils/defenderStore.js +92 -0
- package/dist/utils/defenderStore.js.map +1 -0
- package/dist/utils/diamondAbiGenerator.d.ts +113 -0
- package/dist/utils/diamondAbiGenerator.d.ts.map +1 -0
- package/dist/utils/diamondAbiGenerator.js +415 -0
- package/dist/utils/diamondAbiGenerator.js.map +1 -0
- package/dist/utils/diffDeployedFacets.d.ts +26 -0
- package/dist/utils/diffDeployedFacets.d.ts.map +1 -0
- package/dist/utils/diffDeployedFacets.js +106 -0
- package/dist/utils/diffDeployedFacets.js.map +1 -0
- package/dist/utils/index.d.ts +16 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +35 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/loupe.d.ts +44 -0
- package/dist/utils/loupe.d.ts.map +1 -0
- package/dist/utils/loupe.js +128 -0
- package/dist/utils/loupe.js.map +1 -0
- package/dist/utils/rpcStore.d.ts +36 -0
- package/dist/utils/rpcStore.d.ts.map +1 -0
- package/dist/utils/rpcStore.js +166 -0
- package/dist/utils/rpcStore.js.map +1 -0
- package/dist/utils/signer.d.ts +36 -0
- package/dist/utils/signer.d.ts.map +1 -0
- package/dist/utils/signer.js +91 -0
- package/dist/utils/signer.js.map +1 -0
- package/dist/utils/txlogging.d.ts +13 -0
- package/dist/utils/txlogging.d.ts.map +1 -0
- package/dist/utils/txlogging.js +87 -0
- package/dist/utils/txlogging.js.map +1 -0
- package/dist/utils/workspaceSetup.d.ts +32 -0
- package/dist/utils/workspaceSetup.d.ts.map +1 -0
- package/dist/utils/workspaceSetup.js +311 -0
- package/dist/utils/workspaceSetup.js.map +1 -0
- package/docs/DIAMOND_ABI_CONFIGURATION_SUMMARY.md +40 -0
- package/docs/DIAMOND_ABI_GENERATION.md +220 -0
- package/docs/DIAMOND_ABI_GENERATOR_EXAMPLES.md +1204 -0
- package/docs/DIAMOND_ABI_GENERATOR_IMPLEMENTATION.md +947 -0
- package/docs/DIAMOND_ABI_GENERATOR_QUICK_REFERENCE.md +336 -0
- package/docs/README-DEFENDER.md +394 -0
- package/docs/README_DIAMOND_ABI_GENERATOR.md +303 -0
- package/docs/ROADMAP.md +250 -0
- package/docs/assets/image.png +0 -0
- package/docs/defender-integration.md +451 -0
- package/docs/diamond_module-BaseStrategy_design-v2.uxf +247 -0
- package/docs/diamond_module-BaseStrategy_design.uxf +272 -0
- package/docs/monitoring-troubleshooting.md +556 -0
- package/docs/testing-guide.md +713 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/callbacks/ERC20ProxyFacet.ts +31 -0
- package/examples/Diamond_Config_and_Deployment_examples/diamonds/ProxyDiamond/proxydiamond.config.json +27 -0
- package/examples/Local_Hardhat_Deployer_Script_example/LocalDiamondDeployer.ts +180 -0
- package/examples/OZ_Defender_Deployer_Script_example/OZDiamondDeployer.ts +107 -0
- package/examples/OZ_Defender_Deployer_Script_example/run-oz-deploy.ts +17 -0
- package/examples/Test_examples/ProxyDiamondDeployment.test.ts +202 -0
- package/examples/defender-deployment/.env.example +35 -0
- package/examples/defender-deployment/README.md +415 -0
- package/examples/defender-deployment/contracts/ExampleDiamond.sol +41 -0
- package/examples/defender-deployment/contracts/ExampleFacet1.sol +84 -0
- package/examples/defender-deployment/contracts/ExampleFacet2.sol +104 -0
- package/examples/defender-deployment/contracts/UpgradeFacet.sol +92 -0
- package/examples/defender-deployment/deploy-script.ts +170 -0
- package/examples/defender-deployment/diamond-config.json +36 -0
- package/examples/defender-deployment/upgrade-script.ts +237 -0
- package/examples/hardhat-diamonds-config.example.ts +41 -0
- package/package.json +228 -0
- package/src/core/CallbackManager.ts +70 -0
- package/src/core/DeploymentManager.ts +64 -0
- package/src/core/Diamond.ts +197 -0
- package/src/core/DiamondDeployer.ts +36 -0
- package/src/core/index.ts +4 -0
- package/src/index.ts +5 -0
- package/src/repositories/DBDeploymentRepository.ts +22 -0
- package/src/repositories/DeploymentRepository.ts +12 -0
- package/src/repositories/FileDeploymentRepository.ts +67 -0
- package/src/repositories/databaseHandler.ts +14 -0
- package/src/repositories/index.ts +4 -0
- package/src/repositories/jsonFileHandler.ts +252 -0
- package/src/repositories/prismaDBHandler.ts +10 -0
- package/src/schemas/DeploymentSchema.ts +71 -0
- package/src/schemas/index.ts +1 -0
- package/src/strategies/BaseDeploymentStrategy.ts +649 -0
- package/src/strategies/DeploymentStrategy.ts +25 -0
- package/src/strategies/LocalDeploymentStrategy.ts +5 -0
- package/src/strategies/OZDefenderDeploymentStrategy.ts +849 -0
- package/src/strategies/RPCDeploymentStrategy.ts +881 -0
- package/src/strategies/index.ts +5 -0
- package/src/types/config.ts +34 -0
- package/src/types/defender.ts +24 -0
- package/src/types/deployments.ts +102 -0
- package/src/types/index.ts +4 -0
- package/src/types/rpc.ts +37 -0
- package/src/utils/common.ts +54 -0
- package/src/utils/configurationResolver.ts +141 -0
- package/src/utils/contractMapping.ts +220 -0
- package/src/utils/defenderClients.ts +22 -0
- package/src/utils/defenderStore.ts +62 -0
- package/src/utils/diamondAbiGenerator.ts +523 -0
- package/src/utils/diffDeployedFacets.ts +131 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/loupe.ts +159 -0
- package/src/utils/rpcStore.ts +152 -0
- package/src/utils/signer.ts +93 -0
- package/src/utils/txlogging.ts +97 -0
- package/src/utils/workspaceSetup.ts +315 -0
- package/test/README.md +136 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { ExampleDiamond } from "../../../typechain-types";
|
|
2
|
+
import "@nomicfoundation/hardhat-ethers";
|
|
3
|
+
import {
|
|
4
|
+
CallbackArgs,
|
|
5
|
+
} from "diamonds";
|
|
6
|
+
import hre from "hardhat";
|
|
7
|
+
|
|
8
|
+
export async function createXMPLToken(CallbackArgs: CallbackArgs) {
|
|
9
|
+
const { diamond } = CallbackArgs;
|
|
10
|
+
|
|
11
|
+
const networkName = diamond.networkName;
|
|
12
|
+
const chainID = diamond.chainId;
|
|
13
|
+
const deployInfo = diamond.getDeployedDiamondData();
|
|
14
|
+
|
|
15
|
+
console.log(`In ERC20ProxyFacet after Deploy function, chainID: ${chainID}`);
|
|
16
|
+
console.log(`Network name: ${networkName}`);
|
|
17
|
+
// Get the GeniusDiamond instance
|
|
18
|
+
const diamondName = diamond.diamondName;
|
|
19
|
+
const diamondAddress = deployInfo.DiamondAddress!;
|
|
20
|
+
const deployer = diamond.signer!;
|
|
21
|
+
const diamondArtifactName = `hardhat-diamond-abi/HardhatDiamondABI.sol:${diamondName}`;
|
|
22
|
+
const diamondArtifact = hre.artifacts.readArtifactSync(diamondArtifactName);
|
|
23
|
+
const diamondContract = new hre.ethers.Contract(diamondAddress, diamondArtifact.abi, diamond.provider) as ProxyDiamond;
|
|
24
|
+
const deployerDiamondContract = diamondContract.connect(deployer);
|
|
25
|
+
await deployerDiamondContract.initializeERC20Proxy(
|
|
26
|
+
diamondAddress,
|
|
27
|
+
chainID,
|
|
28
|
+
"ExampleToken",
|
|
29
|
+
"XMPL"
|
|
30
|
+
);
|
|
31
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"protocolVersion": 0.0,
|
|
3
|
+
"facets": {
|
|
4
|
+
"DiamondCutFacet": {
|
|
5
|
+
"priority": 10,
|
|
6
|
+
"versions": {
|
|
7
|
+
"0.0": {}
|
|
8
|
+
}
|
|
9
|
+
},
|
|
10
|
+
"DiamondLoupeFacet": {
|
|
11
|
+
"priority": 20,
|
|
12
|
+
"versions": {
|
|
13
|
+
"0.0": {}
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"ERC20ProxyFacet": {
|
|
17
|
+
"priority": 40,
|
|
18
|
+
"versions": {
|
|
19
|
+
"0.0": {
|
|
20
|
+
"callbacks": [
|
|
21
|
+
"createXMPLToken"
|
|
22
|
+
]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Diamond,
|
|
3
|
+
DiamondDeployer,
|
|
4
|
+
DeploymentManager,
|
|
5
|
+
LocalDeploymentStrategy,
|
|
6
|
+
FileDeploymentRepository,
|
|
7
|
+
DeploymentRepository,
|
|
8
|
+
impersonateSigner,
|
|
9
|
+
setEtherBalance,
|
|
10
|
+
DiamondConfig,
|
|
11
|
+
DiamondPathsConfig,
|
|
12
|
+
cutKey,
|
|
13
|
+
impersonateAndFundSigner
|
|
14
|
+
} from 'diamonds';
|
|
15
|
+
import { JsonRpcProvider } from '@ethersproject/providers';
|
|
16
|
+
import { Signer, ethers } from 'ethers';
|
|
17
|
+
import hre from 'hardhat';
|
|
18
|
+
import "@nomicfoundation/hardhat-ethers";
|
|
19
|
+
import { SignerWithAddress } from '@nomicfoundation/hardhat-ethers/signers';
|
|
20
|
+
import { join } from 'path';
|
|
21
|
+
import 'hardhat-diamonds';
|
|
22
|
+
import { HardhatEthersProvider } from '@nomicfoundation/hardhat-ethers/internal/hardhat-ethers-provider';
|
|
23
|
+
|
|
24
|
+
export interface LocalDiamondDeployerConfig extends DiamondConfig {
|
|
25
|
+
provider?: JsonRpcProvider | HardhatEthersProvider;
|
|
26
|
+
signer?: SignerWithAddress;
|
|
27
|
+
localDiamondDeployerKey?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class LocalDiamondDeployer {
|
|
31
|
+
private static instances: Map<string, LocalDiamondDeployer> = new Map();
|
|
32
|
+
private deployInProgress: boolean = false;
|
|
33
|
+
private deployComplete: boolean = false;
|
|
34
|
+
private diamond: Diamond | undefined;
|
|
35
|
+
private verbose: boolean = true;
|
|
36
|
+
private config: LocalDiamondDeployerConfig;
|
|
37
|
+
private provider: JsonRpcProvider | HardhatEthersProvider;
|
|
38
|
+
private signer: SignerWithAddress;
|
|
39
|
+
private diamondName: string;
|
|
40
|
+
private networkName: string = 'hardhat';
|
|
41
|
+
private chainId: bigint | number = 31337;
|
|
42
|
+
private repository: DeploymentRepository;
|
|
43
|
+
|
|
44
|
+
constructor(config: LocalDiamondDeployerConfig, repository: DeploymentRepository) {
|
|
45
|
+
this.config = config as DiamondConfig;
|
|
46
|
+
this.diamondName = config.diamondName;
|
|
47
|
+
this.provider = config.provider || hre.ethers.provider;
|
|
48
|
+
if (!config.networkName) {
|
|
49
|
+
// TODO account for "unknown" as hardhat
|
|
50
|
+
config.networkName = (this.provider as JsonRpcProvider)._network.name;
|
|
51
|
+
} else {
|
|
52
|
+
this.networkName = config.networkName;
|
|
53
|
+
}
|
|
54
|
+
if (!config.chainId) {
|
|
55
|
+
config.chainId = (this.provider as JsonRpcProvider)._network.chainId;
|
|
56
|
+
} else {
|
|
57
|
+
this.chainId = config.chainId;
|
|
58
|
+
}
|
|
59
|
+
this.signer = config.signer!;
|
|
60
|
+
// this.config.signer = this.signer;
|
|
61
|
+
this.repository = repository!;
|
|
62
|
+
|
|
63
|
+
// TODO make provider signer and repository optional (this may be handled in diamond constructor already)
|
|
64
|
+
this.diamond = new Diamond(this.config, repository);
|
|
65
|
+
this.diamond.setProvider(this.provider);
|
|
66
|
+
this.diamond.setSigner(this.signer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
public static async getInstance(config: LocalDiamondDeployerConfig): Promise<LocalDiamondDeployer> {
|
|
70
|
+
if (!config.provider) {
|
|
71
|
+
config.provider = hre.ethers.provider;
|
|
72
|
+
} else {
|
|
73
|
+
hre.ethers.provider = config.provider as any;
|
|
74
|
+
}
|
|
75
|
+
if (!config.networkName) {
|
|
76
|
+
const networkName = (await config.provider?.getNetwork()).name || 'hardhat';
|
|
77
|
+
config.networkName = networkName === 'unknown' ? 'hardhat' : networkName;
|
|
78
|
+
}
|
|
79
|
+
if (!config.chainId) {
|
|
80
|
+
config.chainId = (await config.provider.getNetwork()).chainId || 31337;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const key = config.localDiamondDeployerKey || await (cutKey(
|
|
84
|
+
config.diamondName,
|
|
85
|
+
config.networkName,
|
|
86
|
+
(config.chainId ?? 31337).toString()
|
|
87
|
+
));
|
|
88
|
+
|
|
89
|
+
if (!this.instances.has(key)) {
|
|
90
|
+
const hardhatDiamonds: DiamondPathsConfig = hre.diamonds?.getDiamondConfig(config.diamondName);
|
|
91
|
+
const deployedDiamondDataFileName = `${config.diamondName.toLowerCase()}-${config.networkName.toLowerCase()}-${config.chainId.toString()}.json`;
|
|
92
|
+
const defaultDeployedDiamondDataFilePath = join(
|
|
93
|
+
'diamonds',
|
|
94
|
+
config.diamondName,
|
|
95
|
+
'deployments',
|
|
96
|
+
deployedDiamondDataFileName
|
|
97
|
+
);
|
|
98
|
+
const defaultConfigFilePath = join(
|
|
99
|
+
'diamonds',
|
|
100
|
+
config.diamondName,
|
|
101
|
+
`${config.diamondName.toLowerCase()}.config.json`
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
config.deploymentsPath = config.deploymentsPath || hardhatDiamonds?.deploymentsPath
|
|
105
|
+
|| 'diamonds';
|
|
106
|
+
config.contractsPath = hardhatDiamonds?.contractsPath || 'contracts';
|
|
107
|
+
config.callbacksPath = hardhatDiamonds?.callbacksPath
|
|
108
|
+
|| join('diamonds', config.diamondName, 'callbacks');
|
|
109
|
+
config.deployedDiamondDataFilePath = config.deployedDiamondDataFilePath
|
|
110
|
+
|| hardhatDiamonds?.deployedDiamondDataFilePath
|
|
111
|
+
|| defaultDeployedDiamondDataFilePath;
|
|
112
|
+
config.configFilePath = config.configFilePath
|
|
113
|
+
|| hardhatDiamonds?.configFilePath
|
|
114
|
+
|| defaultConfigFilePath;
|
|
115
|
+
|
|
116
|
+
const repository = new FileDeploymentRepository(config);
|
|
117
|
+
repository.setWriteDeployedDiamondData(config.writeDeployedDiamondData || hardhatDiamonds?.writeDeployedDiamondData || false);
|
|
118
|
+
const deployedDiamondData = repository.loadDeployedDiamondData();
|
|
119
|
+
|
|
120
|
+
const [signer0] = await hre.ethers.getSigners();
|
|
121
|
+
// ethers.provider = config.provider;
|
|
122
|
+
if (!deployedDiamondData.DeployerAddress) {
|
|
123
|
+
config.signer = signer0;
|
|
124
|
+
} else {
|
|
125
|
+
config.signer = await hre.ethers.getSigner(deployedDiamondData.DeployerAddress);
|
|
126
|
+
await impersonateAndFundSigner(deployedDiamondData.DeployerAddress, config.provider as any);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const instance = new LocalDiamondDeployer(config, repository);
|
|
130
|
+
this.instances.set(key, instance);
|
|
131
|
+
}
|
|
132
|
+
return this.instances.get(key)!;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public async deployDiamond(): Promise<Diamond> {
|
|
136
|
+
const chainId = (await this.provider.getNetwork()).chainId || 31337;
|
|
137
|
+
const key = cutKey(this.diamondName, this.networkName, chainId.toString());
|
|
138
|
+
if (this.deployComplete) {
|
|
139
|
+
console.log(`Deployment already completed for ${this.diamondName} on ${this.networkName}-${chainId.toString()}`);
|
|
140
|
+
return Promise.resolve(this.diamond!);
|
|
141
|
+
}
|
|
142
|
+
else if (this.deployInProgress) {
|
|
143
|
+
console.log(`Deployment already in progress for ${this.networkName}`);
|
|
144
|
+
// Wait for the deployment to complete
|
|
145
|
+
while (this.deployInProgress) {
|
|
146
|
+
await new Promise((resolve) => setTimeout(resolve, 1000));
|
|
147
|
+
}
|
|
148
|
+
return Promise.resolve(this.diamond!);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
this.deployInProgress = true;
|
|
152
|
+
|
|
153
|
+
// Make Deployment Strategy configurable.
|
|
154
|
+
const strategy = new LocalDeploymentStrategy(this.verbose);
|
|
155
|
+
const deployer = new DiamondDeployer(this.diamond!, strategy);
|
|
156
|
+
|
|
157
|
+
await deployer.deployDiamond();
|
|
158
|
+
|
|
159
|
+
this.deployComplete = true;
|
|
160
|
+
this.deployInProgress = false;
|
|
161
|
+
|
|
162
|
+
return deployer.getDiamond();
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
public async getDiamondDeployed(): Promise<Diamond> {
|
|
166
|
+
if (this.deployComplete && this.diamond) {
|
|
167
|
+
return this.diamond;
|
|
168
|
+
}
|
|
169
|
+
const diamond = await this.deployDiamond();
|
|
170
|
+
return diamond;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public async getDiamond(): Promise<Diamond> {
|
|
174
|
+
return this.diamond!;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
public async setVerbose(useVerboseLogging: boolean): Promise<void> {
|
|
178
|
+
this.verbose = useVerboseLogging;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Diamond,
|
|
3
|
+
DiamondDeployer,
|
|
4
|
+
FileDeploymentRepository,
|
|
5
|
+
DeploymentRepository,
|
|
6
|
+
DiamondConfig,
|
|
7
|
+
cutKey
|
|
8
|
+
} from 'diamonds';
|
|
9
|
+
|
|
10
|
+
import { JsonRpcProvider } from '@ethersproject/providers';
|
|
11
|
+
import { ethers } from 'hardhat';
|
|
12
|
+
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
|
|
13
|
+
import { OZDefenderDeploymentStrategy } from 'diamonds'; // Adjust based on your export path
|
|
14
|
+
import { join } from 'path';
|
|
15
|
+
|
|
16
|
+
export interface OZDiamondDeployerConfig extends DiamondConfig {
|
|
17
|
+
provider?: JsonRpcProvider;
|
|
18
|
+
signer?: SignerWithAddress;
|
|
19
|
+
ozDiamondDeployerKey?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export class OZDiamondDeployer {
|
|
23
|
+
private static instances: Map<string, OZDiamondDeployer> = new Map();
|
|
24
|
+
private deployInProgress = false;
|
|
25
|
+
private deployComplete = false;
|
|
26
|
+
private config: OZDiamondDeployerConfig;
|
|
27
|
+
private diamond: Diamond;
|
|
28
|
+
private provider: JsonRpcProvider;
|
|
29
|
+
private signer: SignerWithAddress;
|
|
30
|
+
private repository: DeploymentRepository;
|
|
31
|
+
|
|
32
|
+
constructor(config: OZDiamondDeployerConfig, repository: DeploymentRepository) {
|
|
33
|
+
this.config = config;
|
|
34
|
+
this.provider = config.provider || ethers.provider;
|
|
35
|
+
this.signer = config.signer!;
|
|
36
|
+
this.repository = repository;
|
|
37
|
+
|
|
38
|
+
this.diamond = new Diamond(config, repository);
|
|
39
|
+
this.diamond.setProvider(this.provider);
|
|
40
|
+
this.diamond.setSigner(this.signer);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public static async getInstance(config: OZDiamondDeployerConfig): Promise<OZDiamondDeployer> {
|
|
44
|
+
config.provider = config.provider || ethers.provider;
|
|
45
|
+
|
|
46
|
+
const net = await config.provider.getNetwork();
|
|
47
|
+
config.networkName = config.networkName || (net.name === 'unknown' ? 'hardhat' : net.name);
|
|
48
|
+
config.chainId = config.chainId || net.chainId;
|
|
49
|
+
|
|
50
|
+
const key = config.ozDiamondDeployerKey || await cutKey(config.diamondName, config.networkName, config.chainId.toString());
|
|
51
|
+
|
|
52
|
+
if (!this.instances.has(key)) {
|
|
53
|
+
const defaultPaths = {
|
|
54
|
+
deploymentsPath: 'diamonds',
|
|
55
|
+
contractsPath: 'contracts',
|
|
56
|
+
callbacksPath: join('diamonds', config.diamondName, 'callbacks'),
|
|
57
|
+
deployedDiamondDataFilePath: join('diamonds', config.diamondName, 'deployments', `${config.diamondName.toLowerCase()}-${config.networkName.toLowerCase()}-${config.chainId}.json`),
|
|
58
|
+
configFilePath: join('diamonds', config.diamondName, `${config.diamondName.toLowerCase()}.config.json`)
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
config.deploymentsPath ||= defaultPaths.deploymentsPath;
|
|
62
|
+
config.contractsPath ||= defaultPaths.contractsPath;
|
|
63
|
+
config.callbacksPath ||= defaultPaths.callbacksPath;
|
|
64
|
+
config.deployedDiamondDataFilePath ||= defaultPaths.deployedDiamondDataFilePath;
|
|
65
|
+
config.configFilePath ||= defaultPaths.configFilePath;
|
|
66
|
+
|
|
67
|
+
const repository = new FileDeploymentRepository(config);
|
|
68
|
+
const [signer0] = await ethers.getSigners();
|
|
69
|
+
config.signer = signer0;
|
|
70
|
+
|
|
71
|
+
const instance = new OZDiamondDeployer(config, repository);
|
|
72
|
+
this.instances.set(key, instance);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return this.instances.get(key)!;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
public async deployDiamond(): Promise<Diamond> {
|
|
79
|
+
if (this.deployComplete) return this.diamond;
|
|
80
|
+
if (this.deployInProgress) {
|
|
81
|
+
console.log(`Deployment already in progress. Waiting...`);
|
|
82
|
+
while (this.deployInProgress) await new Promise(res => setTimeout(res, 1000));
|
|
83
|
+
return this.diamond;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
this.deployInProgress = true;
|
|
87
|
+
const strategy = new OZDefenderDeploymentStrategy(
|
|
88
|
+
process.env.DEFENDER_API_KEY!,
|
|
89
|
+
process.env.DEFENDER_API_SECRET!,
|
|
90
|
+
process.env.DEFENDER_RELAYER_ADDRESS!, // required
|
|
91
|
+
true, // auto-approve
|
|
92
|
+
process.env.DEFENDER_SAFE_ADDRESS!,
|
|
93
|
+
'Safe' // TODO this should be configurable.
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
const deployer = new DiamondDeployer(this.diamond, strategy);
|
|
97
|
+
await deployer.deployDiamond();
|
|
98
|
+
|
|
99
|
+
this.deployComplete = true;
|
|
100
|
+
this.deployInProgress = false;
|
|
101
|
+
return deployer.getDiamond();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public async getDiamond(): Promise<Diamond> {
|
|
105
|
+
return this.diamond;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { OZDiamondDeployer } from './OZDiamondDeployer';
|
|
2
|
+
import { config } from 'dotenv';
|
|
3
|
+
config();
|
|
4
|
+
|
|
5
|
+
async function main() {
|
|
6
|
+
const deployer = await OZDiamondDeployer.getInstance({
|
|
7
|
+
diamondName: 'GeniusDiamond'
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const diamond = await deployer.deployDiamond();
|
|
11
|
+
console.log(`🚀 Deployed Diamond at: ${diamond.getDeployedDiamondData().DiamondAddress}`);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
main().catch(err => {
|
|
15
|
+
console.error(err);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
});
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { debug } from 'debug';
|
|
2
|
+
import { pathExistsSync } from "fs-extra";
|
|
3
|
+
import { expect, assert } from 'chai';
|
|
4
|
+
import { ethers } from 'hardhat';
|
|
5
|
+
import hre from 'hardhat';
|
|
6
|
+
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
|
|
7
|
+
import { JsonRpcProvider } from '@ethersproject/providers';
|
|
8
|
+
import { multichain } from 'hardhat-multichain';
|
|
9
|
+
import { getInterfaceID } from '../../scripts/utils/helpers';
|
|
10
|
+
import { LocalDiamondDeployer, LocalDiamondDeployerConfig } from '../../scripts/setup/LocalDiamondDeployer';
|
|
11
|
+
import { Diamond, deleteDeployInfo } from 'diamonds';
|
|
12
|
+
import {
|
|
13
|
+
ProxyDiamond,
|
|
14
|
+
IERC20Upgradeable__factory,
|
|
15
|
+
IDiamondCut__factory,
|
|
16
|
+
IDiamondLoupe__factory
|
|
17
|
+
} from '../../typechain-types/';
|
|
18
|
+
|
|
19
|
+
describe('🧪 Multichain Fork and Diamond Deployment Tests', async function () {
|
|
20
|
+
const diamondName = 'ProxyDiamond';
|
|
21
|
+
const log: debug.Debugger = debug('GNUSDeploy:log:${diamondName}');
|
|
22
|
+
this.timeout(0); // Extended indefinitely for diamond deployment time
|
|
23
|
+
|
|
24
|
+
let networkProviders = multichain.getProviders() || new Map<string, JsonRpcProvider>();
|
|
25
|
+
|
|
26
|
+
if (process.argv.includes('test-multichain')) {
|
|
27
|
+
const networkNames = process.argv[process.argv.indexOf('--chains') + 1].split(',');
|
|
28
|
+
if (networkNames.includes('hardhat')) {
|
|
29
|
+
networkProviders.set('hardhat', ethers.provider);
|
|
30
|
+
}
|
|
31
|
+
} else if (process.argv.includes('test') || process.argv.includes('coverage')) {
|
|
32
|
+
networkProviders.set('hardhat', ethers.provider);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
for (const [networkName, provider] of networkProviders.entries()) {
|
|
36
|
+
describe(`🔗 Chain: ${networkName} 🔷 Diamond: ${diamondName}`, function () {
|
|
37
|
+
let diamond: Diamond;
|
|
38
|
+
let signers: SignerWithAddress[];
|
|
39
|
+
let signer0: string;
|
|
40
|
+
let signer1: string;
|
|
41
|
+
let signer2: string;
|
|
42
|
+
let owner: string;
|
|
43
|
+
let ownerSigner: SignerWithAddress;
|
|
44
|
+
let proxyDiamond: ProxyDiamond;
|
|
45
|
+
let signer0Diamond: ProxyDiamond;
|
|
46
|
+
let signer1Diamond: ProxyDiamond;
|
|
47
|
+
let signer2Diamond: ProxyDiamond;
|
|
48
|
+
let ownerDiamond: ProxyDiamond;
|
|
49
|
+
|
|
50
|
+
let ethersMultichain: typeof ethers;
|
|
51
|
+
let snapshotId: string;
|
|
52
|
+
|
|
53
|
+
before(async function () {
|
|
54
|
+
const config = {
|
|
55
|
+
diamondName: diamondName,
|
|
56
|
+
networkName: networkName,
|
|
57
|
+
provider: provider,
|
|
58
|
+
// chainId: (await provider.getNetwork()).chainId,
|
|
59
|
+
// writeDeployedDiamondData: false,
|
|
60
|
+
// configFilePath: `diamonds/GeniusDiamond/proxydiamond.config.json`,
|
|
61
|
+
} as LocalDiamondDeployerConfig;
|
|
62
|
+
const diamondDeployer = await LocalDiamondDeployer.getInstance(config);
|
|
63
|
+
diamond = await diamondDeployer.getDiamondDeployed();
|
|
64
|
+
const deployInfo = diamond.getDeployedDiamondData();
|
|
65
|
+
|
|
66
|
+
const hardhatDiamondAbiPath = 'hardhat-diamond-abi/HardhatDiamondABI.sol:';
|
|
67
|
+
const diamondArtifactName = `${hardhatDiamondAbiPath}${diamond.diamondName}`;
|
|
68
|
+
proxyDiamond = await ethers.getContractAt(diamondArtifactName, deployInfo.DiamondAddress!) as ProxyDiamond;
|
|
69
|
+
|
|
70
|
+
ethersMultichain = ethers;
|
|
71
|
+
ethersMultichain.provider = provider;
|
|
72
|
+
|
|
73
|
+
// Retrieve the signers for the chain
|
|
74
|
+
signers = await ethersMultichain.getSigners();
|
|
75
|
+
signer0 = signers[0].address;
|
|
76
|
+
signer1 = signers[1].address;
|
|
77
|
+
signer2 = signers[2].address;
|
|
78
|
+
signer0Diamond = proxyDiamond.connect(signers[0]);
|
|
79
|
+
signer1Diamond = proxyDiamond.connect(signers[1]);
|
|
80
|
+
signer2Diamond = proxyDiamond.connect(signers[2]);
|
|
81
|
+
|
|
82
|
+
// get the signer for the owner
|
|
83
|
+
owner = deployInfo.DeployerAddress; // this will be = signer0 for hardhat;
|
|
84
|
+
ownerSigner = await ethersMultichain.getSigner(owner);
|
|
85
|
+
ownerDiamond = proxyDiamond.connect(ownerSigner);
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
beforeEach(async function () {
|
|
89
|
+
snapshotId = await provider.send('evm_snapshot', []);
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
afterEach(async () => {
|
|
93
|
+
await provider.send('evm_revert', [snapshotId]);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
it(`should ensure that ${networkName} chain object can be retrieved and reused`, async function () {
|
|
97
|
+
|
|
98
|
+
expect(provider).to.not.be.undefined;
|
|
99
|
+
// expect(diamond).to.not.be.null;
|
|
100
|
+
|
|
101
|
+
const { chainId } = await provider.getNetwork();
|
|
102
|
+
expect(chainId).to.be.a('number');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
it(`should verify that ${networkName} diamond is deployed and we can get hardhat signers on ${networkName}`, async function () {
|
|
106
|
+
|
|
107
|
+
expect(signers).to.be.an('array');
|
|
108
|
+
expect(signers).to.have.lengthOf(20);
|
|
109
|
+
expect(signers[0]).to.be.instanceOf(SignerWithAddress);
|
|
110
|
+
|
|
111
|
+
expect(owner).to.not.be.undefined;
|
|
112
|
+
expect(owner).to.be.a('string');
|
|
113
|
+
// expect(owner).to.be.properAddress;
|
|
114
|
+
expect(ownerSigner).to.be.instanceOf(SignerWithAddress);
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it(`should verify that ${networkName} providers are defined and have valid block numbers`, async function () {
|
|
118
|
+
log(`Checking chain provider for: ${networkName}`);
|
|
119
|
+
expect(provider).to.not.be.undefined;
|
|
120
|
+
|
|
121
|
+
const blockNumber = await ethersMultichain.provider.getBlockNumber();
|
|
122
|
+
log(`Block number for ${networkName}: ${blockNumber}`);
|
|
123
|
+
|
|
124
|
+
expect(blockNumber).to.be.a('number');
|
|
125
|
+
// Fails for hardhat because it defaults to 0.
|
|
126
|
+
if (networkName !== 'hardhat') {
|
|
127
|
+
expect(blockNumber).to.be.greaterThan(0);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// This isn't a perfect check, because it is trying to place the current block in
|
|
131
|
+
// a range relative to the configured block number used for caching.
|
|
132
|
+
// The default of zero is to account for hardhat chain. It also possible that no
|
|
133
|
+
// block number is configured in the hardhat.config.js file which will always fetch
|
|
134
|
+
// the latest block number. This will also cause it to fail.
|
|
135
|
+
const configBlockNumber = hre.config.chainManager?.chains?.[networkName]?.blockNumber ?? 0;
|
|
136
|
+
expect(blockNumber).to.be.gte(configBlockNumber);
|
|
137
|
+
|
|
138
|
+
expect(blockNumber).to.be.lte(configBlockNumber + 500);
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// it(`should verify ERC173 contract ownership on ${networkName}`, async function () {
|
|
142
|
+
// // check if the owner is the deployer and transfer ownership to the deployer
|
|
143
|
+
// const currentContractOwner = await ownerDiamond.owner();
|
|
144
|
+
// expect(currentContractOwner.toLowerCase()).to.be.eq(await owner.toLowerCase());
|
|
145
|
+
// });
|
|
146
|
+
|
|
147
|
+
it(`should validate ERC165 interface compatibility on ${networkName}`, async function () {
|
|
148
|
+
// Test ERC165 interface compatibility
|
|
149
|
+
const supportsERC165 = await proxyDiamond.supportsInterface('0x01ffc9a7');
|
|
150
|
+
expect(supportsERC165).to.be.true;
|
|
151
|
+
|
|
152
|
+
log(`Diamond deployed and validated on ${networkName}`);
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it(`should validate IDiamondCut interface compatibility on ${networkName}`, async function () {
|
|
156
|
+
// Test ERC165 interface compatibility
|
|
157
|
+
const iDiamonCutInterface = IDiamondCut__factory.createInterface();
|
|
158
|
+
// Generate the IDiamondCut interface ID by XORing with the base interface ID.
|
|
159
|
+
const iDiamondCutInterfaceID = getInterfaceID(iDiamonCutInterface);
|
|
160
|
+
// const supportsIDiamondCut = await proxyDiamond.supportsInterface('0x1f931c1c');
|
|
161
|
+
const supportsERC165 = await proxyDiamond.supportsInterface(iDiamondCutInterfaceID._hex);
|
|
162
|
+
expect(supportsERC165).to.be.true;
|
|
163
|
+
|
|
164
|
+
log(`DiamondCut Facet interface support validated on ${networkName}`);
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
it(`should validate IDiamondLoupe interface compatibility on ${networkName}`, async function () {
|
|
168
|
+
// Test ERC165 interface compatibility
|
|
169
|
+
const iDiamondLoupeInterface = IDiamondLoupe__factory.createInterface();
|
|
170
|
+
// Generate the IDiamondLoupe interface ID by XORing with the base interface ID.
|
|
171
|
+
const iDiamondLoupeInterfaceID = getInterfaceID(iDiamondLoupeInterface);
|
|
172
|
+
// const supportsIDiamondLoupe = await proxyDiamond.supportsInterface('0x48e3885f');
|
|
173
|
+
const supportsERC165 = await proxyDiamond.supportsInterface(iDiamondLoupeInterfaceID._hex);
|
|
174
|
+
expect(supportsERC165).to.be.true;
|
|
175
|
+
log(`DiamondLoupe Facet interface support validated on ${networkName}`);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
it(`should verify ERC165 supported interface for ERC20 on ${networkName}`, async function () {
|
|
179
|
+
log(`Validating ERC20 interface on chain: ${networkName}`);
|
|
180
|
+
const IERC20UpgradeableInterface = IERC20Upgradeable__factory.createInterface();
|
|
181
|
+
// Generate the ERC20 interface ID by XORing with the base interface ID.
|
|
182
|
+
const IERC20InterfaceID = getInterfaceID(IERC20UpgradeableInterface);
|
|
183
|
+
// Assert that the `diamond` contract supports the ERC20 interface.
|
|
184
|
+
// assert(
|
|
185
|
+
// await proxyDiamond?.supportsInterface(IERC20InterfaceID._hex),
|
|
186
|
+
// "Doesn't support IERC20Upgradeable",
|
|
187
|
+
// );
|
|
188
|
+
|
|
189
|
+
// Test ERC165 interface compatibility for ERC20 '0x37c8e2a0'
|
|
190
|
+
// const supportsERC20 = await proxyDiamond?.supportsInterface(IERC20InterfaceID._hex);
|
|
191
|
+
|
|
192
|
+
// Test ERC165 interface compatibility for ERC20Upgradeable '0x36372b07'
|
|
193
|
+
const supportsERC20 = await proxyDiamond?.supportsInterface('0x36372b07');
|
|
194
|
+
|
|
195
|
+
expect(supportsERC20).to.be.true;
|
|
196
|
+
|
|
197
|
+
log(`ERC20 interface validated on ${networkName}`);
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# OpenZeppelin Defender Configuration
|
|
2
|
+
# Get these from your Defender dashboard: https://defender.openzeppelin.com/
|
|
3
|
+
DEFENDER_API_KEY=your_defender_api_key_here
|
|
4
|
+
DEFENDER_API_SECRET=your_defender_api_secret_here
|
|
5
|
+
|
|
6
|
+
# Defender Relayer Configuration
|
|
7
|
+
# The address of your Defender Relayer (optional for deployment, required for automation)
|
|
8
|
+
DEFENDER_RELAYER_ADDRESS=0x1234567890123456789012345678901234567890
|
|
9
|
+
|
|
10
|
+
# Multi-signature Safe Configuration
|
|
11
|
+
# Address of your Gnosis Safe or similar multi-sig wallet
|
|
12
|
+
DEFENDER_SAFE_ADDRESS=0x0987654321098765432109876543210987654321
|
|
13
|
+
|
|
14
|
+
# Deployment Configuration
|
|
15
|
+
# Enable automatic approval of Defender proposals (use with caution)
|
|
16
|
+
AUTO_APPROVE=false
|
|
17
|
+
|
|
18
|
+
# Network Configuration for Testing
|
|
19
|
+
# Sepolia Testnet (recommended for testing)
|
|
20
|
+
SEPOLIA_RPC_URL=https://sepolia.infura.io/v3/YOUR_INFURA_KEY
|
|
21
|
+
|
|
22
|
+
# Mumbai Testnet (Polygon)
|
|
23
|
+
MUMBAI_RPC_URL=https://polygon-mumbai.infura.io/v3/YOUR_INFURA_KEY
|
|
24
|
+
|
|
25
|
+
# Private Key for Deployment (NEVER commit this to version control)
|
|
26
|
+
# Use a dedicated deployment account with limited funds
|
|
27
|
+
DEPLOYER_PRIVATE_KEY=your_private_key_here_for_testing_only
|
|
28
|
+
|
|
29
|
+
# Contract Verification (optional)
|
|
30
|
+
ETHERSCAN_API_KEY=your_etherscan_api_key
|
|
31
|
+
POLYGONSCAN_API_KEY=your_polygonscan_api_key
|
|
32
|
+
|
|
33
|
+
# Debug and Logging
|
|
34
|
+
DEBUG=false
|
|
35
|
+
VERBOSE_DEPLOYMENT=true
|