2024-12-13 10:41:11 +00:00
|
|
|
import std/options, chronos, web3, stew/byteutils, stint, strutils, results, chronicles
|
2024-10-31 11:20:07 +00:00
|
|
|
|
|
|
|
import waku/incentivization/rpc
|
|
|
|
|
2024-12-12 08:19:06 +00:00
|
|
|
const SimpleTransferGasUsed = Quantity(21000)
|
2024-10-31 11:20:07 +00:00
|
|
|
|
2024-12-13 08:35:09 +00:00
|
|
|
proc isEligibleTxId*(
|
|
|
|
eligibilityProof: EligibilityProof,
|
|
|
|
expectedToAddress: Address,
|
|
|
|
expectedValue: UInt256,
|
|
|
|
ethClient: string,
|
2024-12-13 10:29:13 +00:00
|
|
|
): Future[Result[void, string]] {.async.} =
|
2024-12-13 08:35:09 +00:00
|
|
|
## We consider a tx eligible,
|
|
|
|
## in the context of service incentivization PoC,
|
|
|
|
## if it is confirmed and pays the expected amount to the server's address.
|
|
|
|
## See spec: https://github.com/waku-org/specs/blob/master/standards/core/incentivization.md
|
|
|
|
if eligibilityProof.proofOfPayment.isNone():
|
2024-12-13 10:29:13 +00:00
|
|
|
return err("Eligibility proof is empty")
|
2024-12-13 10:58:34 +00:00
|
|
|
var web3: Web3
|
|
|
|
try:
|
|
|
|
web3 = await newWeb3(ethClient)
|
|
|
|
except ValueError:
|
|
|
|
let errorMsg =
|
|
|
|
"Failed to set up a web3 provider connection: " & getCurrentExceptionMsg()
|
|
|
|
error "exception in isEligibleTxId", error = $errorMsg
|
|
|
|
return err($errorMsg)
|
2024-12-13 10:54:07 +00:00
|
|
|
var tx: TransactionObject
|
|
|
|
var txReceipt: ReceiptObject
|
2024-12-13 10:58:34 +00:00
|
|
|
let txHash = TxHash.fromHex(byteutils.toHex(eligibilityProof.proofOfPayment.get()))
|
2024-10-31 11:20:07 +00:00
|
|
|
try:
|
2024-12-13 08:35:09 +00:00
|
|
|
# TODO: make requests in parallel (?)
|
2024-12-13 10:54:07 +00:00
|
|
|
tx = await web3.provider.eth_getTransactionByHash(txHash)
|
|
|
|
txReceipt = await web3.getMinedTransactionReceipt(txHash)
|
2024-12-13 10:41:11 +00:00
|
|
|
except ValueError:
|
|
|
|
let errorMsg = "Failed to fetch tx or tx receipt: " & getCurrentExceptionMsg()
|
|
|
|
error "exception in isEligibleTxId", error = $errorMsg
|
|
|
|
return err($errorMsg)
|
2024-12-13 10:54:07 +00:00
|
|
|
# check that it is not a contract creation tx
|
|
|
|
let toAddressOption = txReceipt.to
|
|
|
|
if toAddressOption.isNone:
|
|
|
|
# this is a contract creation tx
|
|
|
|
return err("A contract creation tx is not eligible")
|
|
|
|
# check that it is a simple transfer (not a contract call)
|
|
|
|
# a simple transfer uses 21000 gas
|
|
|
|
let gasUsed = txReceipt.gasUsed
|
|
|
|
let isSimpleTransferTx = (gasUsed == SimpleTransferGasUsed)
|
|
|
|
if not isSimpleTransferTx:
|
|
|
|
return err("A contract call tx is not eligible")
|
|
|
|
# check that the to address is "as expected"
|
|
|
|
let toAddress = toAddressOption.get()
|
|
|
|
if toAddress != expectedToAddress:
|
|
|
|
return err("Wrong destination address: " & $toAddress)
|
|
|
|
# check that the amount is "as expected"
|
|
|
|
let txValue = tx.value
|
|
|
|
if txValue != expectedValue:
|
|
|
|
return err("Wrong tx value: got " & $txValue & ", expected " & $expectedValue)
|
|
|
|
defer:
|
|
|
|
await web3.close()
|
|
|
|
return ok()
|