add minimal implementation of freeRegistrationAddress

This commit is contained in:
Václav Pavlín 2025-09-16 15:34:08 +02:00
parent b4508dd0d4
commit 22ecf905e6
No known key found for this signature in database
GPG Key ID: B378FB31BB6D89A5
5 changed files with 49 additions and 15 deletions

View File

@ -34,10 +34,12 @@
"gas-report": "forge test --gas-report 2>&1 | (tee /dev/tty | awk '/Test result:/ {found=1; buffer=\"\"; next} found && !/Ran/ {buffer=buffer $0 ORS} /Ran/ {found=0} END {printf \"%s\", buffer}' > .gas-report)",
"release": "commit-and-tag-version",
"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: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:sepolia:price_calculator": "export RPC_URL=https://ethereum-sepolia-public.nodies.app && ./envCheck.sh && FOUNDRY_PROFILE=sepolia forge script --chain 11155111 script/Deploy.s.sol:DeployPriceCalculator --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
"deploy:sepolia:wakurln_impl_v2": "export RPC_URL=https://ethereum-sepolia-public.nodies.app && ./envCheck.sh && FOUNDRY_PROFILE=sepolia forge script --chain 11155111 script/Deploy.s.sol:DeployWakuRlnV2 --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
"deploy:sepolia:proxy": "export RPC_URL=https://ethereum-sepolia-public.nodies.app && ./envCheck.sh && FOUNDRY_PROFILE=linea_sepolia forge script --chain 11155111 script/Deploy.s.sol:DeployProxy --rpc-url $RPC_URL --broadcast --verify -vv --account $ACCOUNT --legacy --sender $ETH_FROM",
"deploy:sepolia": "npm run deploy:sepolia:price_calculator && npm run deploy:sepolia:wakurln_impl_v2 && npm run deploy:sepolia:proxy",
"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: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: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",

View File

