chore: patch foundry template (#34)

This commit is contained in:
Aaryamann Challani
2024-01-11 14:59:18 +05:30
committed by GitHub
parent 35f2182669
commit 9ee3217886
58 changed files with 1423 additions and 13517 deletions

19
.editorconfig Normal file
View File

@@ -0,0 +1,19 @@
# EditorConfig http://EditorConfig.org
# top-most EditorConfig file
root = true
# All files
[*]
charset = utf-8
end_of_line = lf
indent_size = 2
indent_style = space
insert_final_newline = true
trim_trailing_whitespace = true
[*.sol]
indent_size = 4
[*.tree]
indent_size = 1

View File

@@ -1,3 +1,5 @@
ETHERSCAN_API_KEY=<YOUR_ETHERSCAN_KEY>
SEPOLIA_URL=https://eth-sepolia.alchemyapi.io/v2/<YOUR ALCHEMY KEY>
PRIVATE_KEY=<YOUR_PRIVATE_KEY>
export PRIVATE_KEY="0x"
export POLYGONSCAN_ZKEVM_TESTNET_API_KEY=""
export SEPOLIA_ETHERSCAN_API_KEY=""
export SEPOLIA_RPC_URL=""
export POLYGON_ZKEVM_TESTNET_RPC_URL=""

15
.gas-snapshot Normal file
View File

@@ -0,0 +1,15 @@
RlnTest:test__Constants() (gas: 7921)
RlnTest:test__InvalidRegistration__DuplicateCommitment(uint256) (runs: 1000, μ: 120248, ~: 120248)
RlnTest:test__InvalidRegistration__FullSet() (gas: 1242442)
RlnTest:test__InvalidRegistration__InsufficientDeposit(uint256) (runs: 1000, μ: 17189, ~: 17189)
RlnTest:test__InvalidRegistration__InvalidIdCommitment(uint256) (runs: 1000, μ: 16963, ~: 16968)
RlnTest:test__InvalidSlash__InvalidProof() (gas: 958986)
RlnTest:test__InvalidSlash__MemberNotRegistered(uint256) (runs: 1000, μ: 30287, ~: 30287)
RlnTest:test__InvalidSlash__NoStake(uint256,address) (runs: 1000, μ: 301136, ~: 301143)
RlnTest:test__InvalidSlash__ToRlnAddress() (gas: 128396)
RlnTest:test__InvalidSlash__ToZeroAddress() (gas: 128301)
RlnTest:test__InvalidWithdraw__InsufficientContractBalance() (gas: 126872)
RlnTest:test__InvalidWithdraw__InsufficientWithdrawalBalance() (gas: 10494)
RlnTest:test__ValidRegistration(uint256) (runs: 1000, μ: 112053, ~: 112053)
RlnTest:test__ValidSlash(uint256,address) (runs: 1000, μ: 184955, ~: 184966)
RlnTest:test__ValidWithdraw(address) (runs: 1000, μ: 183699, ~: 183687)

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
lib/** linguist-vendored

13
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,13 @@
## Description
Describe the changes made in your pull request here.
## Checklist
Ensure you completed **all of the steps** below before submitting your pull request:
- [ ] Added natspec comments?
- [ ] Ran `forge snapshot`?
- [ ] Ran `pnpm lint`?
- [ ] Ran `forge test`?
- [ ] Ran `pnpm verify`?

View File

@@ -1,60 +1,211 @@
name: CI
name: "CI"
env:
API_KEY_ALCHEMY: ${{ secrets.API_KEY_ALCHEMY }}
FOUNDRY_PROFILE: "ci"
on:
push:
branches: [main]
paths:
- "**.sol"
- "scripts/**.ts"
- "test/**.ts"
- "hardhat.config.ts"
- "package.json"
- ".github/workflows/ci.yml"
workflow_dispatch:
pull_request:
branches: [main]
paths:
- "**.sol"
- "scripts/**.ts"
- "test/**.ts"
- "hardhat.config.ts"
- "package.json"
- ".github/workflows/ci.yml"
push:
branches:
- "main"
jobs:
lint:
runs-on: "ubuntu-latest"
steps:
- name: "Check out the repo"
uses: "actions/checkout@v3"
with:
submodules: "recursive"
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
- name: "Install Pnpm"
uses: "pnpm/action-setup@v2"
with:
version: "8"
- name: "Install Node.js"
uses: "actions/setup-node@v3"
with:
cache: "pnpm"
node-version: "lts/*"
- name: "Install the Node.js dependencies"
run: "pnpm install"
- name: "Lint the contracts"
run: "pnpm lint"
- name: "Add lint summary"
run: |
echo "## Lint result" >> $GITHUB_STEP_SUMMARY
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
build:
runs-on: "ubuntu-latest"
steps:
- name: "Check out the repo"
uses: "actions/checkout@v3"
with:
submodules: "recursive"
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
- name: "Install Pnpm"
uses: "pnpm/action-setup@v2"
with:
version: "8"
- name: "Install Node.js"
uses: "actions/setup-node@v3"
with:
cache: "pnpm"
node-version: "lts/*"
- name: "Install the Node.js dependencies"
run: "pnpm install"
- name: "Build the contracts and print their size"
run: "forge build --sizes"
- name: "Add build summary"
run: |
echo "## Build result" >> $GITHUB_STEP_SUMMARY
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
test:
needs: ["lint", "build"]
runs-on: "ubuntu-latest"
steps:
- name: "Check out the repo"
uses: "actions/checkout@v3"
with:
submodules: "recursive"
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
- name: "Install Pnpm"
uses: "pnpm/action-setup@v2"
with:
version: "8"
- name: "Install Node.js"
uses: "actions/setup-node@v3"
with:
cache: "pnpm"
node-version: "lts/*"
- name: "Install the Node.js dependencies"
run: "pnpm install"
- name: "Show the Foundry config"
run: "forge config"
- name: "Generate a fuzz seed that changes weekly to avoid burning through RPC allowance"
run: >
echo "FOUNDRY_FUZZ_SEED=$(
echo $(($EPOCHSECONDS - $EPOCHSECONDS % 604800))
)" >> $GITHUB_ENV
- name: "Run the tests"
run: "forge test"
- name: "Add test summary"
run: |
echo "## Tests result" >> $GITHUB_STEP_SUMMARY
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
coverage:
needs: ["lint", "build"]
runs-on: "ubuntu-latest"
steps:
- name: "Check out the repo"
uses: "actions/checkout@v3"
with:
submodules: "recursive"
- name: "Install Pnpm"
uses: "pnpm/action-setup@v2"
with:
version: "8"
- name: "Install Node.js"
uses: "actions/setup-node@v3"
with:
cache: "pnpm"
node-version: "lts/*"
- name: "Install the Node.js dependencies"
run: "pnpm install"
- name: "Install Foundry"
uses: "foundry-rs/foundry-toolchain@v1"
- name: "Generate the coverage report using the unit and the integration tests"
run: 'forge coverage --match-path "test/**/*.sol" --report lcov'
- name: "Upload coverage report to Codecov"
uses: "codecov/codecov-action@v3"
with:
files: "./lcov.info"
- name: "Add coverage summary"
run: |
echo "## Coverage result" >> $GITHUB_STEP_SUMMARY
echo "✅ Uploaded to Codecov" >> $GITHUB_STEP_SUMMARY
verify:
# TODO: Write Rln certora spec
if: false
needs: ["lint", "build"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
- name: Install Python
uses: actions/setup-python@v2
with: { python-version: 3.9 }
- name: Install Java
uses: actions/setup-java@v1
with: { java-version: "11", java-package: jre }
- name: Install Certora CLI
run: pip3 install certora-cli==5.0.5
- name: Install Solidity
run: |
wget https://github.com/ethereum/solidity/releases/download/v0.8.20/solc-static-linux
chmod +x solc-static-linux
sudo mv solc-static-linux /usr/local/bin/solc
- name: "Install Pnpm"
uses: "pnpm/action-setup@v2"
with:
version: nightly
version: "8"
- uses: actions/setup-node@v3
- name: "Install Node.js"
uses: "actions/setup-node@v3"
with:
node-version: 16
cache: "yarn"
- id: dependencies
run: yarn install
cache: "pnpm"
node-version: "lts/*"
- id: lint
run: yarn lint
- name: "Install the Node.js dependencies"
run: "pnpm install"
- id: test
run: yarn test:verbose
- name: Verify rules
run: "pnpm verify"
env:
CERTORAKEY: ${{ secrets.CERTORAKEY }}
- id: coverage
run: yarn coverage
- id: upload-coverage
# run only in pull requests
if: github.event_name == 'pull_request'
uses: zgosalvez/github-actions-report-lcov@v1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
coverage-files: lcov.info
artifact-name: code-coverage-report
strategy:
fail-fast: false
max-parallel: 16

27
.gitignore vendored
View File

@@ -1,14 +1,19 @@
node_modules
.env
coverage
coverage.json
typechain
#Hardhat files
# directories
cache
artifacts
#Foundry files
cache_forge
node_modules
out
# files
*.env
*.log
.DS_Store
.pnp.*
lcov.info
yarn.lock
# broadcasts
!broadcast
broadcast/*
broadcast/*/31337/
.certora_internal

2
.gitmodules vendored
View File

@@ -1,4 +1,4 @@
[submodule "lib/forge-std"]
branch = "v1"
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
branch = v1.6.0

View File

@@ -1,5 +1,19 @@
node_modules
artifacts
# directories
broadcast
cache
coverage*
gasReporterOutput.json
lib
deployments
node_modules
out
# files
*.env
*.log
.DS_Store
.pnp.*
lcov.info
package-lock.json
pnpm-lock.yaml
yarn.lock
slither.config.json

7
.prettierrc.yml Normal file
View File

@@ -0,0 +1,7 @@
bracketSpacing: true
printWidth: 120
proseWrap: "always"
singleQuote: false
tabWidth: 2
trailingComma: "all"
useTabs: false

View File

@@ -1,7 +1,13 @@
{
"extends": "solhint:recommended",
"rules": {
"compiler-version": ["error", "^0.8.0"],
"func-visibility": ["warn", { "ignoreConstructors": true }]
"code-complexity": ["error", 8],
"compiler-version": ["error", ">=0.8.19"],
"func-name-mixedcase": "off",
"func-visibility": ["error", { "ignoreConstructors": true }],
"max-line-length": ["error", 120],
"named-parameters-mapping": "warn",
"no-console": "off",
"not-rely-on-time": "off"
}
}

View File

@@ -1 +1,3 @@
node_modules
test/**
src/RlnVerifier.sol

15
PROPERTIES.md Normal file
View File

@@ -0,0 +1,15 @@
## Protocol properties and invariants
Below is a list of all documented properties and invariants of this project that must hold true.
- **Property** - Describes the property of the project / protocol that should ultimately be tested and formaly verified.
- **Type** - Properties are split into 5 main types: **Valid State**, **State Transition**, **Variable Transition**,
**High-Level Property**, **Unit Test**
- **Risk** - One of **High**, **Medium** and **Low**, depending on the property's risk factor
- **Tested** - Whether this property has been (fuzz) tested
| **Property** | **Type** | **Risk** | **Tested** |
| ------------ | -------- | -------- | ---------- |
| | | | |
| | | | |
| | | | |

View File

@@ -1,60 +1,78 @@
# Hardhat Project for rln-contract
# rln-contract [![Github Actions][gha-badge]][gha] [![Foundry][foundry-badge]][foundry] [![License: MIT][license-badge]][license]
## Requirements
[gha]: https://github.com/vacp2p/foundry-template/actions
[gha-badge]: https://github.com/vacp2p/foundry-template/actions/workflows/ci.yml/badge.svg
[foundry]: https://getfoundry.sh/
[foundry-badge]: https://img.shields.io/badge/Built%20with-Foundry-FFDB1C.svg
[license]: https://opensource.org/licenses/MIT
[license-badge]: https://img.shields.io/badge/License-MIT-blue.svg
The following will need to be installed in order to use this repo. Please follow the links and instructions.
A Foundry-based project for Rate Limiting Nullifiers.
- [Git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git)
- You'll know you've done it right if you can run `git --version`
- [Foundry / Foundryup](https://github.com/gakonst/foundry)
- This will install `forge`, `cast`, and `anvil`
- You can test you've installed them right by running `forge --version` and get an output like: `forge 0.2.0 (92f8951 2022-08-06T00:09:32.96582Z)`
- To get the latest of each, just run `foundryup`
- [Yarn](https://classic.yarnpkg.com/lang/en/docs/install)
## Getting Started
## Compilation
```shell
yarn compile
```sh
pnpm install # install Solhint, Prettier, and other Node.js deps
forge install # install Foundry's dependencies
```
## Testing with Hardhat
If this is your first time with Foundry, check out the
[installation](https://github.com/foundry-rs/foundry#installation) instructions.
```shell
yarn test:hardhat
## Usage
### Compilation
```sh
forge build
```
## Testing with Foundry
### Format
```shell
yarn test:foundry
```sh
forge fmt
```
## Deploying
### Clean
### Locally
Deletes the build artifacts and cache directories:
- To deploy on a local node, first start the local node and then run the deploy script
```shell
yarn node
yarn deploy:localhost
```sh
forge clean
```
### Sepolia
### Gas Usage
- To deploy to an target network (like Sepolia), use the name as mentioned in the Hardhat config file.
Get a gas report:
```shell
yarn deploy:sepolia
# You may verify the contract using
yarn verify:sepolia # Ensure you have set ETHERSCAN_API_KEY in your env
```sh
forge test --gas-report
```
## References
### Test
For more information, see https://hardhat.org/hardhat-runner/docs/guides/project-setup
Run the tests:
```sh
forge test
```
### Deployment
Ensure you setup the .env file with the correct values mentioned in the .env.example file.
```sh
./script/deploy.sh rln <network>
```
Where `<network>` is one of -
- `sepolia`
- `polygon-zkevm`
This will deploy the RLN contract, with its associated libraries to the specified network.
If forge supports the network, it will also verify the contract on the block explorer.
## License
Dual-licensed under MIT or Apache 2.0, refer to [LICENSE-MIT](LICENSE-MIT) or [LICENSE-APACHE](LICENSE-APACHE) for more information.
This project is dual licensed under MIT and APACHE-2.0.

8
certora/certora.conf Normal file
View File

@@ -0,0 +1,8 @@
{
"files": ["src/Rln.sol"],
"msg": "Verifying Rln.sol",
"rule_sanity": "basic",
"verify": "Rln:certora/specs/Rln.spec",
"wait_for_results": "all",
}

9
certora/specs/Rln.spec Normal file
View File

@@ -0,0 +1,9 @@
methods {
function root() external returns (uint256) envfree;
}
rule checkDefaultRootIsCorrect {
uint256 defaultRoot = 15019797232609675441998260052101280400536945603062888308240081994073687793470;
assert root() == defaultRoot;
}

28
codecov.yml Normal file
View File

@@ -0,0 +1,28 @@
codecov:
require_ci_to_pass: false
comment: false
ignore:
- "script"
- "test"
coverage:
status:
project:
default:
# advanced settings
# Prevents PR from being blocked with a reduction in coverage.
# Note, if we want to re-enable this, a `threshold` value can be used
# allow coverage to drop by x% while still posting a success status.
# `informational`: https://docs.codecov.com/docs/commit-status#informational
# `threshold`: https://docs.codecov.com/docs/commit-status#threshold
informational: true
patch:
default:
# advanced settings
# Prevents PR from being blocked with a reduction in coverage.
# Note, if we want to re-enable this, a `threshold` value can be used
# allow coverage to drop by x% while still posting a success status.
# `informational`: https://docs.codecov.com/docs/commit-status#informational
# `threshold`: https://docs.codecov.com/docs/commit-status#threshold
informational: true

View File

@@ -1,9 +0,0 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity 0.8.15;
interface IVerifier {
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[2] memory input)
external
view
returns (bool);
}

View File

@@ -1,882 +0,0 @@
// SPDX-License-Identifier: MIT
// Forked from https://github.com/kilic/rlnapp/
pragma solidity 0.8.15;
interface IPoseidonHasher {
/// @notice Hashes the input using the Poseidon hash function, n = 2, second input is the constant 0
/// @param input The input to hash
function hash(uint256 input) external pure returns (uint256 result);
}
contract PoseidonHasher is IPoseidonHasher {
uint256 public constant Q = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 constant C0 = 4417881134626180770308697923359573201005643519861877412381846989312604493735;
uint256 constant C1 = 5433650512959517612316327474713065966758808864213826738576266661723522780033;
uint256 constant C2 = 13641176377184356099764086973022553863760045607496549923679278773208775739952;
uint256 constant C3 = 17949713444224994136330421782109149544629237834775211751417461773584374506783;
uint256 constant C4 = 13765628375339178273710281891027109699578766420463125835325926111705201856003;
uint256 constant C5 = 19179513468172002314585757290678967643352171735526887944518845346318719730387;
uint256 constant C6 = 5157412437176756884543472904098424903141745259452875378101256928559722612176;
uint256 constant C7 = 535160875740282236955320458485730000677124519901643397458212725410971557409;
uint256 constant C8 = 1050793453380762984940163090920066886770841063557081906093018330633089036729;
uint256 constant C9 = 10665495010329663932664894101216428400933984666065399374198502106997623173873;
uint256 constant C10 = 19965634623406616956648724894636666805991993496469370618546874926025059150737;
uint256 constant C11 = 13007250030070838431593222885902415182312449212965120303174723305710127422213;
uint256 constant C12 = 16877538715074991604507979123743768693428157847423939051086744213162455276374;
uint256 constant C13 = 18211747749504876135588847560312685184956239426147543810126553367063157141465;
uint256 constant C14 = 18151553319826126919739798892854572062191241985315767086020821632812331245635;
uint256 constant C15 = 19957033149976712666746140949846950406660099037474791840946955175819555930825;
uint256 constant C16 = 3469514863538261843186854830917934449567467100548474599735384052339577040841;
uint256 constant C17 = 989698510043911779243192466312362856042600749099921773896924315611668507708;
uint256 constant C18 = 12568377015646290945235387813564567111330046038050864455358059568128000172201;
uint256 constant C19 = 20856104135605479600325529349246932565148587186338606236677138505306779314172;
uint256 constant C20 = 8206918720503535523121349917159924938835810381723474192155637697065780938424;
uint256 constant C21 = 1309058477013932989380617265069188723120054926187607548493110334522527703566;
uint256 constant C22 = 14076116939332667074621703729512195584105250395163383769419390236426287710606;
uint256 constant C23 = 10153498892749751942204288991871286290442690932856658983589258153608012428674;
uint256 constant C24 = 18202499207234128286137597834010475797175973146805180988367589376893530181575;
uint256 constant C25 = 12739388830157083522877690211447248168864006284243907142044329113461613743052;
uint256 constant C26 = 15123358710467780770838026754240340042441262572309759635224051333176022613949;
uint256 constant C27 = 19925004701844594370904593774447343836015483888496504201331110250494635362184;
uint256 constant C28 = 10352416606816998476681131583320899030072315953910679608943150613208329645891;
uint256 constant C29 = 10567371822366244361703342347428230537114808440249611395507235283708966113221;
uint256 constant C30 = 5635498582763880627392290206431559361272660937399944184533035305989295959602;
uint256 constant C31 = 11866432933224219174041051738704352719163271639958083608224676028593315904909;
uint256 constant C32 = 5795020705294401441272215064554385591292330721703923167136157291459784140431;
uint256 constant C33 = 9482202378699252817564375087302794636287866584767523335624368774856230692758;
uint256 constant C34 = 4245237636894546151746468406560945873445548423466753843402086544922216329298;
uint256 constant C35 = 12000500941313982757584712677991730019124834399479314697467598397927435905133;
uint256 constant C36 = 7596790274058425558167520209857956363736666939016807569082239187494363541787;
uint256 constant C37 = 2484867918246116343205467273440098378820186751202461278013576281097918148877;
uint256 constant C38 = 18312645949449997391810445935615409295369169383463185688973803378104013950190;
uint256 constant C39 = 15320686572748723004980855263301182130424010735782762814513954166519592552733;
uint256 constant C40 = 12618438900597948888520621062416758747872180395546164387827245287017031303859;
uint256 constant C41 = 17438141672027706116733201008397064011774368832458707512367404736905021019585;
uint256 constant C42 = 6374197807230665998865688675365359100400438034755781666913068586172586548950;
uint256 constant C43 = 2189398913433273865510950346186699930188746169476472274335177556702504595264;
uint256 constant C44 = 6268495580028970231803791523870131137294646402347399003576649137450213034606;
uint256 constant C45 = 17896250365994900261202920044129628104272791547990619503076839618914047059275;
uint256 constant C46 = 13692156312448722528008862371944543449350293305158722920787736248435893008873;
uint256 constant C47 = 15234446864368744483209945022439268713300180233589581910497691316744177619376;
uint256 constant C48 = 1572426502623310766593681563281600503979671244997798691029595521622402217227;
uint256 constant C49 = 80103447810215150918585162168214870083573048458555897999822831203653996617;
uint256 constant C50 = 8228820324013669567851850635126713973797711779951230446503353812192849106342;
uint256 constant C51 = 5375851433746509614045812476958526065449377558695752132494533666370449415873;
uint256 constant C52 = 12115998939203497346386774317892338270561208357481805380546938146796257365018;
uint256 constant C53 = 9764067909645821279940531410531154041386008396840887338272986634350423466622;
uint256 constant C54 = 8538708244538850542384936174629541085495830544298260335345008245230827876882;
uint256 constant C55 = 7140127896620013355910287215441004676619168261422440177712039790284719613114;
uint256 constant C56 = 14297402962228458726038826185823085337698917275385741292940049024977027409762;
uint256 constant C57 = 6667115556431351074165934212337261254608231545257434281887966406956835140819;
uint256 constant C58 = 20226761165244293291042617464655196752671169026542832236139342122602741090001;
uint256 constant C59 = 12038289506489256655759141386763477208196694421666339040483042079632134429119;
uint256 constant C60 = 19027757334170818571203982241812412991528769934917288000224335655934473717551;
uint256 constant C61 = 16272152964456553579565580463468069884359929612321610357528838696790370074720;
uint256 constant C62 = 2500392889689246014710135696485946334448570271481948765283016105301740284071;
uint256 constant C63 = 8595254970528530312401637448610398388203855633951264114100575485022581946023;
uint256 constant C64 = 11635945688914011450976408058407206367914559009113158286982919675551688078198;
uint256 constant C65 = 614739068603482619581328040478536306925147663946742687395148680260956671871;
uint256 constant C66 = 18692271780377861570175282183255720350972693125537599213951106550953176268753;
uint256 constant C67 = 4987059230784976306647166378298632695585915319042844495357753339378260807164;
uint256 constant C68 = 21851403978498723616722415377430107676258664746210815234490134600998983955497;
uint256 constant C69 = 9830635451186415300891533983087800047564037813328875992115573428596207326204;
uint256 constant C70 = 4842706106434537116860242620706030229206345167233200482994958847436425185478;
uint256 constant C71 = 6422235064906823218421386871122109085799298052314922856340127798647926126490;
uint256 constant C72 = 4564364104986856861943331689105797031330091877115997069096365671501473357846;
uint256 constant C73 = 1944043894089780613038197112872830569538541856657037469098448708685350671343;
uint256 constant C74 = 21179865974855950600518216085229498748425990426231530451599322283119880194955;
uint256 constant C75 = 14296697761894107574369608843560006996183955751502547883167824879840894933162;
uint256 constant C76 = 12274619649702218570450581712439138337725246879938860735460378251639845671898;
uint256 constant C77 = 16371396450276899401411886674029075408418848209575273031725505038938314070356;
uint256 constant C78 = 3702561221750983937578095019779188631407216522704543451228773892695044653565;
uint256 constant C79 = 19721616877735564664624984774636557499099875603996426215495516594530838681980;
uint256 constant C80 = 6383350109027696789969911008057747025018308755462287526819231672217685282429;
uint256 constant C81 = 20860583956177367265984596617324237471765572961978977333122281041544719622905;
uint256 constant C82 = 5766390934595026947545001478457407504285452477687752470140790011329357286275;
uint256 constant C83 = 4043175758319898049344746138515323336207420888499903387536875603879441092484;
uint256 constant C84 = 15579382179133608217098622223834161692266188678101563820988612253342538956534;
uint256 constant C85 = 1864640783252634743892105383926602930909039567065240010338908865509831749824;
uint256 constant C86 = 15943719865023133586707144161652035291705809358178262514871056013754142625673;
uint256 constant C87 = 2326415993032390211558498780803238091925402878871059708106213703504162832999;
uint256 constant C88 = 19995326402773833553207196590622808505547443523750970375738981396588337910289;
uint256 constant C89 = 5143583711361588952673350526320181330406047695593201009385718506918735286622;
uint256 constant C90 = 15436006486881920976813738625999473183944244531070780793506388892313517319583;
uint256 constant C91 = 16660446760173633166698660166238066533278664023818938868110282615200613695857;
uint256 constant C92 = 4966065365695755376133119391352131079892396024584848298231004326013366253934;
uint256 constant C93 = 20683781957411705574951987677641476019618457561419278856689645563561076926702;
uint256 constant C94 = 17280836839165902792086432296371645107551519324565649849400948918605456875699;
uint256 constant C95 = 17045635513701208892073056357048619435743564064921155892004135325530808465371;
uint256 constant C96 = 17055032967194400710390142791334572297458033582458169295920670679093585707295;
uint256 constant C97 = 15727174639569115300068198908071514334002742825679221638729902577962862163505;
uint256 constant C98 = 1001755657610446661315902885492677747789366510875120894840818704741370398633;
uint256 constant C99 = 18638547332826171619311285502376343504539399518545103511265465604926625041234;
uint256 constant C100 = 6751954224763196429755298529194402870632445298969935050224267844020826420799;
uint256 constant C101 = 3526747115904224771452549517614107688674036840088422555827581348280834879405;
uint256 constant C102 = 15705897908180497062880001271426561999724005008972544196300715293701537574122;
uint256 constant C103 = 574386695213920937259007343820417029802510752426579750428758189312416867750;
uint256 constant C104 = 15973040855000600860816974646787367136127946402908768408978806375685439868553;
uint256 constant C105 = 20934130413948796333037139460875996342810005558806621330680156931816867321122;
uint256 constant C106 = 6918585327145564636398173845411579411526758237572034236476079610890705810764;
uint256 constant C107 = 14158163500813182062258176233162498241310167509137716527054939926126453647182;
uint256 constant C108 = 4164602626597695668474100217150111342272610479949122406544277384862187287433;
uint256 constant C109 = 12146526846507496913615390662823936206892812880963914267275606265272996025304;
uint256 constant C110 = 10153527926900017763244212043512822363696541810586522108597162891799345289938;
uint256 constant C111 = 13564663485965299104296214940873270349072051793008946663855767889066202733588;
uint256 constant C112 = 5612449256997576125867742696783020582952387615430650198777254717398552960096;
uint256 constant C113 = 12151885480032032868507892738683067544172874895736290365318623681886999930120;
uint256 constant C114 = 380452237704664384810613424095477896605414037288009963200982915188629772177;
uint256 constant C115 = 9067557551252570188533509616805287919563636482030947363841198066124642069518;
uint256 constant C116 = 21280306817619711661335268484199763923870315733198162896599997188206277056900;
uint256 constant C117 = 5567165819557297006750252582140767993422097822227408837378089569369734876257;
uint256 constant C118 = 10411936321072105429908396649383171465939606386380071222095155850987201580137;
uint256 constant C119 = 21338390051413922944780864872652000187403217966653363270851298678606449622266;
uint256 constant C120 = 12156296560457833712186127325312904760045212412680904475497938949653569234473;
uint256 constant C121 = 4271647814574748734312113971565139132510281260328947438246615707172526380757;
uint256 constant C122 = 9061738206062369647211128232833114177054715885442782773131292534862178874950;
uint256 constant C123 = 10134551893627587797380445583959894183158393780166496661696555422178052339133;
uint256 constant C124 = 8932270237664043612366044102088319242789325050842783721780970129656616386103;
uint256 constant C125 = 3339412934966886386194449782756711637636784424032779155216609410591712750636;
uint256 constant C126 = 9704903972004596791086522314847373103670545861209569267884026709445485704400;
uint256 constant C127 = 17467570179597572575614276429760169990940929887711661192333523245667228809456;
uint256 constant M00 = 2910766817845651019878574839501801340070030115151021261302834310722729507541;
uint256 constant M01 = 19727366863391167538122140361473584127147630672623100827934084310230022599144;
uint256 constant M10 = 5776684794125549462448597414050232243778680302179439492664047328281728356345;
uint256 constant M11 = 8348174920934122550483593999453880006756108121341067172388445916328941978568;
function hash(uint256 input) external pure override returns (uint256 result) {
return _hash(input);
}
function _hash(uint256 input) internal pure returns (uint256 result) {
assembly {
// Poseidon parameters should be t = 2, RF = 8, RP = 56
// We load the characteristic
let q := Q
// In zerokit implementation, if we pass inp = [a0,a1,..,an] to Poseidon what is effectively hashed is [0,a0,a1,..,an]
// Note that a sequence of MIX-ARK involves 3 Bn254 field additions before the mulmod happens. Worst case we have a value corresponding to 2*(p-1) which is less than 2^256 and hence doesn't overflow
//ROUND 0 - FULL
let s0 := C0
let s1 := add(input, C1)
// SBOX
let t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 1 - FULL
s0 := add(s0, C2)
s1 := add(s1, C3)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 2 - FULL
s0 := add(s0, C4)
s1 := add(s1, C5)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 3 - FULL
s0 := add(s0, C6)
s1 := add(s1, C7)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 4 - PARTIAL
s0 := add(s0, C8)
s1 := add(s1, C9)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 5 - PARTIAL
s0 := add(s0, C10)
s1 := add(s1, C11)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 6 - PARTIAL
s0 := add(s0, C12)
s1 := add(s1, C13)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 7 - PARTIAL
s0 := add(s0, C14)
s1 := add(s1, C15)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 8 - PARTIAL
s0 := add(s0, C16)
s1 := add(s1, C17)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 9 - PARTIAL
s0 := add(s0, C18)
s1 := add(s1, C19)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 10 - PARTIAL
s0 := add(s0, C20)
s1 := add(s1, C21)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 11 - PARTIAL
s0 := add(s0, C22)
s1 := add(s1, C23)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 12 - PARTIAL
s0 := add(s0, C24)
s1 := add(s1, C25)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 13 - PARTIAL
s0 := add(s0, C26)
s1 := add(s1, C27)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 14 - PARTIAL
s0 := add(s0, C28)
s1 := add(s1, C29)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 15 - PARTIAL
s0 := add(s0, C30)
s1 := add(s1, C31)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 16 - PARTIAL
s0 := add(s0, C32)
s1 := add(s1, C33)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 17 - PARTIAL
s0 := add(s0, C34)
s1 := add(s1, C35)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 18 - PARTIAL
s0 := add(s0, C36)
s1 := add(s1, C37)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 19 - PARTIAL
s0 := add(s0, C38)
s1 := add(s1, C39)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 20 - PARTIAL
s0 := add(s0, C40)
s1 := add(s1, C41)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 21 - PARTIAL
s0 := add(s0, C42)
s1 := add(s1, C43)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 22 - PARTIAL
s0 := add(s0, C44)
s1 := add(s1, C45)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 23 - PARTIAL
s0 := add(s0, C46)
s1 := add(s1, C47)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 24 - PARTIAL
s0 := add(s0, C48)
s1 := add(s1, C49)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 25 - PARTIAL
s0 := add(s0, C50)
s1 := add(s1, C51)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 26 - PARTIAL
s0 := add(s0, C52)
s1 := add(s1, C53)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 27 - PARTIAL
s0 := add(s0, C54)
s1 := add(s1, C55)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 28 - PARTIAL
s0 := add(s0, C56)
s1 := add(s1, C57)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 29 - PARTIAL
s0 := add(s0, C58)
s1 := add(s1, C59)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 30 - PARTIAL
s0 := add(s0, C60)
s1 := add(s1, C61)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 31 - PARTIAL
s0 := add(s0, C62)
s1 := add(s1, C63)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 32 - PARTIAL
s0 := add(s0, C64)
s1 := add(s1, C65)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 33 - PARTIAL
s0 := add(s0, C66)
s1 := add(s1, C67)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 34 - PARTIAL
s0 := add(s0, C68)
s1 := add(s1, C69)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 35 - PARTIAL
s0 := add(s0, C70)
s1 := add(s1, C71)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 36 - PARTIAL
s0 := add(s0, C72)
s1 := add(s1, C73)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 37 - PARTIAL
s0 := add(s0, C74)
s1 := add(s1, C75)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 38 - PARTIAL
s0 := add(s0, C76)
s1 := add(s1, C77)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 39 - PARTIAL
s0 := add(s0, C78)
s1 := add(s1, C79)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 40 - PARTIAL
s0 := add(s0, C80)
s1 := add(s1, C81)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 41 - PARTIAL
s0 := add(s0, C82)
s1 := add(s1, C83)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 42 - PARTIAL
s0 := add(s0, C84)
s1 := add(s1, C85)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 43 - PARTIAL
s0 := add(s0, C86)
s1 := add(s1, C87)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 44 - PARTIAL
s0 := add(s0, C88)
s1 := add(s1, C89)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 45 - PARTIAL
s0 := add(s0, C90)
s1 := add(s1, C91)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 46 - PARTIAL
s0 := add(s0, C92)
s1 := add(s1, C93)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 47 - PARTIAL
s0 := add(s0, C94)
s1 := add(s1, C95)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 48 - PARTIAL
s0 := add(s0, C96)
s1 := add(s1, C97)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 49 - PARTIAL
s0 := add(s0, C98)
s1 := add(s1, C99)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 50 - PARTIAL
s0 := add(s0, C100)
s1 := add(s1, C101)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 51 - PARTIAL
s0 := add(s0, C102)
s1 := add(s1, C103)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 52 - PARTIAL
s0 := add(s0, C104)
s1 := add(s1, C105)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 53 - PARTIAL
s0 := add(s0, C106)
s1 := add(s1, C107)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 54 - PARTIAL
s0 := add(s0, C108)
s1 := add(s1, C109)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 55 - PARTIAL
s0 := add(s0, C110)
s1 := add(s1, C111)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 56 - PARTIAL
s0 := add(s0, C112)
s1 := add(s1, C113)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 57 - PARTIAL
s0 := add(s0, C114)
s1 := add(s1, C115)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 58 - PARTIAL
s0 := add(s0, C116)
s1 := add(s1, C117)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 59 - PARTIAL
s0 := add(s0, C118)
s1 := add(s1, C119)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 60 - FULL
s0 := add(s0, C120)
s1 := add(s1, C121)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 61 - FULL
s0 := add(s0, C122)
s1 := add(s1, C123)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 62 - FULL
s0 := add(s0, C124)
s1 := add(s1, C125)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
t := add(mulmod(s0, M00, q), mulmod(s1, M01, q))
s1 := add(mulmod(s0, M10, q), mulmod(s1, M11, q))
s0 := t
//ROUND 63 - FULL
s0 := add(s0, C126)
s1 := add(s1, C127)
// SBOX
t := mulmod(s0, s0, q)
s0 := mulmod(mulmod(t, t, q), s0, q)
t := mulmod(s1, s1, q)
s1 := mulmod(mulmod(t, t, q), s1, q)
// MIX
s0 := mod(add(mulmod(s0, M00, q), mulmod(s1, M01, q)), q)
result := s0
}
}
}

View File

@@ -1,18 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import "./RlnBase.sol";
contract Rln is RlnBase {
constructor(uint256 membershipDeposit, uint256 depth, address _poseidonHasher, address _verifier)
RlnBase(membershipDeposit, depth, _poseidonHasher, _verifier)
{}
function _validateRegistration(uint256 idCommitment) internal pure override {}
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
internal
pure
override
{}
}

View File

@@ -1,16 +0,0 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getUnnamedAccounts } = hre;
const { deploy } = deployments;
const [deployer] = await getUnnamedAccounts();
await deploy("PoseidonHasher", {
from: deployer,
log: true,
});
};
export default func;
func.tags = ["PoseidonHasher"];

View File

@@ -1,16 +0,0 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getUnnamedAccounts } = hre;
const { deploy } = deployments;
const [deployer] = await getUnnamedAccounts();
await deploy("Verifier", {
from: deployer,
log: true,
});
};
export default func;
func.tags = ["RlnVerifier"];

View File

@@ -1,22 +0,0 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getUnnamedAccounts } = hre;
const { deploy } = deployments;
const [deployer] = await getUnnamedAccounts();
const poseidonHasherAddress = (await deployments.get("PoseidonHasher"))
.address;
const rlnVerifierAddress = (await deployments.get("Verifier")).address;
await deploy("Rln", {
from: deployer,
log: true,
args: [1000000000000000, 20, poseidonHasherAddress, rlnVerifierAddress],
});
};
export default func;
func.tags = ["Rln"];
func.dependencies = ["PoseidonHasher", "RlnVerifier"];

File diff suppressed because one or more lines are too long

View File

@@ -1,394 +0,0 @@
{
"11155111": [
{
"name": "sepolia",
"chainId": "11155111",
"contracts": {
"PoseidonHasher": {
"address": "0xa1554EAF0DF18C05956249aac375e212edeD2CcF",
"abi": [
{
"inputs": [
{
"internalType": "uint256",
"name": "input",
"type": "uint256"
}
],
"name": "hash",
"outputs": [
{
"internalType": "uint256",
"name": "result",
"type": "uint256"
}
],
"stateMutability": "pure",
"type": "function"
}
]
},
"RLN": {
"address": "0xB8144E3214080f179D037bbb4dcaaa6B87f224E4",
"abi": [
{
"inputs": [
{
"internalType": "uint256",
"name": "membershipDeposit",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "depth",
"type": "uint256"
},
{
"internalType": "address",
"name": "_poseidonHasher",
"type": "address"
},
{
"internalType": "address",
"name": "_verifier",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "DuplicateIdCommitment",
"type": "error"
},
{
"inputs": [],
"name": "FullTree",
"type": "error"
},
{
"inputs": [],
"name": "InsufficientContractBalance",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "required",
"type": "uint256"
},
{
"internalType": "uint256",
"name": "provided",
"type": "uint256"
}
],
"name": "InsufficientDeposit",
"type": "error"
},
{
"inputs": [],
"name": "InsufficientWithdrawalBalance",
"type": "error"
},
{
"inputs": [],
"name": "InvalidProof",
"type": "error"
},
{
"inputs": [
{
"internalType": "address",
"name": "to",
"type": "address"
}
],
"name": "InvalidReceiverAddress",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
}
],
"name": "MemberHasNoStake",
"type": "error"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
}
],
"name": "MemberNotRegistered",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "MemberRegistered",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
},
{
"indexed": false,
"internalType": "uint256",
"name": "index",
"type": "uint256"
}
],
"name": "MemberWithdrawn",
"type": "event"
},
{
"inputs": [],
"name": "DEPTH",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "MEMBERSHIP_DEPOSIT",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "SET_SIZE",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "idCommitmentIndex",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "members",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "poseidonHasher",
"outputs": [
{
"internalType": "contract IPoseidonHasher",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
}
],
"name": "register",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "idCommitment",
"type": "uint256"
},
{
"internalType": "address payable",
"name": "receiver",
"type": "address"
},
{
"internalType": "uint256[8]",
"name": "proof",
"type": "uint256[8]"
}
],
"name": "slash",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"name": "stakedAmounts",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "verifier",
"outputs": [
{
"internalType": "contract IVerifier",
"name": "",
"type": "address"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "withdraw",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "",
"type": "address"
}
],
"name": "withdrawalBalance",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
}
]
},
"Verifier": {
"address": "0xb81Faa6F0126dedB55A45eb63E8430B270A00303",
"abi": [
{
"inputs": [
{
"internalType": "uint256[2]",
"name": "a",
"type": "uint256[2]"
},
{
"internalType": "uint256[2][2]",
"name": "b",
"type": "uint256[2][2]"
},
{
"internalType": "uint256[2]",
"name": "c",
"type": "uint256[2]"
},
{
"internalType": "uint256[2]",
"name": "input",
"type": "uint256[2]"
}
],
"name": "verifyProof",
"outputs": [
{
"internalType": "bool",
"name": "r",
"type": "bool"
}
],
"stateMutability": "view",
"type": "function"
}
]
}
}
}
]
}

View File

@@ -1 +0,0 @@
11155111

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,41 @@
# Full reference https://github.com/foundry-rs/foundry/tree/master/config
[profile.default]
src = 'contracts'
out = 'out'
libs = ['node_modules', 'lib']
test = 'test'
cache_path = 'cache_forge'
auto_detect_solc = false
block_timestamp = 1_680_220_800 # March 31, 2023 at 00:00 GMT
bytecode_hash = "none"
cbor_metadata = false
evm_version = "paris"
fuzz = { runs = 1_000 }
gas_reports = ["*"]
libs = ["lib"]
optimizer = true
optimizer_runs = 10_000
out = "out"
script = "script"
solc = "0.8.19"
src = "src"
test = "test"
[profile.ci]
fuzz = { runs = 10_000 }
verbosity = 4
[etherscan]
sepolia = { key = "${SEPOLIA_ETHERSCAN_API_KEY}" }
polygon-zkevm-testnet = { key = "${POLYGONSCAN_ZKEVM_TESTNET_API_KEY}" }
[fmt]
bracket_spacing = true
int_types = "long"
line_length = 120
multiline_func_header = "all"
number_underscore = "thousands"
quote_style = "double"
tab_width = 4
wrap_comments = true
[rpc_endpoints]
localhost = "http://localhost:8545"
sepolia = "${SEPOLIA_RPC_URL}"
polygon-zkevm-testnet = "${POLYGON_ZKEVM_TESTNET_RPC_URL}"

View File

@@ -1,58 +0,0 @@
import * as dotenv from "dotenv";
import { HardhatUserConfig } from "hardhat/config";
import { NetworksUserConfig } from "hardhat/types";
import "@nomicfoundation/hardhat-foundry";
import "hardhat-deploy";
import "@nomiclabs/hardhat-etherscan";
import "@nomiclabs/hardhat-ethers";
import "@nomiclabs/hardhat-waffle";
import "hardhat-gas-reporter";
import "solidity-docgen";
dotenv.config();
const { SEPOLIA_URL, PRIVATE_KEY, ETHERSCAN_API_KEY } = process.env;
const getNetworkConfig = (): NetworksUserConfig | undefined => {
if (SEPOLIA_URL && PRIVATE_KEY) {
return {
sepolia: {
url: SEPOLIA_URL,
accounts: [PRIVATE_KEY],
forking: {
url: SEPOLIA_URL,
},
verify: {
etherscan: {
apiKey: ETHERSCAN_API_KEY,
apiUrl: "https://api-sepolia.etherscan.io",
},
},
},
localhost_integration: {
url: "http://localhost:8545",
},
};
}
return undefined;
};
// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more
const config: HardhatUserConfig = {
solidity: {
compilers: [
{
version: "0.8.15",
},
{
version: "0.6.11",
},
],
},
networks: getNetworkConfig(),
};
export default config;

View File

@@ -1,51 +1,35 @@
{
"name": "rln-contract",
"license": "(MIT OR Apache-2.0)",
"scripts": {
"start": "hardhat node --export-all deployments/allDeployments.json",
"compile": "hardhat compile",
"test": "yarn test:foundry && yarn test:hardhat",
"test:verbose": "yarn test:foundry -vvv && yarn test:hardhat --verbose",
"test:hardhat": "hardhat test",
"test:hardhat:localhost": "yarn test:hardhat --network localhost",
"test:hardhat:sepolia": "yarn test:hardhat --network sepolia",
"test:foundry": "forge test",
"deploy": "hardhat deploy --export-all deployments/allDeployments.json --network",
"deploy:sepolia": "yarn deploy sepolia",
"deploy:localhost": "yarn deploy localhost",
"verify:sepolia": "hardhat --network sepolia etherscan-verify",
"coverage": "forge coverage --report lcov",
"fmt": "prettier --write \"**/*.{js,ts}\"",
"lint": "prettier --check \"**/*.{js,ts}\"",
"prepare": "husky install",
"docgen": "hardhat docgen"
"name": "@vacp2p/rln-contracts",
"description": "Contracts for RLN's onchain registry set",
"version": "1.0.0",
"author": {
"name": "p1ge0nh8er",
"url": "https://github.com/vacp2p"
},
"devDependencies": {
"@nomicfoundation/hardhat-foundry": "^1.0.0",
"@nomiclabs/hardhat-ethers": "npm:hardhat-deploy-ethers",
"@nomiclabs/hardhat-etherscan": "^3.1.7",
"@nomiclabs/hardhat-waffle": "^2.0.3",
"@types/chai": "^4.3.4",
"@types/mocha": "^9.1.1",
"@types/node": "^16.11.6",
"chai": "^4.3.6",
"ethereum-waffle": "^3.4.4",
"ethers": "^5.7.2",
"hardhat": "^2.9.9",
"hardhat-deploy": "0.11.20",
"hardhat-gas-reporter": "^1.0.8",
"husky": "^8.0.2",
"lint-staged": "^13.0.3",
"ts-node": "^10.8.1",
"typescript": "^4.7.4",
"solidity-docgen": "0.6.0-beta.35"
"prettier": "^3.0.0",
"solhint-community": "^3.6.0"
},
"keywords": [
"blockchain",
"ethereum",
"forge",
"foundry",
"smart-contracts",
"solidity",
"template"
],
"private": true,
"scripts": {
"clean": "rm -rf cache out",
"lint": "pnpm lint:sol && pnpm prettier:check",
"verify": "certoraRun certora/certora.conf",
"lint:sol": "forge fmt --check && pnpm solhint {script,src,test,certora}/**/*.sol",
"prettier:check": "prettier --check **/*.{json,md,yml} --ignore-path=.prettierignore",
"prettier:write": "prettier --write **/*.{json,md,yml} --ignore-path=.prettierignore"
},
"dependencies": {
"dotenv": "^16.0.1"
},
"lint-staged": {
"**/*": [
"prettier --write --ignore-unknown"
]
"@zk-kit/imt.sol": "2.0.0-beta",
"poseidon-solidity": "^0.0.5"
}
}

470
pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,470 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@zk-kit/imt.sol':
specifier: 2.0.0-beta
version: 2.0.0-beta
poseidon-solidity:
specifier: ^0.0.5
version: 0.0.5
devDependencies:
prettier:
specifier: ^3.0.0
version: 3.0.0
solhint-community:
specifier: ^3.6.0
version: 3.6.0
packages:
/@babel/code-frame@7.22.5:
resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/highlight': 7.22.5
dev: true
/@babel/helper-validator-identifier@7.22.5:
resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==}
engines: {node: '>=6.9.0'}
dev: true
/@babel/highlight@7.22.5:
resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==}
engines: {node: '>=6.9.0'}
dependencies:
'@babel/helper-validator-identifier': 7.22.5
chalk: 2.4.2
js-tokens: 4.0.0
dev: true
/@solidity-parser/parser@0.16.1:
resolution: {integrity: sha512-PdhRFNhbTtu3x8Axm0uYpqOy/lODYQK+MlYSgqIsq2L8SFYEHJPHNUiOTAJbDGzNjjr1/n9AcIayxafR/fWmYw==}
dependencies:
antlr4ts: 0.5.0-alpha.4
dev: true
/@zk-kit/imt.sol@2.0.0-beta:
resolution: {integrity: sha512-bH7RvI5WHAEswUwPspUY582O2+71xbYv5aL+DM4xkaA0GdMyMLUwf5c1yJ4wrt46hp07iXCXJsLXdtLNsTnvZw==}
dependencies:
poseidon-solidity: 0.0.5
dev: false
/ajv@6.12.6:
resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==}
dependencies:
fast-deep-equal: 3.1.3
fast-json-stable-stringify: 2.1.0
json-schema-traverse: 0.4.1
uri-js: 4.4.1
dev: true
/ajv@8.12.0:
resolution: {integrity: sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==}
dependencies:
fast-deep-equal: 3.1.3
json-schema-traverse: 1.0.0
require-from-string: 2.0.2
uri-js: 4.4.1
dev: true
/ansi-regex@5.0.1:
resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==}
engines: {node: '>=8'}
dev: true
/ansi-styles@3.2.1:
resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==}
engines: {node: '>=4'}
dependencies:
color-convert: 1.9.3
dev: true
/ansi-styles@4.3.0:
resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==}
engines: {node: '>=8'}
dependencies:
color-convert: 2.0.1
dev: true
/antlr4@4.13.0:
resolution: {integrity: sha512-zooUbt+UscjnWyOrsuY/tVFL4rwrAGwOivpQmvmUDE22hy/lUA467Rc1rcixyRwcRUIXFYBwv7+dClDSHdmmew==}
engines: {node: '>=16'}
dev: true
/antlr4ts@0.5.0-alpha.4:
resolution: {integrity: sha512-WPQDt1B74OfPv/IMS2ekXAKkTZIHl88uMetg6q3OTqgFxZ/dxDXI0EWLyZid/1Pe6hTftyg5N7gel5wNAGxXyQ==}
dev: true
/argparse@2.0.1:
resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==}
dev: true
/ast-parents@0.0.1:
resolution: {integrity: sha512-XHusKxKz3zoYk1ic8Un640joHbFMhbqneyoZfoKnEGtf2ey9Uh/IdpcQplODdO/kENaMIWsD0nJm4+wX3UNLHA==}
dev: true
/astral-regex@2.0.0:
resolution: {integrity: sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==}
engines: {node: '>=8'}
dev: true
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
dev: true
/brace-expansion@2.0.1:
resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==}
dependencies:
balanced-match: 1.0.2
dev: true
/callsites@3.1.0:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'}
dev: true
/chalk@2.4.2:
resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==}
engines: {node: '>=4'}
dependencies:
ansi-styles: 3.2.1
escape-string-regexp: 1.0.5
supports-color: 5.5.0
dev: true
/chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
dev: true
/color-convert@1.9.3:
resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==}
dependencies:
color-name: 1.1.3
dev: true
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
engines: {node: '>=7.0.0'}
dependencies:
color-name: 1.1.4
dev: true
/color-name@1.1.3:
resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==}
dev: true
/color-name@1.1.4:
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
dev: true
/commander@10.0.1:
resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==}
engines: {node: '>=14'}
dev: true
/cosmiconfig@8.2.0:
resolution: {integrity: sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==}
engines: {node: '>=14'}
dependencies:
import-fresh: 3.3.0
js-yaml: 4.1.0
parse-json: 5.2.0
path-type: 4.0.0
dev: true
/emoji-regex@8.0.0:
resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==}
dev: true
/error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
dependencies:
is-arrayish: 0.2.1
dev: true
/escape-string-regexp@1.0.5:
resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==}
engines: {node: '>=0.8.0'}
dev: true
/fast-deep-equal@3.1.3:
resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==}
dev: true
/fast-diff@1.3.0:
resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==}
dev: true
/fast-json-stable-stringify@2.1.0:
resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==}
dev: true
/fs.realpath@1.0.0:
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
dev: true
/glob@8.1.0:
resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==}
engines: {node: '>=12'}
dependencies:
fs.realpath: 1.0.0
inflight: 1.0.6
inherits: 2.0.4
minimatch: 5.1.6
once: 1.4.0
dev: true
/has-flag@3.0.0:
resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==}
engines: {node: '>=4'}
dev: true
/has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
dev: true
/ignore@5.2.4:
resolution: {integrity: sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==}
engines: {node: '>= 4'}
dev: true
/import-fresh@3.3.0:
resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==}
engines: {node: '>=6'}
dependencies:
parent-module: 1.0.1
resolve-from: 4.0.0
dev: true
/inflight@1.0.6:
resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==}
dependencies:
once: 1.4.0
wrappy: 1.0.2
dev: true
/inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/is-arrayish@0.2.1:
resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==}
dev: true
/is-fullwidth-code-point@3.0.0:
resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==}
engines: {node: '>=8'}
dev: true
/js-tokens@4.0.0:
resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==}
dev: true
/js-yaml@4.1.0:
resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==}
hasBin: true
dependencies:
argparse: 2.0.1
dev: true
/json-parse-even-better-errors@2.3.1:
resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==}
dev: true
/json-schema-traverse@0.4.1:
resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==}
dev: true
/json-schema-traverse@1.0.0:
resolution: {integrity: sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==}
dev: true
/lines-and-columns@1.2.4:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: true
/lodash.truncate@4.4.2:
resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==}
dev: true
/lodash@4.17.21:
resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==}
dev: true
/minimatch@5.1.6:
resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==}
engines: {node: '>=10'}
dependencies:
brace-expansion: 2.0.1
dev: true
/once@1.4.0:
resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==}
dependencies:
wrappy: 1.0.2
dev: true
/parent-module@1.0.1:
resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==}
engines: {node: '>=6'}
dependencies:
callsites: 3.1.0
dev: true
/parse-json@5.2.0:
resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==}
engines: {node: '>=8'}
dependencies:
'@babel/code-frame': 7.22.5
error-ex: 1.3.2
json-parse-even-better-errors: 2.3.1
lines-and-columns: 1.2.4
dev: true
/path-type@4.0.0:
resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==}
engines: {node: '>=8'}
dev: true
/pluralize@8.0.0:
resolution: {integrity: sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==}
engines: {node: '>=4'}
dev: true
/poseidon-solidity@0.0.5:
resolution: {integrity: sha512-NzrvSwHzvZgT4hvg2GyGqeR+UOU/eLSEt4wAoXEua+VaR7NTKKwx1X9bPlh1VMBEVEno+IWvkRBbidFGzTeAqQ==}
dev: false
/prettier@2.8.8:
resolution: {integrity: sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==}
engines: {node: '>=10.13.0'}
hasBin: true
requiresBuild: true
dev: true
optional: true
/prettier@3.0.0:
resolution: {integrity: sha512-zBf5eHpwHOGPC47h0zrPyNn+eAEIdEzfywMoYn2XPi0P44Zp0tSq64rq0xAREh4auw2cJZHo9QUob+NqCQky4g==}
engines: {node: '>=14'}
hasBin: true
dev: true
/punycode@2.3.0:
resolution: {integrity: sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==}
engines: {node: '>=6'}
dev: true
/require-from-string@2.0.2:
resolution: {integrity: sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==}
engines: {node: '>=0.10.0'}
dev: true
/resolve-from@4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
dev: true
/semver@6.3.1:
resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==}
hasBin: true
dev: true
/slice-ansi@4.0.0:
resolution: {integrity: sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==}
engines: {node: '>=10'}
dependencies:
ansi-styles: 4.3.0
astral-regex: 2.0.0
is-fullwidth-code-point: 3.0.0
dev: true
/solhint-community@3.6.0:
resolution: {integrity: sha512-3WGi8nB9VSdC7B3xawktFoQkJEgX6rsUe7jWZJteDBdix+tAOGN+2ZhRr7Cyv1s+h5BRLSsNOXoh7Vg9KEeQbg==}
hasBin: true
dependencies:
'@solidity-parser/parser': 0.16.1
ajv: 6.12.6
antlr4: 4.13.0
ast-parents: 0.0.1
chalk: 4.1.2
commander: 10.0.1
cosmiconfig: 8.2.0
fast-diff: 1.3.0
glob: 8.1.0
ignore: 5.2.4
js-yaml: 4.1.0
lodash: 4.17.21
pluralize: 8.0.0
semver: 6.3.1
strip-ansi: 6.0.1
table: 6.8.1
text-table: 0.2.0
optionalDependencies:
prettier: 2.8.8
dev: true
/string-width@4.2.3:
resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==}
engines: {node: '>=8'}
dependencies:
emoji-regex: 8.0.0
is-fullwidth-code-point: 3.0.0
strip-ansi: 6.0.1
dev: true
/strip-ansi@6.0.1:
resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==}
engines: {node: '>=8'}
dependencies:
ansi-regex: 5.0.1
dev: true
/supports-color@5.5.0:
resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==}
engines: {node: '>=4'}
dependencies:
has-flag: 3.0.0
dev: true
/supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
dependencies:
has-flag: 4.0.0
dev: true
/table@6.8.1:
resolution: {integrity: sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA==}
engines: {node: '>=10.0.0'}
dependencies:
ajv: 8.12.0
lodash.truncate: 4.4.2
slice-ansi: 4.0.0
string-width: 4.2.3
strip-ansi: 6.0.1
dev: true
/text-table@0.2.0:
resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==}
dev: true
/uri-js@4.4.1:
resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==}
dependencies:
punycode: 2.3.0
dev: true
/wrappy@1.0.2:
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
dev: true

