From 27eb7ba749b8b8427b419b69710a6b1f95412353 Mon Sep 17 00:00:00 2001 From: Viraz Malhotra Date: Wed, 23 Oct 2024 16:16:47 +0530 Subject: [PATCH] feat: add manual ci for querying grant role events (#336) - closes #337 --- .changeset/sharp-eggs-lay.md | 5 + .../manual-query-grant-role-event.yml | 36 +++++ .gitignore | 5 +- .../scripts/hardhat/eventFilter.ts | 143 ++++++++++++++++++ .../scripts/hardhat/index.ts | 1 + 5 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 .changeset/sharp-eggs-lay.md create mode 100644 .github/workflows/manual-query-grant-role-event.yml create mode 100644 packages/solidity-contracts/scripts/hardhat/eventFilter.ts diff --git a/.changeset/sharp-eggs-lay.md b/.changeset/sharp-eggs-lay.md new file mode 100644 index 00000000..68f9e33c --- /dev/null +++ b/.changeset/sharp-eggs-lay.md @@ -0,0 +1,5 @@ +--- +'@fuel-bridge/solidity-contracts': minor +--- + +add manual ci for querying grant role events diff --git a/.github/workflows/manual-query-grant-role-event.yml b/.github/workflows/manual-query-grant-role-event.yml new file mode 100644 index 00000000..fcbdd018 --- /dev/null +++ b/.github/workflows/manual-query-grant-role-event.yml @@ -0,0 +1,36 @@ +name: Manually Query Grant Role Events + +on: + workflow_dispatch: + inputs: + contractAddress: + description: 'Enter the contract address for which you wanna query the grant role events for' + required: true + type: string + rpc: + description: 'Enter network rpc' + required: true + default: 'https://rpc.ankr.com/eth' + type: string + +jobs: + verify-upgrade: + runs-on: ubuntu-latest + env: + RPC_URL: ${{ github.event.inputs.rpc }} + steps: + - uses: actions/checkout@v3 + - uses: FuelLabs/github-actions/setups/node@master + with: + node-version: 20.16.0 + pnpm-version: 9.0.6 + - name: Query Events + run: | + npx hardhat compile && npx hardhat grant-role-event-filter --contract ${{ github.event.inputs.contractAddress }} + working-directory: ./packages/solidity-contracts + - name: Upload event payload as an artifact + uses: actions/upload-artifact@v4 + with: + name: event-query-payload + path: grantedRoles.json + retention-days: 90 diff --git a/.gitignore b/.gitignore index e392f12c..60c2166b 100644 --- a/.gitignore +++ b/.gitignore @@ -26,4 +26,7 @@ packages/fungible-token/exports/types dist # verification ci artifacts -packages/solidity-contracts/verification.json \ No newline at end of file +packages/solidity-contracts/verification.json + +# grant role query ci artifacts +packages/solidity-contracts/grantedRoles.json \ No newline at end of file diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts new file mode 100644 index 00000000..bf0c4e9b --- /dev/null +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -0,0 +1,143 @@ +import { task } from 'hardhat/config'; +import { HardhatRuntimeEnvironment } from 'hardhat/types'; +import { writeFileSync } from 'fs'; + +task( + 'grant-role-event-filter', + 'Filters grant role event for a specific contract to keep track of assigned roles' +) + .addParam('contract', 'address of the contract') + .setAction( + async (taskArgs: any, hre: HardhatRuntimeEnvironment): Promise => { + const provider = new hre.ethers.JsonRpcProvider(process.env.RPC_URL); + + // fetching the abi from the artifacts would require the contract name as an input so avoiding that + const grantRoleEvenABI = [ + { + inputs: [ + { + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + internalType: 'address', + name: 'account', + type: 'address', + }, + ], + name: 'hasRole', + outputs: [ + { + internalType: 'bool', + name: '', + type: 'bool', + }, + ], + stateMutability: 'view', + type: 'function', + }, + { + anonymous: false, + inputs: [ + { + indexed: true, + internalType: 'bytes32', + name: 'role', + type: 'bytes32', + }, + { + indexed: true, + internalType: 'address', + name: 'account', + type: 'address', + }, + { + indexed: true, + internalType: 'address', + name: 'sender', + type: 'address', + }, + ], + name: 'RoleGranted', + type: 'event', + }, + ]; + + // existing roles + const DEFAULT_ADMIN_ROLE = hre.ethers.ZeroHash; + const PAUSER_ROLE = hre.ethers.keccak256( + hre.ethers.toUtf8Bytes('PAUSER_ROLE') + ); + const COMMITTER_ROLE = hre.ethers.keccak256( + hre.ethers.toUtf8Bytes('COMMITTER_ROLE') + ); + const SET_RATE_LIMITER_ROLE = hre.ethers.keccak256( + hre.ethers.toUtf8Bytes('SET_RATE_LIMITER_ROLE') + ); + + const FROM_BLOCK = 20620432; + + const roles = [ + { name: 'DEFAULT_ADMIN_ROLE', value: DEFAULT_ADMIN_ROLE }, + { name: 'PAUSER_ROLE', value: PAUSER_ROLE }, + { name: 'COMMITTER_ROLE', value: COMMITTER_ROLE }, + { name: 'SET_RATE_LIMITER_ROLE', value: SET_RATE_LIMITER_ROLE }, + ]; + + const contract = new hre.ethers.Contract( + taskArgs.contract, + grantRoleEvenABI, + provider + ); + + const eventPayload: any = []; + + try { + const events = await contract.queryFilter( + contract.filters.RoleGranted(), + FROM_BLOCK + ); + + // check for duplicate events (where the role id and the account are the same) + const filteredEvents = events.reduce((previous: any, current: any) => { + // typing bug with array of (EventLog | Log) type + const isDuplicate = previous.find( + (event: any) => + // typing bug with element of (EventLog | Log) type + event.args[0] === current.args[0] && + event.args[1] === current.args[1] + ); + + if (!isDuplicate) { + return previous.concat([current]); + } else { + return previous; + } + }, []); + + for (const event of filteredEvents) { + const eventArgs: any = {}; + + // only checking for active roles + const hasRole = await contract.hasRole(event.args[0], event.args[1]); + if (hasRole) { + // computing the `role` in a readable format + eventArgs.role = + roles.find((role) => role.value === event.args[0])?.name || + 'UNKNOWN_ROLE'; + eventArgs.account = event.args[1]; + + eventPayload.push(eventArgs); + } + } + + writeFileSync( + 'grantedRoles.json', + JSON.stringify(eventPayload, undefined, 2) + ); + } catch (error) { + throw new Error(`Unable to filter and query events: ${error}`); + } + } + ); diff --git a/packages/solidity-contracts/scripts/hardhat/index.ts b/packages/solidity-contracts/scripts/hardhat/index.ts index 9d0021fd..422b3bfd 100644 --- a/packages/solidity-contracts/scripts/hardhat/index.ts +++ b/packages/solidity-contracts/scripts/hardhat/index.ts @@ -12,3 +12,4 @@ export * from './withdrawalResume'; export * from './withdrawalBlacklist'; export * from './withdrawalWhitelist'; export * from './verifyMainnetDeployment'; +export * from './eventFilter';