Skip to content

Commit

Permalink
Merge pull request #114 from valory-xyz/gnosis_preparation
Browse files Browse the repository at this point in the history
chore: updating scripts and deploying token-based service contracts on chiado
  • Loading branch information
mariapiamo authored Sep 21, 2023
2 parents 1df9f06 + cb5dcd2 commit 388cf7e
Show file tree
Hide file tree
Showing 15 changed files with 905 additions and 446 deletions.
7 changes: 6 additions & 1 deletion .gitleaksignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@ f0bbda32a3c2c12a69a1fcef0c360eb524b27ab9:scripts/deployment/globals_mainnet.json
d818b0e6ed7f4ebd557b2502cdedea2cadeb22d5:scripts/audit_3_chains/audit.sh:generic-api-key:32
d818b0e6ed7f4ebd557b2502cdedea2cadeb22d5:scripts/audit_3_chains/audit.sh:generic-api-key:43
d818b0e6ed7f4ebd557b2502cdedea2cadeb22d5:scripts/audit_3_chains/audit.sh:generic-api-key:85
d818b0e6ed7f4ebd557b2502cdedea2cadeb22d5:scripts/audit_3_chains/audit.sh:generic-api-key:86
d818b0e6ed7f4ebd557b2502cdedea2cadeb22d5:scripts/audit_3_chains/audit.sh:generic-api-key:86
d780294b8dccf047391a71b75dade50a6b89003b:scripts/deployment/l2/globals_gnosis_chiado.json:generic-api-key:1
f7b0036b3b5d2be2b81a56d2a4f10a91653fa872:scripts/deployment/l2/bridges/gnosis/test_service_registry_token_utility_change_drainer.js:generic-api-key:44
71afff8bddeb852787f7294d7838832d5bb26a34:scripts/deployment/l2/bridges/gnosis/test_service_registry_token_utility_change_drainer.js:generic-api-key:44
d780294b8dccf047391a71b75dade50a6b89003b:scripts/deployment/l2/globals_gnosis_chiado.json:generic-api-key:2
7d2fbdb1556dc3ed289edf7e116b378b6f6a9d83:scripts/deployment/l2/bridges/gnosis/test_service_registry_token_utility_change_drainer.js:generic-api-key:44
16 changes: 13 additions & 3 deletions docs/configuration.json
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,19 @@
"address": "0x31D3202d8744B16A120117A053459DDFAE93c855"
},
{
"name": "ServiceManager",
"artifact": "abis/0.8.19/ServiceManager.json",
"address": "0x29086141ecdc310058fc23273F8ef7881d20C2f7"
"name": "ServiceRegistryTokenUtility",
"artifact": "abis/0.8.19/ServiceRegistryTokenUtility.json",
"address": "0xc2c7E40674f1C7Bb99eFe5680Efd79842502bED4"
},
{
"name": "ServiceManagerToken",
"artifact": "abis/0.8.19/ServiceManagerToken.json",
"address": "0xc965a32185590Eb5a5fffDba29E96126b7650eDe"
},
{
"name": "OperatorWhitelist",
"artifact": "abis/0.8.19/OperatorWhitelist.json",
"address": "0x6f7661F52fE1919996d0A4F68D09B344093a349d"
},
{
"name": "GnosisSafeMultisig",
Expand Down
4 changes: 2 additions & 2 deletions hardhat.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,8 @@ module.exports = {
network: "chiado",
chainId: 10200,
urls: {
apiURL: "https://blockscout.com/gnosis/chiado/api",
browserURL: "https://blockscout.com/gnosis/chiado",
apiURL: "https://gnosis-chiado.blockscout.com/api",
browserURL: "https://gnosis-chiado.blockscout.com/",
},
},
{
Expand Down
30 changes: 23 additions & 7 deletions scripts/audit_chains/audit_contracts_setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ async function checkServiceRegistry(chainId, provider, globalsInstance, configCo

// Check manager
const manager = await serviceRegistry.manager();
if (chainId === "1" || chainId === "5") {
// ServiceRegistryManagerToken for L1
if (chainId === "1" || chainId === "5" || chainId === "10200") {
// ServiceRegistryManagerToken for L1 and L2 that currently have the full setup
customExpect(manager, globalsInstance["serviceManagerTokenAddress"], log + ", function: manager()");
} else {
// ServiceRegistryManager for L2
Expand Down Expand Up @@ -217,8 +217,8 @@ async function checkServiceManager(chainId, provider, globalsInstance, configCon
const paused = await serviceManager.paused();
customExpect(paused, false, log + ", function: paused()");

// Checks for L1 only
if (chainId === "1" || chainId === "5") {
// Checks for L1 and L2 that currently have the full setup
if (chainId === "1" || chainId === "5" || chainId === "10200") {
// Version
const version = await serviceManager.version();
customExpect(version, "1.1.1", log + ", function: version()");
Expand Down Expand Up @@ -253,7 +253,11 @@ async function checkServiceRegistryTokenUtility(chainId, provider, globalsInstan

// Check drainer
const drainer = await serviceRegistryTokenUtility.drainer();
customExpect(drainer, globalsInstance["treasuryAddress"], log + ", function: drainer()");
if (chainId === "1" || chainId === "5") {
customExpect(drainer, globalsInstance["timelockAddress"], log + ", function: drainer()");
} else {
customExpect(drainer, globalsInstance["bridgeMediatorAddress"], log + ", function: drainer()");
}

// Check service registry
const serviceRegistry = await serviceRegistryTokenUtility.serviceRegistry();
Expand Down Expand Up @@ -423,8 +427,20 @@ async function main() {
let log = initLog + ", contract: " + "ServiceRegistryL2";
await checkServiceRegistry(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "ServiceRegistryL2", log);

log = initLog + ", contract: " + "ServiceManager";
await checkServiceManager(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "ServiceManager", log);
// Make an exception for the chiado network for now as it operates with the ServiceManagerToken
if (configs[i]["chainId"] === "10200") {
log = initLog + ", contract: " + "ServiceManagerToken";
await checkServiceManager(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "ServiceManagerToken", log);

log = initLog + ", contract: " + "ServiceRegistryTokenUtility";
await checkServiceRegistryTokenUtility(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "ServiceRegistryTokenUtility", log);

log = initLog + ", contract: " + "OperatorWhitelist";
await checkOperatorWhitelist(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "OperatorWhitelist", log);
} else {
log = initLog + ", contract: " + "ServiceManager";
await checkServiceManager(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "ServiceManager", log);
}

log = initLog + ", contract: " + "GnosisSafeMultisig";
await checkGnosisSafeImplementation(configs[i]["chainId"], providers[i], globals[i], configs[i]["contracts"], "GnosisSafeMultisig", log);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ async function main() {
console.log("Correct wallet setup");
}

// Mock Token contract across the bridge must change the drainer address
// Mock Timelock contract across the bridge must change the drainer address
const rawPayload = serviceRegistryL2.interface.encodeFunctionData("changeDrainer", [homeMediatorAddress]);
// Pack the second part of data
const target = serviceRegistryL2Address;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
/*global process*/

const { ethers } = require("ethers");

async function main() {
const ALCHEMY_API_KEY_GOERLI = process.env.ALCHEMY_API_KEY_GOERLI;
const goerliURL = "https://eth-goerli.g.alchemy.com/v2/" + ALCHEMY_API_KEY_GOERLI;
const goerliProvider = new ethers.providers.JsonRpcProvider(goerliURL);
await goerliProvider.getBlockNumber().then((result) => {
console.log("Current block number goerli: " + result);
});

const chiadoURL = "https://rpc.chiadochain.net";
const chiadoProvider = new ethers.providers.JsonRpcProvider(chiadoURL);
await chiadoProvider.getBlockNumber().then((result) => {
console.log("Current block number chiado: " + result);
});

const fs = require("fs");
// AMBProxy address on goerli
const AMBProxyAddress = "0x87A19d769D875964E9Cd41dDBfc397B2543764E6";
const AMBProxyJSON = "abis/bridges/gnosis/EternalStorageProxy.json";
let contractFromJSON = fs.readFileSync(AMBProxyJSON, "utf8");
const AMBProxyABI = JSON.parse(contractFromJSON);
const AMBProxy = new ethers.Contract(AMBProxyAddress, AMBProxyABI, goerliProvider);

// Test deployed HomeMediator address on chiado
const homeMediatorAddress = "0x0a50009D55Ed5700ac8FF713709d5Ad5fa843896";
const homeMediatorJSON = "abis/bridges/gnosis/HomeMediator.json";
contractFromJSON = fs.readFileSync(homeMediatorJSON, "utf8");
let parsedFile = JSON.parse(contractFromJSON);
const homeMediatorABI = parsedFile["abi"];
const homeMediator = new ethers.Contract(homeMediatorAddress, homeMediatorABI, chiadoProvider);

// Mock Timelock contract address on goerli (has AMBProxy address in it already)
const mockTimelockAddress = "0x5b03476a21e9c7cEB8dB1Bd9F24664e480FDcc43";
const mockTimelockJSON = "abis/bridges/gnosis/test/MockTimelock.json";
contractFromJSON = fs.readFileSync(mockTimelockJSON, "utf8");
parsedFile = JSON.parse(contractFromJSON);
const mockTimelockABI = parsedFile["abi"];
const mockTimelock = new ethers.Contract(mockTimelockAddress, mockTimelockABI, goerliProvider);

// ServiceRegistryL2 address on chiado
const serviceRegistryL2Address = "0x31D3202d8744B16A120117A053459DDFAE93c855";
const serviceRegistryL2JSON = "artifacts/contracts/ServiceRegistryL2.sol/ServiceRegistryL2.json";
contractFromJSON = fs.readFileSync(serviceRegistryL2JSON, "utf8");
parsedFile = JSON.parse(contractFromJSON);
const serviceRegistryL2ABI = parsedFile["abi"];
const serviceRegistryL2 = new ethers.Contract(serviceRegistryL2Address, serviceRegistryL2ABI, chiadoProvider);

// Get the EOA
const account = ethers.utils.HDNode.fromMnemonic(process.env.TESTNET_MNEMONIC).derivePath("m/44'/60'/0'/0/0");
const EOAgoerli = new ethers.Wallet(account, goerliProvider);
const EOAchiado = new ethers.Wallet(account, chiadoProvider);
console.log("EOA address",EOAgoerli.address);
if (EOAchiado.address == EOAgoerli.address) {
console.log("Correct wallet setup");
}

// Mock Timelock contract across the bridge must change the manager address
const globalsFile = fs.readFileSync("globals.json", "utf8");
parsedFile = JSON.parse(globalsFile);
const rawPayload = serviceRegistryL2.interface.encodeFunctionData("changeManager", [parsedFile.serviceManagerTokenAddress]);
// Pack the second part of data
const target = serviceRegistryL2Address;
const value = 0;
const payload = ethers.utils.arrayify(rawPayload);
const data = ethers.utils.solidityPack(
["address", "uint96", "uint32", "bytes"],
[target, value, payload.length, payload]
);

// Build the final payload to be passed from the imaginary Timelock
const mediatorPayload = await homeMediator.interface.encodeFunctionData("processMessageFromForeign", [data]);
const requestGasLimit = "2000000";
const timelockPayload = await AMBProxy.interface.encodeFunctionData("requireToPassMessage", [homeMediatorAddress,
mediatorPayload, requestGasLimit]);

// Send the message to chiado receiver
const tx = await mockTimelock.connect(EOAgoerli).execute(timelockPayload);
console.log("Timelock data execution hash", tx.hash);
await tx.wait();

// Wait for the event of a processed data on chiado
// catch NewFxMessage event from serviceRegistryL2 and MessageReceived event from homeMediator
// Compare the data sent and the data from the NewFxMessage event that must match
// MessageReceived(uint256 indexed stateId, address indexed sender, bytes message)
let waitForEvent = true;
while (waitForEvent) {
// Check for the last 100 blocks in order to catch the event
const events = await homeMediator.queryFilter("MessageReceived", -200);
events.forEach((item) => {
const msg = item["args"]["data"];
if (msg == data) {
console.log("Event MessageReceived. Message in chiado:", msg);
waitForEvent = false;
}
});
// Continue waiting for the event if none was received
if (waitForEvent) {
console.log("Waiting for the receive event, next update in 5 minutes ...");
// Sleep for a minute
await new Promise(r => setTimeout(r, 300000));
}
}
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/*global process*/

const { ethers } = require("ethers");

async function main() {
const ALCHEMY_API_KEY_GOERLI = process.env.ALCHEMY_API_KEY_GOERLI;
const goerliURL = "https://eth-goerli.g.alchemy.com/v2/" + ALCHEMY_API_KEY_GOERLI;
const goerliProvider = new ethers.providers.JsonRpcProvider(goerliURL);
await goerliProvider.getBlockNumber().then((result) => {
console.log("Current block number goerli: " + result);
});

const chiadoURL = "https://rpc.chiadochain.net";
const chiadoProvider = new ethers.providers.JsonRpcProvider(chiadoURL);
await chiadoProvider.getBlockNumber().then((result) => {
console.log("Current block number chiado: " + result);
});

const fs = require("fs");
// AMBProxy address on goerli
const AMBProxyAddress = "0x87A19d769D875964E9Cd41dDBfc397B2543764E6";
const AMBProxyJSON = "abis/bridges/gnosis/EternalStorageProxy.json";
let contractFromJSON = fs.readFileSync(AMBProxyJSON, "utf8");
const AMBProxyABI = JSON.parse(contractFromJSON);
const AMBProxy = new ethers.Contract(AMBProxyAddress, AMBProxyABI, goerliProvider);

// Test deployed HomeMediator address on chiado
const homeMediatorAddress = "0x0a50009D55Ed5700ac8FF713709d5Ad5fa843896";
const homeMediatorJSON = "abis/bridges/gnosis/HomeMediator.json";
contractFromJSON = fs.readFileSync(homeMediatorJSON, "utf8");
let parsedFile = JSON.parse(contractFromJSON);
const homeMediatorABI = parsedFile["abi"];
const homeMediator = new ethers.Contract(homeMediatorAddress, homeMediatorABI, chiadoProvider);

// Mock Timelock contract address on goerli (has AMBProxy address in it already)
const mockTimelockAddress = "0x5b03476a21e9c7cEB8dB1Bd9F24664e480FDcc43";
const mockTimelockJSON = "abis/bridges/gnosis/test/MockTimelock.json";
contractFromJSON = fs.readFileSync(mockTimelockJSON, "utf8");
parsedFile = JSON.parse(contractFromJSON);
const mockTimelockABI = parsedFile["abi"];
const mockTimelock = new ethers.Contract(mockTimelockAddress, mockTimelockABI, goerliProvider);

// serviceRegistryTokenUtility address on chiado
const serviceRegistryTokenUtilityAddress = "0xc2c7E40674f1C7Bb99eFe5680Efd79842502bED4";
const serviceRegistryTokenUtilityJSON = "artifacts/contracts/ServiceRegistryTokenUtility.sol/ServiceRegistryTokenUtility.json";
contractFromJSON = fs.readFileSync(serviceRegistryTokenUtilityJSON, "utf8");
parsedFile = JSON.parse(contractFromJSON);
const serviceRegistryTokenUtilityABI = parsedFile["abi"];
const serviceRegistryTokenUtility = new ethers.Contract(serviceRegistryTokenUtilityAddress, serviceRegistryTokenUtilityABI, chiadoProvider);

// Get the EOA
const account = ethers.utils.HDNode.fromMnemonic(process.env.TESTNET_MNEMONIC).derivePath("m/44'/60'/0'/0/0");
const EOAgoerli = new ethers.Wallet(account, goerliProvider);
const EOAchiado = new ethers.Wallet(account, chiadoProvider);
console.log("EOA address",EOAgoerli.address);
if (EOAchiado.address == EOAgoerli.address) {
console.log("Correct wallet setup");
}

// Mock Timelock contract across the bridge must change the drainer address
const rawPayload = serviceRegistryTokenUtility.interface.encodeFunctionData("changeDrainer", [homeMediatorAddress]);
// Pack the second part of data
const target = serviceRegistryTokenUtilityAddress;
const value = 0;
const payload = ethers.utils.arrayify(rawPayload);
const data = ethers.utils.solidityPack(
["address", "uint96", "uint32", "bytes"],
[target, value, payload.length, payload]
);

// Build the final payload to be passed from the imaginary Timelock
const mediatorPayload = await homeMediator.interface.encodeFunctionData("processMessageFromForeign", [data]);
const requestGasLimit = "2000000";
const timelockPayload = await AMBProxy.interface.encodeFunctionData("requireToPassMessage", [homeMediatorAddress,
mediatorPayload, requestGasLimit]);

// Send the message to chiado receiver
const tx = await mockTimelock.connect(EOAgoerli).execute(timelockPayload);
console.log("Timelock data execution hash", tx.hash);
await tx.wait();

// Wait for the event of a processed data on chiado
// catch NewFxMessage event from serviceRegistryTokenUtility and MessageReceived event from homeMediator
// Compare the data sent and the data from the NewFxMessage event that must match
// MessageReceived(uint256 indexed stateId, address indexed sender, bytes message)
let waitForEvent = true;
while (waitForEvent) {
// Check for the last 100 blocks in order to catch the event
const events = await homeMediator.queryFilter("MessageReceived", -200);
events.forEach((item) => {
const msg = item["args"]["data"];
if (msg == data) {
console.log("Event MessageReceived. Message in chiado:", msg);
waitForEvent = false;
}
});
// Continue waiting for the event if none was received
if (waitForEvent) {
console.log("Waiting for the receive event, next update in 5 minutes ...");
// Sleep for a minute
await new Promise(r => setTimeout(r, 300000));
}
}
}

main()
.then(() => process.exit(0))
.catch((error) => {
console.error(error);
process.exit(1);
});
12 changes: 11 additions & 1 deletion scripts/deployment/l2/deploy_13_change_managers.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ async function main() {
const gasPriceInGwei = parsedData.gasPriceInGwei;
const serviceRegistryTokenUtilityAddress = parsedData.serviceRegistryTokenUtilityAddress;
const serviceManagerTokenAddress = parsedData.serviceManagerTokenAddress;
let bridgeMediatorAddress = parsedData.bridgeMediatorAddress;
let EOA;

let networkURL;
Expand All @@ -36,6 +37,8 @@ async function main() {
networkURL = "https://rpc.gnosischain.com";
} else if (providerName === "chiado") {
networkURL = "https://rpc.chiadochain.net";
// For the chiado network, the mock timelock contract is set as the owner
bridgeMediatorAddress = parsedData.bridgeMediatorMockTimelockAddress;
} else {
console.log("Unknown network provider", providerName);
return;
Expand All @@ -60,12 +63,19 @@ async function main() {
const gasPrice = ethers.utils.parseUnits(gasPriceInGwei, "gwei");

// Transaction signing and execution
// 13. EOA to change the manager of ServiceRegistryTokenUtility to ServiceManagerToken calling `changeManager(ServiceManagerToken)`;
// 13a. EOA to change the manager of ServiceRegistryTokenUtility to ServiceManagerToken calling `changeManager(ServiceManagerToken)`;
console.log("You are signing the following transaction: serviceRegistryTokenUtility.connect(EOA).changeManager(serviceManagerTokenAddress)");
let result = await serviceRegistryTokenUtility.connect(EOA).changeManager(serviceManagerTokenAddress, { gasPrice });
// Transaction details
console.log("Contract address:", serviceRegistryTokenUtilityAddress);
console.log("Transaction:", result.hash);

// 13b. EOA to change the drainer of ServiceRegistryTokenUtility to BridgeMediator
console.log("You are signing the following transaction: serviceRegistryTokenUtility.connect(EOA).changeDrainer(bridgeMediatorAddress)");
result = await serviceRegistryTokenUtility.connect(EOA).changeDrainer(bridgeMediatorAddress, { gasPrice });
// Transaction details
console.log("Contract address:", serviceRegistryTokenUtilityAddress);
console.log("Transaction:", result.hash);
}

main()
Expand Down
Loading

0 comments on commit 388cf7e

Please sign in to comment.