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)", "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", "release": "commit-and-tag-version",
"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: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: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: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: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: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: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: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) { function run() public broadcast returns (address) {
address priceCalcAddr; address priceCalcAddr;
address wakuRlnV2ImplAddr; address wakuRlnV2ImplAddr;
address freeRegistrationAddress;
try vm.envAddress("PRICE_CALCULATOR_ADDRESS") returns (address envPriceCalcAddress) { try vm.envAddress("PRICE_CALCULATOR_ADDRESS") returns (address envPriceCalcAddress) {
console.log("Loading price calculator address from environment variable"); 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); 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 price calculator address: %s", priceCalcAddr);
console.log("Using WakuRLNV2 address: %s", wakuRlnV2ImplAddr); 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( bytes memory data = abi.encodeCall(
WakuRlnV2.initialize, WakuRlnV2.initialize,
( (
@ -87,7 +97,8 @@ contract DeployProxy is BaseScript {
MIN_RATELIMIT_PER_MEMBERSHIP, MIN_RATELIMIT_PER_MEMBERSHIP,
MAX_RATELIMIT_PER_MEMBERSHIP, MAX_RATELIMIT_PER_MEMBERSHIP,
ACTIVE_DURATION, ACTIVE_DURATION,
GRACE_PERIOD_DURATION GRACE_PERIOD_DURATION,
_freeRegistrationAddress
) )
); );
return new ERC1967Proxy(_wakuRlnV2ImplAddr, data); 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 /// @notice Indices of erased memberships that can be reused for new registrations
uint32[] public indicesOfLazilyErasedMemberships; uint32[] public indicesOfLazilyErasedMemberships;
/// @notice Address which is allowed to register for free
address public freeRegistrationAddress;
struct MembershipInfo { struct MembershipInfo {
/// @notice the deposit amount (in tokens) to register this membership /// @notice the deposit amount (in tokens) to register this membership
uint256 depositAmount; uint256 depositAmount;
@ -124,7 +127,8 @@ abstract contract MembershipUpgradeable is Initializable {
uint32 _minMembershipRateLimit, uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit, uint32 _maxMembershipRateLimit,
uint32 _activeDurationForNewMemberships, uint32 _activeDurationForNewMemberships,
uint32 _gracePeriodDurationForNewMemberships uint32 _gracePeriodDurationForNewMemberships,
address _freeRegistrationAddress
) )
internal internal
onlyInitializing onlyInitializing
@ -135,7 +139,8 @@ abstract contract MembershipUpgradeable is Initializable {
_minMembershipRateLimit, _minMembershipRateLimit,
_maxMembershipRateLimit, _maxMembershipRateLimit,
_activeDurationForNewMemberships, _activeDurationForNewMemberships,
_gracePeriodDurationForNewMemberships _gracePeriodDurationForNewMemberships,
_freeRegistrationAddress
); );
} }
@ -145,7 +150,8 @@ abstract contract MembershipUpgradeable is Initializable {
uint32 _minMembershipRateLimit, uint32 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit, uint32 _maxMembershipRateLimit,
uint32 _activeDurationForNewMemberships, uint32 _activeDurationForNewMemberships,
uint32 _gracePeriodDurationForNewMemberships uint32 _gracePeriodDurationForNewMemberships,
address _freeRegistrationAddress
) )
internal internal
onlyInitializing onlyInitializing
@ -161,6 +167,7 @@ abstract contract MembershipUpgradeable is Initializable {
maxMembershipRateLimit = _maxMembershipRateLimit; maxMembershipRateLimit = _maxMembershipRateLimit;
activeDurationForNewMemberships = _activeDurationForNewMemberships; activeDurationForNewMemberships = _activeDurationForNewMemberships;
gracePeriodDurationForNewMemberships = _gracePeriodDurationForNewMemberships; gracePeriodDurationForNewMemberships = _gracePeriodDurationForNewMemberships;
freeRegistrationAddress = _freeRegistrationAddress;
} }
/// @dev acquire a membership and transfer the deposit to the contract /// @dev acquire a membership and transfer the deposit to the contract
@ -189,7 +196,11 @@ abstract contract MembershipUpgradeable is Initializable {
revert CannotExceedMaxTotalRateLimit(); 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 // Possibly reuse an index of an erased membership
(index, indexReused) = _getFreeIndex(); (index, indexReused) = _getFreeIndex();
@ -205,7 +216,9 @@ abstract contract MembershipUpgradeable is Initializable {
index: index 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 /// @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 _minMembershipRateLimit,
uint32 _maxMembershipRateLimit, uint32 _maxMembershipRateLimit,
uint32 _activeDuration, uint32 _activeDuration,
uint32 _gracePeriod uint32 _gracePeriod,
address _freeRegistrationAddress
) )
public public
initializer initializer
@ -87,7 +88,8 @@ contract WakuRlnV2 is Initializable, OwnableUpgradeable, UUPSUpgradeable, Member
_minMembershipRateLimit, _minMembershipRateLimit,
_maxMembershipRateLimit, _maxMembershipRateLimit,
_activeDuration, _activeDuration,
_gracePeriod _gracePeriod,
_freeRegistrationAddress
); );
MAX_MEMBERSHIP_SET_SIZE = uint32(1 << MERKLE_TREE_DEPTH); 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 // Note: grace period duration may be equal to zero
gracePeriodDurationForNewMemberships = _gracePeriodDurationForNewMembership; 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)); IPriceCalculator priceCalculator = (new DeployPriceCalculator()).deploy(address(token));
WakuRlnV2 wakuRlnV2 = (new DeployWakuRlnV2()).deploy(); 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)); w = WakuRlnV2(address(proxy));
@ -773,7 +773,7 @@ contract WakuRlnV2Test is Test {
function test__Upgrade() external { function test__Upgrade() external {
address testImpl = address(new WakuRlnV2()); 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 proxy = address(new ERC1967Proxy(testImpl, data));
address newImpl = address(new WakuRlnV2()); address newImpl = address(new WakuRlnV2());