From fa40674b1bb777a65d9595afeb79e1946bae88c5 Mon Sep 17 00:00:00 2001 From: Moray Grieve Date: Tue, 17 Dec 2024 12:27:11 +0000 Subject: [PATCH] Add large calldata test (#391) * Call data size test * Addition of large call data test --- src/python/ten/test/baserunner.py | 10 ++-- src/python/ten/test/contracts/calldata.py | 5 ++ src/solidity/contracts/calldata/CallData.sol | 19 ++++++++ tests/generic/gen_cor_134/pysystest.xml | 38 +++++++++++++++ tests/generic/gen_cor_134/run.py | 51 ++++++++++++++++++++ tests/ten/ten_cor_117/pysystest.xml | 2 +- 6 files changed, 119 insertions(+), 6 deletions(-) create mode 100644 src/solidity/contracts/calldata/CallData.sol create mode 100644 tests/generic/gen_cor_134/pysystest.xml create mode 100644 tests/generic/gen_cor_134/run.py diff --git a/src/python/ten/test/baserunner.py b/src/python/ten/test/baserunner.py index b59fa4ad..aeb7ac2a 100644 --- a/src/python/ten/test/baserunner.py +++ b/src/python/ten/test/baserunner.py @@ -251,11 +251,11 @@ def __print_cost(self, runner, url, web3, user_id, eth_price): pass def get_eth_price(self): - url = "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD" - response = requests.get(url) - - if response.status_code == 200: - return float(response.json()['USD']) + try: + url = "https://min-api.cryptocompare.com/data/price?fsym=ETH&tsyms=USD" + response = requests.get(url) + if response.status_code == 200: return float(response.json()['USD']) + except: return None return None @staticmethod diff --git a/src/python/ten/test/contracts/calldata.py b/src/python/ten/test/contracts/calldata.py index 047c88fc..629bd788 100644 --- a/src/python/ten/test/contracts/calldata.py +++ b/src/python/ten/test/contracts/calldata.py @@ -2,6 +2,11 @@ from ten.test.contracts.default import DefaultContract +class CallData(DefaultContract): + SOURCE = os.path.join(PROJECT.root, 'src', 'solidity', 'contracts', 'calldata', 'CallData.sol') + CONTRACT = 'CallData' + + class CallDataTwoPhase(DefaultContract): SOURCE = os.path.join(PROJECT.root, 'src', 'solidity', 'contracts', 'calldata', 'CallDataTwoPhase.sol') CONTRACT = 'CallDataTwoPhase' diff --git a/src/solidity/contracts/calldata/CallData.sol b/src/solidity/contracts/calldata/CallData.sol new file mode 100644 index 00000000..e74e721a --- /dev/null +++ b/src/solidity/contracts/calldata/CallData.sol @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity ^0.8.0; + +contract CallData { + uint256 public lastSum; + + function processLargeData(uint256[] memory data) public { + uint256 sum = 0; + for (uint256 i = 0; i < data.length; i++) { + sum += data[i]; + } + lastSum = sum; + } + + function getLastSum() public view returns (uint256) { + return lastSum; + } +} + diff --git a/tests/generic/gen_cor_134/pysystest.xml b/tests/generic/gen_cor_134/pysystest.xml new file mode 100644 index 00000000..e555bd8a --- /dev/null +++ b/tests/generic/gen_cor_134/pysystest.xml @@ -0,0 +1,38 @@ + + + + + Gas: Large call data + + + + + + + gas + + + ten.sepolia + ten.uat + ten.dev + ten.local + ten.sim + arbitrum.sepolia + ganache + sepolia + + + + + + + + + + + + + diff --git a/tests/generic/gen_cor_134/run.py b/tests/generic/gen_cor_134/run.py new file mode 100644 index 00000000..d787be47 --- /dev/null +++ b/tests/generic/gen_cor_134/run.py @@ -0,0 +1,51 @@ +from pysys.constants import FAILED, PASSED +from ten.test.basetest import TenNetworkTest +from ten.test.utils.properties import Properties +from ten.test.contracts.calldata import CallData + + +class PySysTest(TenNetworkTest): + + def execute(self): + # connect to the network (use an ephemeral account) + network = self.get_network_connection() + web3, account = network.connect(self, private_key=self.get_ephemeral_pk(), check_funds=False) + self.distribute_native(account, network.ETH_ALLOC) + + # deploy the contract + calldata = CallData(self, web3, Properties().L2PublicCallbacks) + calldata.deploy(network, account) + + # transact (the first should be rejected so we just check later ones go through) + self.transact(calldata, web3, account, limit=5000, expect_pass=False) + self.transact(calldata, web3, account, limit=1000) + self.transact(calldata, web3, account, limit=500) + + def transact(self, calldata, web3, account, limit, expect_pass=True): + # build the transaction + large_array = [i for i in range(limit)] + target = calldata.contract.functions.processLargeData(large_array) + nonce = web3.eth.get_transaction_count(account.address) + params = {'nonce': nonce, + 'chainId': web3.eth.chain_id, + 'gasPrice': web3.eth.gas_price} + params['gas'] = int(1.1 * target.estimate_gas(params)) + build_tx = target.build_transaction(params) + + # sign, send and wait + try: + signed_tx = account.sign_transaction(build_tx) + tx_hash = web3.eth.send_raw_transaction(signed_tx.rawTransaction) + tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash) + if tx_receipt.status == 1: + self.log.info('Transaction confirmed') + self.log.info('Expected sum: %d' % sum(large_array)) + self.log.info('Call shows value: %d', calldata.contract.functions.getLastSum().call()) + self.assertTrue(calldata.contract.functions.getLastSum().call() == sum(large_array)) + else: + self.log.error('Transaction failed') + if expect_pass: self.addOutcome(FAILED,outcomeReason='Expected tx to succeed') + except Exception as e: + self.log.error('Error %s' % e) + if expect_pass: self.addOutcome(FAILED,outcomeReason='Expected tx to succeed') + else: self.addOutcome(PASSED,outcomeReason='Expected tx to fail') diff --git a/tests/ten/ten_cor_117/pysystest.xml b/tests/ten/ten_cor_117/pysystest.xml index dcc932d7..2987739d 100644 --- a/tests/ten/ten_cor_117/pysystest.xml +++ b/tests/ten/ten_cor_117/pysystest.xml @@ -5,7 +5,7 @@ Callbacks: privacy callback with large call data