feat(WakuRlnRegistry): uups proxy (#9)

* feat(WakuRlnRegistry): uups proxy

* feat: deployments
This commit is contained in:
Aaryamann Challani 2023-09-11 09:31:16 +05:30 committed by GitHub
parent e5eefe4891
commit 19fded82bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1188 additions and 542 deletions

3
.gitmodules vendored
View File

@ -9,3 +9,6 @@
[submodule "lib/openzeppelin-contracts"]
path = lib/openzeppelin-contracts
url = https://github.com/Openzeppelin/openzeppelin-contracts
[submodule "lib/openzeppelin-contracts-upgradeable"]
path = lib/openzeppelin-contracts-upgradeable
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable

View File

@ -3,20 +3,22 @@ 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";
import {UUPSUpgradeable} from "openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol";
import {OwnableUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/access/OwnableUpgradeable.sol";
import {ERC1967Proxy} from "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol";
error StorageAlreadyExists(address storageAddress);
error NoStorageContractAvailable();
error IncompatibleStorage();
error IncompatibleStorageIndex();
contract WakuRlnRegistry is Ownable {
contract WakuRlnRegistry is OwnableUpgradeable, UUPSUpgradeable {
uint16 public nextStorageIndex;
mapping(uint16 => address) public storages;
uint16 public usingStorageIndex = 0;
IPoseidonHasher public immutable poseidonHasher;
IPoseidonHasher public poseidonHasher;
event NewStorageContract(uint16 index, address storageAddress);
@ -25,10 +27,13 @@ contract WakuRlnRegistry is Ownable {
_;
}
constructor(address _poseidonHasher) Ownable() {
function initialize(address _poseidonHasher) external initializer {
poseidonHasher = IPoseidonHasher(_poseidonHasher);
__Ownable_init();
}
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
function _insertIntoStorageMap(address storageAddress) internal {
storages[nextStorageIndex] = storageAddress;
emit NewStorageContract(nextStorageIndex, storageAddress);

View File

@ -1,5 +1,5 @@
import { HardhatRuntimeEnvironment } from "hardhat/types";
import { DeployFunction } from "hardhat-deploy/types";
import { DeployFunction, DeploymentSubmission } from "hardhat-deploy/types";
const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const { deployments, getUnnamedAccounts } = hre;
@ -10,10 +10,21 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const poseidonHasherAddress = (await deployments.get("PoseidonHasher"))
.address;
await deploy("WakuRlnRegistry", {
const implRes = await deploy("WakuRlnRegistry_Implementation", {
contract: "WakuRlnRegistry",
from: deployer,
log: true,
args: [poseidonHasherAddress],
});
let initializeAbi = ["function initialize(address _poseidonHasher)"];
let iface = new hre.ethers.utils.Interface(initializeAbi);
const data = iface.encodeFunctionData("initialize", [poseidonHasherAddress]);
await deploy("WakuRlnRegistry_Proxy", {
contract: "ERC1967Proxy",
from: deployer,
log: true,
args: [implRes.address, data],
});
};

View File

@ -6,9 +6,12 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
const [deployer] = await getUnnamedAccounts();
const wakuRlnRegistry = await deployments.get("WakuRlnRegistry");
const proxyDeployment = await deployments.get("WakuRlnRegistry_Proxy");
const wakuRlnRegistry = await deployments.get(
"WakuRlnRegistry_Implementation"
);
const registryContract = new hre.ethers.Contract(
wakuRlnRegistry.address,
proxyDeployment.address,
wakuRlnRegistry.abi,
hre.ethers.provider.getSigner(deployer)
);
@ -43,3 +46,11 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) {
export default func;
func.dependencies = ["WakuRlnRegistry"];
func.tags = ["WakuRlnStorage"];
func.skip = async (hre: HardhatRuntimeEnvironment) => {
// skip if already deployed
const wakuRlnStorage = await hre.deployments.getOrNull("WakuRlnStorage_0");
if (wakuRlnStorage) {
return true;
}
return false;
};

View File

@ -5,7 +5,7 @@
"chainId": "11155111",
"contracts": {
"PoseidonHasher": {
"address": "0x9c1c939aCB5c356c91fF2f27E9FD29C5C95E671b",
"address": "0x6b81Eaf30b0C16A9842458A3131fBa78745907A8",
"abi": [
{
"inputs": [],
@ -41,20 +41,9 @@
}
]
},
"WakuRlnRegistry": {
"address": "0x0A988fd9CA5BAebDf098b8A73621b2AaDa6492E8",
"WakuRlnRegistry_Implementation": {
"address": "0xF1935b338321013f11068abCafC548A7B0db732C",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_poseidonHasher",
"type": "address"
}
],
"stateMutability": "nonpayable",
"type": "constructor"
},
{
"inputs": [],
"name": "IncompatibleStorage",
@ -81,6 +70,51 @@
"name": "StorageAlreadyExists",
"type": "error"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "previousAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "AdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "beacon",
"type": "address"
}
],
"name": "BeaconUpgraded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"anonymous": false,
"inputs": [
@ -119,6 +153,19 @@
"name": "OwnershipTransferred",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
}
],
"name": "Upgraded",
"type": "event"
},
{
"inputs": [],
"name": "forceProgress",
@ -126,6 +173,19 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "_poseidonHasher",
"type": "address"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [],
"name": "newStorage",
@ -172,6 +232,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "proxiableUUID",
"outputs": [
{
"internalType": "bytes32",
"name": "",
"type": "bytes32"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
@ -273,6 +346,37 @@
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newImplementation",
"type": "address"
}
],
"name": "upgradeTo",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
},
{
"inputs": [
{
"internalType": "address",
"name": "newImplementation",
"type": "address"
},
{
"internalType": "bytes",
"name": "data",
"type": "bytes"
}
],
"name": "upgradeToAndCall",
"outputs": [],
"stateMutability": "payable",
"type": "function"
},
{
"inputs": [],
"name": "usingStorageIndex",
@ -288,8 +392,82 @@
}
]
},
"WakuRlnRegistry_Proxy": {
"address": "0xF471d71E9b1455bBF4b85d475afb9BB0954A29c4",
"abi": [
{
"inputs": [
{
"internalType": "address",
"name": "_logic",
"type": "address"
},
{
"internalType": "bytes",
"name": "_data",
"type": "bytes"
}
],
"stateMutability": "payable",
"type": "constructor"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "address",
"name": "previousAdmin",
"type": "address"
},
{
"indexed": false,
"internalType": "address",
"name": "newAdmin",
"type": "address"
}
],
"name": "AdminChanged",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "beacon",
"type": "address"
}
],
"name": "BeaconUpgraded",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": true,
"internalType": "address",
"name": "implementation",
"type": "address"
}
],
"name": "Upgraded",
"type": "event"
},
{
"stateMutability": "payable",
"type": "fallback"
},
{
"stateMutability": "payable",
"type": "receive"
}
]
},
"WakuRlnStorage_0": {
"address": "0x02A29114ECDE0Da4D6DB61eAE73a86486cB88c10",
"address": "0x58322513A35a8f747AF5A385bA14C2AbE602AA59",
"abi": [
{
"inputs": [

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 one or more lines are too long

View File

@ -20,7 +20,7 @@ uint16 contractIndex
constructor(address _poseidonHasher, uint16 _contractIndex) public
```
### \_register
### _register
```solidity
function _register(uint256 idCommitment) internal
@ -30,8 +30,8 @@ Registers a member
#### Parameters
| Name | Type | Description |
| ------------ | ------- | ------------------------------ |
| Name | Type | Description |
| ---- | ---- | ----------- |
| idCommitment | uint256 | The idCommitment of the member |
### register
@ -50,8 +50,8 @@ Allows a user to register as a member
#### Parameters
| Name | Type | Description |
| ------------ | ------- | ------------------------------ |
| Name | Type | Description |
| ---- | ---- | ----------- |
| idCommitment | uint256 | The idCommitment of the member |
### slash
@ -64,13 +64,13 @@ _Allows a user to slash a member_
#### Parameters
| Name | Type | Description |
| ------------ | --------------- | ------------------------------ |
| idCommitment | uint256 | The idCommitment of the member |
| receiver | address payable | |
| proof | uint256[8] | |
| Name | Type | Description |
| ---- | ---- | ----------- |
| idCommitment | uint256 | The idCommitment of the member |
| receiver | address payable | |
| proof | uint256[8] | |
### \_validateRegistration
### _validateRegistration
```solidity
function _validateRegistration(uint256 idCommitment) internal view
@ -78,7 +78,7 @@ function _validateRegistration(uint256 idCommitment) internal view
_Inheriting contracts MUST override this function_
### \_validateSlash
### _validateSlash
```solidity
function _validateSlash(uint256 idCommitment, address payable receiver, uint256[8] proof) internal pure
@ -154,13 +154,28 @@ event NewStorageContract(uint16 index, address storageAddress)
modifier onlyUsableStorage()
```
### constructor
### initialize
```solidity
constructor(address _poseidonHasher) public
function initialize(address _poseidonHasher) external
```
### \_insertIntoStorageMap
### _authorizeUpgrade
```solidity
function _authorizeUpgrade(address newImplementation) internal
```
_Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
{upgradeTo} and {upgradeToAndCall}.
Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
```solidity
function _authorizeUpgrade(address) internal override onlyOwner {}
```_
### _insertIntoStorageMap
```solidity
function _insertIntoStorageMap(address storageAddress) internal
@ -201,3 +216,4 @@ function register(uint16 storageIndex, uint256 commitment) external
```solidity
function forceProgress() external
```

@ -0,0 +1 @@
Subproject commit 3d4c0d5741b131c231e558d7a6213392ab3672a5

View File

@ -36,9 +36,9 @@
"hardhat-gas-reporter": "^1.0.8",
"husky": "^8.0.2",
"lint-staged": "^13.0.3",
"solidity-docgen": "0.6.0-beta.35",
"ts-node": "^10.8.1",
"typescript": "^4.7.4",
"solidity-docgen": "0.6.0-beta.35"
"typescript": "^4.7.4"
},
"dependencies": {
"dotenv": "^16.0.1"

View File

@ -1,10 +1,11 @@
@ensdomains/=node_modules/@ensdomains/
ds-test/=lib/forge-std/lib/ds-test/src/
erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/
erc4626-tests/=lib/openzeppelin-contracts-upgradeable/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-upgradeable/=lib/openzeppelin-contracts-upgradeable/
openzeppelin-contracts/=lib/openzeppelin-contracts/
openzeppelin/=lib/openzeppelin-contracts/contracts/
openzeppelin/=lib/openzeppelin-contracts-upgradeable/contracts/
rln-contract/=lib/rln-contract/contracts/

View File

@ -4,6 +4,8 @@ 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 {ERC1967Proxy} from "openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import {noDuplicate, noInvalidCommitment, isValidCommitment} from "./utils.sol";
import "forge-std/Test.sol";
import "forge-std/StdCheats.sol";
@ -16,7 +18,10 @@ contract WakuRlnRegistryTest is Test {
function setUp() public {
poseidonHasher = new PoseidonHasher();
wakuRlnRegistry = new WakuRlnRegistry(address(poseidonHasher));
address implementation = address(new WakuRlnRegistry());
bytes memory data = abi.encodeCall(WakuRlnRegistry.initialize, address(poseidonHasher));
address proxy = address(new ERC1967Proxy(implementation, data));
wakuRlnRegistry = WakuRlnRegistry(proxy);
}
function test__NewStorage() public {

View File

@ -7,8 +7,13 @@ describe("WakuRlnRegistry", () => {
});
it("should register new memberships", async () => {
const rlnRegistry = await ethers.getContract(
"WakuRlnRegistry",
const registryDeployment = await deployments.get("WakuRlnRegistry_Proxy");
const implDeployment = await deployments.get(
"WakuRlnRegistry_Implementation"
);
const rlnRegistry = new ethers.Contract(
registryDeployment.address,
implDeployment.abi,
ethers.provider.getSigner(0)
);
const rlnStorage = await ethers.getContract(