forge install: rln-contract

This commit is contained in:
rymnc 2023-07-31 10:51:15 +05:30
parent ab739fb92b
commit c4f531c7bb
No known key found for this signature in database
GPG Key ID: AAA088D5C68ECD34
15 changed files with 192 additions and 2088 deletions

6
.gitmodules vendored
View File

@ -2,3 +2,9 @@
path = lib/forge-std
url = https://github.com/foundry-rs/forge-std
branch = v1.5.2
[submodule "lib/rln-contract"]
path = lib/rln-contract
url = https://github.com/vacp2p/rln-contract
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/Openzeppelin/openzeppelin-contracts

3
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,3 @@
{
"solidity.compileUsingRemoteVersion": "v0.8.15+commit.e14f2714"
}

File diff suppressed because it is too large Load Diff

View File

@ -1,64 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {IPoseidonHasher} from "./PoseidonHasher.sol";
/// The tree is full
error FullTree();
/// Member is already registered
error DuplicateIdCommitment();
contract RLN {
/// @notice The depth of the merkle tree
uint256 public immutable DEPTH = 20;
/// @notice The size of the merkle tree, i.e 2^depth
uint256 public immutable SET_SIZE;
/// @notice The index of the next member to be registered
uint256 public idCommitmentIndex = 1;
/// @notice The membership status of each member
/// maps from idCommitment to their index in the set
mapping(uint256 => bool) public members;
/// @notice The Poseidon hasher contract
IPoseidonHasher public immutable poseidonHasher;
/// Emitted when a new member is added to the set
/// @param idCommitment The idCommitment of the member
/// @param index The index of the member in the set
event MemberRegistered(uint256 idCommitment, uint256 index);
constructor(uint256[] memory constructMembers, address _poseidonHasher) {
poseidonHasher = IPoseidonHasher(_poseidonHasher);
SET_SIZE = 1 << DEPTH;
if (constructMembers.length > SET_SIZE) revert FullTree();
for (uint256 i = 0; i < constructMembers.length;) {
_register(constructMembers[i]);
unchecked {
++i;
}
}
}
/// Registers a member
/// @param idCommitment The idCommitment of the member
function _register(uint256 idCommitment) internal {
if (members[idCommitment] != false) revert DuplicateIdCommitment();
members[idCommitment] = true;
emit MemberRegistered(idCommitment, idCommitmentIndex);
idCommitmentIndex += 1;
}
/// 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);
}
}

53
contracts/WakuRln.sol Normal file
View File

@ -0,0 +1,53 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import {IPoseidonHasher} from "rln-contract/PoseidonHasher.sol";
import {RlnBase, DuplicateIdCommitment} from "rln-contract/RlnBase.sol";
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";
error NotImplemented();
contract WakuRln is Ownable, RlnBase {
constructor(address _poseidonHasher) Ownable() RlnBase(0, 20, _poseidonHasher, address(0)) {}
/// Registers a member
/// @param idCommitment The idCommitment of the member
function _register(uint256 idCommitment) internal {
_validateRegistration(idCommitment);
members[idCommitment] = 1;
emit MemberRegistered(idCommitment, idCommitmentIndex);
idCommitmentIndex += 1;
}
function register(uint256[] memory idCommitments) external onlyOwner {
uint256 len = idCommitments.length;
for (uint256 i = 0; i < len;) {
_register(idCommitments[i]);
unchecked {
++i;
}
}
}
function register(uint256 idCommitment) external payable override {
revert NotImplemented();
}
function slash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof) external pure override {
revert NotImplemented();
}
function _validateRegistration(uint256 idCommitment) internal view override {
if (members[idCommitment] != 0) revert DuplicateIdCommitment();
}
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
internal
pure
override
{
revert NotImplemented();
}
}

View File

