Skip to content

Conversation

@adklempner
Copy link
Member

@adklempner adklempner commented Oct 24, 2025

Problem / Description

Previous to this, the ABIs for the contracts were manually added to the rln package (not clear how).
Additionally, code related to calling the contracts was not typed, so any breaking changes to the ABI would not be detected at compile time.

Solution

  • Create a script that:
  1. cloneshttps://github.com/waku-org/waku-rlnv2-contract
  2. compiles it
  3. uses the output to generate typesafe ABI code using wagmi

The rest of the code has been updated to use viem, which provides clean and typesafe ways to interact with the smart contracts.

Also adds new methods that were introduced in latest contract changes, specifically the ability to query for merkle root and merkle proof for a commitment directly from the smart contract.

Notes


Checklist

  • Code changes are covered by unit tests.
  • Code changes are covered by e2e tests, if applicable.
  • Dogfooding has been performed, if feasible.
  • A test version has been published, if required.
  • All CI checks pass successfully.

@adklempner adklempner force-pushed the feat/rln-contract-gen-types branch from 1fcf108 to a88dd8c Compare October 24, 2025 22:43
@github-actions
Copy link

github-actions bot commented Oct 24, 2025

size-limit report 📦

Path Size Loading time (3g) Running time (snapdragon) Total time
Waku node 96.38 KB (0%) 2 s (0%) 1.5 s (-2.24% 🔽) 3.5 s
Waku Simple Light Node 147.7 KB (0%) 3 s (0%) 1.2 s (-13.1% 🔽) 4.2 s
ECIES encryption 22.62 KB (0%) 453 ms (0%) 284 ms (-45.27% 🔽) 736 ms
Symmetric encryption 22 KB (0%) 440 ms (0%) 335 ms (-36.28% 🔽) 775 ms
DNS discovery 52.17 KB (0%) 1.1 s (0%) 881 ms (-7.32% 🔽) 2 s
Peer Exchange discovery 52.91 KB (0%) 1.1 s (0%) 944 ms (+17.78% 🔺) 2.1 s
Peer Cache Discovery 46.64 KB (0%) 933 ms (0%) 953 ms (+103.53% 🔺) 1.9 s
Privacy preserving protocols 77.26 KB (0%) 1.6 s (0%) 1.4 s (+36.77% 🔺) 2.9 s
Waku Filter 79.78 KB (0%) 1.6 s (0%) 576 ms (-56.68% 🔽) 2.2 s
Waku LightPush 78 KB (0%) 1.6 s (0%) 1.1 s (-14.21% 🔽) 2.7 s
History retrieval protocols 83.66 KB (0%) 1.7 s (0%) 1.1 s (-38.76% 🔽) 2.7 s
Deterministic Message Hashing 28.98 KB (0%) 580 ms (0%) 751 ms (+63.88% 🔺) 1.4 s

@adklempner adklempner force-pushed the feat/rln-contract-gen-types branch from 264f2c0 to 5ea574e Compare October 27, 2025 20:48
@adklempner adklempner force-pushed the feat/rln-contract-gen-types branch 3 times, most recently from 70922e5 to 7e5680f Compare November 11, 2025 21:42
@adklempner adklempner marked this pull request as ready for review November 12, 2025 03:58
@adklempner adklempner requested a review from a team as a code owner November 12, 2025 03:58
@weboko weboko requested a review from Copilot November 12, 2025 11:52
Copilot finished reviewing on behalf of weboko November 12, 2025 11:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR migrates the RLN package from ethers.js to viem for Ethereum interactions and introduces automated contract type generation using wagmi CLI. The changes enable type-safe contract interactions by generating TypeScript bindings directly from the smart contract ABIs.

Key changes:

  • Replaced ethers.js with viem for all blockchain interactions
  • Automated ABI generation via wagmi CLI from waku-rlnv2-contract repository
  • Updated all contract interaction code to use viem's type-safe APIs
  • Added new methods for querying merkle root and merkle proof directly from contracts

Reviewed Changes

