Skip to content

Commit 27eb7ba

Browse files
authored
feat: add manual ci for querying grant role events (#336)
- closes #337
1 parent e29e1e6 commit 27eb7ba

File tree

5 files changed

+189
-1
lines changed

5 files changed

+189
-1
lines changed

.changeset/sharp-eggs-lay.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@fuel-bridge/solidity-contracts': minor
3+
---
4+
5+
add manual ci for querying grant role events
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: Manually Query Grant Role Events
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
contractAddress:
7+
description: 'Enter the contract address for which you wanna query the grant role events for'
8+
required: true
9+
type: string
10+
rpc:
11+
description: 'Enter network rpc'
12+
required: true
13+
default: 'https://rpc.ankr.com/eth'
14+
type: string
15+
16+
jobs:
17+
verify-upgrade:
18+
runs-on: ubuntu-latest
19+
env:
20+
RPC_URL: ${{ github.event.inputs.rpc }}
21+
steps:
22+
- uses: actions/checkout@v3
23+
- uses: FuelLabs/github-actions/setups/node@master
24+
with:
25+
node-version: 20.16.0
26+
pnpm-version: 9.0.6
27+
- name: Query Events
28+
run: |
29+
npx hardhat compile && npx hardhat grant-role-event-filter --contract ${{ github.event.inputs.contractAddress }}
30+
working-directory: ./packages/solidity-contracts
31+
- name: Upload event payload as an artifact
32+
uses: actions/upload-artifact@v4
33+
with:
34+
name: event-query-payload
35+
path: grantedRoles.json
36+
retention-days: 90

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,7 @@ packages/fungible-token/exports/types
2626
dist
2727

2828
# verification ci artifacts
29-
packages/solidity-contracts/verification.json
29+
packages/solidity-contracts/verification.json
30+
31+
# grant role query ci artifacts
32+
packages/solidity-contracts/grantedRoles.json
Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import { task } from 'hardhat/config';
2+
import { HardhatRuntimeEnvironment } from 'hardhat/types';
3+
import { writeFileSync } from 'fs';
4+
5+
task(
6+
'grant-role-event-filter',
7+
'Filters grant role event for a specific contract to keep track of assigned roles'
8+
)
9+
.addParam('contract', 'address of the contract')
10+
.setAction(
11+
async (taskArgs: any, hre: HardhatRuntimeEnvironment): Promise<void> => {
12+
const provider = new hre.ethers.JsonRpcProvider(process.env.RPC_URL);
13+
14+
// fetching the abi from the artifacts would require the contract name as an input so avoiding that
15+
const grantRoleEvenABI = [
16+
{
17+
inputs: [
18+
{
19+
internalType: 'bytes32',
20+
name: 'role',
21+
type: 'bytes32',
22+
},
23+
{
24+
internalType: 'address',
25+
name: 'account',
26+
type: 'address',
27+
},
28+
],
29+
name: 'hasRole',
30+
outputs: [
31+
{
32+
internalType: 'bool',
33+
name: '',
34+
type: 'bool',
35+
},
36+
],
37+
stateMutability: 'view',
38+
type: 'function',
39+
},
40+
{
41+
anonymous: false,
42+
inputs: [
43+
{
44+
indexed: true,
45+
internalType: 'bytes32',
46+
name: 'role',
47+
type: 'bytes32',
48+
},
49+
{
50+
indexed: true,
51+
internalType: 'address',
52+
name: 'account',
53+
type: 'address',
54+
},
55+
{
56+
indexed: true,
57+
internalType: 'address',
58+
name: 'sender',
59+
type: 'address',
60+
},
61+
],
62+
name: 'RoleGranted',
63+
type: 'event',
64+
},
65+
];
66+
67+
// existing roles
68+
const DEFAULT_ADMIN_ROLE = hre.ethers.ZeroHash;
69+
const PAUSER_ROLE = hre.ethers.keccak256(
70+
hre.ethers.toUtf8Bytes('PAUSER_ROLE')
71+
);
72+
const COMMITTER_ROLE = hre.ethers.keccak256(
73+
hre.ethers.toUtf8Bytes('COMMITTER_ROLE')
74+
);
75+
const SET_RATE_LIMITER_ROLE = hre.ethers.keccak256(
76+
hre.ethers.toUtf8Bytes('SET_RATE_LIMITER_ROLE')
77+
);
78+
79+
const FROM_BLOCK = 20620432;
80+
81+
const roles = [
82+
{ name: 'DEFAULT_ADMIN_ROLE', value: DEFAULT_ADMIN_ROLE },
83+
{ name: 'PAUSER_ROLE', value: PAUSER_ROLE },
84+
{ name: 'COMMITTER_ROLE', value: COMMITTER_ROLE },
85+
{ name: 'SET_RATE_LIMITER_ROLE', value: SET_RATE_LIMITER_ROLE },
86+
];
87+
88+
const contract = new hre.ethers.Contract(
89+
taskArgs.contract,
90+
grantRoleEvenABI,
91+
provider
92+
);
93+
94+
const eventPayload: any = [];
95+
96+
try {
97+
const events = await contract.queryFilter(
98+
contract.filters.RoleGranted(),
99+
FROM_BLOCK
100+
);
101+
102+
// check for duplicate events (where the role id and the account are the same)
103+
const filteredEvents = events.reduce((previous: any, current: any) => {
104+
// typing bug with array of (EventLog | Log) type
105+
const isDuplicate = previous.find(
106+
(event: any) =>
107+
// typing bug with element of (EventLog | Log) type
108+
event.args[0] === current.args[0] &&
109+
event.args[1] === current.args[1]
110+
);
111+
112+
if (!isDuplicate) {
113+
return previous.concat([current]);
114+
} else {
115+
return previous;
116+
}
117+
}, []);
118+
119+
for (const event of filteredEvents) {
120+
const eventArgs: any = {};
121+
122+
// only checking for active roles
123+
const hasRole = await contract.hasRole(event.args[0], event.args[1]);
124+
if (hasRole) {
125+
// computing the `role` in a readable format
126+
eventArgs.role =
127+
roles.find((role) => role.value === event.args[0])?.name ||
128+
'UNKNOWN_ROLE';
129+
eventArgs.account = event.args[1];
130+
131+
eventPayload.push(eventArgs);
132+
}
133+
}
134+
135+
writeFileSync(
136+
'grantedRoles.json',
137+
JSON.stringify(eventPayload, undefined, 2)
138+
);
139+
} catch (error) {
140+
throw new Error(`Unable to filter and query events: ${error}`);
141+
}
142+
}
143+
);

packages/solidity-contracts/scripts/hardhat/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ export * from './withdrawalResume';
1212
export * from './withdrawalBlacklist';
1313
export * from './withdrawalWhitelist';
1414
export * from './verifyMainnetDeployment';
15+
export * from './eventFilter';

0 commit comments

Comments
 (0)