mirror of
https://github.com/logos-messaging/logos-messaging-rlnv2-contract.git
synced 2026-01-02 14:03:07 +00:00
feat: deploy to Linea (#18)
This commit is contained in:
parent
cbd56ed0f4
commit
e46ce5aa1c
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -9,3 +9,6 @@
|
|||||||
[submodule "lib/openzeppelin-contracts-upgradeable"]
|
[submodule "lib/openzeppelin-contracts-upgradeable"]
|
||||||
path = lib/openzeppelin-contracts-upgradeable
|
path = lib/openzeppelin-contracts-upgradeable
|
||||||
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
|
url = https://github.com/OpenZeppelin/openzeppelin-contracts-upgradeable
|
||||||
|
[submodule "lib/foundry-devops"]
|
||||||
|
path = lib/foundry-devops
|
||||||
|
url = https://github.com/Cyfrin/foundry-devops
|
||||||
|
|||||||
27
README.md
27
README.md
@ -139,17 +139,30 @@ $ forge test
|
|||||||
|
|
||||||
## Owner privileges
|
## Owner privileges
|
||||||
|
|
||||||
The contract implementation aims to follow the [specification](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md) that also describes ownership (see [Governance and upgradability](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md#governance-and-upgradability) section).
|
The contract implementation aims to follow the
|
||||||
|
[specification](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md)
|
||||||
|
that also describes ownership (see
|
||||||
|
[Governance and upgradability](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md#governance-and-upgradability)
|
||||||
|
section).
|
||||||
|
|
||||||
As of commit afb858, the `Owner` privileges are assigned to the `msg.sender` of the membership registration transaction.
|
As of commit afb858, the `Owner` privileges are assigned to the `msg.sender` of the membership registration transaction.
|
||||||
The `Owner` has the following privileges:
|
The `Owner` has the following privileges:
|
||||||
|
|
||||||
- set the token and price of one message published per epoch ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/LinearPriceCalculator.sol#L25));
|
- set the token and price of one message published per epoch
|
||||||
- authorize upgrades to a new implementation contract ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L99));
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/LinearPriceCalculator.sol#L25));
|
||||||
- set the price calculator contract address ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L267));
|
- authorize upgrades to a new implementation contract
|
||||||
- set the maximum total rate limit of all memberships in the membership set ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L273));
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L99));
|
||||||
- set the minimum ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L287)) and maximum ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L280)) rate limit of one membership;
|
- set the price calculator contract address
|
||||||
- set the duration of the active period ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L295)) and grace period ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L302)) of new memberships (see the [state transition diagram of a membership](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md#membership-lifecycle)).
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L267));
|
||||||
|
- set the maximum total rate limit of all memberships in the membership set
|
||||||
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L273));
|
||||||
|
- set the minimum ([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L287)) and maximum
|
||||||
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L280)) rate limit of one
|
||||||
|
membership;
|
||||||
|
- set the duration of the active period
|
||||||
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L295)) and grace period
|
||||||
|
([link](https://github.com/waku-org/waku-rlnv2-contract/blob/main/src/WakuRlnV2.sol#L302)) of new memberships (see the
|
||||||
|
[state transition diagram of a membership](https://github.com/waku-org/specs/blob/81b9fd588bff39894608746774b0903b067b5cdf/standards/core/rln-contract.md#membership-lifecycle)).
|
||||||
|
|
||||||
The pause functionality for contract functions is not yet implemented.
|
The pause functionality for contract functions is not yet implemented.
|
||||||
|
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
solc = "0.8.24"
|
solc = "0.8.24"
|
||||||
src = "src"
|
src = "src"
|
||||||
test = "test"
|
test = "test"
|
||||||
|
fs_permissions = [{ access = "read", path = "./broadcast" }]
|
||||||
|
|
||||||
[fuzz]
|
[fuzz]
|
||||||
max_test_rejects = 128_000
|
max_test_rejects = 128_000
|
||||||
|
|||||||
1
lib/foundry-devops
vendored
Submodule
1
lib/foundry-devops
vendored
Submodule
@ -0,0 +1 @@
|
|||||||
|
Subproject commit 47393d0a85ad9f6aa127ba2aed2bf9a7a7488bcf
|
||||||
10
package.json
10
package.json
@ -36,7 +36,13 @@
|
|||||||
"adorno": "pnpm prettier:write && forge fmt && forge snapshot && pnpm gas-report",
|
"adorno": "pnpm prettier:write && forge fmt && forge snapshot && pnpm gas-report",
|
||||||
"deploy:sepolia": "./envCheck.sh && FOUNDRY_PROFILE=sepolia forge script --chain sepolia script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
"deploy:sepolia": "./envCheck.sh && FOUNDRY_PROFILE=sepolia forge script --chain sepolia script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||||
"deploy:cardona": "export RPC_URL=https://rpc.cardona.zkevm-rpc.com && ./envCheck.sh && FOUNDRY_PROFILE=cardona forge script --chain 2442 script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
"deploy:cardona": "export RPC_URL=https://rpc.cardona.zkevm-rpc.com && ./envCheck.sh && FOUNDRY_PROFILE=cardona forge script --chain 2442 script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||||
"deploy:linea_sepolia": "export RPC_URL=https://rpc.sepolia.linea.build && ./envCheck.sh && FOUNDRY_PROFILE=linea_sepolia forge script --chain 59141 script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
"deploy:localhost:price_calculator": "./envCheck.sh && forge script script/Deploy.s.sol:DeployPriceCalculator --rpc-url $RPC_URL --broadcast -vv --sender $ETH_FROM --account $ACCOUNT",
|
||||||
"deploy:localhost": "./envCheck.sh && forge script script/Deploy.s.sol:Deploy --rpc-url $RPC_URL --broadcast -vv --account $ACCOUNT --sender $ETH_FROM"
|
"deploy:localhost:wakurln_impl_v2": "./envCheck.sh && forge script script/Deploy.s.sol:DeployWakuRlnV2 --rpc-url $RPC_URL --broadcast -vv --sender $ETH_FROM --account $ACCOUNT",
|
||||||
|
"deploy:localhost:proxy": "./envCheck.sh && forge script script/Deploy.s.sol:DeployProxy --rpc-url $RPC_URL --broadcast -vv --sender $ETH_FROM --account $ACCOUNT",
|
||||||
|
"deploy:localhost": "npm run deploy:localhost:price_calculator && npm run deploy:localhost:wakurln_impl_v2 && npm run deploy:localhost:proxy",
|
||||||
|
"deploy:linea_sepolia:price_calculator": "export RPC_URL=https://rpc.sepolia.linea.build && ./envCheck.sh && FOUNDRY_PROFILE=linea_sepolia forge script --chain 59141 script/Deploy.s.sol:DeployPriceCalculator --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||||
|
"deploy:linea_sepolia:wakurln_impl_v2": "export RPC_URL=https://rpc.sepolia.linea.build && ./envCheck.sh && FOUNDRY_PROFILE=linea_sepolia forge script --chain 59141 script/Deploy.s.sol:DeployWakuRlnV2 --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||||
|
"deploy:linea_sepolia:proxy": "export RPC_URL=https://rpc.sepolia.linea.build && ./envCheck.sh && FOUNDRY_PROFILE=linea_sepolia forge script --chain 59141 script/Deploy.s.sol:DeployProxy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
|
||||||
|
"deploy:linea_sepolia": "npm run deploy:linea_sepolia:price_calculator && npm run deploy:linea_sepolia:wakurln_impl_v2 && npm run deploy:linea_sepolia:proxy"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,25 +2,24 @@
|
|||||||
pragma solidity >=0.8.19 <=0.9.0;
|
pragma solidity >=0.8.19 <=0.9.0;
|
||||||
|
|
||||||
import { WakuRlnV2 } from "../src/WakuRlnV2.sol";
|
import { WakuRlnV2 } from "../src/WakuRlnV2.sol";
|
||||||
|
import { IPriceCalculator } from "../src/IPriceCalculator.sol";
|
||||||
import { LinearPriceCalculator } from "../src/LinearPriceCalculator.sol";
|
import { LinearPriceCalculator } from "../src/LinearPriceCalculator.sol";
|
||||||
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
import { PoseidonT3 } from "poseidon-solidity/PoseidonT3.sol";
|
||||||
import { LazyIMT } from "@zk-kit/imt.sol/LazyIMT.sol";
|
import { LazyIMT } from "@zk-kit/imt.sol/LazyIMT.sol";
|
||||||
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
||||||
|
import { DevOpsTools } from "lib/foundry-devops/src/DevOpsTools.sol";
|
||||||
import { BaseScript } from "./Base.s.sol";
|
import { BaseScript } from "./Base.s.sol";
|
||||||
|
import "forge-std/console.sol";
|
||||||
|
|
||||||
contract Deploy is BaseScript {
|
contract DeployPriceCalculator is BaseScript {
|
||||||
function run() public broadcast returns (WakuRlnV2 w, address impl) {
|
function run() public broadcast returns (address) {
|
||||||
address _token = _getTokenAddress();
|
address _token = _getTokenAddress();
|
||||||
return deploy(_token);
|
return address(deploy(_token));
|
||||||
}
|
}
|
||||||
|
|
||||||
function deploy(address _token) public returns (WakuRlnV2 w, address impl) {
|
function deploy(address _token) public returns (IPriceCalculator) {
|
||||||
address priceCalcAddr = address(new LinearPriceCalculator(_token, 0.05 ether));
|
LinearPriceCalculator priceCalculator = new LinearPriceCalculator(_token, 0.05 ether);
|
||||||
impl = address(new WakuRlnV2());
|
return IPriceCalculator(priceCalculator);
|
||||||
bytes memory data = abi.encodeCall(WakuRlnV2.initialize, (priceCalcAddr, 160_000, 20, 600, 180 days, 30 days));
|
|
||||||
address proxy = address(new ERC1967Proxy(impl, data));
|
|
||||||
w = WakuRlnV2(proxy);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _getTokenAddress() internal view returns (address) {
|
function _getTokenAddress() internal view returns (address) {
|
||||||
@ -36,6 +35,65 @@ contract Deploy is BaseScript {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
contract DeployWakuRlnV2 is BaseScript {
|
||||||
|
function run() public broadcast returns (address) {
|
||||||
|
return address(deploy());
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy() public returns (WakuRlnV2) {
|
||||||
|
return new WakuRlnV2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract DeployProxy is BaseScript {
|
||||||
|
uint32 public constant MAX_TOTAL_RATELIMIT_PER_EPOCH = 160_000;
|
||||||
|
uint32 public constant MIN_RATELIMIT_PER_MEMBERSHIP = 20;
|
||||||
|
uint32 public constant MAX_RATELIMIT_PER_MEMBERSHIP = 600;
|
||||||
|
uint32 public constant ACTIVE_DURATION = 180 days;
|
||||||
|
uint32 public constant GRACE_PERIOD_DURATION = 30 days;
|
||||||
|
|
||||||
|
function run() public broadcast returns (address) {
|
||||||
|
address priceCalcAddr;
|
||||||
|
address wakuRlnV2ImplAddr;
|
||||||
|
|
||||||
|
try vm.envAddress("PRICE_CALCULATOR_ADDRESS") returns (address envPriceCalcAddress) {
|
||||||
|
console.log("Loading price calculator address from environment variable");
|
||||||
|
priceCalcAddr = envPriceCalcAddress;
|
||||||
|
} catch {
|
||||||
|
console.log("Loading price calculator address from broadcast directory");
|
||||||
|
priceCalcAddr = DevOpsTools.get_most_recent_deployment("LinearPriceCalculator", block.chainid);
|
||||||
|
}
|
||||||
|
|
||||||
|
try vm.envAddress("WAKURLNV2_ADDRESS") returns (address envWakuRlnV2ImplAddr) {
|
||||||
|
console.log("Loading WakuRlnV2 address from environment variable");
|
||||||
|
wakuRlnV2ImplAddr = envWakuRlnV2ImplAddr;
|
||||||
|
} catch {
|
||||||
|
console.log("Loading WakuRlnV2 address from broadcast directory");
|
||||||
|
wakuRlnV2ImplAddr = DevOpsTools.get_most_recent_deployment("WakuRlnV2", block.chainid);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Using price calculator address: %s", priceCalcAddr);
|
||||||
|
console.log("Using WakuRLNV2 address: %s", wakuRlnV2ImplAddr);
|
||||||
|
|
||||||
|
return address(deploy(priceCalcAddr, wakuRlnV2ImplAddr));
|
||||||
|
}
|
||||||
|
|
||||||
|
function deploy(address _priceCalcAddr, address _wakuRlnV2ImplAddr) public returns (ERC1967Proxy) {
|
||||||
|
bytes memory data = abi.encodeCall(
|
||||||
|
WakuRlnV2.initialize,
|
||||||
|
(
|
||||||
|
_priceCalcAddr,
|
||||||
|
MAX_TOTAL_RATELIMIT_PER_EPOCH,
|
||||||
|
MIN_RATELIMIT_PER_MEMBERSHIP,
|
||||||
|
MAX_RATELIMIT_PER_MEMBERSHIP,
|
||||||
|
ACTIVE_DURATION,
|
||||||
|
GRACE_PERIOD_DURATION
|
||||||
|
)
|
||||||
|
);
|
||||||
|
return new ERC1967Proxy(_wakuRlnV2ImplAddr, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
contract DeployLibs is BaseScript {
|
contract DeployLibs is BaseScript {
|
||||||
function run() public broadcast returns (address poseidonT3, address lazyImt) {
|
function run() public broadcast returns (address poseidonT3, address lazyImt) {
|
||||||
bytes memory poseidonT3Bytecode = type(PoseidonT3).creationCode;
|
bytes memory poseidonT3Bytecode = type(PoseidonT3).creationCode;
|
||||||
|
|||||||
@ -150,7 +150,6 @@ abstract contract MembershipUpgradeable is Initializable {
|
|||||||
internal
|
internal
|
||||||
onlyInitializing
|
onlyInitializing
|
||||||
{
|
{
|
||||||
require(0 < _minMembershipRateLimit);
|
|
||||||
require(_minMembershipRateLimit <= _maxMembershipRateLimit);
|
require(_minMembershipRateLimit <= _maxMembershipRateLimit);
|
||||||
require(_maxMembershipRateLimit <= _maxTotalRateLimit);
|
require(_maxMembershipRateLimit <= _maxTotalRateLimit);
|
||||||
require(_activeDurationForNewMemberships > 0);
|
require(_activeDurationForNewMemberships > 0);
|
||||||
|
|||||||
@ -2,8 +2,7 @@
|
|||||||
pragma solidity >=0.8.19 <0.9.0;
|
pragma solidity >=0.8.19 <0.9.0;
|
||||||
|
|
||||||
import { Test } from "forge-std/Test.sol";
|
import { Test } from "forge-std/Test.sol";
|
||||||
import { Deploy } from "../script/Deploy.s.sol";
|
import { DeployPriceCalculator, DeployWakuRlnV2, DeployProxy } from "../script/Deploy.s.sol";
|
||||||
import { DeploymentConfig } from "../script/DeploymentConfig.s.sol";
|
|
||||||
import "../src/WakuRlnV2.sol"; // solhint-disable-line
|
import "../src/WakuRlnV2.sol"; // solhint-disable-line
|
||||||
import "../src/Membership.sol"; // solhint-disable-line
|
import "../src/Membership.sol"; // solhint-disable-line
|
||||||
import { IPriceCalculator } from "../src/IPriceCalculator.sol";
|
import { IPriceCalculator } from "../src/IPriceCalculator.sol";
|
||||||
@ -16,19 +15,19 @@ import "forge-std/console.sol";
|
|||||||
|
|
||||||
contract WakuRlnV2Test is Test {
|
contract WakuRlnV2Test is Test {
|
||||||
WakuRlnV2 internal w;
|
WakuRlnV2 internal w;
|
||||||
address internal impl;
|
|
||||||
DeploymentConfig internal deploymentConfig;
|
|
||||||
TestToken internal token;
|
TestToken internal token;
|
||||||
|
|
||||||
address internal deployer;
|
address internal deployer;
|
||||||
|
|
||||||
uint256[] noIdCommitmentsToErase = new uint256[](0);
|
uint256[] internal noIdCommitmentsToErase = new uint256[](0);
|
||||||
|
|
||||||
function setUp() public virtual {
|
function setUp() public virtual {
|
||||||
token = new TestToken();
|
token = new TestToken();
|
||||||
|
IPriceCalculator priceCalculator = (new DeployPriceCalculator()).deploy(address(token));
|
||||||
|
WakuRlnV2 wakuRlnV2 = (new DeployWakuRlnV2()).deploy();
|
||||||
|
ERC1967Proxy proxy = (new DeployProxy()).deploy(address(priceCalculator), address(wakuRlnV2));
|
||||||
|
|
||||||
Deploy deployment = new Deploy();
|
w = WakuRlnV2(address(proxy));
|
||||||
(w, impl) = deployment.deploy(address(token));
|
|
||||||
|
|
||||||
// Minting a large number of tokens to not have to worry about
|
// Minting a large number of tokens to not have to worry about
|
||||||
// Not having enough balance
|
// Not having enough balance
|
||||||
@ -61,8 +60,11 @@ contract WakuRlnV2Test is Test {
|
|||||||
w.root(),
|
w.root(),
|
||||||
13_801_897_483_540_040_307_162_267_952_866_411_686_127_372_014_953_358_983_481_592_640_000_001_877_295
|
13_801_897_483_540_040_307_162_267_952_866_411_686_127_372_014_953_358_983_481_592_640_000_001_877_295
|
||||||
);
|
);
|
||||||
(uint32 membershipRateLimit2, uint32 index2, uint256 rateCommitment2) = w.getMembershipInfo(idCommitment);
|
uint32 fetchedMembershipRateLimit2;
|
||||||
assertEq(membershipRateLimit2, membershipRateLimit);
|
uint32 index2;
|
||||||
|
uint256 rateCommitment2;
|
||||||
|
(fetchedMembershipRateLimit2, index2, rateCommitment2) = w.getMembershipInfo(idCommitment);
|
||||||
|
assertEq(fetchedMembershipRateLimit2, membershipRateLimit);
|
||||||
assertEq(index2, 0);
|
assertEq(index2, 0);
|
||||||
assertEq(rateCommitment2, rateCommitment);
|
assertEq(rateCommitment2, rateCommitment);
|
||||||
uint256[20] memory proof = w.getMerkleProof(0);
|
uint256[20] memory proof = w.getMerkleProof(0);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user