Skip to content

Commit f1523df

Browse files
authored
fix(data): use member index from event instead of array position in S… (#1081)
fix(data): use member index from event instead of array position in SemaphoreEthers.getGroupMembers
1 parent 1663372 commit f1523df

2 files changed

Lines changed: 47 additions & 9 deletions

File tree

packages/data/src/ethers.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,21 +219,32 @@ export default class SemaphoreEthers {
219219

220220
const memberAddedEvents = await getEvents(this._contract, "MemberAdded", [groupId], this._options.startBlock)
221221

222+
// Create a map from member index to identity commitment for single additions
223+
const memberAddedEventsMap = new Map<string, string>()
224+
225+
for (const [, index, identityCommitment] of memberAddedEvents) {
226+
memberAddedEventsMap.set(index.toString(), identityCommitment.toString())
227+
}
228+
222229
const members: string[] = []
223230

224231
const merkleTreeSize = await this._contract.getMerkleTreeSize(groupId)
225232

226233
let i = 0
227234

228235
while (i < Number(merkleTreeSize)) {
229-
const identityCommitments = membersAddedEventsMap.get(i.toString())
236+
const batchIdentityCommitments = membersAddedEventsMap.get(i.toString())
230237

231-
if (identityCommitments) {
232-
members.push(...identityCommitments)
238+
if (batchIdentityCommitments) {
239+
members.push(...batchIdentityCommitments)
233240

234-
i += identityCommitments.length
241+
i += batchIdentityCommitments.length
235242
} else {
236-
members.push(memberAddedEvents[i][2])
243+
const singleIdentityCommitment = memberAddedEventsMap.get(i.toString())
244+
245+
if (singleIdentityCommitment) {
246+
members.push(singleIdentityCommitment)
247+
}
237248

238249
i += 1
239250
}

packages/data/tests/ethers.test.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,10 +171,10 @@ describe("SemaphoreEthers", () => {
171171
)
172172
getEventsMocked.mockReturnValueOnce(
173173
Promise.resolve([
174-
[, , "110"],
175-
[, , "111"],
176-
[, , "112"],
177-
[, , "113"]
174+
[, "0", "110"],
175+
[, "1", "111"],
176+
[, "2", "112"],
177+
[, "3", "113"]
178178
])
179179
)
180180

@@ -199,6 +199,33 @@ describe("SemaphoreEthers", () => {
199199

200200
await expect(fun).rejects.toThrow("Group '666' not found")
201201
})
202+
203+
it("Should correctly handle mixed batch and single additions where single additions don't align with array index", async () => {
204+
// Scenario: Batch add members at index 0-1, then single add at index 2
205+
// The MemberAdded events array will have only 1 element (for index 2),
206+
ContractMocked.mockReturnValueOnce({
207+
getGroupAdmin: () => "0xA9C2B639a28cDa8b59C4377e980F75A93dD8605F",
208+
getMerkleTreeSize: () => BigInt(3)
209+
} as any)
210+
211+
const semaphore = new SemaphoreEthers()
212+
213+
// MemberRemoved events - none
214+
getEventsMocked.mockReturnValueOnce(Promise.resolve([]))
215+
// MemberUpdated events - none
216+
getEventsMocked.mockReturnValueOnce(Promise.resolve([]))
217+
// MembersAdded events - batch add at index 0
218+
getEventsMocked.mockReturnValueOnce(Promise.resolve([[, "0", ["100", "101"]]]))
219+
// MemberAdded events - single add at index 2 (only 1 event, but index is 2)
220+
getEventsMocked.mockReturnValueOnce(Promise.resolve([[, "2", "102"]]))
221+
222+
const members = await semaphore.getGroupMembers("42")
223+
224+
expect(members).toHaveLength(3)
225+
expect(members[0]).toBe("100")
226+
expect(members[1]).toBe("101")
227+
expect(members[2]).toBe("102")
228+
})
202229
})
203230

204231
describe("# getGroupVerifiedProofs", () => {

0 commit comments

Comments
 (0)