View File

@@ -1,6 +1,3 @@
@ensdomains/=node_modules/@ensdomains/
ds-test/=lib/forge-std/lib/ds-test/src/
eth-gas-reporter/=node_modules/eth-gas-reporter/
forge-std/=lib/forge-std/src/
hardhat-deploy/=node_modules/hardhat-deploy/
hardhat/=node_modules/hardhat/
@zk-kit/imt.sol/=node_modules/@zk-kit/imt.sol/
poseidon-solidity/=node_modules/poseidon-solidity/

41
script/Base.s.sol Normal file
View File

@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import { Script } from "forge-std/Script.sol";
abstract contract BaseScript is Script {
/// @dev Included to enable compilation of the script without a $MNEMONIC environment variable.
string internal constant TEST_MNEMONIC = "test test test test test test test test test test test junk";
/// @dev Needed for the deterministic deployments.
bytes32 internal constant ZERO_SALT = bytes32(0);
/// @dev The address of the transaction broadcaster.
address internal broadcaster;
/// @dev Used to derive the broadcaster's address if $ETH_FROM is not defined.
string internal mnemonic;
/// @dev Initializes the transaction broadcaster like this:
///
/// - If $ETH_FROM is defined, use it.
/// - Otherwise, derive the broadcaster address from $MNEMONIC.
/// - If $MNEMONIC is not defined, default to a test mnemonic.
///
/// The use case for $ETH_FROM is to specify the broadcaster key and its address via the command line.
constructor() {
address from = vm.envOr({ name: "ETH_FROM", defaultValue: address(0) });
if (from != address(0)) {
broadcaster = from;
} else {
mnemonic = vm.envOr({ name: "MNEMONIC", defaultValue: TEST_MNEMONIC });
(broadcaster,) = deriveRememberKey({ mnemonic: mnemonic, index: 0 });
}
}
modifier broadcast() {
vm.startBroadcast(broadcaster);
_;
vm.stopBroadcast();
}
}

