2021-01-07 20:52:50 +00:00
import
chronos , nimcrypto , options , json , stint ,
test_utils ,
web3
2021-02-04 19:45:09 +00:00
# the address of Ethereum client (ganache-cli for now)
const ethClient = " ws://localhost:8540/ "
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# poseidonHasherCode holds the bytecode of Poseidon hasher solidity smart contract:
# https://github.com/kilic/rlnapp/blob/master/packages/contracts/contracts/crypto/PoseidonHasher.sol
# the solidity contract is compiled separately and the resultant bytecode is copied here
const poseidonHasherCode = readFile ( " tests/v2/poseidonHasher.txt " )
# membershipContractCode contains the bytecode of the membership solidity smart contract:
# https://github.com/kilic/rlnapp/blob/master/packages/contracts/contracts/RLN.sol
# the solidity contract is compiled separately and the resultant bytecode is copied here
const membershipContractCode = readFile ( " tests/v2/membershipContract.txt " )
# the membership contract code in solidity
# uint256 public immutable MEMBERSHIP_DEPOSIT;
# uint256 public immutable DEPTH;
# uint256 public immutable SET_SIZE;
# uint256 public pubkeyIndex = 0;
# mapping(uint256 => uint256) public members;
# IPoseidonHasher public poseidonHasher;
# event MemberRegistered(uint256 indexed pubkey, uint256 indexed index);
# event MemberWithdrawn(uint256 indexed pubkey, uint256 indexed index);
# constructor(
# uint256 membershipDeposit,
# uint256 depth,
# address _poseidonHasher
# ) public {
# MEMBERSHIP_DEPOSIT = membershipDeposit;
# DEPTH = depth;
# SET_SIZE = 1 << depth;
# poseidonHasher = IPoseidonHasher(_poseidonHasher);
# }
# function register(uint256 pubkey) external payable {
# 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 {
# require(pubkeyIndex + pubkeys.length <= SET_SIZE, "RLN, registerBatch: set is full");
# require(msg.value == MEMBERSHIP_DEPOSIT * pubkeys.length, "RLN, registerBatch: membership deposit is not satisfied");
# for (uint256 i = 0; i < pubkeys.length; i++) {
# _register(pubkeys[i]);
# }
# }
# function withdrawBatch(
# uint256[] calldata secrets,
# uint256[] calldata pubkeyIndexes,
# address payable[] calldata receivers
# ) external {
# uint256 batchSize = secrets.length;
# require(batchSize != 0, "RLN, withdrawBatch: batch size zero");
# require(batchSize == pubkeyIndexes.length, "RLN, withdrawBatch: batch size mismatch pubkey indexes");
# require(batchSize == receivers.length, "RLN, withdrawBatch: batch size mismatch receivers");
# for (uint256 i = 0; i < batchSize; i++) {
# _withdraw(secrets[i], pubkeyIndexes[i], receivers[i]);
# }
# }
# function withdraw(
# uint256 secret,
# uint256 _pubkeyIndex,
# address payable receiver
# ) external {
# _withdraw(secret, _pubkeyIndex, receiver);
# }
2021-01-07 20:52:50 +00:00
contract ( MembershipContract ) :
2021-02-04 20:24:28 +00:00
proc register ( pubkey : Uint256 ) # external payable
# proc registerBatch(pubkeys: seq[Uint256]) # external payable
# TODO will add withdraw function after integrating the keyGeneration function (required to compute public keys from secret keys)
# proc withdraw(secret: Uint256, pubkeyIndex: Uint256, receiver: Address)
# proc withdrawBatch( secrets: seq[Uint256], pubkeyIndex: seq[Uint256], receiver: seq[Address])
2021-01-07 20:52:50 +00:00
proc membershipTest ( ) {. async . } =
2021-02-04 19:45:09 +00:00
# connect to the eth client
let web3 = await newWeb3 ( ethClient )
echo " web3 connected "
# fetch the list of registered accounts
2021-01-07 20:52:50 +00:00
let accounts = await web3 . provider . eth_accounts ( )
web3 . defaultAccount = accounts [ 1 ]
2021-02-04 20:24:28 +00:00
echo " contract deployer account address " , web3 . defaultAccount
2021-01-07 20:52:50 +00:00
var balance = await web3 . provider . eth_getBalance ( web3 . defaultAccount , " latest " )
2021-02-04 19:45:09 +00:00
echo " Initial account balance: " , balance
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# deploy the poseidon hash first
let
hasherReceipt = await web3 . deployContract ( poseidonHasherCode )
hasherAddress = hasherReceipt . contractAddress . get
echo " hasher address: " , hasherAddress
# inputs of membership contract constructor
let
membershipFee = 5 . u256
depth = 5 . u256
# encode membership contract inputs to 32 bytes zero-padded
let
membershipFeeEncoded = encode ( membershipFee ) . data
depthEncoded = encode ( depth ) . data
hasherAddressEncoded = encode ( hasherAddress ) . data
# this is the contract constructor input
contractInput = membershipFeeEncoded & depthEncoded & hasherAddressEncoded
echo " encoded membership fee: " , membershipFeeEncoded
echo " encoded depth: " , depthEncoded
echo " encoded hasher address: " , hasherAddressEncoded
echo " encoded contract input: " , contractInput
# deploy membership contract with its constructor inputs
let receipt = await web3 . deployContract ( membershipContractCode , contractInput = contractInput )
2021-01-07 20:52:50 +00:00
var contractAddress = receipt . contractAddress . get
2021-02-04 20:24:28 +00:00
echo " Address of the deployed membership contract: " , contractAddress
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# balance = await web3.provider.eth_getBalance(web3.defaultAccount , "latest")
# echo "Account balance after the contract deployment: ", balance
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# prepare a contract sender to interact with it
echo " registering a user... "
var sender = web3 . contractSender ( MembershipContract , contractAddress ) # creates a Sender object with a web3 field and contract address of type Address
2021-01-07 20:52:50 +00:00
# send takes three parameters, c: ContractCallBase, value = 0.u256, gas = 3000000'u64 gasPrice = 0
# should use send proc for the contract functions that update the state of the contract
2021-02-04 20:24:28 +00:00
echo " The hash of registration tx: " , await sender . register ( 20 . u256 ) . send ( value = membershipFee ) # value is the membership fee
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# var members: array[2, uint256] = [20.u256, 21.u256]
# echo "This is the batch registration result ", await sender.registerBatch(members).send(value = (members.len * membershipFee)) # value is the membership fee
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
# balance = await web3.provider.eth_getBalance(web3.defaultAccount , "latest")
# echo "Balance after registration: ", balance
2021-01-07 20:52:50 +00:00
await web3 . close ( )
2021-02-04 19:45:09 +00:00
echo " closed "
2021-01-07 20:52:50 +00:00
2021-02-04 20:24:28 +00:00
2021-01-07 20:52:50 +00:00
waitFor membershipTest ( )
2021-02-04 20:24:28 +00:00
echo " rln-relay test ended "