rln-contract/contracts/Rln.sol

95 lines
2.7 KiB
Solidity
Raw Normal View History

2022-08-09 17:29:04 +00:00
pragma solidity 0.8.15;
2022-06-23 13:36:10 +00:00
import { IPoseidonHasher } from "./PoseidonHasher.sol";
contract RLN {
uint256 public immutable MEMBERSHIP_DEPOSIT;
uint256 public immutable DEPTH;
uint256 public immutable SET_SIZE;
uint256 public pubkeyIndex = 0;
2022-11-25 09:04:30 +00:00
// This mapping is used to keep track of the public keys that have been registered
// with the stake
2022-06-23 13:36:10 +00:00
mapping(uint256 => uint256) public members;
IPoseidonHasher public poseidonHasher;
event MemberRegistered(uint256 pubkey, uint256 index);
2022-11-25 09:04:30 +00:00
event MemberWithdrawn(uint256 pubkey);
2022-06-23 13:36:10 +00:00
constructor(
uint256 membershipDeposit,
uint256 depth,
address _poseidonHasher
) {
2022-06-23 13:36:10 +00:00
MEMBERSHIP_DEPOSIT = membershipDeposit;
DEPTH = depth;
SET_SIZE = 1 << depth;
poseidonHasher = IPoseidonHasher(_poseidonHasher);
}
function register(uint256 pubkey) external payable {
2022-11-25 09:04:30 +00:00
require(members[pubkey] == 0, "RLN, register: pubkey already registered");
2022-06-23 13:36:10 +00:00
require(pubkeyIndex < SET_SIZE, "RLN, register: set is full");
require(msg.value == MEMBERSHIP_DEPOSIT, "RLN, register: membership deposit is not satisfied");
_register(pubkey);
}
function registerBatch(uint256[] calldata pubkeys) external payable {
uint256 pubkeylen = pubkeys.length;
require(pubkeyIndex + pubkeylen <= SET_SIZE, "RLN, registerBatch: set is full");
require(msg.value == MEMBERSHIP_DEPOSIT * pubkeylen, "RLN, registerBatch: membership deposit is not satisfied");
for (uint256 i = 0; i < pubkeylen; i++) {
2022-06-23 13:36:10 +00:00
_register(pubkeys[i]);
}
}
function _register(uint256 pubkey) internal {
2022-11-25 09:04:30 +00:00
// Set the pubkey to the value of the tx
members[pubkey] = msg.value;
2022-06-23 13:36:10 +00:00
emit MemberRegistered(pubkey, pubkeyIndex);
pubkeyIndex += 1;
}
function withdrawBatch(
uint256[] calldata secrets,
address payable[] calldata receivers
) external {
uint256 batchSize = secrets.length;
require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
require(batchSize == receivers.length, "RLN, withdrawBatch: batch size mismatch receivers");
for (uint256 i = 0; i < batchSize; i++) {
2022-11-25 09:04:30 +00:00
_withdraw(secrets[i], receivers[i]);
2022-06-23 13:36:10 +00:00
}
}
function withdraw(
uint256 secret,
address payable receiver
) external {
2022-11-25 09:04:30 +00:00
_withdraw(secret, receiver);
2022-06-23 13:36:10 +00:00
}
function _withdraw(
uint256 secret,
address payable receiver
) internal {
// derive public key
uint256 pubkey = hash(secret);
2022-11-25 09:04:30 +00:00
require(members[pubkey] != 0, "RLN, _withdraw: member doesn't exist");
require(receiver != address(0), "RLN, _withdraw: empty receiver address");
2022-06-23 13:36:10 +00:00
// refund deposit
2022-11-25 09:04:30 +00:00
(bool sent, bytes memory data) = receiver.call{value: members[pubkey]}("");
require(sent, "transfer failed");
2022-06-23 13:36:10 +00:00
2022-11-25 09:04:30 +00:00
// delete member only if refund is successful
members[pubkey] = 0;
emit MemberWithdrawn(pubkey);
2022-06-23 13:36:10 +00:00
}
function hash(uint256 input) internal view returns (uint256) {
2022-06-23 13:36:10 +00:00
return poseidonHasher.hash(input);
}
}