diff --git a/tools/changeDelayTimelock/.gitignore b/tools/changeDelayTimelock/.gitignore new file mode 100644 index 00000000..bcbd021a --- /dev/null +++ b/tools/changeDelayTimelock/.gitignore @@ -0,0 +1,2 @@ +change_delay_output-* +change_delay_timelock.json \ No newline at end of file diff --git a/tools/changeDelayTimelock/README.md b/tools/changeDelayTimelock/README.md new file mode 100644 index 00000000..7df7878a --- /dev/null +++ b/tools/changeDelayTimelock/README.md @@ -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 +``` + + diff --git a/tools/changeDelayTimelock/changeDelayTimelock.ts b/tools/changeDelayTimelock/changeDelayTimelock.ts new file mode 100644 index 00000000..3fb5f103 --- /dev/null +++ b/tools/changeDelayTimelock/changeDelayTimelock.ts @@ -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); +}); diff --git a/tools/changeDelayTimelock/change_delay_timelock.json.example b/tools/changeDelayTimelock/change_delay_timelock.json.example new file mode 100644 index 00000000..0a4ec9d0 --- /dev/null +++ b/tools/changeDelayTimelock/change_delay_timelock.json.example @@ -0,0 +1,7 @@ +{ + "timelockContractAddress": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "newMinDelay": 1800, + "timeLockDelay": "", + "predecessor": "", + "timelockSalt": "" +} \ No newline at end of file