@ -55,6 +55,7 @@ contract DeployProxy is BaseScript {
function run() public broadcast returns (address) {
address priceCalcAddr;
address wakuRlnV2ImplAddr;
address freeRegistrationAddress;
try vm.envAddress("PRICE_CALCULATOR_ADDRESS") returns (address envPriceCalcAddress) {
console.log("Loading price calculator address from environment variable");
@ -72,13 +73,22 @@ contract DeployProxy is BaseScript {
wakuRlnV2ImplAddr = DevOpsTools.get_most_recent_deployment("WakuRlnV2", block.chainid);
}
try vm.envAddress("FREE_REGISTRATION_ADDRESS") returns (address envFreeRegistrationAddress) {
console.log("Loading free registration address from environment variable");
freeRegistrationAddress = envFreeRegistrationAddress;
} catch {
console.log("Loading free registration address from broadcast directory");
freeRegistrationAddress = DevOpsTools.get_most_recent_deployment("FreeRegistration", block.chainid);
}
console.log("Using free registration address: %s", freeRegistrationAddress);
console.log("Using price calculator address: %s", priceCalcAddr);
console.log("Using WakuRLNV2 address: %s", wakuRlnV2ImplAddr);
return address(deploy(priceCalcAddr, wakuRlnV2ImplAddr));
return address(deploy(priceCalcAddr, wakuRlnV2ImplAddr, freeRegistrationAddress));
}
function deploy(address _priceCalcAddr, address _wakuRlnV2ImplAddr) public returns (ERC1967Proxy) {
function deploy(address _priceCalcAddr, address _wakuRlnV2ImplAddr, address _freeRegistrationAddress) public returns (ERC1967Proxy) {
bytes memory data = abi.encodeCall(
WakuRlnV2.initialize,
(
@ -87,7 +97,8 @@ contract DeployProxy is BaseScript {
MIN_RATELIMIT_PER_MEMBERSHIP,
MAX_RATELIMIT_PER_MEMBERSHIP,
ACTIVE_DURATION,
GRACE_PERIOD_DURATION
GRACE_PERIOD_DURATION,
_freeRegistrationAddress
)
);
return new ERC1967Proxy(_wakuRlnV2ImplAddr, data);

View File

@ -65,6 +65,9 @@ abstract contract MembershipUpgradeable is Initializable {
/// @notice Indices of erased memberships that can be reused for new registrations
uint32[] public indicesOfLazilyErasedMemberships;
/// @notice Address which is allowed to register for free
address public freeRegistrationAddress;
struct MembershipInfo {
/// @notice the deposit amount (in tokens) to register this membership
uint256 depositAmount;
@ -124,7 +127,8 @@ abstract contract MembershipUpgradeable is Initializable {
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _activeDurationForNewMemberships,
uint32 _gracePeriodDurationForNewMemberships
uint32 _gracePeriodDurationForNewMemberships,
address _freeRegistrationAddress
)
internal
onlyInitializing
@ -135,7 +139,8 @@ abstract contract MembershipUpgradeable is Initializable {
_minMembershipRateLimit,
_maxMembershipRateLimit,
_activeDurationForNewMemberships,
_gracePeriodDurationForNewMemberships
_gracePeriodDurationForNewMemberships,
_freeRegistrationAddress
);
}
@ -145,7 +150,8 @@ abstract contract MembershipUpgradeable is Initializable {
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _activeDurationForNewMemberships,
uint32 _gracePeriodDurationForNewMemberships
uint32 _gracePeriodDurationForNewMemberships,
address _freeRegistrationAddress
)
internal
onlyInitializing
@ -161,6 +167,7 @@ abstract contract MembershipUpgradeable is Initializable {
maxMembershipRateLimit = _maxMembershipRateLimit;
activeDurationForNewMemberships = _activeDurationForNewMemberships;
gracePeriodDurationForNewMemberships = _gracePeriodDurationForNewMemberships;
freeRegistrationAddress = _freeRegistrationAddress;
}
/// @dev acquire a membership and transfer the deposit to the contract
@ -189,7 +196,11 @@ abstract contract MembershipUpgradeable is Initializable {
revert CannotExceedMaxTotalRateLimit();
}
(address token, uint256 depositAmount) = priceCalculator.calculate(_rateLimit);
(address token, uint256 depositAmount) = (address(0), 0);
if (priceCalculator != IPriceCalculator(address(0)) && _sender != address(freeRegistrationAddress)) {
(token, depositAmount) = priceCalculator.calculate(_rateLimit);
}
// Possibly reuse an index of an erased membership
(index, indexReused) = _getFreeIndex();
@ -205,7 +216,9 @@ abstract contract MembershipUpgradeable is Initializable {
index: index
});
IERC20(token).safeTransferFrom(_sender, address(this), depositAmount);
if (priceCalculator != IPriceCalculator(address(0)) && _sender != address(freeRegistrationAddress)) {
IERC20(token).safeTransferFrom(_sender, address(this), depositAmount);
}
}
/// @notice Checks if a rate limit is within the allowed bounds

View File

@ -74,7 +74,8 @@ contract WakuRlnV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable, Member
uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit,
uint32 _activeDuration,
uint32 _gracePeriod
uint32 _gracePeriod,
address _freeRegistrationAddress
)
public
initializer
@ -87,7 +88,8 @@ contract WakuRlnV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable, Member
_minMembershipRateLimit,
_maxMembershipRateLimit,
_activeDuration,
_gracePeriod
_gracePeriod,
_freeRegistrationAddress
);
MAX_MEMBERSHIP_SET_SIZE = uint32(1 << MERKLE_TREE_DEPTH);
@ -305,4 +307,10 @@ contract WakuRlnV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable, Member
// Note: grace period duration may be equal to zero
gracePeriodDurationForNewMemberships = _gracePeriodDurationForNewMembership;
}
/// @notice Set the address that can register for free (e.g. ZKPassport Verifier wrapper address)
/// @param _freeRegistrationAddress new free registration address
function setFreeRegistrationAddress(address _freeRegistrationAddress) external onlyOwner {
freeRegistrationAddress = _freeRegistrationAddress;
}
}

View File

@ -32,7 +32,7 @@ contract WakuRlnV2Test is Test {
IPriceCalculator priceCalculator = (new DeployPriceCalculator()).deploy(address(token));
WakuRlnV2 wakuRlnV2 = (new DeployWakuRlnV2()).deploy();
ERC1967Proxy proxy = (new DeployProxy()).deploy(address(priceCalculator), address(wakuRlnV2));
ERC1967Proxy proxy = (new DeployProxy()).deploy(address(priceCalculator), address(wakuRlnV2), address(0));
w = WakuRlnV2(address(proxy));
@ -773,7 +773,7 @@ contract WakuRlnV2Test is Test {
function test__Upgrade() external {
address testImpl = address(new WakuRlnV2());
bytes memory data = abi.encodeCall(WakuRlnV2.initialize, (address(0), 100, 1, 10, 10 minutes, 4 minutes));
bytes memory data = abi.encodeCall(WakuRlnV2.initialize, (address(0), 100, 1, 10, 10 minutes, 4 minutes, address(0)));
address proxy = address(new ERC1967Proxy(testImpl, data));
address newImpl = address(new WakuRlnV2());