Skip to content

Commit

Permalink
Merge pull request #364 from 0xPolygonHermez/feature/add-tool-change-…
Browse files Browse the repository at this point in the history
…delay

add tool to change minDelay timelock
  • Loading branch information
invocamanman authored Jan 29, 2025
2 parents 9521339 + ff1ebfa commit 17bb90d
Show file tree
Hide file tree
Showing 4 changed files with 165 additions and 0 deletions.
2 changes: 2 additions & 0 deletions tools/changeDelayTimelock/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
change_delay_output-*
change_delay_timelock.json
35 changes: 35 additions & 0 deletions tools/changeDelayTimelock/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Change minDelay PolygonZkEVMTimelock
Script to change `minDelay` from `PolygonZkEVMTimelock`

## Install
```
npm i
```

## Setup
- Config file `change_delay_timelock.json`:
- `timelockContractAddress`: timelock contract address
- `newMinDelay`: new `minDelay`
- `timeLockDelay`: timelockDelay (by defalult `timeLockDelay` == current `minDelay`)
- `timelockSalt(optional)`: timelock salt
- `predecessor(optional)`: timelock predecessor
- A network should be selected when running the script
- examples: `--network sepolia` or `--network mainnet`
- This uses variables set in `hardhat.config.ts`
- Which uses some environment variables that should be set in `.env`
> All paths are from root repository
## Usage
> All commands are done from root repository.
- Copy configuration file:
```
cp ./tools/changeDelayTimelock/change_delay_timelock.json.example ./tools/changeDelayTimelock/change_delay_timelock.json
```
- Set your parameters
- Run tool:
```
npx hardhat run ./tools/changeDelayTimelock/changeDelayTimelock.ts --network localhost
```


121 changes: 121 additions & 0 deletions tools/changeDelayTimelock/changeDelayTimelock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
/* eslint-disable no-await-in-loop, no-use-before-define, no-lonely-if */
/* eslint-disable no-console, no-inner-declarations, no-undef, import/no-unresolved */
import {utils} from "ffjavascript";
import path = require("path");
import fs = require("fs");

import * as dotenv from "dotenv";
dotenv.config({path: path.resolve(__dirname, "../../../.env")});
import {ethers, network, upgrades} from "hardhat";
import { PolygonZkEVMTimelock } from "../../typechain-types";

const parameters = require("./change_delay_timelock.json");
const dateStr = new Date().toISOString();
const pathOutputJson = path.resolve(__dirname, `./change_delay_output-${dateStr}.json`);

async function main() {

const outputJson = {} as any;

const timelockContractFactory = await ethers.getContractFactory("PolygonZkEVMTimelock");
const timelockContract = (await timelockContractFactory.attach(
parameters.timelockContractAddress
)) as PolygonZkEVMTimelock;

console.log("#######################\n");
console.log("timelockContract address: ", timelockContract.target)
console.log("#######################\n");

const timelockDelay = parameters.timeLockDelay ? parameters.timeLockDelay : Number(await timelockContract.getMinDelay());
const salt = parameters.timelockSalt || ethers.ZeroHash;
const predecessor = parameters.predecessor || ethers.ZeroHash;

const operation = genOperation(
parameters.timelockContractAddress,
0, // value
timelockContract.interface.encodeFunctionData(
'updateDelay',
[parameters.newMinDelay],
),
predecessor, // predecessor
salt // salt
);

// Schedule operation
const scheduleData = timelockContractFactory.interface.encodeFunctionData("schedule", [
operation.target,
operation.value,
operation.data,
operation.predecessor,
operation.salt,
timelockDelay,
]);

// Execute operation
const executeData = timelockContractFactory.interface.encodeFunctionData("execute", [
operation.target,
operation.value,
operation.data,
operation.predecessor,
operation.salt,
]);

console.log("timelockDelay: ", timelockDelay)
console.log({scheduleData});
console.log({executeData});

outputJson.scheduleData = scheduleData;
outputJson.executeData = executeData;

// Decode the scheduleData for better readability
const timelockTx = timelockContractFactory.interface.parseTransaction({data: scheduleData});
const paramsArray = timelockTx?.fragment.inputs as any;
const objectDecoded = {} as any;

for (let i = 0; i < paramsArray?.length; i++) {
const currentParam = paramsArray[i];
objectDecoded[currentParam.name] = timelockTx?.args[i];

if (currentParam.name == "data") {
const decodedTimelockTx = timelockContractFactory.interface.parseTransaction({
data: timelockTx?.args[i],
});
const objectDecodedData = {} as any;
const paramsArrayData = decodedTimelockTx?.fragment.inputs as any;

objectDecodedData.signature = decodedTimelockTx?.signature;
objectDecodedData.selector = decodedTimelockTx?.selector;

for (let j = 0; j < paramsArrayData?.length; j++) {
const currentParam = paramsArrayData[j];
objectDecodedData[currentParam.name] = decodedTimelockTx?.args[j];
}
objectDecoded["decodedData"] = objectDecodedData;
}
}
outputJson.decodedScheduleData = objectDecoded;

await fs.writeFileSync(pathOutputJson, JSON.stringify(utils.stringifyBigInts(outputJson), null, 1));
}

// OZ test functions
function genOperation(target: any, value: any, data: any, predecessor: any, salt: any) {
const abiEncoded = ethers.AbiCoder.defaultAbiCoder().encode(
["address", "uint256", "bytes", "uint256", "bytes32"],
[target, value, data, predecessor, salt]
);
const id = ethers.keccak256(abiEncoded);
return {
id,
target,
value,
data,
predecessor,
salt,
};
}

main().catch((e) => {
console.error(e);
process.exit(1);
});
7 changes: 7 additions & 0 deletions tools/changeDelayTimelock/change_delay_timelock.json.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"timelockContractAddress": "0x0165878A594ca255338adfa4d48449f69242Eb8F",
"newMinDelay": 1800,
"timeLockDelay": "",
"predecessor": "",
"timelockSalt": ""
}

0 comments on commit 17bb90d

Please sign in to comment.