@ -10,7 +10,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const poseidonHasherAddress = (await deployments.get("PoseidonHasher"))
.address;
await deploy("RLN", {
await deploy("WakuRln", {
from: deployer,
log: true,
args: [[], poseidonHasherAddress],
@ -18,5 +18,5 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
};
export default func;
func.tags = ["RLN"];
func.tags = ["WakuRln"];
func.dependencies = ["PoseidonHasher"];

View File

@ -1,922 +1,20 @@
# Solidity API
## IPoseidonHasher
### hash
```solidity
function hash(uint256 input) external pure returns (uint256 result)
```
Hashes the input using the Poseidon hash function, n = 2, second input is the constant 0
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| input | uint256 | The input to hash |
## PoseidonHasher
### Q
```solidity
uint256 Q
```
### C0
```solidity
uint256 C0
```
### C1
```solidity
uint256 C1
```
### C2
```solidity
uint256 C2
```
### C3
```solidity
uint256 C3
```
### C4
```solidity
uint256 C4
```
### C5
```solidity
uint256 C5
```
### C6
```solidity
uint256 C6
```
### C7
```solidity
uint256 C7
```
### C8
```solidity
uint256 C8
```
### C9
```solidity
uint256 C9
```
### C10
```solidity
uint256 C10
```
### C11
```solidity
uint256 C11
```
### C12
```solidity
uint256 C12
```
### C13
```solidity
uint256 C13
```
### C14
```solidity
uint256 C14
```
### C15
```solidity
uint256 C15
```
### C16
```solidity
uint256 C16
```
### C17
```solidity
uint256 C17
```
### C18
```solidity
uint256 C18
```
### C19
```solidity
uint256 C19
```
### C20
```solidity
uint256 C20
```
### C21
```solidity
uint256 C21
```
### C22
```solidity
uint256 C22
```
### C23
```solidity
uint256 C23
```
### C24
```solidity
uint256 C24
```
### C25
```solidity
uint256 C25
```
### C26
```solidity
uint256 C26
```
### C27
```solidity
uint256 C27
```
### C28
```solidity
uint256 C28
```
### C29
```solidity
uint256 C29
```
### C30
```solidity
uint256 C30
```
### C31
```solidity
uint256 C31
```
### C32
```solidity
uint256 C32
```
### C33
```solidity
uint256 C33
```
### C34
```solidity
uint256 C34
```
### C35
```solidity
uint256 C35
```
### C36
```solidity
uint256 C36
```
### C37
```solidity
uint256 C37
```
### C38
```solidity
uint256 C38
```
### C39
```solidity
uint256 C39
```
### C40
```solidity
uint256 C40
```
### C41
```solidity
uint256 C41
```
### C42
```solidity
uint256 C42
```
### C43
```solidity
uint256 C43
```
### C44
```solidity
uint256 C44
```
### C45
```solidity
uint256 C45
```
### C46
```solidity
uint256 C46
```
### C47
```solidity
uint256 C47
```
### C48
```solidity
uint256 C48
```
### C49
```solidity
uint256 C49
```
### C50
```solidity
uint256 C50
```
### C51
```solidity
uint256 C51
```
### C52
```solidity
uint256 C52
```
### C53
```solidity
uint256 C53
```
### C54
```solidity
uint256 C54
```
### C55
```solidity
uint256 C55
```
### C56
```solidity
uint256 C56
```
### C57
```solidity
uint256 C57
```
### C58
```solidity
uint256 C58
```
### C59
```solidity
uint256 C59
```
### C60
```solidity
uint256 C60
```
### C61
```solidity
uint256 C61
```
### C62
```solidity
uint256 C62
```
### C63
```solidity
uint256 C63
```
### C64
```solidity
uint256 C64
```
### C65
```solidity
uint256 C65
```
### C66
```solidity
uint256 C66
```
### C67
```solidity
uint256 C67
```
### C68
```solidity
uint256 C68
```
### C69
```solidity
uint256 C69
```
### C70
```solidity
uint256 C70
```
### C71
```solidity
uint256 C71
```
### C72
```solidity
uint256 C72
```
### C73
```solidity
uint256 C73
```
### C74
```solidity
uint256 C74
```
### C75
```solidity
uint256 C75
```
### C76
```solidity
uint256 C76
```
### C77
```solidity
uint256 C77
```
### C78
```solidity
uint256 C78
```
### C79
```solidity
uint256 C79
```
### C80
```solidity
uint256 C80
```
### C81
```solidity
uint256 C81
```
### C82
```solidity
uint256 C82
```
### C83
```solidity
uint256 C83
```
### C84
```solidity
uint256 C84
```
### C85
```solidity
uint256 C85
```
### C86
```solidity
uint256 C86
```
### C87
```solidity
uint256 C87
```
### C88
```solidity
uint256 C88
```
### C89
```solidity
uint256 C89
```
### C90
```solidity
uint256 C90
```
### C91
```solidity
uint256 C91
```
### C92
```solidity
uint256 C92
```
### C93
```solidity
uint256 C93
```
### C94
```solidity
uint256 C94
```
### C95
```solidity
uint256 C95
```
### C96
```solidity
uint256 C96
```
### C97
```solidity
uint256 C97
```
### C98
```solidity
uint256 C98
```
### C99
```solidity
uint256 C99
```
### C100
```solidity
uint256 C100
```
### C101
```solidity
uint256 C101
```
### C102
```solidity
uint256 C102
```
### C103
```solidity
uint256 C103
```
### C104
```solidity
uint256 C104
```
### C105
```solidity
uint256 C105
```
### C106
```solidity
uint256 C106
```
### C107
```solidity
uint256 C107
```
### C108
```solidity
uint256 C108
```
### C109
```solidity
uint256 C109
```
### C110
```solidity
uint256 C110
```
### C111
```solidity
uint256 C111
```
### C112
```solidity
uint256 C112
```
### C113
```solidity
uint256 C113
```
### C114
```solidity
uint256 C114
```
### C115
```solidity
uint256 C115
```
### C116
```solidity
uint256 C116
```
### C117
```solidity
uint256 C117
```
### C118
```solidity
uint256 C118
```
### C119
```solidity
uint256 C119
```
### C120
```solidity
uint256 C120
```
### C121
```solidity
uint256 C121
```
### C122
```solidity
uint256 C122
```
### C123
```solidity
uint256 C123
```
### C124
```solidity
uint256 C124
```
### C125
```solidity
uint256 C125
```
### C126
```solidity
uint256 C126
```
### C127
```solidity
uint256 C127
```
### M00
```solidity
uint256 M00
```
### M01
```solidity
uint256 M01
```
### M10
```solidity
uint256 M10
```
### M11
```solidity
uint256 M11
```
### hash
```solidity
function hash(uint256 input) external pure returns (uint256 result)
```
Hashes the input using the Poseidon hash function, n = 2, second input is the constant 0
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| input | uint256 | The input to hash |
### _hash
```solidity
function _hash(uint256 input) internal pure returns (uint256 result)
```
## FullTree
```solidity
error FullTree()
```
The tree is full
## DuplicateIdCommitment
```solidity
error DuplicateIdCommitment()
```
Member is already registered
## RLN
### DEPTH
```solidity
uint256 DEPTH
```
The depth of the merkle tree
### SET_SIZE
```solidity
uint256 SET_SIZE
```
The size of the merkle tree, i.e 2^depth
### idCommitmentIndex
```solidity
uint256 idCommitmentIndex
```
The index of the next member to be registered
### members
```solidity
mapping(uint256 => bool) members
```
The membership status of each member
maps from idCommitment to their index in the set
### poseidonHasher
```solidity
contract IPoseidonHasher poseidonHasher
```
The Poseidon hasher contract
### MemberRegistered
## NotImplemented
```solidity
event MemberRegistered(uint256 idCommitment, uint256 index)
error NotImplemented()
```
Emitted when a new member is added to the set
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| idCommitment | uint256 | The idCommitment of the member |
| index | uint256 | The index of the member in the set |
## WakuRln
### constructor
```solidity
constructor(uint256[] constructMembers, address _poseidonHasher) public
constructor(address _poseidonHasher) public
```
### _register
### \_register
```solidity
function _register(uint256 idCommitment) internal
@ -926,22 +24,56 @@ Registers a member
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| Name | Type | Description |
| ------------ | ------- | ------------------------------ |
| idCommitment | uint256 | The idCommitment of the member |
### hash
### register
```solidity
function hash(uint256 input) internal view returns (uint256)
function register(uint256[] idCommitments) external
```
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
### register
```solidity
function register(uint256 idCommitment) external payable
```
Allows a user to register as a member
#### Parameters
| Name | Type | Description |
| ---- | ---- | ----------- |
| input | uint256 | The value to hash |
| Name | Type | Description |
| ------------ | ------- | ------------------------------ |
| idCommitment | uint256 | The idCommitment of the member |
### slash
```solidity
function slash(uint256 idCommitment, address payable receiver, uint256[8] proof) external pure
```
_Allows a user to slash a member_
#### Parameters
| Name | Type | Description |
| ------------ | --------------- | ------------------------------ |
| idCommitment | uint256 | The idCommitment of the member |
| receiver | address payable | |
| proof | uint256[8] | |
### \_validateRegistration
```solidity
function _validateRegistration(uint256 idCommitment) internal view
```
_Inheriting contracts MUST override this function_
### \_validateSlash
```solidity
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] proof) internal pure
```

@ -0,0 +1 @@
Subproject commit fd81a96f01cc42ef1c9a5399364968d0e07e9e90

1
lib/rln-contract Submodule

@ -0,0 +1 @@
Subproject commit a092b934a6293203abbd4b9e3412db23ff59877e

10
remappings.txt Normal file
View File

@ -0,0 +1,10 @@
@ensdomains/=node_modules/@ensdomains/
ds-test/=lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
eth-gas-reporter/=node_modules/eth-gas-reporter/
forge-std/=lib/forge-std/src/
hardhat-deploy/=node_modules/hardhat-deploy/
hardhat/=node_modules/hardhat/
openzeppelin-contracts/=lib/openzeppelin-contracts/
openzeppelin/=lib/openzeppelin-contracts/contracts/
rln-contract/=lib/rln-contract/contracts/

View File

@ -1,28 +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,32 +0,0 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import "../contracts/PoseidonHasher.sol";
import "../contracts/Rln.sol";
import "forge-std/Test.sol";
import "forge-std/StdCheats.sol";
import "forge-std/console.sol";
contract RLNTest is Test {
using stdStorage for StdStorage;
RLN public rln;
PoseidonHasher public poseidon;
uint256 public constant MEMBERSHIP_DEPOSIT = 1000000000000000;
uint256 public constant DEPTH = 20;
uint256 public constant SET_SIZE = 1048576;
/// @dev Setup the testing environment.
function setUp() public {
poseidon = new PoseidonHasher();
uint256[] memory constructMembers = new uint256[](0);
rln = new RLN(constructMembers, address(poseidon));
}
/// @dev Ensure that you can hash a value.
function test__Constants() public {
assertEq(rln.DEPTH(), DEPTH);
assertEq(rln.SET_SIZE(), SET_SIZE);
}
}

68
test/WakuRln.t.sol Normal file
View File

@ -0,0 +1,68 @@
// SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.15;
import {PoseidonHasher} from "rln-contract/PoseidonHasher.sol";
import "../contracts/WakuRLn.sol";
import "forge-std/Test.sol";
import "forge-std/StdCheats.sol";
function noDuplicate(uint256[] calldata ids) pure returns (bool) {
uint256 len = ids.length;
for (uint256 i = 0; i < len; i++) {
for (uint256 j = i + 1; j < len; j++) {
if (ids[i] == ids[j]) {
return false;
}
}
}
return true;
}
contract WakuRlnTest is Test {
using stdStorage for StdStorage;
WakuRln public wakuRln;
PoseidonHasher public poseidon;
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();
wakuRln = new WakuRln(address(poseidon));
}
/// @dev Ensure that you can hash a value.
function test__Constants() public {
assertEq(wakuRln.DEPTH(), DEPTH);
assertEq(wakuRln.SET_SIZE(), SET_SIZE);
}
function test__ValidRegistration(uint256[] calldata idCommitments) public {
// Register a batch of commitments
vm.assume(idCommitments.length < 10_000);
vm.assume(noDuplicate(idCommitments));
wakuRln.register(idCommitments);
}
function test__InvalidRegistration__Duplicate() public {
// Register a batch of commitments
uint256[] memory idCommitments = new uint256[](2);
idCommitments[0] = 1;
idCommitments[1] = 1;
vm.expectRevert(DuplicateIdCommitment.selector);
wakuRln.register(idCommitments);
}
function test__InvalidFeatures() public {
uint256 idCommitment = 1;
vm.expectRevert(NotImplemented.selector);
wakuRln.register(idCommitment);
vm.expectRevert(NotImplemented.selector);
wakuRln.slash(idCommitment, payable(address(0)), zeroedProof);
}
}

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,8 +0,0 @@
import { expect } from "chai";
import { ethers, deployments } from "hardhat";
describe("RLN", () => {
beforeEach(async () => {
await deployments.fixture(["RLN"]);
});
});