From a4fe9b716c5c09c97f759ebd2ad02cdeff07fa1e Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 12:39:42 +0530 Subject: [PATCH 01/11] chore: update gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) 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 From 637bee6c1361e438322148a38d2eba2273c59d3c Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 12:40:43 +0530 Subject: [PATCH 02/11] feat: add grant role event filter script --- .../scripts/hardhat/eventFilter.ts | 45 +++++++++++++++++++ .../scripts/hardhat/index.ts | 1 + 2 files changed, 46 insertions(+) create mode 100644 packages/solidity-contracts/scripts/hardhat/eventFilter.ts diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts new file mode 100644 index 00000000..f2e797d0 --- /dev/null +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -0,0 +1,45 @@ +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); + + const grantRoleEvent = [ + 'event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)', + ]; + + const contract = new hre.ethers.Contract( + taskArgs.contract, + grantRoleEvent, + provider + ); + + const eventPayload: any = []; + + try { + const events = await contract.queryFilter( + contract.filters.RoleGranted() + ); + + events.forEach((event) => { + const eventArgs: any = {}; + eventArgs.role = event.args[0]; + eventArgs.account = event.args[1]; + eventArgs.sender = event.args[2]; + + eventPayload.push(eventArgs); + }); + + writeFileSync('grantedRoles.json', JSON.stringify(eventPayload)); + } catch (error) { + throw new Error(`Unable to 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'; From 2a0755f88ac8338caeabe0dfcc632dd4f8f35281 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 12:42:21 +0530 Subject: [PATCH 03/11] chore: small tocuhup --- packages/solidity-contracts/scripts/hardhat/eventFilter.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index f2e797d0..5cbdea1c 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -11,13 +11,13 @@ task( async (taskArgs: any, hre: HardhatRuntimeEnvironment): Promise => { const provider = new hre.ethers.JsonRpcProvider(process.env.RPC_URL); - const grantRoleEvent = [ + const grantRoleEvenABI = [ 'event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)', ]; const contract = new hre.ethers.Contract( taskArgs.contract, - grantRoleEvent, + grantRoleEvenABI, provider ); @@ -39,7 +39,7 @@ task( writeFileSync('grantedRoles.json', JSON.stringify(eventPayload)); } catch (error) { - throw new Error(`Unable to query events: ${error}`); + throw new Error(`Unable to filter and query events: ${error}`); } } ); From b6c27fbb60659aa848646d0371dcbfb2a7d3db20 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 13:21:51 +0530 Subject: [PATCH 04/11] feat: add manual ci for querying grant role events --- .../manual-query-grant-role-event.yml | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/manual-query-grant-role-event.yml 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 From a28a2a03763f813be7756955ef4d402fa90e0fc4 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 13:22:52 +0530 Subject: [PATCH 05/11] chore: add changeset --- .changeset/sharp-eggs-lay.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/sharp-eggs-lay.md 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 From 7b539def78611233cccf00f581ae8d7dc2954e90 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 13:32:33 +0530 Subject: [PATCH 06/11] chore: add comment --- packages/solidity-contracts/scripts/hardhat/eventFilter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index 5cbdea1c..10227154 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -28,7 +28,8 @@ task( contract.filters.RoleGranted() ); - events.forEach((event) => { + events.forEach((event: any) => { + // Typing bug in the `event` type const eventArgs: any = {}; eventArgs.role = event.args[0]; eventArgs.account = event.args[1]; From 6dfd2d4f2d70fb0a56ed7c80809e7902c73c3b35 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 15:41:35 +0530 Subject: [PATCH 07/11] refactor: add check for active roles --- .../scripts/hardhat/eventFilter.ts | 90 +++++++++++++++++-- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index 10227154..251db952 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -12,7 +12,74 @@ task( const provider = new hre.ethers.JsonRpcProvider(process.env.RPC_URL); const grantRoleEvenABI = [ - 'event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender)', + { + 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 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( @@ -28,15 +95,20 @@ task( contract.filters.RoleGranted() ); - events.forEach((event: any) => { - // Typing bug in the `event` type - const eventArgs: any = {}; - eventArgs.role = event.args[0]; - eventArgs.account = event.args[1]; - eventArgs.sender = event.args[2]; + for (const event of events) { + // only checking for active roles + const hasRole = await contract.hasRole(event.args[0], event.args[1]); + if (hasRole) { + const eventArgs: any = {}; + // 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); - }); + eventPayload.push(eventArgs); + } + } writeFileSync('grantedRoles.json', JSON.stringify(eventPayload)); } catch (error) { From bf3b60c0ebaee12d13fd27cfb5fb1f78a90a3ad4 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 17:16:23 +0530 Subject: [PATCH 08/11] refactor: add a filter for duplicate role and accounts --- .../scripts/hardhat/eventFilter.ts | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index 251db952..c003f875 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -75,6 +75,8 @@ task( 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 }, @@ -91,15 +93,32 @@ task( const eventPayload: any = []; try { - const events = await contract.queryFilter( - contract.filters.RoleGranted() + let events = await contract.queryFilter( + contract.filters.RoleGranted(), + FROM_BLOCK ); - for (const event of events) { + // check for duplicate events (where the role id and the account are the same) + const filteredEvents = events.reduce((previous, current) => { + const isDuplicate = previous.find( + (event) => + 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) { - const eventArgs: any = {}; // computing the `role` in a readable format eventArgs.role = roles.find((role) => role.value === event.args[0])?.name || From f5f6bc0e471804a0b325ffc9b8a68c791670b640 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Tue, 15 Oct 2024 17:23:34 +0530 Subject: [PATCH 09/11] chore: small touchup --- packages/solidity-contracts/scripts/hardhat/eventFilter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index c003f875..57f10ee7 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -93,7 +93,7 @@ task( const eventPayload: any = []; try { - let events = await contract.queryFilter( + const events = await contract.queryFilter( contract.filters.RoleGranted(), FROM_BLOCK ); From a425cada2ac66300ec9a861d47f81091ca18faaf Mon Sep 17 00:00:00 2001 From: viraj124 Date: Wed, 16 Oct 2024 17:23:30 +0530 Subject: [PATCH 10/11] chore: prettify event payload json --- packages/solidity-contracts/scripts/hardhat/eventFilter.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index 57f10ee7..c69806e0 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -11,6 +11,7 @@ task( 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: [ @@ -129,7 +130,7 @@ task( } } - writeFileSync('grantedRoles.json', JSON.stringify(eventPayload)); + writeFileSync('grantedRoles.json', JSON.stringify(eventPayload, undefined, 2)); } catch (error) { throw new Error(`Unable to filter and query events: ${error}`); } From 49cee883b5a40e6f208bad698a0a9a24adcb0993 Mon Sep 17 00:00:00 2001 From: viraj124 Date: Wed, 16 Oct 2024 17:27:51 +0530 Subject: [PATCH 11/11] fix: typing bugs --- .../solidity-contracts/scripts/hardhat/eventFilter.ts | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts index c69806e0..bf0c4e9b 100644 --- a/packages/solidity-contracts/scripts/hardhat/eventFilter.ts +++ b/packages/solidity-contracts/scripts/hardhat/eventFilter.ts @@ -100,9 +100,11 @@ task( ); // check for duplicate events (where the role id and the account are the same) - const filteredEvents = events.reduce((previous, current) => { + const filteredEvents = events.reduce((previous: any, current: any) => { + // typing bug with array of (EventLog | Log) type const isDuplicate = previous.find( - (event) => + (event: any) => + // typing bug with element of (EventLog | Log) type event.args[0] === current.args[0] && event.args[1] === current.args[1] ); @@ -130,7 +132,10 @@ task( } } - writeFileSync('grantedRoles.json', JSON.stringify(eventPayload, undefined, 2)); + writeFileSync( + 'grantedRoles.json', + JSON.stringify(eventPayload, undefined, 2) + ); } catch (error) { throw new Error(`Unable to filter and query events: ${error}`); }