20
script/Deploy.s.sol Normal file
View File

@@ -0,0 +1,20 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.19;
import { Verifier } from "../src/RlnVerifier.sol";
import { Rln } from "../src/Rln.sol";
import { BaseScript } from "./Base.s.sol";
import { DeploymentConfig } from "./DeploymentConfig.s.sol";
contract Deploy is BaseScript {
function run() public returns (Rln rln, DeploymentConfig deploymentConfig) {
deploymentConfig = new DeploymentConfig(broadcaster);
vm.startBroadcast(broadcaster);
// step 1: deploy the verifier
Verifier verifier = new Verifier();
// step 2: deploy the rln contract
rln = new Rln(0, 20, address(verifier));
vm.stopBroadcast();
}
}

View File

@@ -0,0 +1,51 @@
//// SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.8.19;
import { Script } from "forge-std/Script.sol";
contract DeploymentConfig is Script {
error DeploymentConfig_InvalidDeployerAddress();
error DeploymentConfig_NoConfigForChain(uint256);
struct NetworkConfig {
address deployer;
}
NetworkConfig public activeNetworkConfig;
address private deployer;
constructor(address _broadcaster) {
if (_broadcaster == address(0)) revert DeploymentConfig_InvalidDeployerAddress();
deployer = _broadcaster;
if (block.chainid == 31_337) {
activeNetworkConfig = getOrCreateAnvilEthConfig();
} else if (block.chainid == 11_155_111) {
activeNetworkConfig = getOrCreateSepoliaEthConfig();
} else if (block.chainid == 1442) {
activeNetworkConfig = getOrCreatePolygonZkevmConfig();
} else {
revert DeploymentConfig_NoConfigForChain(block.chainid);
}
}
function getOrCreateAnvilEthConfig() public view returns (NetworkConfig memory) {
return NetworkConfig({ deployer: deployer });
}
function getOrCreateSepoliaEthConfig() public view returns (NetworkConfig memory) {
return NetworkConfig({ deployer: deployer });
}
function getOrCreatePolygonZkevmConfig() public view returns (NetworkConfig memory) {
return NetworkConfig({ deployer: deployer });
}
// This function is a hack to have it excluded by `forge coverage` until
// https://github.com/foundry-rs/foundry/issues/2988 is fixed.
// See: https://github.com/foundry-rs/foundry/issues/2988#issuecomment-1437784542
// for more info.
// solhint-disable-next-line
function test() public { }
}

