diff --git a/tests/e2e_web3js_test.go b/tests/e2e_web3js_test.go index a16326da7..9f3ccf780 100644 --- a/tests/e2e_web3js_test.go +++ b/tests/e2e_web3js_test.go @@ -24,6 +24,10 @@ var ( func TestWeb3_E2E(t *testing.T) { + t.Run("build EVM state", func(t *testing.T) { + runWeb3Test(t, "build_evm_state_test") + }) + t.Run("test setup sanity check", func(t *testing.T) { runWeb3Test(t, "setup_test") }) diff --git a/tests/web3js/build_evm_state_test.js b/tests/web3js/build_evm_state_test.js new file mode 100644 index 000000000..a7df7d6b7 --- /dev/null +++ b/tests/web3js/build_evm_state_test.js @@ -0,0 +1,112 @@ +const utils = require('web3-utils') +const { assert } = require('chai') +const conf = require('./config') +const helpers = require('./helpers') +const web3 = conf.web3 + +it('should handle a large number of EVM interactions', async () => { + let latest = await web3.eth.getBlockNumber() + assert.equal(latest, 2n) + + let eoaCount = 20 + let accounts = [] + + // Generate 20 EOAs + // Fund them with some arbitrary number of tokens + // Make them do transfers to each other + + for (let i = 0; i < eoaCount; i++) { + let receiver = web3.eth.accounts.create() + + let transferValue = utils.toWei('0.15', 'ether') + let transfer = await helpers.signAndSend({ + from: conf.eoa.address, + to: receiver.address, + value: transferValue, + gasPrice: conf.minGasPrice, + gasLimit: 21_000, + }) + + assert.equal(transfer.receipt.status, conf.successStatus) + assert.equal(transfer.receipt.from, conf.eoa.address) + assert.equal(transfer.receipt.to, receiver.address) + + // check balance was moved + let receiverWei = await web3.eth.getBalance(receiver.address) + assert.equal(receiverWei, transferValue) + + accounts.push(receiver) + } + + let senderBalance = await web3.eth.getBalance(conf.eoa.address) + assert.equal(senderBalance, 1999999999937000000n) + + let transferAmounts = ['0.01', '0.03', '0.05'] + for (let i = 0; i < eoaCount; i++) { + let sender = accounts[i] + + for (let j = 0; j < 3; j++) { + let receiver = randomItem(accounts) + + let amount = randomItem(transferAmounts) + let transferValue = utils.toWei(amount, 'ether') + let transfer = await helpers.signAndSendFrom(sender, { + from: sender.address, + to: receiver.address, + value: transferValue, + gasPrice: conf.minGasPrice, + gasLimit: 21_000, + }) + + assert.equal(transfer.receipt.status, conf.successStatus) + assert.equal(transfer.receipt.from, sender.address) + assert.equal(transfer.receipt.to, receiver.address) + } + } + + latest = await web3.eth.getBlockNumber() + assert.equal(latest, 82n) + + for (let i = 0; i < eoaCount; i++) { + let sender = accounts[i] + + let deployed = await helpers.deployContractFrom(sender, 'storage') + let contractAddress = deployed.receipt.contractAddress + + assert.equal(deployed.receipt.status, conf.successStatus) + assert.isString(contractAddress) + assert.equal(deployed.receipt.from, sender.address) + + let storeNumber = Math.floor(Math.random() * 10_000) + // set the value on the contract, to its current value + let updateData = deployed.contract.methods.store(storeNumber).encodeABI() + // store a value in the contract + let res = await helpers.signAndSendFrom(sender, { + from: sender.address, + to: contractAddress, + data: updateData, + value: '0', + gasPrice: conf.minGasPrice, + }) + assert.equal(res.receipt.status, conf.successStatus) + + sender = randomItem(accounts) + let sumA = Math.floor(Math.random() * 10_000) + let sumB = Math.floor(Math.random() * 100_000) + res = await helpers.signAndSendFrom(sender, { + from: sender.address, + to: contractAddress, + data: deployed.contract.methods.sum(sumA, sumB).encodeABI(), + gas: 55_000, + gasPrice: conf.minGasPrice + }) + assert.equal(res.receipt.status, conf.successStatus) + } + + latest = await web3.eth.getBlockNumber() + assert.equal(latest, 142n) +}) + +function randomItem(items) { + return items[Math.floor(Math.random() * items.length)] +} diff --git a/tests/web3js/helpers.js b/tests/web3js/helpers.js index edef69a37..0b4ddb51f 100644 --- a/tests/web3js/helpers.js +++ b/tests/web3js/helpers.js @@ -36,6 +36,30 @@ async function deployContract(name) { } } +async function deployContractFrom(from, name) { + const abi = require(`../fixtures/${name}ABI.json`) + const code = await fs.promises.readFile(`${__dirname}/../fixtures/${name}.byte`, 'utf8') + const contractABI = new web3.eth.Contract(abi, { handleReverted: true }) + + let data = contractABI + .deploy({ data: `0x${code}` }) + .encodeABI() + + let signed = await from.signTransaction({ + from: from.address, + data: data, + value: '0', + gasPrice: conf.minGasPrice, + }) + + let receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction) + + return { + contract: new web3.eth.Contract(abi, receipt.contractAddress, { handleReverted: true }), + receipt: receipt + } +} + // signAndSend signs a transactions and submits it to the network, // returning a transaction hash and receipt async function signAndSend(tx) { @@ -49,6 +73,19 @@ async function signAndSend(tx) { } } +// signAndSendFrom signs a transactions from the given EOA and submits it +// to the network, returning a transaction hash and receipt +async function signAndSendFrom(from, tx) { + const signedTx = await from.signTransaction(tx) + // send transaction and make sure interaction was success + const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction) + + return { + hash: signedTx.transactionHash, + receipt: receipt, + } +} + // callRPCMethod accepts a method name and its params and // makes a POST request to the JSON-RPC API server. // Returns a promise for the response. @@ -67,4 +104,6 @@ async function callRPCMethod(methodName, params) { exports.signAndSend = signAndSend exports.deployContract = deployContract +exports.deployContractFrom = deployContractFrom exports.callRPCMethod = callRPCMethod +exports.signAndSendFrom = signAndSendFrom