Skip to content

Commit

Permalink
Write Gnosis JSON file (#2093)
Browse files Browse the repository at this point in the history
  • Loading branch information
shahthepro authored Jun 7, 2024
1 parent 802e58d commit a52ee8e
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 29 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ contracts/.certora_*
contracts/.last_confs
**/*.bak

*-gov-tx.json

# Coverage #
coverage
coverage.json
Expand Down
10 changes: 9 additions & 1 deletion contracts/contracts/interfaces/ITimelockController.sol
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,13 @@ interface ITimelockController {
bytes[] calldata payloads,
bytes32 predecessor,
bytes32 salt
) external;
) external view returns (bytes32);

function isOperationDone(bytes32 opHash) external view returns (bool);

function isOperationReady(bytes32 opHash) external view returns (bool);

function isOperation(bytes32 opHash) external view returns (bool);

function getMinDelay() external view returns (uint256);
}
133 changes: 105 additions & 28 deletions contracts/utils/deploy.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
const hre = require("hardhat");
const { BigNumber } = require("ethers");

const fs = require("fs");
const path = require("path");

const {
advanceTime,
advanceBlocks,
Expand Down Expand Up @@ -933,6 +936,38 @@ async function useTransitionGovernance() {
return guardianHasAccess;
}

function buildAndWriteGnosisJson(targets, calldata, safeAddress) {
const json = {
version: "1.0",
chainId: "1",
createdAt: parseInt(Date.now() / 1000),
meta: {
name: "Transaction Batch",
description: "",
txBuilderVersion: "1.16.1",
createdFromSafeAddress: safeAddress || addresses.mainnet.Guardian,
createdFromOwnerAddress: "",
},
transactions: targets.map((target, i) => ({
to: target,
value: "0",
data: calldata[i],
contractMethod: null,
contractInputValues: null,
})),
};

const fileName = path.join(
__dirname,
"../build",
Date.now().toString() + "-gov-tx.json"
);

fs.writeFileSync(fileName, JSON.stringify(json, undefined, 2));

console.log("Wrote Gnosis Safe JSON to ", fileName);
}

async function handleTransitionGovernance(propDesc, propArgs) {
const { timelockAddr } = await getNamedAccounts();

Expand All @@ -955,41 +990,83 @@ async function handleTransitionGovernance(propDesc, propArgs) {
keccak256(toUtf8Bytes(propDesc)), // Salt
];

console.log(args);
const opHash = await timelock.hashOperationBatch(...args);

log(`Reducing required queue time to 60 seconds`);
/* contracts/timelock/Timelock.sol storage slot layout:
* slot[0] address admin
* slot[1] address pendingAdmin
* slot[2] uint256 delay
*/
await setStorageAt(
timelock.address,
"0x2",
"0x000000000000000000000000000000000000000000000000000000000000003c" // 60 seconds
);
if (await timelock.isOperationDone(opHash)) {
// Already executed
return;
}

log(`Scheduling batch on Timelock...`);
await timelock.connect(guradian).scheduleBatch(...args, 60);
const isScheduled = await timelock.isOperation(opHash);
const reduceTime = !isScheduled;

log(`Preparing to execute...`);
await advanceTime(60 + 5);
await advanceBlocks(2);
if (!isScheduled) {
// Needs to be scheduled
const scheduleData = timelock.interface.encodeFunctionData(
"scheduleBatch(address[],uint256[],bytes[],bytes32,bytes32,uint256)",
[...args, await timelock.getMinDelay()]
);

buildAndWriteGnosisJson(
[timelock.address],
[scheduleData],
addresses.mainnet.Guardian
);

if (reduceTime) {
log(`Reducing required queue time to 60 seconds`);
/* contracts/timelock/Timelock.sol storage slot layout:
* slot[0] address admin
* slot[1] address pendingAdmin
* slot[2] uint256 delay
*/
await setStorageAt(
timelock.address,
"0x2",
"0x000000000000000000000000000000000000000000000000000000000000003c" // 60 seconds
);

log(`Scheduling batch on Timelock...`);
await timelock.connect(guradian).scheduleBatch(...args, 60);
}
}

if (!(await timelock.isOperationReady(opHash))) {
log(`Preparing to execute...`);
await advanceTime((await timelock.getMinDelay()) + 10);
await advanceBlocks(2);
}

if (isScheduled) {
// Write execution data
const executeData = timelock.interface.encodeFunctionData(
"executeBatch(address[],uint256[],bytes[],bytes32,bytes32)",
[...args]
);

buildAndWriteGnosisJson(
[timelock.address],
[executeData],
addresses.mainnet.Guardian
);
}

log(`Executing batch on Timelock...`);
await timelock.connect(guradian).executeBatch(...args);

log(`Setting queue time back to 172800 seconds`);
/* contracts/timelock/Timelock.sol storage slot layout:
* slot[0] address admin
* slot[1] address pendingAdmin
* slot[2] uint256 delay
*/
await setStorageAt(
timelock.address,
"0x2",
"0x000000000000000000000000000000000000000000000000000000000002a300" // 172800 seconds
);
if (reduceTime) {
log(`Setting queue time back to 172800 seconds`);
/* contracts/timelock/Timelock.sol storage slot layout:
* slot[0] address admin
* slot[1] address pendingAdmin
* slot[2] uint256 delay
*/
await setStorageAt(
timelock.address,
"0x2",
"0x000000000000000000000000000000000000000000000000000000000002a300" // 172800 seconds
);
}
}

/**
Expand Down

0 comments on commit a52ee8e

Please sign in to comment.