Copilot reviewed 21 out of 23 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
packages/rln/wagmi.config.ts Configures wagmi CLI to generate TypeScript bindings from Foundry contracts
packages/rln/src/contract/wagmi/generated.ts Auto-generated type-safe contract ABIs (977 lines)
packages/rln/src/contract/rln_base_contract.ts Migrated from ethers Contract to viem getContract with type-safe reads/writes
packages/rln/src/utils/walletClient.ts New utility to create viem client from window.ethereum
packages/rln/src/types.ts Updated to use viem WalletClient instead of ethers.Signer
packages/rln/generate_contract_abi.sh Shell script to clone, build, and generate contract types
packages/rln/package.json Removed ethers dependency, added viem and wagmi tooling

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 194 to 196
const fromBlock = options.fromBlock
? BigInt(options.fromBlock!)
: BigInt(this.deployBlock!);
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant non-null assertion after already checking with ternary operator. Line 195 uses options.fromBlock! after already checking options.fromBlock in the ternary condition. The non-null assertion is unnecessary here. Additionally, line 196 uses this.deployBlock! which could be undefined if the create() method hasn't been awaited, leading to a potential runtime error.

Suggested change
const fromBlock = options.fromBlock
? BigInt(options.fromBlock!)
: BigInt(this.deployBlock!);
let fromBlock: bigint;
if (options.fromBlock !== undefined) {
fromBlock = BigInt(options.fromBlock);
} else {
if (this.deployBlock === undefined) {
throw new Error("deployBlock is undefined. Ensure the contract is initialized and create() has been awaited before calling fetchMembers.");
}
fromBlock = BigInt(this.deployBlock);
}

