Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: Add smart contract e2e tests #85

Merged
merged 16 commits into from
Sep 24, 2024
10 changes: 10 additions & 0 deletions .github/workflows/test-e2e.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,16 @@ jobs:
pip3 install yq
yq --version

- name: Install polycli
run: |
POLYCLI_VERSION="${{ vars.POLYCLI_VERSION }}"
tmp_dir=$(mktemp -d)
curl -L "https://github.com/0xPolygon/polygon-cli/releases/download/${POLYCLI_VERSION}/polycli_${POLYCLI_VERSION}_linux_amd64.tar.gz" | tar -xz -C "$tmp_dir"
mv "$tmp_dir"/* /usr/local/bin/polycli
rm -rf "$tmp_dir"
sudo chmod +x /usr/local/bin/polycli
/usr/local/bin/polycli version

- name: Install foundry
uses: foundry-rs/foundry-toolchain@v1

Expand Down
18 changes: 9 additions & 9 deletions test/access-list-e2e.bats
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ setup() {

readonly erigon_sequencer_node=${KURTOSIS_ERIGON_SEQUENCER:-cdk-erigon-sequencer-001}
readonly kurtosis_sequencer_wrapper=${KURTOSIS_SEQUENCER_WRAPPER:-"kurtosis service exec $enclave $erigon_sequencer_node"}
readonly key=${SENDER_key:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"}
readonly key=${SENDER_PRIVATE_KEY:-"12d7de8621a77640c9241b2595ba78ce443d05e94090365ab3bb5e19df82c625"}
readonly receiver=${RECEIVER:-"0x85dA99c8a7C2C95964c8EfD687E95E632Fc533D6"}
readonly data_dir=${ACL_DATA_DIR:-"/home/erigon/data/dynamic-kurtosis-sequencer/txpool/acls"}
}
Expand Down Expand Up @@ -33,7 +33,7 @@ set_acl_mode() {
@test "Test Block List - Sending regular transaction when address not in block list" {
local value="10ether"
run set_acl_mode "blocklist"
run sendTx $l2_rpc_url $key $receiver $value
run send_tx $l2_rpc_url $key $receiver $value

assert_success
assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)"
Expand All @@ -42,7 +42,7 @@ set_acl_mode() {
@test "Test Block List - Sending contracts deploy transaction when address not in block list" {
local contract_artifact="./contracts/erc20mock/ERC20Mock.json"
run set_acl_mode "blocklist"
run deployContract $l2_rpc_url $key $contract_artifact
run deploy_contract $l2_rpc_url $key $contract_artifact

assert_success

Expand All @@ -56,7 +56,7 @@ set_acl_mode() {
run set_acl_mode "blocklist"
run add_to_access_list "blocklist" "sendTx"

run sendTx $l2_rpc_url $key $receiver $value
run send_tx $l2_rpc_url $key $receiver $value

assert_failure
assert_output --partial "sender disallowed to send tx by ACL policy"
Expand All @@ -67,7 +67,7 @@ set_acl_mode() {

run set_acl_mode "blocklist"
run add_to_access_list "blocklist" "deploy"
run deployContract $l2_rpc_url $key $contract_artifact
run deploy_contract $l2_rpc_url $key $contract_artifact

assert_failure
assert_output --partial "sender disallowed to deploy contract by ACL policy"
Expand All @@ -77,7 +77,7 @@ set_acl_mode() {
local value="10ether"

run set_acl_mode "allowlist"
run sendTx $l2_rpc_url $key $receiver $value
run send_tx $l2_rpc_url $key $receiver $value

assert_failure
assert_output --partial "sender disallowed to send tx by ACL policy"
Expand All @@ -87,7 +87,7 @@ set_acl_mode() {
local contract_artifact="./contracts/erc20mock/ERC20Mock.json"

run set_acl_mode "allowlist"
run deployContract $l2_rpc_url $key $contract_artifact
run deploy_contract $l2_rpc_url $key $contract_artifact

assert_failure
assert_output --partial "sender disallowed to deploy contract by ACL policy"
Expand All @@ -98,7 +98,7 @@ set_acl_mode() {

run set_acl_mode "allowlist"
run add_to_access_list "allowlist" "sendTx"
run sendTx $l2_rpc_url $key $receiver $value
run send_tx $l2_rpc_url $key $receiver $value

assert_success
assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)"
Expand All @@ -109,7 +109,7 @@ set_acl_mode() {

run set_acl_mode "allowlist"
run add_to_access_list "allowlist" "deploy"
run deployContract $l2_rpc_url $key $contract_artifact
run deploy_contract $l2_rpc_url $key $contract_artifact

assert_success

Expand Down
158 changes: 141 additions & 17 deletions test/basic-e2e.bats
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,176 @@ setup() {
}

@test "Send EOA transaction" {
local sender_addr=$(cast wallet address --private-key "$private_key")
local initial_nonce=$(cast nonce "$sender_addr" --rpc-url "$rpc_url") || return 1
local sender_addr=$(cast wallet address --private-key "$sender_private_key")
local initial_nonce=$(cast nonce "$sender_addr" --rpc-url "$l2_rpc_url") || return 1
local value="10ether"

# case 1: Transaction successful sender has sufficient balance
run sendTx "$l2_rpc_url" "$sender_private_key" "$receiver" "$value"
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 "$rpc_url") || return 1
local sender_balance=$(cast balance "$sender_addr" --ether --rpc-url "$l2_rpc_url") || return 1
local excessive_value=$(echo "$sender_balance + 1" | bc)"ether"
run sendTx "$private_key" "$receiver" "$excessive_value"
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 "$rpc_url") || return 1
local final_nonce=$(cast nonce "$sender_addr" --rpc-url "$l2_rpc_url") || return 1
assert_equal "$final_nonce" "$(echo "$initial_nonce + 1" | bc)"
}

@test "Deploy ERC20Mock contract" {
@test "Test ERC20Mock contract" {
local contract_artifact="./contracts/erc20mock/ERC20Mock.json"
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_B=$(cast wallet new | grep "Address" | awk '{print $2}')

# Deploy ERC20Mock
run deployContract "$l2_rpc_url" "$sender_private_key" "$contract_artifact"
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"

run sendTx "$l2_rpc_url" "$sender_private_key" "$contract_addr" "$mint_fn_sig" "$receiver" "$amount"
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}\)"

# Assert that balance is correct
run queryContract "$l2_rpc_url" "$contract_addr" "$balance_of_fn_sig" "$receiver"
## Case 2: Insufficient gas scenario => Transactions fails
# nonce would not increase since transaction fails at the node's pre-validation check
# Get bytecode from the contract artifact
local bytecode=$(jq -r .bytecode "$contract_artifact")
if [[ -z "$bytecode" || "$bytecode" == "null" ]]; then
echo "Error: Failed to read bytecode from $contract_artifact"
return 1
fi

# Estimate gas, gas price and gas cost
local gas_units=$(cast estimate --rpc-url "$l2_rpc_url" --create "$bytecode")
rachit77 marked this conversation as resolved.
Show resolved Hide resolved
gas_units=$(echo "scale=0; $gas_units / 2" | bc)
local gas_price=$(cast gas-price --rpc-url "$l2_rpc_url")
local value=$(echo "$gas_units * $gas_price" | bc)
local value_ether=$(cast to-unit "$value" ether)"ether"

# Transfer insufficient funds
rachit77 marked this conversation as resolved.
Show resolved Hide resolved
cast_output=$(cast send --rpc-url "$l2_rpc_url" --private-key "$sender_private_key" "$address_A" --value "$value_ether" --legacy 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to send transaction. Output:"
echo "$cast_output"
return 1
fi
Comment on lines +78 to +83
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you simply use the send_tx function? Seems like we could spare a couple of lines of code. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the send_tx function, there are a few redundant balance checks for the sender and receiver. These checks have already been verified in other test cases, so I decided it would be more efficient to skip them for subsequent transactions to avoid unnecessary repetition.

WDYT?

Copy link
Collaborator

@Stefan-Ethernal Stefan-Ethernal Sep 24, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like too much there are the balance checks in the send_tx, it should be extracted as a separate function IMO, and invoked only when needed (basically keeping these helper functions focused), but that's probably a separate topic...

For now, I'm ok with this, but eventually, I would like never to call the cast send explicitly but rely on the helper function (because it has validations and error checks).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Merging this for now, will refactor the part you suggested when we increase the scope e2e tests.


# Fetch initial nonce for address_A
local address_A_initial_nonce=$(cast nonce "$address_A" --rpc-url "$l2_rpc_url") || return 1
# Attempt to deploy contract with insufficient gas
run deploy_contract "$l2_rpc_url" "$address_A_private_key" "$contract_artifact"
assert_failure

## Case 3: Transaction should fail as address_A tries to transfer more tokens than it has
# nonce would not increase
# Transfer funds for gas fees to address_A
value_ether="4ether"
cast_output=$(cast send --rpc-url "$l2_rpc_url" --private-key "$sender_private_key" "$address_A" --value "$value_ether" --legacy 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to send transaction. Output:"
echo "$cast_output"
return 1
fi
Comment on lines +95 to +100
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't you simply use the send_tx function? Seems like we could spare a couple of lines of code. WDYT?


# Fetch balance of address_A to simulate excessive transfer
run query_contract "$l2_rpc_url" "$contract_addr" "$balance_of_fn_sig" "$address_A"
assert_success
local address_A_Balance=$(echo "$output" | tail -n 1)
address_A_Balance=$(echo "$address_A_Balance" | xargs)

# Set excessive amount for transfer
local excessive_amount=$(echo "$address_A_Balance + 1" | bc)

# Attempt transfer of excessive amount from address_A to address_B
local tranferFnSig="transfer(address,uint256)"
run send_tx "$l2_rpc_url" "$address_A_private_key" "$contract_addr" "$tranferFnSig" "$address_B" "$excessive_amount"
assert_failure

# Verify balance of address_A after failed transaction
run query_contract "$l2_rpc_url" "$contract_addr" "$balance_of_fn_sig" "$address_A"
assert_success
address_A_BalanceAfterFailedTx=$(echo "$output" | tail -n 1)
address_A_BalanceAfterFailedTx=$(echo "$address_A_BalanceAfterFailedTx" | xargs)

# Ensure balance is unchanged
assert_equal "$address_A_BalanceAfterFailedTx" "$address_A_Balance"

# Verify balance of address_B is still zero
run query_contract "$l2_rpc_url" "$contract_addr" "$balance_of_fn_sig" "$address_B"
assert_success
receiverBalance=$(echo "$output" | tail -n 1)
local address_B_Balance=$(echo "$output" | tail -n 1)
address_B_Balance=$(echo "$address_B_Balance" | xargs)

# Convert balance and amount to a standard format for comparison (e.g., remove any leading/trailing whitespace)
receiverBalance=$(echo "$receiverBalance" | xargs)
amount=$(echo "$amount" | xargs)
assert_equal "$address_B_Balance" "0"

# Check if the balance is equal to the amount
assert_equal "$receiverBalance" "$amount"
# Nonce should not increase
local address_A_final_nonce=$(cast nonce "$address_A" --rpc-url "$l2_rpc_url") || return 1
assert_equal "$address_A_final_nonce" "$address_A_initial_nonce"
}


@test "Deploy and test UniswapV3 contract" {
# 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}')

# Transfer funds for gas
local value_ether="50ether"
cast_output=$(cast send --rpc-url "$l2_rpc_url" --private-key "$sender_private_key" "$address_A" --value "$value_ether" --legacy 2>&1)
if [[ $? -ne 0 ]]; then
echo "Error: Failed to send transaction. Output:"
echo "$cast_output"
return 1
fi

run polycli loadtest uniswapv3 --legacy -v 600 --rpc-url $l2_rpc_url --private-key $address_A_private_key
assert_success

# Remove ANSI escape codes from the output
output=$(echo "$output" | sed -r "s/\x1B\[[0-9;]*[mGKH]//g")

# Check if the WETH9 contract were deployed
rachit77 marked this conversation as resolved.
Show resolved Hide resolved
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=WETH9"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=UniswapV3Factory"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=UniswapInterfaceMulticall"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=ProxyAdmin"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=TickLens"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=NFTDescriptor"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=NonfungibleTokenPositionDescriptor"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=TransparentUpgradeableProxy"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=NonfungiblePositionManager"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=V3Migrator"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=UniswapV3Staker"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=QuoterV2"
assert_output --regexp "Contract deployed address=0x[a-fA-F0-9]{40} name=SwapRouter02"

# Check if ERC20 tokens were minted
assert_output --regexp "Minted tokens amount=[0-9]+ recipient=0x[a-fA-F0-9]{40} token=SwapperA"
assert_output --regexp "Minted tokens amount=[0-9]+ recipient=0x[a-fA-F0-9]{40} token=SwapperB"

# Check if liquidity pool was created and initialized
assert_output --regexp "Pool created and initialized fees=[0-9]+"

# Check if liquidity was provided to the pool
assert_output --regexp "Liquidity provided to the pool liquidity=[0-9]+"

# Check if transaction got executed successfully
assert_output --regexp "Starting main load test loop currentNonce=[0-9]+"
assert_output --regexp "Finished main load test loop lastNonce=[0-9]+ startNonce=[0-9]+"
assert_output --regexp "Got final block number currentNonce=[0-9]+ final block number=[0-9]+"
assert_output --regexp "Num errors numErrors=0"
assert_output --regexp "Finished"
}

6 changes: 3 additions & 3 deletions test/bridge-e2e.bats
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ setup() {
echo "Initial receiver balance of native token on L2 $initial_receiver_balance" >&3

# Query for initial sender balance
run queryContract "$l1_rpc_url" "$gas_token_addr" "$balance_of_fn_sig" "$sender_addr"
run query_contract "$l1_rpc_url" "$gas_token_addr" "$balance_of_fn_sig" "$sender_addr"
assert_success
local gas_token_init_sender_balance=$(echo "$output" | tail -n 1 | awk '{print $1}')
echo "Initial sender balance $gas_token_init_sender_balance" of gas token on L1 >&3
Expand All @@ -90,7 +90,7 @@ setup() {
assert_success

# Assert that balance of gas token (on the L1) is correct
run queryContract "$l1_rpc_url" "$gas_token_addr" "$balance_of_fn_sig" "$sender_addr"
run query_contract "$l1_rpc_url" "$gas_token_addr" "$balance_of_fn_sig" "$sender_addr"
assert_success
local gas_token_final_sender_balance=$(echo "$output" |
tail -n 1 |
Expand All @@ -104,7 +104,7 @@ setup() {

# Send approve transaction to the gas token on L1
deposit_ether_value="0.1ether"
run sendTx "$l1_rpc_url" "$sender_private_key" "$gas_token_addr" "$approve_fn_sig" "$bridge_addr" "$deposit_ether_value"
run send_tx "$l1_rpc_url" "$sender_private_key" "$gas_token_addr" "$approve_fn_sig" "$bridge_addr" "$deposit_ether_value"
assert_success
assert_output --regexp "Transaction successful \(transaction hash: 0x[a-fA-F0-9]{64}\)"

Expand Down
Loading
Loading