mirror of
https://github.com/waku-org/waku-rlnv1-contract.git
synced 2025-02-22 12:18:11 +00:00
Merge pull request #3 from waku-org/waku-rln-registry
feat: waku rln registry contract to enable autosharding
This commit is contained in:
commit
6188737f78
@ -2,13 +2,17 @@
|
||||
pragma solidity 0.8.15;
|
||||
|
||||
import {IPoseidonHasher} from "rln-contract/PoseidonHasher.sol";
|
||||
import {RlnBase, DuplicateIdCommitment} from "rln-contract/RlnBase.sol";
|
||||
import {RlnBase, DuplicateIdCommitment, FullTree} 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)) {}
|
||||
uint16 public immutable contractIndex;
|
||||
|
||||
constructor(address _poseidonHasher, uint16 _contractIndex) Ownable() RlnBase(0, 20, _poseidonHasher, address(0)) {
|
||||
contractIndex = _contractIndex;
|
||||
}
|
||||
|
||||
/// Registers a member
|
||||
/// @param idCommitment The idCommitment of the member
|
||||
@ -21,7 +25,7 @@ contract WakuRln is Ownable, RlnBase {
|
||||
idCommitmentIndex += 1;
|
||||
}
|
||||
|
||||
function register(uint256[] memory idCommitments) external onlyOwner {
|
||||
function register(uint256[] calldata idCommitments) external onlyOwner {
|
||||
uint256 len = idCommitments.length;
|
||||
for (uint256 i = 0; i < len;) {
|
||||
_register(idCommitments[i]);
|
||||
@ -41,6 +45,7 @@ contract WakuRln is Ownable, RlnBase {
|
||||
|
||||
function _validateRegistration(uint256 idCommitment) internal view override {
|
||||
if (members[idCommitment] != 0) revert DuplicateIdCommitment();
|
||||
if (idCommitmentIndex >= SET_SIZE) revert FullTree();
|
||||
}
|
||||
|
||||
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] calldata proof)
|
||||
|
86
contracts/WakuRlnRegistry.sol
Normal file
86
contracts/WakuRlnRegistry.sol
Normal file
@ -0,0 +1,86 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity 0.8.15;
|
||||
|
||||
import {WakuRln} from "./WakuRln.sol";
|
||||
import {IPoseidonHasher} from "rln-contract/PoseidonHasher.sol";
|
||||
import {Ownable} from "openzeppelin-contracts/contracts/access/Ownable.sol";
|
||||
|
||||
error StorageAlreadyExists(address storageAddress);
|
||||
error NoStorageContractAvailable();
|
||||
error IncompatibleStorage();
|
||||
error IncompatibleStorageIndex();
|
||||
|
||||
contract WakuRlnRegistry is Ownable {
|
||||
uint16 public nextStorageIndex;
|
||||
mapping(uint16 => address) public storages;
|
||||
|
||||
uint16 public usingStorageIndex = 0;
|
||||
|
||||
IPoseidonHasher public immutable poseidonHasher;
|
||||
|
||||
event NewStorageContract(uint16 index, address storageAddress);
|
||||
|
||||
modifier onlyUsableStorage() {
|
||||
if (usingStorageIndex >= nextStorageIndex) revert NoStorageContractAvailable();
|
||||
_;
|
||||
}
|
||||
|
||||
constructor(address _poseidonHasher) Ownable() {
|
||||
poseidonHasher = IPoseidonHasher(_poseidonHasher);
|
||||
}
|
||||
|
||||
function _insertIntoStorageMap(address storageAddress) internal {
|
||||
storages[nextStorageIndex] = storageAddress;
|
||||
emit NewStorageContract(nextStorageIndex, storageAddress);
|
||||
nextStorageIndex += 1;
|
||||
}
|
||||
|
||||
function registerStorage(address storageAddress) external onlyOwner {
|
||||
if (storages[nextStorageIndex] != address(0)) revert StorageAlreadyExists(storageAddress);
|
||||
WakuRln wakuRln = WakuRln(storageAddress);
|
||||
if (wakuRln.poseidonHasher() != poseidonHasher) revert IncompatibleStorage();
|
||||
if (wakuRln.contractIndex() != nextStorageIndex) revert IncompatibleStorageIndex();
|
||||
_insertIntoStorageMap(storageAddress);
|
||||
}
|
||||
|
||||
function newStorage() external onlyOwner {
|
||||
WakuRln newStorageContract = new WakuRln(address(poseidonHasher), nextStorageIndex);
|
||||
_insertIntoStorageMap(address(newStorageContract));
|
||||
}
|
||||
|
||||
function register(uint256[] calldata commitments) external payable onlyUsableStorage {
|
||||
// iteratively check if the storage contract is full, and increment the usingStorageIndex if it is
|
||||
while (true) {
|
||||
try WakuRln(storages[usingStorageIndex]).register(commitments) {
|
||||
break;
|
||||
} catch (bytes memory err) {
|
||||
if (keccak256(err) != keccak256(abi.encodeWithSignature("FullTree()"))) {
|
||||
assembly {
|
||||
revert(add(32, err), mload(err))
|
||||
}
|
||||
// when there are no further storage contracts available, revert
|
||||
} else if (usingStorageIndex + 1 >= nextStorageIndex) {
|
||||
revert NoStorageContractAvailable();
|
||||
}
|
||||
usingStorageIndex += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function register(uint16 storageIndex, uint256[] calldata commitments) external payable {
|
||||
if (storageIndex >= nextStorageIndex) revert NoStorageContractAvailable();
|
||||
WakuRln(storages[storageIndex]).register(commitments);
|
||||
}
|
||||
|
||||
function register(uint16 storageIndex, uint256 commitment) external payable {
|
||||
if (storageIndex >= nextStorageIndex) revert NoStorageContractAvailable();
|
||||
// optimize the gas used below
|
||||
uint256[] memory commitments = new uint256[](1);
|
||||
commitments[0] = commitment;
|
||||
WakuRln(storages[storageIndex]).register(commitments);
|
||||
}
|
||||
|
||||
function forceProgress() external onlyOwner onlyUsableStorage {
|
||||
usingStorageIndex += 1;
|
||||
}
|
||||
}
|
@ -10,7 +10,7 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const poseidonHasherAddress = (await deployments.get("PoseidonHasher"))
|
||||
.address;
|
||||
|
||||
await deploy("WakuRln", {
|
||||
await deploy("WakuRlnRegistry", {
|
||||
from: deployer,
|
||||
log: true,
|
||||
args: [poseidonHasherAddress],
|
||||
@ -18,5 +18,5 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
};
|
||||
|
||||
export default func;
|
||||
func.tags = ["WakuRln"];
|
||||
func.tags = ["WakuRlnRegistry"];
|
||||
func.dependencies = ["PoseidonHasher"];
|
45
deploy/003_deploy_rln.ts
Normal file
45
deploy/003_deploy_rln.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import { HardhatRuntimeEnvironment } from "hardhat/types";
|
||||
import { DeployFunction, DeploymentSubmission } from "hardhat-deploy/types";
|
||||
|
||||
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
|
||||
const { deployments, getUnnamedAccounts } = hre;
|
||||
|
||||
const [deployer] = await getUnnamedAccounts();
|
||||
|
||||
const wakuRlnRegistry = await deployments.get("WakuRlnRegistry");
|
||||
const registryContract = new hre.ethers.Contract(
|
||||
wakuRlnRegistry.address,
|
||||
wakuRlnRegistry.abi,
|
||||
hre.ethers.provider.getSigner(deployer)
|
||||
);
|
||||
|
||||
const indexOfStorageToBeDeployed = await registryContract.nextStorageIndex();
|
||||
const tx = await registryContract.newStorage();
|
||||
await tx.wait();
|
||||
|
||||
const poseidonHasherAddress = (await deployments.get("PoseidonHasher"))
|
||||
.address;
|
||||
const storageAddress = await registryContract.storages(
|
||||
indexOfStorageToBeDeployed
|
||||
);
|
||||
const extendedArtifact = await deployments.getExtendedArtifact("WakuRln");
|
||||
|
||||
console.log("Storage address: ", storageAddress);
|
||||
const d: DeploymentSubmission = {
|
||||
abi: extendedArtifact.abi,
|
||||
address: storageAddress,
|
||||
args: [poseidonHasherAddress, indexOfStorageToBeDeployed],
|
||||
bytecode: extendedArtifact.bytecode,
|
||||
deployedBytecode: extendedArtifact.deployedBytecode,
|
||||
receipt: tx,
|
||||
transactionHash: tx.hash,
|
||||
metadata: extendedArtifact.metadata,
|
||||
solcInput: extendedArtifact.solcInput,
|
||||
devdoc: extendedArtifact.devdoc,
|
||||
};
|
||||
console.log(d);
|
||||
deployments.save(`WakuRlnStorage_${indexOfStorageToBeDeployed}`, d);
|
||||
};
|
||||
|
||||
export default func;
|
||||
func.dependencies = ["WakuRlnRegistry"];
|
@ -334,6 +334,861 @@
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WakuRlnRegistry": {
|
||||
"address": "0x50D658a2ab7f66f4B73E27e8731B8b13Cd06Df8A",
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_poseidonHasher",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "string",
|
||||
"name": "reason",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"name": "FailedToRegister",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "NoStorageContractAvailable",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "storageAddress",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "StorageAlreadyExists",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "uint16",
|
||||
"name": "index",
|
||||
"type": "uint16"
|
||||
},
|
||||
{
|
||||
"indexed": false,
|
||||
"internalType": "address",
|
||||
"name": "storageAddress",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "NewStorageContract",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"type": "event"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "newStorage",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "nextStorageIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "poseidonHasher",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPoseidonHasher",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "commitment",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "register",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "storageAddress",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "registerStorage",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"name": "storages",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "usingStorageIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WakuRlnStorage_0": {
|
||||
"address": "0x02c233d3899c3A435631AC857DAD5555F4f9656C",
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_poseidonHasher",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "_contractIndex",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "DuplicateIdCommitment",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "NotImplemented",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"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": "contractIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"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": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "poseidonHasher",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPoseidonHasher",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256[]",
|
||||
"name": "idCommitments",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "register",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "idCommitment",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "register",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"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": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "stakedAmounts",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "verifier",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IVerifier",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "withdrawalBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
},
|
||||
"WakuRlnStorage_1": {
|
||||
"address": "0x662Be55E75c829A03c52CDba4Ab7dAde4e1be8a9",
|
||||
"abi": [
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "_poseidonHasher",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "_contractIndex",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "constructor"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "DuplicateIdCommitment",
|
||||
"type": "error"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "NotImplemented",
|
||||
"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"
|
||||
},
|
||||
{
|
||||
"anonymous": false,
|
||||
"inputs": [
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "previousOwner",
|
||||
"type": "address"
|
||||
},
|
||||
{
|
||||
"indexed": true,
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "OwnershipTransferred",
|
||||
"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": "contractIndex",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint16",
|
||||
"name": "",
|
||||
"type": "uint16"
|
||||
}
|
||||
],
|
||||
"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": "owner",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "poseidonHasher",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IPoseidonHasher",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256[]",
|
||||
"name": "idCommitments",
|
||||
"type": "uint256[]"
|
||||
}
|
||||
],
|
||||
"name": "register",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "idCommitment",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "register",
|
||||
"outputs": [],
|
||||
"stateMutability": "payable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "renounceOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"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": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"name": "stakedAmounts",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "newOwner",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "transferOwnership",
|
||||
"outputs": [],
|
||||
"stateMutability": "nonpayable",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "verifier",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "contract IVerifier",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [],
|
||||
"name": "withdraw",
|
||||
"outputs": [],
|
||||
"stateMutability": "pure",
|
||||
"type": "function"
|
||||
},
|
||||
{
|
||||
"inputs": [
|
||||
{
|
||||
"internalType": "address",
|
||||
"name": "",
|
||||
"type": "address"
|
||||
}
|
||||
],
|
||||
"name": "withdrawalBalance",
|
||||
"outputs": [
|
||||
{
|
||||
"internalType": "uint256",
|
||||
"name": "",
|
||||
"type": "uint256"
|
||||
}
|
||||
],
|
||||
"stateMutability": "view",
|
||||
"type": "function"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
317
deployments/sepolia/WakuRlnRegistry.json
Normal file
317
deployments/sepolia/WakuRlnRegistry.json
Normal file
File diff suppressed because one or more lines are too long
364
deployments/sepolia/WakuRlnStorage_0.json
Normal file
364
deployments/sepolia/WakuRlnStorage_0.json
Normal file
File diff suppressed because one or more lines are too long
364
deployments/sepolia/WakuRlnStorage_1.json
Normal file
364
deployments/sepolia/WakuRlnStorage_1.json
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
118
docs/index.md
118
docs/index.md
@ -8,10 +8,16 @@ error NotImplemented()
|
||||
|
||||
## WakuRln
|
||||
|
||||
### contractIndex
|
||||
|
||||
```solidity
|
||||
uint16 contractIndex
|
||||
```
|
||||
|
||||
### constructor
|
||||
|
||||
```solidity
|
||||
constructor(address _poseidonHasher) public
|
||||
constructor(address _poseidonHasher, uint16 _contractIndex) public
|
||||
```
|
||||
|
||||
### \_register
|
||||
@ -85,3 +91,113 @@ function withdraw() external pure
|
||||
```
|
||||
|
||||
Allows a user to withdraw funds allocated to them upon slashing a member
|
||||
|
||||
## StorageAlreadyExists
|
||||
|
||||
```solidity
|
||||
error StorageAlreadyExists(address storageAddress)
|
||||
```
|
||||
|
||||
## NoStorageContractAvailable
|
||||
|
||||
```solidity
|
||||
error NoStorageContractAvailable()
|
||||
```
|
||||
|
||||
## IncompatibleStorage
|
||||
|
||||
```solidity
|
||||
error IncompatibleStorage()
|
||||
```
|
||||
|
||||
## IncompatibleStorageIndex
|
||||
|
||||
```solidity
|
||||
error IncompatibleStorageIndex()
|
||||
```
|
||||
|
||||
## WakuRlnRegistry
|
||||
|
||||
### nextStorageIndex
|
||||
|
||||
```solidity
|
||||
uint16 nextStorageIndex
|
||||
```
|
||||
|
||||
### storages
|
||||
|
||||
```solidity
|
||||
mapping(uint16 => address) storages
|
||||
```
|
||||
|
||||
### usingStorageIndex
|
||||
|
||||
```solidity
|
||||
uint16 usingStorageIndex
|
||||
```
|
||||
|
||||
### poseidonHasher
|
||||
|
||||
```solidity
|
||||
contract IPoseidonHasher poseidonHasher
|
||||
```
|
||||
|
||||
### NewStorageContract
|
||||
|
||||
```solidity
|
||||
event NewStorageContract(uint16 index, address storageAddress)
|
||||
```
|
||||
|
||||
### onlyUsableStorage
|
||||
|
||||
```solidity
|
||||
modifier onlyUsableStorage()
|
||||
```
|
||||
|
||||
### constructor
|
||||
|
||||
```solidity
|
||||
constructor(address _poseidonHasher) public
|
||||
```
|
||||
|
||||
### \_insertIntoStorageMap
|
||||
|
||||
```solidity
|
||||
function _insertIntoStorageMap(address storageAddress) internal
|
||||
```
|
||||
|
||||
### registerStorage
|
||||
|
||||
```solidity
|
||||
function registerStorage(address storageAddress) external
|
||||
```
|
||||
|
||||
### newStorage
|
||||
|
||||
```solidity
|
||||
function newStorage() external
|
||||
```
|
||||
|
||||
### register
|
||||
|
||||
```solidity
|
||||
function register(uint256[] commitments) external payable
|
||||
```
|
||||
|
||||
### register
|
||||
|
||||
```solidity
|
||||
function register(uint16 storageIndex, uint256[] commitments) external payable
|
||||
```
|
||||
|
||||
### register
|
||||
|
||||
```solidity
|
||||
function register(uint16 storageIndex, uint256 commitment) external payable
|
||||
```
|
||||
|
||||
### forceProgress
|
||||
|
||||
```solidity
|
||||
function forceProgress() external
|
||||
```
|
||||
|
@ -7,4 +7,6 @@ cache_path = 'cache_forge'
|
||||
|
||||
# 5667: Unused function parameter. Remove or comment out the variable name to silence this warning.
|
||||
# 5740: Unreachable code.
|
||||
ignored_error_codes = [5667, 5740]
|
||||
ignored_error_codes = [5667, 5740]
|
||||
# setting this to allow expensive larger inserts during tests
|
||||
memory_limit = 100_000_000
|
||||
|
@ -1,23 +1,12 @@
|
||||
// SPDX-License-Identifier: Unlicense
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.15;
|
||||
|
||||
import {PoseidonHasher} from "rln-contract/PoseidonHasher.sol";
|
||||
import "../contracts/WakuRLn.sol";
|
||||
import "./utils.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;
|
||||
|
||||
@ -33,7 +22,7 @@ contract WakuRlnTest is Test {
|
||||
/// @dev Setup the testing environment.
|
||||
function setUp() public {
|
||||
poseidon = new PoseidonHasher();
|
||||
wakuRln = new WakuRln(address(poseidon));
|
||||
wakuRln = new WakuRln(address(poseidon), 0);
|
||||
}
|
||||
|
||||
/// @dev Ensure that you can hash a value.
|
||||
|
103
test/WakuRlnRegistry.t.sol
Normal file
103
test/WakuRlnRegistry.t.sol
Normal file
@ -0,0 +1,103 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.15;
|
||||
|
||||
import "../contracts/WakuRlnRegistry.sol";
|
||||
import {PoseidonHasher} from "rln-contract/PoseidonHasher.sol";
|
||||
import {DuplicateIdCommitment, FullTree} from "rln-contract/RlnBase.sol";
|
||||
import {noDuplicate} from "./utils.sol";
|
||||
import "forge-std/Test.sol";
|
||||
import "forge-std/StdCheats.sol";
|
||||
|
||||
contract WakuRlnRegistryTest is Test {
|
||||
using stdStorage for StdStorage;
|
||||
|
||||
WakuRlnRegistry public wakuRlnRegistry;
|
||||
PoseidonHasher public poseidonHasher;
|
||||
|
||||
function setUp() public {
|
||||
poseidonHasher = new PoseidonHasher();
|
||||
wakuRlnRegistry = new WakuRlnRegistry(address(poseidonHasher));
|
||||
}
|
||||
|
||||
function test__NewStorage() public {
|
||||
wakuRlnRegistry.newStorage();
|
||||
}
|
||||
|
||||
function test__RegisterStorage_BadIndex() public {
|
||||
wakuRlnRegistry.registerStorage(address(new WakuRln(address(poseidonHasher), 0)));
|
||||
address newStorage = address(new WakuRln(address(poseidonHasher), 0));
|
||||
vm.expectRevert(IncompatibleStorageIndex.selector);
|
||||
wakuRlnRegistry.registerStorage(newStorage);
|
||||
}
|
||||
|
||||
function test__RegisterStorage_BadImpl() public {
|
||||
address newStorage = address(new WakuRln(address(new PoseidonHasher()), 0));
|
||||
vm.expectRevert(IncompatibleStorage.selector);
|
||||
wakuRlnRegistry.registerStorage(newStorage);
|
||||
}
|
||||
|
||||
function test__Register(uint256[] calldata commitments) public {
|
||||
vm.assume(noDuplicate(commitments));
|
||||
wakuRlnRegistry.newStorage();
|
||||
wakuRlnRegistry.register(commitments);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration_Duplicate(uint256[] calldata commitments) public {
|
||||
vm.assume(!noDuplicate(commitments));
|
||||
wakuRlnRegistry.newStorage();
|
||||
vm.expectRevert(DuplicateIdCommitment.selector);
|
||||
wakuRlnRegistry.register(commitments);
|
||||
}
|
||||
|
||||
function test__forceProgression() public {
|
||||
wakuRlnRegistry.newStorage();
|
||||
wakuRlnRegistry.forceProgress();
|
||||
require(wakuRlnRegistry.usingStorageIndex() == 1);
|
||||
}
|
||||
|
||||
function test__SingleRegistration(uint256 commitment) public {
|
||||
wakuRlnRegistry.newStorage();
|
||||
wakuRlnRegistry.register(0, commitment);
|
||||
}
|
||||
|
||||
function test__InvalidSingleRegistration__NoStorageContract(uint256 commitment) public {
|
||||
wakuRlnRegistry.newStorage();
|
||||
vm.expectRevert(NoStorageContractAvailable.selector);
|
||||
wakuRlnRegistry.register(1, commitment);
|
||||
}
|
||||
|
||||
function test__InvalidSingleRegistration__Duplicate(uint256 commitment) public {
|
||||
wakuRlnRegistry.newStorage();
|
||||
wakuRlnRegistry.register(0, commitment);
|
||||
vm.expectRevert(DuplicateIdCommitment.selector);
|
||||
wakuRlnRegistry.register(0, commitment);
|
||||
}
|
||||
|
||||
function test__InvalidSingleRegistration__FullTree() public {
|
||||
vm.pauseGasMetering();
|
||||
wakuRlnRegistry.newStorage();
|
||||
WakuRln wakuRln = WakuRln(wakuRlnRegistry.storages(0));
|
||||
uint256 setSize = wakuRln.SET_SIZE();
|
||||
// setSize - 1 because RlnBase uses 1-indexing
|
||||
for (uint256 i = 0; i < setSize - 1; i++) {
|
||||
wakuRlnRegistry.register(0, i);
|
||||
}
|
||||
vm.resumeGasMetering();
|
||||
vm.expectRevert(FullTree.selector);
|
||||
wakuRlnRegistry.register(0, setSize);
|
||||
}
|
||||
|
||||
function test__InvalidRegistration__NoStorageContract() public {
|
||||
vm.pauseGasMetering();
|
||||
wakuRlnRegistry.newStorage();
|
||||
address storageContract = wakuRlnRegistry.storages(0);
|
||||
uint256 setSize = WakuRln(storageContract).SET_SIZE();
|
||||
|
||||
uint256[] memory commitments = new uint256[](setSize);
|
||||
for (uint256 i = 1; i < setSize; i++) {
|
||||
commitments[i] = i;
|
||||
}
|
||||
vm.expectRevert(NoStorageContractAvailable.selector);
|
||||
wakuRlnRegistry.register(commitments);
|
||||
}
|
||||
}
|
14
test/utils.sol
Normal file
14
test/utils.sol
Normal file
@ -0,0 +1,14 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.15;
|
||||
|
||||
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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user