Skip to content
This repository was archived by the owner on Mar 11, 2025. It is now read-only.

Commit 0c7b4f7

Browse files
committed
chore: add hardhat cli command to configure sygma-x after deployments
1 parent 11b9f67 commit 0c7b4f7

File tree

11 files changed

+343
-23
lines changed

11 files changed

+343
-23
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Requires `yarn` and `@nomicfoundation/hardhat`.
3131
`test` - Runs mocha tests <br>
3232
`typechain` - Generate Typechain typings for compiled contracts <br>
3333
`verify` - Verifies contract on Etherscan <br>
34+
* custom hardhat commands: <bt>
35+
`configure-sygma --file [path to config json]` - configures sygma after deployments
3436
* custom commands: <br>
3537
`yarn run test`: Runs tests.
3638

hardhat.config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import "@nomicfoundation/hardhat-chai-matchers";
66
import "@nomicfoundation/hardhat-verify";
77
import "hardhat-deploy";
88

9+
import "./scripts/tasks";
10+
911
dotenv.config();
1012

1113
const config: HardhatUserConfig = {
@@ -20,6 +22,10 @@ const config: HardhatUserConfig = {
2022
},
2123
},
2224
networks: {
25+
localhost: {
26+
live: false,
27+
saveDeployments: true,
28+
},
2329
sepolia: {
2430
url: `${process.env.SEPOLIA_PROVIDER_URL}`,
2531
accounts: [

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"scripts": {
1212
"compile": "npx hardhat compile",
1313
"coverage": "npx hardhat coverage",
14+
"configure:sygma": "npx hardhat configure-sygma",
1415
"deploy": "npx hardhat deploy --network",
1516
"lint:typescript": "eslint 'test/**/*.ts' 'scripts/**/*.ts'",
1617
"lint:typescript:fix": "prettier --config .prettierrc.json --write 'scripts/**/*.ts' 'test/**/*.ts' 'hardhat.config.ts'",
@@ -24,7 +25,7 @@
2425
"@chainsafe/eslint-config": "^2.1.1",
2526
"@metamask/eth-sig-util": "^7.0.0",
2627
"@nomicfoundation/hardhat-chai-matchers": "^2.0.2",
27-
"@nomicfoundation/hardhat-ethers": "^3.0.4",
28+
"@nomicfoundation/hardhat-ethers": "^3.0.5",
2829
"@nomicfoundation/hardhat-network-helpers": "^1.0.10",
2930
"@nomicfoundation/hardhat-toolbox": "^3.0.0",
3031
"@nomicfoundation/hardhat-verify": "^1.0.0",

scripts/environments/testnet.json

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
{
2+
"localhost": {
3+
"domainID": "1",
4+
"specterAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
5+
"routerAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
6+
"executorAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
7+
"verifiersAddresses": ["0x990D2FcF3AEe2D543aCf75CEc053eF16c0eAfAA1","0x990D2FcF3AEe2D543aCf75CEc053eF16c0eAfAA1"],
8+
"securityModel": 1,
9+
"slotIndex": 1,
10+
"access": {
11+
"feeRouterAdmin": "0xe9f23A8289764280697a03aC06795eA92a170e42",
12+
"feeHandlerAdmin": "0xe9f23A8289764280697a03aC06795eA92a170e42",
13+
"accessControl": {
14+
"0x80ae1c28": "0xe9f23A8289764280697a03aC06795eA92a170e42",
15+
"0xffaac0eb": "0xe9f23A8289764280697a03aC06795eA92a170e42",
16+
"0x9d33b6d4": "0xe9f23A8289764280697a03aC06795eA92a170e42",
17+
"0x8b63aebf": "0xe9f23A8289764280697a03aC06795eA92a170e42",
18+
"0x8c0c2631": "0xe9f23A8289764280697a03aC06795eA92a170e42",
19+
"0xedc20c3c": "0xe9f23A8289764280697a03aC06795eA92a170e42",
20+
"0xd15ef64e": "0xe9f23A8289764280697a03aC06795eA92a170e42",
21+
"0x8a3234c7": "0xe9f23A8289764280697a03aC06795eA92a170e42",
22+
"0xbd2a1820": "0xe9f23A8289764280697a03aC06795eA92a170e42",
23+
"0xd2e5fae9": "0xe9f23A8289764280697a03aC06795eA92a170e42",
24+
"0xd8236744": "0xe9f23A8289764280697a03aC06795eA92a170e42",
25+
"0x366b4885": "0xe9f23A8289764280697a03aC06795eA92a170e42",
26+
"0x6ba6db6b": "0xe9f23A8289764280697a03aC06795eA92a170e42"
27+
}
28+
},
29+
"erc20": [
30+
{
31+
"name": "ERC20LRTest",
32+
"symbol": "ERC20TST",
33+
"address": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
34+
"resourceID": "0x0000000000000000000000000000000000000000000000000000000000000300",
35+
"feeType": "undefined",
36+
"strategy": "lr",
37+
"decimals": "18"
38+
}
39+
],
40+
"permissionlessGeneric": {
41+
"resourceID": "0x0000000000000000000000000000000000000000000000000000000000000500",
42+
"feeType": "undefined"
43+
}
44+
},
45+
"sepolia": {
46+
"domainID": "2",
47+
"specterAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
48+
"routerAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
49+
"executorAddress": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
50+
"verifiersAddresses": ["0x990D2FcF3AEe2D543aCf75CEc053eF16c0eAfAA1","0x990D2FcF3AEe2D543aCf75CEc053eF16c0eAfAA1"],
51+
"securityModel": 1,
52+
"slotIndex": 1,
53+
"access": {
54+
"feeRouterAdmin": "0xe9f23A8289764280697a03aC06795eA92a170e42",
55+
"feeHandlerAdmin": "0xe9f23A8289764280697a03aC06795eA92a170e42",
56+
"accessControl": {
57+
"0x80ae1c28": "0xe9f23A8289764280697a03aC06795eA92a170e42",
58+
"0xffaac0eb": "0xe9f23A8289764280697a03aC06795eA92a170e42",
59+
"0x9d33b6d4": "0xe9f23A8289764280697a03aC06795eA92a170e42",
60+
"0x8b63aebf": "0xe9f23A8289764280697a03aC06795eA92a170e42",
61+
"0x8c0c2631": "0xe9f23A8289764280697a03aC06795eA92a170e42",
62+
"0xedc20c3c": "0xe9f23A8289764280697a03aC06795eA92a170e42",
63+
"0xd15ef64e": "0xe9f23A8289764280697a03aC06795eA92a170e42",
64+
"0x8a3234c7": "0xe9f23A8289764280697a03aC06795eA92a170e42",
65+
"0xbd2a1820": "0xe9f23A8289764280697a03aC06795eA92a170e42",
66+
"0xd2e5fae9": "0xe9f23A8289764280697a03aC06795eA92a170e42",
67+
"0xd8236744": "0xe9f23A8289764280697a03aC06795eA92a170e42",
68+
"0x366b4885": "0xe9f23A8289764280697a03aC06795eA92a170e42",
69+
"0x6ba6db6b": "0xe9f23A8289764280697a03aC06795eA92a170e42"
70+
}
71+
},
72+
"erc20": [
73+
{
74+
"name": "ERC20LRTest",
75+
"symbol": "ERC20TST",
76+
"address": "0x455E5AA18469bC6ccEF49594645666C587A3a71B",
77+
"resourceID": "0x0000000000000000000000000000000000000000000000000000000000000300",
78+
"feeType": "undefined",
79+
"strategy": "lr",
80+
"decimals": "18"
81+
}
82+
],
83+
"permissionlessGeneric": {
84+
"resourceID": "0x0000000000000000000000000000000000000000000000000000000000000500",
85+
"feeType": "undefined"
86+
}
87+
}
88+
}

scripts/migrations/01_deployCoreContracts.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,6 @@ const deployFunc: DeployFunction = async function ({
1212
const { deployer } = await getNamedAccounts();
1313

1414
const domainID = process.env.BRIDGE_DOMAIN_ID;
15-
const reannounceAdminAddress =
16-
process.env.FUNCTIONS_ACCESS_ADMIN_ADDRESS ?? deployer;
1715
const spectreDomainIDs = process.env.SPECTRE_DOMAIN_IDS ?? 0;
1816
const spectreAddresses = process.env.SPECTRE_ADDRESSES ?? ethers.ZeroAddress;
1917

@@ -33,7 +31,7 @@ const deployFunc: DeployFunction = async function ({
3331

3432
const accessControlArgs = [
3533
accessControlFuncSignatures,
36-
Array(accessControlFuncSignatures.length).fill(reannounceAdminAddress),
34+
Array(accessControlFuncSignatures.length).fill(deployer),
3735
];
3836
const accessControlInstance = await deploy("AccessControlSegregator", {
3937
from: deployer,
@@ -44,9 +42,6 @@ const deployFunc: DeployFunction = async function ({
4442
console.log(
4543
`Access control segregator contract successfully deployed to: ${accessControlInstance.address}`,
4644
);
47-
console.log(
48-
`Granted all admin functions rights to: ${reannounceAdminAddress}`,
49-
);
5045

5146
const specterProxyArgs = [spectreDomainIDs, spectreAddresses];
5247
const spectreProxyInstance = await deploy("SpectreProxy", {

scripts/migrations/02_deployHandlers.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type { HardhatRuntimeEnvironment } from "hardhat/types";
22
import type { DeployFunction } from "hardhat-deploy/dist/types";
33

4+
import { DEPLOYMENTS } from "../types";
45
import { verifyContract } from "../utils";
56

67
const deployFunc: DeployFunction = async function ({
@@ -10,15 +11,9 @@ const deployFunc: DeployFunction = async function ({
1011
const { deploy } = deployments;
1112
const { deployer } = await getNamedAccounts();
1213
try {
13-
const bridgeInstance = await deployments.get("Bridge");
14-
const routerInstance = await deployments.get("Router");
15-
const executorInstance = await deployments.get("Executor");
14+
const bridgeInstance = await deployments.get(DEPLOYMENTS.Bridge);
1615

17-
const erc20HandlerArgs = [
18-
bridgeInstance.address,
19-
routerInstance.address,
20-
executorInstance.address,
21-
];
16+
const erc20HandlerArgs = [bridgeInstance.address];
2217
const erc20HandlerInstance = await deploy("ERC20Handler", {
2318
from: deployer,
2419
args: erc20HandlerArgs,
@@ -29,10 +24,7 @@ const deployFunc: DeployFunction = async function ({
2924
`ERC20 handler contract successfully deployed to: ${erc20HandlerInstance.address}`,
3025
);
3126

32-
const permissionlessGenericHandlerArgs = [
33-
bridgeInstance.address,
34-
executorInstance.address,
35-
];
27+
const permissionlessGenericHandlerArgs = [bridgeInstance.address];
3628
const permissionlessGenericHandlerInstance = await deploy(
3729
"PermissionlessGenericHandler",
3830
{
@@ -49,7 +41,7 @@ const deployFunc: DeployFunction = async function ({
4941
`Permissionless generic handler contract successfully deployed to: ${permissionlessGenericHandlerInstance.address}`,
5042
);
5143

52-
const feeHandlerRouterArgs = [routerInstance.address];
44+
const feeHandlerRouterArgs = [bridgeInstance.address];
5345
const feeHandlerRouterInstance = await deploy("FeeHandlerRouter", {
5446
from: deployer,
5547
args: feeHandlerRouterArgs,
@@ -63,7 +55,6 @@ const deployFunc: DeployFunction = async function ({
6355
const basicFeeHandlerArgs = [
6456
bridgeInstance.address,
6557
feeHandlerRouterInstance.address,
66-
routerInstance.address,
6758
];
6859
const basicFeeHandlerInstance = await deploy("BasicFeeHandler", {
6960
from: deployer,
@@ -78,7 +69,6 @@ const deployFunc: DeployFunction = async function ({
7869
const percentageFeeHandlerArgs = [
7970
bridgeInstance.address,
8071
feeHandlerRouterInstance.address,
81-
routerInstance.address,
8272
];
8373
const percentageFeeHandlerInstance = await deploy(
8474
"PercentageERC20FeeHandlerEVM",

scripts/tasks/configureSygma.ts

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { task } from "hardhat/config";
2+
3+
import { getNetworksConfig } from "../../test/deployments";
4+
import { DEPLOYMENTS } from "../types";
5+
6+
const EMPTY_SET_RESOURCE_DATA = "0x";
7+
8+
task("configure-sygma", "Configures all Sygma contracts after deployments")
9+
.addParam("file", "Environment for which you want to configure Sygma")
10+
.setAction(async (_, hre) => {
11+
const networksConfig = getNetworksConfig();
12+
const currentNetworkConfig = networksConfig[hre.network.name];
13+
// remove the current network from networks config
14+
delete networksConfig[hre.network.name];
15+
16+
const accessSegregatorDeployment = await hre.deployments.get(
17+
DEPLOYMENTS.AccessSegregator,
18+
);
19+
const accessControlInstance = await hre.ethers.getContractAt(
20+
DEPLOYMENTS.AccessSegregator,
21+
accessSegregatorDeployment.address,
22+
);
23+
24+
const spectreProxyDeployment = await hre.deployments.get(
25+
DEPLOYMENTS.SpectreProxy,
26+
);
27+
const spectreProxyInstance = await hre.ethers.getContractAt(
28+
DEPLOYMENTS.SpectreProxy,
29+
spectreProxyDeployment.address,
30+
);
31+
32+
const bridgeDeployment = await hre.deployments.get(DEPLOYMENTS.Bridge);
33+
const bridgeInstance = await hre.ethers.getContractAt(
34+
DEPLOYMENTS.Bridge,
35+
bridgeDeployment.address,
36+
);
37+
38+
const erc20HandlerDeployment = await hre.deployments.get(
39+
DEPLOYMENTS.ERC20Handler,
40+
);
41+
const erc20HandlerInstance = await hre.ethers.getContractAt(
42+
DEPLOYMENTS.ERC20Handler,
43+
erc20HandlerDeployment.address,
44+
);
45+
46+
const executorDeployment = await hre.deployments.get(DEPLOYMENTS.Executor);
47+
const executorInstance = await hre.ethers.getContractAt(
48+
DEPLOYMENTS.Executor,
49+
executorDeployment.address,
50+
);
51+
52+
await spectreProxyInstance.adminSetSpectreAddress(
53+
currentNetworkConfig.domainID,
54+
currentNetworkConfig.specterAddress,
55+
);
56+
57+
await bridgeInstance.adminChangeRouterAddress(
58+
currentNetworkConfig.routerAddress,
59+
);
60+
61+
await bridgeInstance.adminChangeExecutorAddress(
62+
currentNetworkConfig.executorAddress,
63+
);
64+
65+
for (const network of Object.values(networksConfig)) {
66+
await executorInstance.adminChangeSlotIndex(
67+
network.domainID,
68+
network.slotIndex,
69+
);
70+
71+
await executorInstance.adminSetVerifiers(
72+
network.securityModel,
73+
network.verifiersAddresses,
74+
);
75+
}
76+
77+
for (const erc20Token of currentNetworkConfig.erc20) {
78+
const erc20HandlerAddress = await erc20HandlerInstance.getAddress();
79+
const erc20TokenInstance = await hre.ethers.getContractAt(
80+
"ERC20PresetMinterPauser",
81+
erc20Token.address,
82+
);
83+
84+
await bridgeInstance.adminSetResource(
85+
erc20HandlerAddress,
86+
erc20Token.resourceID,
87+
await erc20TokenInstance.getAddress(),
88+
EMPTY_SET_RESOURCE_DATA,
89+
);
90+
91+
// strategy can be either mb (mint/burn) or lr (lock/release)
92+
if (erc20Token.strategy == "mb") {
93+
await erc20TokenInstance.grantRole(
94+
await erc20TokenInstance.MINTER_ROLE(),
95+
erc20HandlerAddress,
96+
);
97+
await bridgeInstance.adminSetBurnable(
98+
erc20HandlerAddress,
99+
erc20Token.address,
100+
);
101+
}
102+
}
103+
104+
// check json config if func access right should be renounced
105+
const reannounceAdminAddress = process.env.FUNCTIONS_ACCESS_ADMIN_ADDRESS;
106+
if (reannounceAdminAddress) {
107+
for (const [func, admin] of Object.entries(
108+
currentNetworkConfig.access.accessControl,
109+
)) {
110+
console.log("Granting access for function %s to %s", func, admin);
111+
await accessControlInstance.grantAccess(func, admin);
112+
console.log(
113+
`Granted all admin functions rights to: ${reannounceAdminAddress}`,
114+
);
115+
await accessControlInstance.grantAccess(func, admin);
116+
}
117+
}
118+
console.log("Sygma-x successfully configured");
119+
});

scripts/tasks/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from "./configureSygma";

scripts/types.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
export enum DEPLOYMENTS {
2+
AccessSegregator = "AccessControlSegregator",
3+
SpectreProxy = "SpectreProxy",
4+
Bridge = "Bridge",
5+
Router = "Router",
6+
Executor = "Executor",
7+
ERC20Handler = "ERC20Handler",
8+
}
9+
10+
export type Token = {
11+
name: string;
12+
symbol: string;
13+
address: string;
14+
resourceID: string;
15+
feeType: string;
16+
strategy: "lr" | "mb";
17+
decimals: string;
18+
};
19+
20+
export enum FeeHandlerType {
21+
BASIC = "basic",
22+
PERCENTAGE = "percentage",
23+
UNDEFINED = "undefined",
24+
}
25+
26+
export type NetworkConfig = {
27+
domainID: string;
28+
specterAddress: string;
29+
routerAddress: string;
30+
executorAddress: string;
31+
verifiersAddresses: Array<string>;
32+
slotIndex: number;
33+
securityModel: number;
34+
access: {
35+
feeRouterAdmin: string;
36+
feeHandlerAdmin: string;
37+
accessControl: {
38+
[key: string]: string;
39+
};
40+
};
41+
erc20: Array<Token>;
42+
permissionlessGeneric: {
43+
resourceID: string;
44+
feeType: FeeHandlerType;
45+
};
46+
};

0 commit comments

Comments
 (0)