logos-messaging-nim/tests/incentivization/test_poc_eligibility.nim

208 lines
7.5 KiB
Nim

{.used.}
import std/options, testutils/unittests, chronos, web3, stint, tests/testlib/testasync
import
waku/node/peer_manager,
waku/incentivization/[rpc, eligibility_manager],
../waku_rln_relay/[utils_onchain, utils]
const TxHashNonExisting =
TxHash.fromHex("0x0000000000000000000000000000000000000000000000000000000000000000")
# Anvil RPC URL
const EthClient = "ws://127.0.0.1:8540"
const TxValueExpectedWei = 1000.u256
## Storage.sol contract from https://remix.ethereum.org/
## Compiled with Solidity compiler version "0.8.26+commit.8a97fa7a"
const ExampleStorageContractBytecode =
"6080604052348015600e575f80fd5b506101438061001c5f395ff3fe608060405234801561000f575f80fd5b5060043610610034575f3560e01c80632e64cec1146100385780636057361d14610056575b5f80fd5b610040610072565b60405161004d919061009b565b60405180910390f35b610070600480360381019061006b91906100e2565b61007a565b005b5f8054905090565b805f8190555050565b5f819050919050565b61009581610083565b82525050565b5f6020820190506100ae5f83018461008c565b92915050565b5f80fd5b6100c181610083565b81146100cb575f80fd5b50565b5f813590506100dc816100b8565b92915050565b5f602082840312156100f7576100f66100b4565b5b5f610104848285016100ce565b9150509291505056fea26469706673582212209a0dd35336aff1eb3eeb11db76aa60a1427a12c1b92f945ea8c8d1dfa337cf2264736f6c634300081a0033"
contract(ExampleStorageContract):
proc number(): UInt256 {.view.}
proc store(num: UInt256)
proc retrieve(): UInt256 {.view.}
#[
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.2 <0.9.0;
/**
* @title Storage
* @dev Store & retrieve value in a variable
* @custom:dev-run-script ./scripts/deploy_with_ethers.ts
*/
contract Storage {
uint256 number;
/**
* @dev Store value in variable
* @param num value to store
*/
function store(uint256 num) public {
number = num;
}
/**
* @dev Return value
* @return value of 'number'
*/
function retrieve() public view returns (uint256){
return number;
}
}
]#
proc setup(
manager: EligibilityManager
): Future[(TxHash, TxHash, TxHash, TxHash, TxHash, Address, Address)] {.async.} =
## Populate the local chain (connected to via manager)
## with txs required for eligibility testing.
##
## 1. Depoly a dummy contract that has a publicly callable function.
## (While doing so, we confirm a contract creation tx.)
## 2. Confirm these transactions:
## - a contract call tx (eligibility test must fail)
## - a simple transfer with the wrong receiver (must fail)
## - a simple transfer with the wrong amount (must fail)
## - a simple transfer with the right receiver and amount (must pass)
let web3 = manager.web3
let accounts = await web3.provider.eth_accounts()
web3.defaultAccount = accounts[0]
let sender = web3.defaultAccount
let receiverExpected = accounts[1]
let receiverNotExpected = accounts[2]
let txValueEthExpected = TxValueExpectedWei
let txValueEthNotExpected = txValueEthExpected + 1
# wrong receiver, wrong amount
let txHashWrongReceiverRightAmount =
await web3.sendEthTransfer(sender, receiverNotExpected, txValueEthExpected)
# right receiver, wrong amount
let txHashRightReceiverWrongAmount =
await web3.sendEthTransfer(sender, receiverExpected, txValueEthNotExpected)
# right receiver, right amount
let txHashRightReceiverRightAmount =
await web3.sendEthTransfer(sender, receiverExpected, txValueEthExpected)
let receipt = await web3.deployContract(ExampleStorageContractBytecode)
let txHashContractCreation = receipt.transactionHash
let exampleStorageContractAddress = receipt.contractAddress.get()
let exampleStorageContract =
web3.contractSender(ExampleStorageContract, exampleStorageContractAddress)
let txHashContractCall = await exampleStorageContract.store(1.u256).send()
return (
txHashWrongReceiverRightAmount, txHashRightReceiverWrongAmount,
txHashRightReceiverRightAmount, txHashContractCreation, txHashContractCall,
receiverExpected, receiverNotExpected,
)
suite "Waku Incentivization PoC Eligibility Proofs":
## Tests for service incentivization PoC.
## In a client-server interaction, a client submits an eligibility proof to the server.
## The server provides the service if and only if the proof is valid.
## In PoC, a txid serves as eligibility proof.
## The txid reflects the confirmed payment from the client to the server.
## The request is eligible if the tx is confirmed and pays the correct amount to the correct address.
## The tx must also be of a "simple transfer" type (not a contract creation, not a contract call).
## See spec: https://github.com/waku-org/specs/blob/master/standards/core/incentivization.md
## Start Anvil
let runAnvil {.used.} = runAnvil()
var txHashWrongReceiverRightAmount, txHashRightReceiverWrongAmount,
txHashRightReceiverRightAmount, txHashContractCreation, txHashContractCall: TxHash
var receiverExpected, receiverNotExpected: Address
var manager {.threadvar.}: EligibilityManager
asyncSetup:
manager = await EligibilityManager.init(EthClient)
(
txHashWrongReceiverRightAmount, txHashRightReceiverWrongAmount,
txHashRightReceiverRightAmount, txHashContractCreation, txHashContractCall,
receiverExpected, receiverNotExpected,
) = await manager.setup()
asyncTeardown:
await manager.close()
asyncTest "incentivization PoC: non-existent tx is not eligible":
## Test that an unconfirmed tx is not eligible.
let eligibilityProof =
EligibilityProof(proofOfPayment: some(@(TxHashNonExisting.bytes())))
let isEligible = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
check:
isEligible.isErr()
asyncTest "incentivization PoC: contract creation tx is not eligible":
## Test that a contract creation tx is not eligible.
let eligibilityProof =
EligibilityProof(proofOfPayment: some(@(txHashContractCreation.bytes())))
let isEligible = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
check:
isEligible.isErr()
asyncTest "incentivization PoC: contract call tx is not eligible":
## Test that a contract call tx is not eligible.
## This assumes a payment in native currency (ETH), not a token.
let eligibilityProof =
EligibilityProof(proofOfPayment: some(@(txHashContractCall.bytes())))
let isEligible = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
check:
isEligible.isErr()
asyncTest "incentivization PoC: simple transfer tx is eligible":
## Test that a simple transfer tx is eligible (if necessary conditions hold).
let eligibilityProof =
EligibilityProof(proofOfPayment: some(@(txHashRightReceiverRightAmount.bytes())))
let isEligible = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
assert isEligible.isOk(), isEligible.error
asyncTest "incentivization PoC: double-spend tx is not eligible":
## Test that the same tx submitted twice is not eligible the second time
let eligibilityProof =
EligibilityProof(proofOfPayment: some(@(txHashRightReceiverRightAmount.bytes())))
let isEligibleOnce = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
let isEligibleTwice = await manager.isEligibleTxId(
eligibilityProof, receiverExpected, TxValueExpectedWei
)
assert isEligibleOnce.isOk()
assert isEligibleTwice.isErr(), isEligibleTwice.error
# Stop Anvil daemon
stopAnvil(runAnvil)