Copilot uses AI. Check for mistakes.
const registeredMemberEvents =
await this.contract.getEvents.MembershipRegistered({
fromBlock,
toBlock: fromBlock + BigInt(options.fetchRange!)
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing null check for options.fetchRange. Lines 200, 204, and 209 use options.fetchRange! with non-null assertion, but there's no guarantee this value exists. This will cause undefined to be converted to NaN when passed to BigInt(), resulting in a runtime error.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reading it again, we don't actually need these events tracked with the new version of RLN smart contracts

Copy link
Member Author

@adklempner adklempner Nov 14, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we will, but I will re-implement when doing #2722

return undefined;
}
private async getMemberIndex(idCommitmentBigInt: bigint): Promise<number> {
return (await this.contract.read.memberships([idCommitmentBigInt]))[5];
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic number index [5] without explanation. Line 652 accesses array element at index 5 without documentation. According to the ABI at lines 573-584 in generated.ts, index 5 corresponds to the 'index' field of the membership struct. Consider adding a comment or using destructuring with named variables for clarity.

Suggested change
return (await this.contract.read.memberships([idCommitmentBigInt]))[5];
// According to the ABI, index 5 corresponds to the 'index' field of the membership struct
const [, , , , , index] = await this.contract.read.memberships([idCommitmentBigInt]);
return index;

Copilot uses AI. Check for mistakes.
"include": ["src"],
"exclude": ["src/**/*.spec.ts", "src/test_utils"]
}
"exclude": ["wagmi.config.ts"]
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed exclusion of test files and test_utils. The original exclusion pattern [\"src/**/*.spec.ts\", \"src/test_utils\"] was removed and replaced with only [\"wagmi.config.ts\"]. This means test files and test utilities will now be included in the build output, which is likely unintended and could increase bundle size.

Suggested change
"exclude": ["wagmi.config.ts"]
"exclude": ["wagmi.config.ts", "src/**/*.spec.ts", "src/test_utils"]

Copilot uses AI. Check for mistakes.
return;
}

const blockNumber = Number(evt.blockNumber);
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Converting blockNumber to Number repeatedly in loop. Line 229 converts evt.blockNumber to Number inside the forEach loop (lines 225-256). If the block number exceeds JavaScript's MAX_SAFE_INTEGER (2^53-1), this conversion will lose precision. Consider keeping as bigint for accuracy or add a check for safe integer range.

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

current block number on linea sepolia is 20646374 so this shouldn't be an issue

@adklempner adklempner requested a review from Copilot November 12, 2025 21:03
Copilot finished reviewing on behalf of adklempner November 12, 2025 21:05
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 21 out of 23 changed files in this pull request and generated 4 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 323 to 325
* Withdraw deposited tokens after membership is erased
* @param token - Token address to withdraw
* NOTE: Funds are sent to msg.sender (the walletClient's address)
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment on line 325 mentions that "Funds are sent to msg.sender (the walletClient's address)", but the function signature no longer includes a walletAddress parameter. This is a breaking API change that should be clearly documented. The previous implementation accepted walletAddress as a parameter but now it implicitly uses the wallet client's address. Consider noting this in the PR description or adding a migration guide.

Suggested change
* Withdraw deposited tokens after membership is erased
* @param token - Token address to withdraw
* NOTE: Funds are sent to msg.sender (the walletClient's address)
* Withdraw deposited tokens after membership is erased.
* @param token - Token address to withdraw
* @note Funds are sent to msg.sender (the walletClient's address).
* @breaking The `walletAddress` parameter has been removed. This function now always sends funds to the wallet client's address (`msg.sender`).

Copilot uses AI. Check for mistakes.
We use `wagmi` to generate TypeScript bindings for interacting with the RLN smart contracts. When changes are pushed to the `waku-rlnv2-contract` repository, run the following script to fetch and build the latest contracts and generate the TypeScript bindings:

```
./generate_contract_abi.sh
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script name in package.json is setup:contract-abi but the README refers to ./generate_contract_abi.sh. The npm script should be referenced instead for consistency: npm run setup:contract-abi

Suggested change
./generate_contract_abi.sh
npm run setup:contract-abi

Copilot uses AI. Check for mistakes.
"prepublish": "npm run build",
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build"
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build",
"setup:contract-abi": "./setup-contract-abi.sh",
Copy link

Copilot AI Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file path in the package.json script is ./setup-contract-abi.sh, but the actual file is named generate_contract_abi.sh. This mismatch will cause the script to fail when executed.

Suggested change
"setup:contract-abi": "./setup-contract-abi.sh",
"setup:contract-abi": "./generate_contract_abi.sh",

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you robot

);
}

const [account] = await ethereum.request({ method: "eth_requestAccounts" });
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is not safe if .request doesn't resolve into array

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks like viem has a fully-typed polyfill for window which includes all the rpc requests, replacing with that


export const RLN_CONTRACT = {
chainId: 59141,
address: "0xb9cd878c90e49f797b4431fbf4fb333108cb90e6",
Copy link
Collaborator

@weboko weboko Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we get these addresses from some other place similarly to abi?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately no; we can move this elsewhere but this is a value that needs to be manually set for now.

"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build"
"reset-hard": "git clean -dfx -e .idea && git reset --hard && npm i && npm run build",
"setup:contract-abi": "./setup-contract-abi.sh",
"generate:contract": "npx wagmi generate"
Copy link
Collaborator

@weboko weboko Nov 12, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

questions:

  1. this command is not needed - if we have previous setup:contract-abi
  2. how is setup:contract-abi supposed to run? before commit / build?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. yes we can remove this one
  2. it only needs to be run if the smart contracts are updated and we need to re-generate typings

@@ -0,0 +1,42 @@
#!/bin/bash
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file is not cross platform and will not work on Windows

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/search?q=org%3Awaku-org+%23%21%2Fbin%2Fbash&type=code

¯_(ツ)_/¯

also, I can't imagine someone trying to make contributions to our repos without WSL, which should enable running bash...

Copy link
Collaborator

@weboko weboko left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good first iteration

left comments in addition to Copilot's

and make sure you properly integrate it with release CI

@adklempner adklempner force-pushed the feat/rln-contract-gen-types branch from 93c152a to e0c6a09 Compare November 13, 2025 01:37
@adklempner adklempner requested a review from Copilot November 13, 2025 01:39
Copilot finished reviewing on behalf of adklempner November 13, 2025 01:41
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 21 out of 23 changed files in this pull request and generated 5 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(rln): replace manual smart contract classes/functions with generate typings

3 participants