80
script/deploy.sh Executable file
View File

@@ -0,0 +1,80 @@
#!/bin/bash
set -e
contract_name="$1"
provided_chain_name="$2"
if [ -z "$contract_name" ]; then
echo "Usage: ./script/deploy.sh <contract_name (rln)> <chain_name (sepolia, polygon-zkevm-testnet)>"
exit 1
fi
if [ -z "$provided_chain_name" ]; then
echo "Usage: ./script/deploy.sh <contract_name (rln)> <chain_name (sepolia, polygon-zkevm-testnet)>"
exit 1
fi
echo "Sourcing .env"
source .env
rpc_url=""
# Check if appropriate env vars are set
if [ "$provided_chain_name" = "sepolia" ]; then
if [ -z "$SEPOLIA_RPC_URL" ]; then
echo "SEPOLIA_RPC_URL is not set"
exit 1
else
rpc_url="$SEPOLIA_RPC_URL"
fi
elif [ "$provided_chain_name" = "polygon-zkevm-testnet" ]; then
if [ -z "$POLYGON_ZKEVM_TESTNET_RPC_URL" ]; then
echo "POLYGON_ZKEVM_TESTNET_RPC_URL is not set"
exit 1
else
rpc_url="$POLYGON_ZKEVM_TESTNET_RPC_URL"
fi
else
echo "Invalid chain name, try again with sepolia/polygon-zkevm-testnet"
exit 1
fi
if [ -z "$PRIVATE_KEY" ]; then
echo "PRIVATE_KEY is not set"
exit 1
fi
echo "Deploying $contract_name..."
# Deploy the contract
if [ "$contract_name" = "rln" ]; then
chain_id=$(cast chain-id --rpc-url "$rpc_url")
chain_name=""
verifier_url=""
if [ -z "$chain_id" ]; then
echo "Failed to get chain id"
exit 1
fi
if [ "$chain_id" = "11155111" ]; then
chain_name="sepolia"
elif [ "$chain_id" = "1442" ]; then
chain_name="polygon-zkevm-testnet"
else
echo "Invalid chain id, try again with sepolia/polygon-zkevm-testnet"
exit 1
fi
forge script script/Deploy.s.sol:Deploy --chain $chain_name --rpc-url $rpc_url --private-key "$PRIVATE_KEY" --broadcast --verify
echo "Deployed Rln contracts, Now verifying"
echo "Verified $rln_name contract, now dumping the artifacts to ./deployments/$chain_id/latest.json"
# Dump the artifacts to ./deployments/$chain_id/latest.json
mkdir -p ./deployments/$chain_id
cat ./broadcast/Deploy.s.sol/$chain_id/run-latest.json | jq -r '.["transactions"]' > ./deployments/$chain_id/latest.json
else
echo "Invalid contract name, please use rln."
fi

