From bf4aab8bb7eb2a9c4f3bf87d522871b58ad29d45 Mon Sep 17 00:00:00 2001 From: dan moore Date: Tue, 21 Jan 2025 11:33:54 +0100 Subject: [PATCH] ci cleanup and add more bats tests --- .github/workflows/ci.yml | 3 - Makefile | 5 +- .../{e2e.bats => batch-verifier.bats} | 0 .../contracts}/erc20mock/ERC20Mock.json | 0 scripts/bats-scripts/eoa-tx.bats | 38 ++++++ .../{basic-e2e.bats => erc20-mock.bats} | 49 ++----- scripts/bats-scripts/helpers/common.bash | 128 ++++++++++++------ 7 files changed, 136 insertions(+), 87 deletions(-) rename scripts/bats-scripts/{e2e.bats => batch-verifier.bats} (100%) rename {contracts => scripts/bats-scripts/contracts}/erc20mock/ERC20Mock.json (100%) create mode 100644 scripts/bats-scripts/eoa-tx.bats rename scripts/bats-scripts/{basic-e2e.bats => erc20-mock.bats} (81%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 72a65af..3061863 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,9 +48,6 @@ jobs: echo "Injecting RPC_URL into .env file" sed -i "s|l2_rpc_url=http://127.0.0.1:.*|l2_rpc_url=$ESCAPED_RPC_URL|" .env - - echo "Dynamically updating BATS_LIB_PATH in .env" - sed -i "s|BATS_LIB_PATH=.*|BATS_LIB_PATH=\"$(pwd)/scripts/bats-scripts/lib\"|" .env # Step 5: Debugging - Output the updated .env file - name: Debug .env File diff --git a/Makefile b/Makefile index e371e4b..861c2c9 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,12 @@ test-bats: sed -i "" "s|BATS_LIB_PATH=.*|BATS_LIB_PATH=\"$(PWD)/scripts/bats-scripts/lib\"|" .env; \ else \ echo "Detected Linux, using Linux sed syntax"; \ - sed -i "s|BATS_LIB_PATH=.*|BATS_LIB_PATH=\"$(PWD)/scripts/bats-scripts/lib\"|" .env; \ + sed -i "s|BATS_LIB_PATH=.*|BATS_LIB_PATH=\"$(pwd)/scripts/bats-scripts/lib\"|" .env; \ fi; \ echo "Sourcing .env and running bats tests"; \ set -a; . $(PWD)/.env; set +a; \ - cd scripts/bats-scripts; bats -p e2e.bats + cd scripts/bats-scripts; bats -p batch-verifier.bats; \ + bats -p eoa-tx.bats .PHONY: test-go test-go: diff --git a/scripts/bats-scripts/e2e.bats b/scripts/bats-scripts/batch-verifier.bats similarity index 100% rename from scripts/bats-scripts/e2e.bats rename to scripts/bats-scripts/batch-verifier.bats diff --git a/contracts/erc20mock/ERC20Mock.json b/scripts/bats-scripts/contracts/erc20mock/ERC20Mock.json similarity index 100% rename from contracts/erc20mock/ERC20Mock.json rename to scripts/bats-scripts/contracts/erc20mock/ERC20Mock.json diff --git a/scripts/bats-scripts/eoa-tx.bats b/scripts/bats-scripts/eoa-tx.bats new file mode 100644 index 0000000..6591850 --- /dev/null +++ b/scripts/bats-scripts/eoa-tx.bats @@ -0,0 +1,38 @@ +setup() { + load 'helpers/common-setup' + load 'helpers/common' + _common_setup + + readonly sender_private_key=${SENDER_PRIVATE_KEY:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"} + receiver=${RECEIVER:-"0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"} +} + +@test "Send EOA transaction" { + echo "Testing EOA transaction" + + local sender_addr=$(cast wallet address --private-key "$sender_private_key") + echo "Sender Address: $sender_addr" + + local initial_nonce=$(cast nonce "$sender_addr" --rpc-url "$l2_rpc_url") || { + echo "Failed to retrieve nonce for sender: $sender_addr using RPC URL: $l2_rpc_url" + return 1 + } + echo "Initial Nonce: $initial_nonce" + + local value="10ether" + + # Case 1: Transaction successful + run send_tx "$l2_rpc_url" "$sender_private_key" "$receiver" "$value" + assert_success + assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)" + + # Case 2: Transaction rejected (insufficient funds) + local sender_balance=$(cast balance "$sender_addr" --ether --rpc-url "$l2_rpc_url") || { + echo "Failed to retrieve balance for sender: $sender_addr using RPC URL: $l2_rpc_url" + return 1 + } + local excessive_value=$(echo "$sender_balance + 1" | bc)"ether" + run send_tx "$l2_rpc_url" "$sender_private_key" "$receiver" "$excessive_value" + assert_failure + assert_output --regexp "Error: Transaction failed.*" +} diff --git a/scripts/bats-scripts/basic-e2e.bats b/scripts/bats-scripts/erc20-mock.bats similarity index 81% rename from scripts/bats-scripts/basic-e2e.bats rename to scripts/bats-scripts/erc20-mock.bats index 072dbe5..aa13a2c 100644 --- a/scripts/bats-scripts/basic-e2e.bats +++ b/scripts/bats-scripts/erc20-mock.bats @@ -4,39 +4,7 @@ setup() { _common_setup readonly sender_private_key=${SENDER_PRIVATE_KEY:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"} - readonly receiver=${RECEIVER:-"0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"} -} - -@test "Send EOA transaction" { - local sender_addr=$(cast wallet address --private-key "$sender_private_key") - local initial_nonce=$(cast nonce "$sender_addr" --rpc-url "$l2_rpc_url") || { - echo "Failed to retrieve nonce for sender: $sender_addr using RPC URL: $l2_rpc_url" - return 1 - } - local value="10ether" - - # case 1: Transaction successful sender has sufficient balance - run send_tx "$l2_rpc_url" "$sender_private_key" "$receiver" "$value" - assert_success - assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)" - - # case 2: Transaction rejected as sender attempts to transfer more than it has in its wallet. - # Transaction will fail pre-validation check on the node and will be dropped subsequently from the pool - # without recording it on the chain and hence nonce will not change - local sender_balance=$(cast balance "$sender_addr" --ether --rpc-url "$l2_rpc_url") || { - echo "Failed to retrieve balance for sender: $sender_addr using RPC URL: $l2_rpc_url" - return 1 - } - local excessive_value=$(echo "$sender_balance + 1" | bc)"ether" - run send_tx "$l2_rpc_url" "$sender_private_key" "$receiver" "$excessive_value" - assert_failure - - # Check whether the sender's nonce was updated correctly - local final_nonce=$(cast nonce "$sender_addr" --rpc-url "$l2_rpc_url") || { - echo "Failed to retrieve nonce for sender: $sender_addr using RPC URL: $l2_rpc_url" - return 1 - } - assert_equal "$final_nonce" "$(echo "$initial_nonce + 1" | bc)" + receiver=${RECEIVER:-"0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"} } @test "Test ERC20Mock contract" { @@ -49,11 +17,18 @@ setup() { # Deploy ERC20Mock run deploy_contract "$l2_rpc_url" "$sender_private_key" "$contract_artifact" assert_success - contract_addr=$(echo "$output" | tail -n 1) - # Mint ERC20 tokens - local amount="5" + # Extract contract address directly from deploy_contract output + local contract_addr + contract_addr=$(echo "$output" | xargs) + echo "Deployed contract address: $contract_addr" + if [[ ! "$contract_addr" =~ ^0x[a-fA-F0-9]{40}$ ]]; then + fail "Invalid contract address extracted: $contract_addr" + fi + + # Continue with minting and remaining cases + local amount="5" run send_tx "$l2_rpc_url" "$sender_private_key" "$contract_addr" "$mint_fn_sig" "$address_A" "$amount" assert_success assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)" @@ -143,7 +118,7 @@ setup() { # Generate new key pair wallet_A_output=$(cast wallet new) address_A=$(echo "$wallet_A_output" | grep "Address" | awk '{print $2}') - address_A_private_key=$(echo "$wallet_A_output" | grep "Private key" | awk '{print $3}') + address_A_private_key=$(echo "$wallet_A_output" | grep "Private key" | awk '{print $3}' | sed 's/^0x//') # Transfer funds for gas local value_ether="50ether" diff --git a/scripts/bats-scripts/helpers/common.bash b/scripts/bats-scripts/helpers/common.bash index 71e148f..be4663d 100644 --- a/scripts/bats-scripts/helpers/common.bash +++ b/scripts/bats-scripts/helpers/common.bash @@ -5,78 +5,88 @@ function deploy_contract() { local private_key="$2" local contract_artifact="$3" - # Check if rpc_url is available - if [[ -z "$rpc_url" ]]; then - echo "Error: rpc_url parameter is not set." + # Validate inputs + if [[ -z "$rpc_url" || -z "$private_key" || -z "$contract_artifact" ]]; then + echo "Error: Missing required parameters." >&2 return 1 fi if [[ ! -f "$contract_artifact" ]]; then - echo "Error: Contract artifact '$contract_artifact' does not exist." + echo "Error: Contract artifact '$contract_artifact' does not exist." >&2 return 1 fi - # Get the sender address - local sender=$(cast wallet address "$private_key") + # Retrieve sender address + local sender + sender=$(cast wallet address --private-key "$private_key") if [[ $? -ne 0 ]]; then - echo "Error: Failed to retrieve sender address." + echo "Error: Failed to retrieve sender address." >&2 return 1 fi - echo "Attempting to deploy contract artifact '$contract_artifact' to $rpc_url (sender: $sender)" >&3 + echo "Deploying contract artifact '$contract_artifact' to $rpc_url (sender: $sender)" - # Get bytecode from the contract artifact - local bytecode=$(jq -r .bytecode "$contract_artifact") + # Extract bytecode + local bytecode + bytecode=$(jq -r '.bytecode' "$contract_artifact") if [[ -z "$bytecode" || "$bytecode" == "null" ]]; then - echo "Error: Failed to read bytecode from $contract_artifact" + echo "Error: Failed to extract bytecode from $contract_artifact." >&2 return 1 fi - # Send the transaction and capture the output + # Calculate gas price + local gas_price gas_price=$(cast gas-price --rpc-url "$rpc_url") - local comp_gas_price=$(bc -l <<< "$gas_price * 1.5" | sed 's/\..*//') if [[ $? -ne 0 ]]; then - echo "Failed to calculate gas price" >&3 - exit 1 + echo "Error: Failed to retrieve gas price." >&2 + return 1 + fi + local comp_gas_price + comp_gas_price=$(bc <<< "$gas_price * 1.5 / 1" | awk '{printf "%.0f", $1}') + if [[ $? -ne 0 || -z "$comp_gas_price" ]]; then + echo "Error: Failed to calculate adjusted gas price." >&2 + return 1 fi - local cast_output=$(cast send --rpc-url "$rpc_url" \ + + # Deploy contract + local cast_output + cast_output=$(cast send --rpc-url "$rpc_url" \ --private-key "$private_key" \ - --gas-price $comp_gas_price \ + --gas-price "$comp_gas_price" \ --legacy \ - --create "$bytecode" \ - 2>&1) + --create "$bytecode" 2>&1) - # Check if cast send was successful if [[ $? -ne 0 ]]; then - echo "Error: Failed to send transaction." - echo "$cast_output" + echo "Error: Contract deployment failed." >&2 + echo "$cast_output" >&2 return 1 fi - echo "Deploy contract output:" >&3 - echo "$cast_output" >&3 - - # Extract the contract address from the output - local deployed_contract_address=$(echo "$cast_output" | grep 'contractAddress' | sed 's/contractAddress\s\+//') - echo "Deployed contract address: $deployed_contract_address" >&3 + echo "Deployment output:" + echo "$cast_output" + # Extract contract address + local deployed_contract_address + deployed_contract_address=$(echo "$cast_output" | awk '/contractAddress/{print $NF}') if [[ -z "$deployed_contract_address" ]]; then - echo "Error: Failed to extract deployed contract address" - echo "$cast_output" + echo "Error: Failed to extract deployed contract address from output." >&2 return 1 fi + # Validate contract address format if [[ ! "$deployed_contract_address" =~ ^0x[a-fA-F0-9]{40}$ ]]; then - echo "Error: Invalid contract address $deployed_contract_address" + echo "Error: Invalid contract address $deployed_contract_address." >&2 return 1 fi - # Print contract address for return - echo "$deployed_contract_address" + echo "Deployed contract address: $deployed_contract_address" + # Return contract address + echo "$deployed_contract_address" return 0 } + function send_tx() { # Check if at least 4 arguments are provided if [[ $# -lt 4 ]]; then @@ -100,24 +110,52 @@ function send_tx() { # Get sender address from private key local sender - sender=$(cast wallet address "$private_key") || { + sender=$(cast wallet address --private-key "$private_key") || { echo "Error: Failed to extract the sender address." return 1 } - # Check if the value_or_function_sig is a numeric value (Ether to be transferred) + # Case 1: Ether transfer (EOA transaction) if [[ "$value_or_function_sig" =~ ^[0-9]+(\.[0-9]+)?(ether)?$ ]]; then - # Case: Ether transfer (EOA transaction) - # Get initial ether balances of sender and receiver - local sender_addr=$(cast wallet address --private-key "$private_key") - local sender_initial_balance receiver_initial_balance - sender_initial_balance=$(cast balance "$sender_addr" --ether --rpc-url "$rpc_url") || return 1 - receiver_initial_balance=$(cast balance "$receiver_addr" --ether --rpc-url "$rpc_url") || return 1 - - send_eoa_transaction "$private_key" "$receiver_addr" "$value_or_function_sig" "$sender_addr" "$sender_initial_balance" "$receiver_initial_balance" + # Send EOA transaction + local tx_output + tx_output=$(cast send --gas-price 1500000000 --rpc-url "$rpc_url" --private-key "$private_key" "$receiver_addr" --value "$value_or_function_sig" --legacy 2>&1) || { + echo "Error: Transaction failed. Output: $tx_output" + return 1 + } + + # Extract transaction hash + local tx_hash + tx_hash=$(echo "$tx_output" | grep -Eo "transactionHash\s+0x[a-fA-F0-9]{64}" | awk '{print $2}') + + if [[ -z "$tx_hash" ]]; then + echo "Error: Transaction hash not found in output." + echo "$tx_output" + return 1 + fi + + echo "Transaction successful (transaction hash: $tx_hash)" + return 0 else - # Case: Smart contract interaction (contract interaction with function signature and parameters) - send_smart_contract_transaction "$private_key" "$receiver_addr" "$value_or_function_sig" "${params[@]}" + # Case 2: Smart contract interaction + local tx_output + tx_output=$(cast send --rpc-url "$rpc_url" --private-key "$private_key" "$receiver_addr" "$value_or_function_sig" "${params[@]}" 2>&1) || { + echo "Error: Contract interaction failed. Output: $tx_output" + return 1 + } + + # Extract transaction hash + local tx_hash + tx_hash=$(echo "$tx_output" | grep -Eo "transactionHash\s+0x[a-fA-F0-9]{64}" | awk '{print $2}') + + if [[ -z "$tx_hash" ]]; then + echo "Error: Transaction hash not found in output." + echo "$tx_output" + return 1 + fi + + echo "Transaction successful (transaction hash: $tx_hash)" + return 0 fi }