View File

@@ -1,3 +1,8 @@
{
"filter_paths": "contracts"
"detectors_to_exclude": "naming-convention,reentrancy-events,solc-version,timestamp",
"filter_paths": "(lib|test)",
"solc_remaps": [
"@openzeppelin/contracts=lib/openzeppelin-contracts/contracts/",
"forge-std/=lib/forge-std/src/"
]
}

14
src/IVerifier.sol Normal file
View File

@@ -0,0 +1,14 @@
// SPDX-License-Identifier: Apache-2.0 OR MIT
pragma solidity >=0.8.19;
interface IVerifier {
function verifyProof(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[2] memory input
)
external
view
returns (bool);
}

26
src/Rln.sol Normal file
View File

@@ -0,0 +1,26 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.19;
import "./RlnBase.sol";
contract Rln is RlnBase {
constructor(
uint256 membershipDeposit,
uint256 depth,
address _verifier
)
RlnBase(membershipDeposit, depth, _verifier)
{ }
function _validateRegistration(uint256 idCommitment) internal pure override { }
function _validateSlash(
uint256 idCommitment,
address payable receiver,
uint256[8] calldata proof
)
internal
pure
override
{ }
}

View File

@@ -1,8 +1,7 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
pragma solidity ^0.8.19;
import {PoseidonHasher} from "./PoseidonHasher.sol";
import { IVerifier } from "./IVerifier.sol";
/// The tree is full
@@ -40,7 +39,14 @@ error InsufficientContractBalance();
/// Invalid proof
error InvalidProof();
/// Invalid pagination query
error InvalidPaginationQuery(uint256 startIndex, uint256 endIndex);
abstract contract RlnBase {
/// @notice The Field
uint256 public constant Q =
21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617;
/// @notice The deposit amount required to register as a member
uint256 public immutable MEMBERSHIP_DEPOSIT;
@@ -61,14 +67,15 @@ abstract contract RlnBase {
/// maps from idCommitment to their index in the set
mapping(uint256 => uint256) public members;
/// @notice the index to commitment mapping
mapping(uint256 => uint256) public indexToCommitment;
/// @notice The membership status of each member
mapping(uint256 => bool) public memberExists;
/// @notice The balance of each user that can be withdrawn
mapping(address => uint256) public withdrawalBalance;
/// @notice The Poseidon hasher contract
PoseidonHasher public immutable poseidonHasher;
/// @notice The groth16 verifier contract
IVerifier public immutable verifier;
@@ -90,11 +97,10 @@ abstract contract RlnBase {
_;
}
constructor(uint256 membershipDeposit, uint256 depth, address _poseidonHasher, address _verifier) {
constructor(uint256 membershipDeposit, uint256 depth, address _verifier) {
MEMBERSHIP_DEPOSIT = membershipDeposit;
DEPTH = depth;
SET_SIZE = 1 << depth;
poseidonHasher = PoseidonHasher(_poseidonHasher);
verifier = IVerifier(_verifier);
deployedBlockNumber = uint32(block.number);
}
@@ -117,6 +123,7 @@ abstract contract RlnBase {
if (idCommitmentIndex >= SET_SIZE) revert FullTree();
members[idCommitment] = idCommitmentIndex;
indexToCommitment[idCommitmentIndex] = idCommitment;
memberExists[idCommitment] = true;
stakedAmounts[idCommitment] = stake;
@@ -129,7 +136,11 @@ abstract contract RlnBase {
/// @dev Allows a user to slash a member
/// @param idCommitment The idCommitment of the member
function slash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
function slash(
uint256 idCommitment,
address payable receiver,
uint256[8] calldata proof
)
external
virtual
onlyValidIdCommitment(idCommitment)
@@ -162,8 +173,10 @@ abstract contract RlnBase {
// delete member
uint256 index = members[idCommitment];
members[idCommitment] = 0;
indexToCommitment[index] = 0;
memberExists[idCommitment] = false;
stakedAmounts[idCommitment] = 0;
// TODO: remove from IMT
// refund deposit
withdrawalBalance[receiver] += amountToTransfer;
@@ -171,7 +184,11 @@ abstract contract RlnBase {
emit MemberWithdrawn(idCommitment, index);
}
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
function _validateSlash(
uint256 idCommitment,
address payable receiver,
uint256[8] calldata proof
)
internal
view
virtual;
@@ -190,19 +207,16 @@ abstract contract RlnBase {
payable(msg.sender).transfer(amount);
}
/// Hashes a value using the Poseidon hasher
/// NOTE: The variant of Poseidon we use accepts only 1 input, assume n=2, and the second input is 0
/// @param input The value to hash
function hash(uint256 input) internal view returns (uint256) {
return poseidonHasher.hash(input);
}
function isValidCommitment(uint256 idCommitment) public view returns (bool) {
return idCommitment != 0 && idCommitment < poseidonHasher.Q();
function isValidCommitment(uint256 idCommitment) public pure returns (bool) {
return idCommitment != 0 && idCommitment < Q;
}
/// @dev Groth16 proof verification
function _verifyProof(uint256 idCommitment, address receiver, uint256[8] calldata proof)
function _verifyProof(
uint256 idCommitment,
address receiver,
uint256[8] calldata proof
)
internal
view
virtual
@@ -215,4 +229,15 @@ abstract contract RlnBase {
[idCommitment, uint256(uint160(receiver))]
);
}
function getCommitments(uint256 startIndex, uint256 endIndex) public view returns (uint256[] memory) {
if (startIndex >= endIndex) revert InvalidPaginationQuery(startIndex, endIndex);
if (endIndex > idCommitmentIndex) revert InvalidPaginationQuery(startIndex, endIndex);
uint256[] memory commitments = new uint256[](endIndex - startIndex);
for (uint256 i = startIndex; i < endIndex; i++) {
commitments[i - startIndex] = indexToCommitment[i];
}
return commitments;
}
}

View File

@@ -1,8 +1,15 @@
// File: https://github.com/Rate-Limiting-Nullifier/rln-contract-v1/blob/main/src/RLNVerifier.sol
// Copyright 2017 Christian Reitwiessner
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
// Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// 2019 OKIMS
// ported to solidity 0.6
@@ -11,7 +18,7 @@
//
//
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.6.11;
pragma solidity ^0.8.19;
library Pairing {
struct G1Point {
@@ -35,12 +42,12 @@ library Pairing {
// Original code point
return G2Point(
[
11559732032986387107991004021392285783925812861821192530917403151452391805634,
10857046999023057135944570762232829481370756359578518086990519993285655852781
11_559_732_032_986_387_107_991_004_021_392_285_783_925_812_861_821_192_530_917_403_151_452_391_805_634,
10_857_046_999_023_057_135_944_570_762_232_829_481_370_756_359_578_518_086_990_519_993_285_655_852_781
],
[
4082367875863433681332203403145435568316851327593401208105741076214120093531,
8495653923123431417604973247489272438418190587263600148770280649306958101930
4_082_367_875_863_433_681_332_203_403_145_435_568_316_851_327_593_401_208_105_741_076_214_120_093_531,
8_495_653_923_123_431_417_604_973_247_489_272_438_418_190_587_263_600_148_770_280_649_306_958_101_930
]
);
@@ -57,7 +64,8 @@ library Pairing {
function negate(G1Point memory p) internal pure returns (G1Point memory r) {
// The prime q in the base field F_q for G1
uint256 q = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
uint256 q =
21_888_242_871_839_275_222_246_405_745_257_275_088_696_311_157_297_823_662_689_037_894_645_226_208_583;
if (p.X == 0 && p.Y == 0) {
return G1Point(0, 0);
}
@@ -108,7 +116,7 @@ library Pairing {
require(p1.length == p2.length, "pairing-lengths-failed");
uint256 elements = p1.length;
uint256 inputSize = elements * 6;
uint256[] memory input = new uint[](inputSize);
uint256[] memory input = new uint256[](inputSize);
for (uint256 i = 0; i < elements; i++) {
input[i * 6 + 0] = p1[i].X;
input[i * 6 + 1] = p1[i].Y;
@@ -131,7 +139,12 @@ library Pairing {
}
/// Convenience method for a pairing check for two pairs.
function pairingProd2(G1Point memory a1, G2Point memory a2, G1Point memory b1, G2Point memory b2)
function pairingProd2(
G1Point memory a1,
G2Point memory a2,
G1Point memory b1,
G2Point memory b2
)
internal
view
returns (bool)
@@ -153,7 +166,11 @@ library Pairing {
G2Point memory b2,
G1Point memory c1,
G2Point memory c2
) internal view returns (bool) {
)
internal
view
returns (bool)
{
G1Point[] memory p1 = new G1Point[](3);
G2Point[] memory p2 = new G2Point[](3);
p1[0] = a1;
@@ -175,7 +192,11 @@ library Pairing {
G2Point memory c2,
G1Point memory d1,
G2Point memory d2
) internal view returns (bool) {
)
internal
view
returns (bool)
{
G1Point[] memory p1 = new G1Point[](4);
G2Point[] memory p2 = new G2Point[](4);
p1[0] = a1;
@@ -209,60 +230,61 @@ contract Verifier {
function verifyingKey() internal pure returns (VerifyingKey memory vk) {
vk.alfa1 = Pairing.G1Point(
20491192805390485299153009773594534940189261866228447918068658471970481763042,
9383485363053290200918347156157836566562967994039712273449902621266178545958
20_491_192_805_390_485_299_153_009_773_594_534_940_189_261_866_228_447_918_068_658_471_970_481_763_042,
9_383_485_363_053_290_200_918_347_156_157_836_566_562_967_994_039_712_273_449_902_621_266_178_545_958
);
vk.beta2 = Pairing.G2Point(
[
4252822878758300859123897981450591353533073413197771768651442665752259397132,
6375614351688725206403948262868962793625744043794305715222011528459656738731
4_252_822_878_758_300_859_123_897_981_450_591_353_533_073_413_197_771_768_651_442_665_752_259_397_132,
6_375_614_351_688_725_206_403_948_262_868_962_793_625_744_043_794_305_715_222_011_528_459_656_738_731
],
[
21847035105528745403288232691147584728191162732299865338377159692350059136679,
10505242626370262277552901082094356697409835680220590971873171140371331206856
21_847_035_105_528_745_403_288_232_691_147_584_728_191_162_732_299_865_338_377_159_692_350_059_136_679,
10_505_242_626_370_262_277_552_901_082_094_356_697_409_835_680_220_590_971_873_171_140_371_331_206_856
]
);
vk.gamma2 = Pairing.G2Point(
[
11559732032986387107991004021392285783925812861821192530917403151452391805634,
10857046999023057135944570762232829481370756359578518086990519993285655852781
11_559_732_032_986_387_107_991_004_021_392_285_783_925_812_861_821_192_530_917_403_151_452_391_805_634,
10_857_046_999_023_057_135_944_570_762_232_829_481_370_756_359_578_518_086_990_519_993_285_655_852_781
],
[
4082367875863433681332203403145435568316851327593401208105741076214120093531,
8495653923123431417604973247489272438418190587263600148770280649306958101930
4_082_367_875_863_433_681_332_203_403_145_435_568_316_851_327_593_401_208_105_741_076_214_120_093_531,
8_495_653_923_123_431_417_604_973_247_489_272_438_418_190_587_263_600_148_770_280_649_306_958_101_930
]
);
vk.delta2 = Pairing.G2Point(
[
12423666958566268737444308034237892912702648013927558883280319245968679130649,
15986964528637281931410749976607406939789163617014270799373312764775965360012
12_423_666_958_566_268_737_444_308_034_237_892_912_702_648_013_927_558_883_280_319_245_968_679_130_649,
15_986_964_528_637_281_931_410_749_976_607_406_939_789_163_617_014_270_799_373_312_764_775_965_360_012
],
[
8394023076056524902583796202128496802110914536948580183128578071394816660799,
4964607673011101982600772762445991192038811950832626693345350322823626470007
8_394_023_076_056_524_902_583_796_202_128_496_802_110_914_536_948_580_183_128_578_071_394_816_660_799,
4_964_607_673_011_101_982_600_772_762_445_991_192_038_811_950_832_626_693_345_350_322_823_626_470_007
]
);
vk.IC = new Pairing.G1Point[](3);
vk.IC[0] = Pairing.G1Point(
1655549413518972190198478012616802994254462093161203201613599472264958303841,
21742734017792296281216385119397138748114275727065024271646515586404591497876
1_655_549_413_518_972_190_198_478_012_616_802_994_254_462_093_161_203_201_613_599_472_264_958_303_841,
21_742_734_017_792_296_281_216_385_119_397_138_748_114_275_727_065_024_271_646_515_586_404_591_497_876
);
vk.IC[1] = Pairing.G1Point(
16497930821522159474595176304955625435616718625609462506360632944366974274906,
10404924572941018678793755094259635830045501866471999610240845041996101882275
16_497_930_821_522_159_474_595_176_304_955_625_435_616_718_625_609_462_506_360_632_944_366_974_274_906,
10_404_924_572_941_018_678_793_755_094_259_635_830_045_501_866_471_999_610_240_845_041_996_101_882_275
);
vk.IC[2] = Pairing.G1Point(
9567910551099174794221497568036631681620409346997815381833929247558241020796,
17282591858786007768931802126325866705896012606427630592145070155065868649172
9_567_910_551_099_174_794_221_497_568_036_631_681_620_409_346_997_815_381_833_929_247_558_241_020_796,
17_282_591_858_786_007_768_931_802_126_325_866_705_896_012_606_427_630_592_145_070_155_065_868_649_172
);
}
function verify(uint256[] memory input, Proof memory proof) internal view returns (uint256) {
uint256 snark_scalar_field = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
uint256 snark_scalar_field =
21_888_242_871_839_275_222_246_405_745_257_275_088_548_364_400_416_034_343_698_204_186_575_808_495_617;
VerifyingKey memory vk = verifyingKey();
require(input.length + 1 == vk.IC.length, "verifier-bad-input");
// Compute the linear combination vk_x
@@ -281,7 +303,12 @@ contract Verifier {
}
/// @return r bool true if proof is valid
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[2] memory input)
function verifyProof(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[2] memory input
)
public
view
returns (bool r)
@@ -290,7 +317,7 @@ contract Verifier {
proof.A = Pairing.G1Point(a[0], a[1]);
proof.B = Pairing.G2Point([b[0][0], b[0][1]], [b[1][0], b[1][1]]);
proof.C = Pairing.G1Point(c[0], c[1]);
uint256[] memory inputValues = new uint[](input.length);
uint256[] memory inputValues = new uint256[](input.length);
for (uint256 i = 0; i < input.length; i++) {
inputValues[i] = input[i];
}

View File

@@ -1,26 +0,0 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import "../contracts/PoseidonHasher.sol";
import "forge-std/Test.sol";
contract PoseidonHasherTest is Test {
PoseidonHasher public poseidon;
/// @dev Setup the testing environment.
function setUp() public {
poseidon = new PoseidonHasher();
}
/// @dev Ensure that you can hash a value.
function testHasher(uint256 value) public {
assertEq(poseidon.hash(value), poseidon.hash(value));
}
function testHasher() public {
assertEq(
poseidon.hash(19014214495641488759237505126948346942972912379615652741039992445865937985820),
0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368
);
}
}

View File

@@ -1,75 +0,0 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import "../contracts/PoseidonHasher.sol";
import "../contracts/RlnBase.sol";
import "./Verifier.sol";
import "forge-std/Test.sol";
import "forge-std/StdCheats.sol";
import "forge-std/console.sol";
contract RlnApp is RlnBase {
uint256 public constant allowedIdCommitment =
19014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 private membershipDeposit = 1000000000000000;
uint256 private depth = 20;
constructor(address _poseidonHasher, address _verifier)
RlnBase(membershipDeposit, depth, _poseidonHasher, _verifier)
{}
function _validateRegistration(uint256 idCommitment) internal pure override {
if (idCommitment != allowedIdCommitment) revert FailedValidation();
}
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
internal
pure
override
{
if (idCommitment == allowedIdCommitment) revert FailedValidation();
}
}
contract RLNAppTest is Test {
RlnApp public rlnApp;
PoseidonHasher public poseidon;
TrueVerifier public trueVerifier;
uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000;
uint256 public constant DEPTH = 20;
uint256 public constant SET_SIZE = 1048576;
uint256[8] public zeroedProof = [0, 0, 0, 0, 0, 0, 0, 0];
function setUp() public {
poseidon = new PoseidonHasher();
trueVerifier = new TrueVerifier();
rlnApp = new RlnApp(address(poseidon), address(trueVerifier));
}
function test__Constants() public {
// sanity checking
assertEq(rlnApp.MEMBERSHIP_DEPOSIT(), MEMBERSHIP_DEPOSIT);
assertEq(rlnApp.DEPTH(), DEPTH);
assertEq(rlnApp.SET_SIZE(), SET_SIZE);
}
function test__InvalidRegistration(uint256 idCommitment) public {
vm.assume(idCommitment != rlnApp.allowedIdCommitment());
vm.assume(rlnApp.isValidCommitment(idCommitment));
vm.expectRevert(FailedValidation.selector);
rlnApp.register{value: MEMBERSHIP_DEPOSIT}(idCommitment);
}
function test__ValidRegistration() public {
rlnApp.register{value: MEMBERSHIP_DEPOSIT}(rlnApp.allowedIdCommitment());
}
function test__InvalidSlash() public {
uint256 allowedIdCommitment = rlnApp.allowedIdCommitment();
rlnApp.register{value: MEMBERSHIP_DEPOSIT}(allowedIdCommitment);
vm.expectRevert(FailedValidation.selector);
rlnApp.slash(allowedIdCommitment, payable(address(this)), zeroedProof);
}
}

View File

@@ -1,34 +1,34 @@
// SPDX-License-Identifier: Unlicense
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.15;
import "../contracts/PoseidonHasher.sol";
import "../contracts/Rln.sol";
import "./Verifier.sol";
import "forge-std/Test.sol";
import { Test, console } from "forge-std/Test.sol";
import "forge-std/StdCheats.sol";
import "forge-std/console.sol";
import { TrueVerifier, FalseVerifier } from "./mocks/VerifierMock.sol";
import { Deploy } from "../script/Deploy.s.sol";
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
import "../src/Rln.sol";
contract RlnTest is Test {
using stdStorage for StdStorage;
Rln public rln;
PoseidonHasher public poseidon;
TrueVerifier public trueVerifier;
FalseVerifier public falseVerifier;
Rln internal rln;
TrueVerifier internal trueVerifier;
FalseVerifier internal falseVerifier;
uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000;
uint256 public constant DEPTH = 20;
uint256 public constant SET_SIZE = 1048576;
uint256[8] public zeroedProof = [0, 0, 0, 0, 0, 0, 0, 0];
/// @dev Setup the testing environment.
function setUp() public {
poseidon = new PoseidonHasher();
function setUp() public virtual {
trueVerifier = new TrueVerifier();
falseVerifier = new FalseVerifier();
rln = new Rln(MEMBERSHIP_DEPOSIT, DEPTH, address(poseidon), address(trueVerifier));
rln = new Rln(MEMBERSHIP_DEPOSIT, DEPTH, address(trueVerifier));
}
uint256 public constant MEMBERSHIP_DEPOSIT = 1_000_000_000_000_000;
uint256 public constant DEPTH = 20;
uint256 public constant SET_SIZE = 1_048_576;
uint256[8] public zeroedProof = [0, 0, 0, 0, 0, 0, 0, 0];
/// @dev Ensure that you can hash a value.
function test__Constants() public {
assertEq(rln.MEMBERSHIP_DEPOSIT(), MEMBERSHIP_DEPOSIT);
@@ -69,12 +69,7 @@ contract RlnTest is Test {
}
function test__InvalidRegistration__FullSet() public {
Rln tempRln = new Rln(
MEMBERSHIP_DEPOSIT,
2,
address(rln.poseidonHasher()),
address(rln.verifier())
);
Rln tempRln = new Rln(MEMBERSHIP_DEPOSIT, 2, address(rln.verifier()));
uint256 setSize = tempRln.SET_SIZE();
for (uint256 i = 1; i <= setSize; i++) {
tempRln.register{ value: MEMBERSHIP_DEPOSIT }(i);
@@ -97,15 +92,18 @@ contract RlnTest is Test {
uint256 balanceBefore = to.balance;
rln.slash(idCommitment, to, zeroedProof);
assertEq(rln.withdrawalBalance(to), MEMBERSHIP_DEPOSIT);
vm.prank(to);
rln.withdraw();
assertEq(rln.stakedAmounts(idCommitment), 0);
assertEq(rln.members(idCommitment), 0);
assertEq(rln.withdrawalBalance(to), 0);
assertEq(to.balance, balanceBefore + MEMBERSHIP_DEPOSIT);
}
function test__InvalidSlash__ToZeroAddress() public {
uint256 idCommitment = 9014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 idCommitment =
9_014_214_495_641_488_759_237_505_126_948_346_942_972_912_379_615_652_741_039_992_445_865_937_985_820;
rln.register{ value: MEMBERSHIP_DEPOSIT }(idCommitment);
assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT);
@@ -114,7 +112,8 @@ contract RlnTest is Test {
}
function test__InvalidSlash__ToRlnAddress() public {
uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 idCommitment =
19_014_214_495_641_488_759_237_505_126_948_346_942_972_912_379_615_652_741_039_992_445_865_937_985_820;
rln.register{ value: MEMBERSHIP_DEPOSIT }(idCommitment);
assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT);
vm.expectRevert(abi.encodeWithSelector(InvalidReceiverAddress.selector, address(rln)));
@@ -150,14 +149,10 @@ contract RlnTest is Test {
}
function test__InvalidSlash__InvalidProof() public {
uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 idCommitment =
19_014_214_495_641_488_759_237_505_126_948_346_942_972_912_379_615_652_741_039_992_445_865_937_985_820;
Rln tempRln = new Rln(
MEMBERSHIP_DEPOSIT,
2,
address(rln.poseidonHasher()),
address(falseVerifier)
);
Rln tempRln = new Rln(MEMBERSHIP_DEPOSIT, 2, address(falseVerifier));
tempRln.register{ value: MEMBERSHIP_DEPOSIT }(idCommitment);
@@ -171,7 +166,8 @@ contract RlnTest is Test {
}
function test__InvalidWithdraw__InsufficientContractBalance() public {
uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 idCommitment =
19_014_214_495_641_488_759_237_505_126_948_346_942_972_912_379_615_652_741_039_992_445_865_937_985_820;
rln.register{ value: MEMBERSHIP_DEPOSIT }(idCommitment);
assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT);
rln.slash(idCommitment, payable(address(this)), zeroedProof);
@@ -186,14 +182,17 @@ contract RlnTest is Test {
function test__ValidWithdraw(address payable to) public {
assumePayable(to);
assumeNotPrecompile(to);
vm.assume(to != address(0));
uint256 idCommitment = 19014214495641488759237505126948346942972912379615652741039992445865937985820;
uint256 idCommitment =
19_014_214_495_641_488_759_237_505_126_948_346_942_972_912_379_615_652_741_039_992_445_865_937_985_820;
rln.register{ value: MEMBERSHIP_DEPOSIT }(idCommitment);
assertEq(rln.stakedAmounts(idCommitment), MEMBERSHIP_DEPOSIT);
rln.slash(idCommitment, to, zeroedProof);
assertEq(rln.stakedAmounts(idCommitment), 0);
assertEq(rln.members(idCommitment), 0);
assertEq(rln.memberExists(idCommitment), false);
vm.prank(to);
rln.withdraw();

View File

@@ -1,24 +0,0 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import {IVerifier} from "../contracts/IVerifier.sol";
contract TrueVerifier is IVerifier {
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[2] memory input)
external
pure
returns (bool)
{
return true;
}
}
contract FalseVerifier is IVerifier {
function verifyProof(uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[2] memory input)
external
pure
returns (bool)
{
return false;
}
}

View File

@@ -0,0 +1,34 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.19;
import { IVerifier } from "../../src/IVerifier.sol";
contract TrueVerifier is IVerifier {
function verifyProof(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[2] memory input
)
external
pure
returns (bool)
{
return true;
}
}
contract FalseVerifier is IVerifier {
function verifyProof(
uint256[2] memory a,
uint256[2][2] memory b,
uint256[2] memory c,
uint256[2] memory input
)
external
pure
returns (bool)
{
return false;
}
}

View File

@@ -1,21 +0,0 @@
import { expect } from "chai";
import { ethers, deployments } from "hardhat";
describe("PoseidonHasher", () => {
beforeEach(async () => {
await deployments.fixture(["PoseidonHasher"]);
});
it("should hash correctly", async function () {
const poseidonHasher = await ethers.getContract("PoseidonHasher");
// We test hashing for a random number
const hash = await poseidonHasher.hash(
"19014214495641488759237505126948346942972912379615652741039992445865937985820"
);
expect(hash._hex).to.eql(
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368"
);
});
});

View File

@@ -1,78 +0,0 @@
import { expect } from "chai";
import { ethers, deployments } from "hardhat";
describe("Rln", () => {
beforeEach(async () => {
await deployments.fixture(["Rln"]);
});
it("should register new memberships", async () => {
const rln = await ethers.getContract("Rln", ethers.provider.getSigner(0));
const price = await rln.MEMBERSHIP_DEPOSIT();
// A valid pair of (id_secret, id_commitment) generated in rust
const idCommitment =
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368";
const registerTx = await rln["register(uint256)"](idCommitment, {
value: price,
});
const txRegisterReceipt = await registerTx.wait();
const pubkey = txRegisterReceipt.events[0].args.idCommitment;
// We ensure the registered id_commitment is the one we passed
expect(
pubkey.toHexString() === idCommitment,
"registered commitment doesn't match passed commitment"
);
});
it("should slash membership", async () => {
const rln = await ethers.getContract("Rln", ethers.provider.getSigner(0));
const price = await rln.MEMBERSHIP_DEPOSIT();
// A valid id_commitment generated in zerokit
const idCommitment =
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368";
const registerTx = await rln["register(uint256)"](idCommitment, {
value: price,
});
await registerTx.wait();
// We slash the id_commitment
const receiverAddress = "0x000000000000000000000000000000000000dead";
const slashTx = rln["slash(uint256,address,uint256[8])"](
idCommitment,
receiverAddress,
[0, 0, 0, 0, 0, 0, 0, 0]
);
await expect(slashTx).to.be.revertedWith("InvalidProof()");
});
it("should not allow multiple registrations with same pubkey", async () => {
const rln = await ethers.getContract("Rln", ethers.provider.getSigner(0));
const price = await rln.MEMBERSHIP_DEPOSIT();
// A valid pair of (id_secret, id_commitment) generated in rust
const idCommitment =
"0x0c3ac305f6a4fe9bfeb3eba978bc876e2a99208b8b56c80160cfb54ba8f02368";
const registerTx = await rln["register(uint256)"](idCommitment, {
value: price,
});
await registerTx.wait();
// Send the same tx again
const registerTx2 = rln["register(uint256)"](idCommitment, {
value: price,
});
await expect(registerTx2).to.be.revertedWith("DuplicateIdCommitment()");
});
});

View File

@@ -1,19 +0,0 @@
{
"compilerOptions": {
"target": "es2018",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"outDir": "dist",
"declaration": true
},
"include": [
"./scripts",
"./test",
"./typechain",
"deploy"
],
"files": [
"./hardhat.config.ts"
]
}

9337
yarn.lock

File diff suppressed because it is too large Load Diff