Skip to content

Commit

Permalink
updated eip-1559 tests
Browse files Browse the repository at this point in the history
  • Loading branch information
IvanAdamovNeon committed Feb 7, 2025
1 parent fc32f01 commit 7c3629a
Show file tree
Hide file tree
Showing 12 changed files with 157 additions and 39 deletions.
118 changes: 99 additions & 19 deletions integration/tests/basic/erc/test_EIP1559.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from utils import helpers
from utils.apiclient import JsonRPCSession
from utils.consts import InstructionTags, COMPUTE_BUDGET_ID
from utils.faucet import Faucet
from utils.models.fee_history_model import EthFeeHistoryResult
from utils.solana_client import SolanaClient
Expand Down Expand Up @@ -103,7 +104,7 @@ def validate_transfer_positive(
base_fee_multiplier = 1.1
max_fee_per_gas = int((base_fee_multiplier * base_fee_per_gas) + max_priority_fee_per_gas)

value = balance_sender_before // 2
value = 10

tx_params = web3_client.make_raw_tx_eip_1559(
chain_id="auto",
Expand Down Expand Up @@ -175,7 +176,7 @@ def validate_deploy_positive(
latest_block: web3.types.BlockData = web3_client._web3.eth.get_block(block_identifier="latest") # noqa
base_fee_per_gas = latest_block.baseFeePerGas # noqa
max_priority_fee_per_gas = web3_client._web3.eth._max_priority_fee() # noqa
max_fee_per_gas = (5 * base_fee_per_gas) + max_priority_fee_per_gas
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas

tx_params = web3_client.make_raw_tx_eip_1559(
chain_id="auto",
Expand Down Expand Up @@ -206,7 +207,7 @@ def validate_deploy_positive(

# Validate that sender's balance decreased by at least the gas fee
assert (
balance_before - balance_after <= total_fee_paid
balance_before - total_fee_paid == balance_after
), f"Sender balance did not decrease by gas fee: {balance_before, balance_after, total_fee_paid}"

# Verify that the effective gas price does not exceed the max fee per gas
Expand All @@ -226,6 +227,7 @@ def validate_deploy_positive(
@allure.feature("EIP Verifications")
@allure.story("EIP-1559: New Transaction Type Support in Neon")
@pytest.mark.usefixtures("accounts", "web3_client")
@pytest.mark.eip_1559
class TestEIP1559:
web3_client: NeonChainWeb3Client
accounts: EthAccounts
Expand Down Expand Up @@ -445,23 +447,22 @@ def test_too_low_fee(
self.web3_client.send_transaction(account=sender, transaction=tx_params, timeout=TX_TIMEOUT)

@pytest.mark.neon_only
@pytest.mark.parametrize("base_fee_multiplier", [1.1, 1.5])
def test_compute_unit_price(
def test_compute_unit_price_default_value(
self,
accounts: EthAccounts,
web3_client: NeonChainWeb3Client,
json_rpc_client: JsonRPCSession,
sol_client: SolanaClient,
base_fee_multiplier,
):
sender = accounts[0]
recipient = accounts[1]

max_priority_fee_per_gas = web3_client.max_priority_fee_per_gas()
base_fee_per_gas = web3_client.base_fee_per_gas()
base_fee_multiplier = 1.1
max_fee_per_gas = int((base_fee_multiplier * base_fee_per_gas) + max_priority_fee_per_gas)

value = 1029380121
value = 10

tx_params = web3_client.make_raw_tx_eip_1559(
chain_id="auto",
Expand All @@ -479,26 +480,102 @@ def test_compute_unit_price(

receipt = web3_client.send_transaction(account=sender, transaction=tx_params)
assert receipt.type == 2
solana_transaction_hash = web3_client.get_solana_trx_by_neon(receipt["transactionHash"].hex())["result"][0]
solana_transaction = sol_client.get_transaction_with_wait(Signature.from_string(solana_transaction_hash))
solana_transactions = web3_client.get_solana_trx_by_neon(receipt["transactionHash"].hex())["result"]
assert len(solana_transactions) == 1
solana_transaction = sol_client.get_transaction_with_wait(Signature.from_string(solana_transactions[0]))

# get ComputeBudget key index
compute_budget_index = -1
for index, account_key in enumerate(solana_transaction.value.transaction.transaction.message.account_keys):
if account_key == COMPUTE_BUDGET_ID:
compute_budget_index = index
break
assert compute_budget_index >= 0, "ComputeBudget not found"

# get setComputeUnitPrice value
cu_price_actual = 0
for instruction in solana_transaction.value.transaction.transaction.message.instructions:
if instruction.program_id_index == compute_budget_index:
decoded_data = base58.b58decode(instruction.data)
instruction_code = decoded_data[:1]
instruction_data = int.from_bytes(decoded_data[1:], "little")
if instruction_code == InstructionTags.SET_COMPUTE_UNIT_PRICE:
cu_price_actual = instruction_data

# make sure the compute unit price equals default value set by var DEFAULT_CU_PRICE in proxy
assert cu_price_actual == 10500

data_list = [instr.data for instr in solana_transaction.value.transaction.transaction.message.instructions]
@pytest.mark.neon_only
def test_compute_unit_price_estimated_value(
self,
accounts: EthAccounts,
web3_client: NeonChainWeb3Client,
json_rpc_client: JsonRPCSession,
sol_client: SolanaClient,
):
account = accounts[0]
contract_iface = helpers.get_contract_interface(
contract="common/Common.sol",
version="0.8.12",
contract_name="Common",
)

cu_price = None
for data in data_list:
instruction_code = base58.b58decode(data).hex()[0:2]
if instruction_code == "03":
cu_price = int.from_bytes(bytes.fromhex(base58.b58decode(data).hex()[2:]), "little")
max_priority_fee_per_gas = web3_client.max_priority_fee_per_gas()
base_fee = int(web3_client.base_fee_per_gas() / 40000) # make it small
max_fee_per_gas = base_fee + max_priority_fee_per_gas

if cu_price is not None:
assert cu_price > 0
else:
raise Exception(f"Compute Budget instruction is not found in Solana transaction {solana_transaction}")
tx_params = web3_client.make_raw_tx_eip_1559(
chain_id="auto",
from_=account.address,
to=None,
value=0,
nonce="auto",
gas="auto",
max_priority_fee_per_gas=max_priority_fee_per_gas,
max_fee_per_gas=max_fee_per_gas,
data=contract_iface["bin"],
access_list=None,
)

receipt = web3_client.send_transaction(account=account, transaction=tx_params)
solana_transaction_hashes = web3_client.get_solana_trx_by_neon(receipt["transactionHash"].hex())["result"]
assert len(solana_transaction_hashes) > 1

# first transactions are "WriteToHolder", so we're interested only in the last one
solana_transaction_hash = solana_transaction_hashes[-1]
solana_transaction = sol_client.get_transaction_with_wait(Signature.from_string(solana_transaction_hash))

# get ComputeBudget index
compute_budget_index = -1
for index, account_key in enumerate(solana_transaction.value.transaction.transaction.message.account_keys):
if account_key == COMPUTE_BUDGET_ID:
compute_budget_index = index
break
assert compute_budget_index >= 0, "ComputeBudget not found"

# get setComputeUnitLimit and setComputeUnitPrice values
cu_price_actual = compute_unit_limit = 0
for instruction in solana_transaction.value.transaction.transaction.message.instructions:
if instruction.program_id_index == compute_budget_index:
decoded_data = base58.b58decode(instruction.data)
instruction_code = decoded_data[:1]
instruction_data = int.from_bytes(decoded_data[1:], "little")

match instruction_code:
case InstructionTags.SET_COMPUTE_UNIT_PRICE:
cu_price_actual = instruction_data
case InstructionTags.SET_COMPUTE_UNIT_LIMIT:
compute_unit_limit = instruction_data

# validate formula computeUnitPrice = baseFeePerGas∗10^{10} / computeUnitLimit / maxPriorityFeePerGas
cu_price_expected = int(base_fee * 10**10 / compute_unit_limit / max_priority_fee_per_gas)
assert cu_price_actual == cu_price_expected, f"Actual: {cu_price_actual}, Expected: {cu_price_expected}"


@allure.feature("EIP Verifications")
@allure.story("EIP-1559: Verify JSON-RPC method eth_maxPriorityFeePerGas")
@pytest.mark.usefixtures("eip1559_setup")
@pytest.mark.eip_1559
class TestRpcMaxPriorityFeePerGas:
@pytest.mark.need_eip1559_blocks(10)
def test_positive(
Expand All @@ -519,6 +596,7 @@ def test_positive(
@allure.story("EIP-1559: Verify JSON-RPC method eth_feeHistory")
@pytest.mark.usefixtures("eip1559_setup")
@pytest.mark.neon_only
@pytest.mark.eip_1559
class TestRpcFeeHistory:
"""
eth_feeHistory
Expand Down Expand Up @@ -758,6 +836,7 @@ def test_negative_cases(
@allure.feature("EIP Verifications")
@allure.story("EIP-1559: Verify accessList does not break transactions")
@pytest.mark.usefixtures("accounts", "web3_client")
@pytest.mark.eip_1559
class TestAccessList:
web3_client: NeonChainWeb3Client
accounts: EthAccounts
Expand Down Expand Up @@ -807,6 +886,7 @@ def test_deploy(
@allure.feature("EIP Verifications")
@allure.story("EIP-1559: multiple tokens")
@pytest.mark.neon_only
@pytest.mark.eip_1559
class TestMultipleTokens:
@pytest.mark.multipletokens
def test_transfer_positive(
Expand Down
8 changes: 4 additions & 4 deletions integration/tests/basic/evm/opcodes/test_base_opcodes.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import allure
import pytest
import web3
from web3.contract import Contract

from utils.accounts import EthAccounts
from utils.consts import ZERO_HASH
Expand All @@ -26,7 +27,7 @@ def mcopy_checker(self, web3_client, faucet, accounts):
return contract

@pytest.fixture(scope="class")
def basefee_checker(self, web3_client, accounts):
def basefee_checker(self, web3_client, accounts) -> Contract:
contract, _ = web3_client.deploy_and_get_contract(
contract="opcodes/EIP1559BaseFee.sol",
contract_name="BaseFeeOpcode",
Expand Down Expand Up @@ -124,16 +125,15 @@ def test_base_fee_trx_type_0(
base_fee_from_log = basefee_checker.events.Log().process_receipt(resp)[0]["args"]["baseFee"]
assert base_fee_from_log == web3_client.gas_price()

@pytest.mark.eip_1559
def test_base_fee_trx_type_2(
self,
web3_client: NeonChainWeb3Client,
accounts: EthAccounts,
basefee_checker,
basefee_checker: Contract,
):
tx = web3_client.make_raw_tx(accounts[0], tx_type=TransactionType.EIP_1559)
instruction_tx = basefee_checker.functions.baseFeeTrx().build_transaction(tx)
instruction_tx["maxFeePerGas"] = 3000000000
instruction_tx["maxPriorityFeePerGas"] = 2500000000
resp = web3_client.send_transaction(accounts[0], instruction_tx)
base_fee_from_log = basefee_checker.events.Log().process_receipt(resp)[0]["args"]["baseFee"]
# Neon specific, it uses maxPriorityFee to pay an Operator
Expand Down
3 changes: 2 additions & 1 deletion integration/tests/basic/rpc/test_eip_1559_eth_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
@allure.feature("EIP Verifications")
@allure.story("EIP-1559: Verify new fields in eth_ JSON-RPC methods")
@pytest.mark.neon_only
@pytest.mark.eip_1559
class TestRpcEthMethods:
def test_get_transaction_by_hash(
self,
Expand All @@ -22,7 +23,7 @@ def test_get_transaction_by_hash(

base_fee_per_gas = web3_client.base_fee_per_gas()
max_priority_fee_per_gas = web3_client._web3.eth._max_priority_fee() # noqa
max_fee_per_gas = (5 * base_fee_per_gas) + max_priority_fee_per_gas
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas

receipt = web3_client.send_tokens_eip_1559(
from_=sender,
Expand Down
5 changes: 3 additions & 2 deletions integration/tests/basic/rpc/test_eip_1559_neon_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
@allure.feature("EIP Verifications")
@allure.story("EIP-1559: Verify new fields in neon_ JSON-RPC methods")
@pytest.mark.neon_only
@pytest.mark.eip_1559
class TestRpcNeonMethods:
def test_neon_get_transaction_by_sender_nonce(
self,
Expand All @@ -21,7 +22,7 @@ def test_neon_get_transaction_by_sender_nonce(
nonce = web3_client.get_nonce(address=sender.address)
base_fee_per_gas = web3_client.base_fee_per_gas()
max_priority_fee_per_gas = web3_client._web3.eth._max_priority_fee() # noqa
max_fee_per_gas = (5 * base_fee_per_gas) + max_priority_fee_per_gas
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas

web3_client.send_tokens_eip_1559(
from_=sender,
Expand Down Expand Up @@ -75,7 +76,7 @@ def test_neon_get_transaction_receipt(

base_fee_per_gas = web3_client.base_fee_per_gas()
max_priority_fee_per_gas = web3_client.max_priority_fee_per_gas()
max_fee_per_gas = (5 * base_fee_per_gas) + max_priority_fee_per_gas
max_fee_per_gas = (2 * base_fee_per_gas) + max_priority_fee_per_gas

receipt = web3_client.send_tokens_eip_1559(
from_=sender,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def test_send_simple_single_trx(self, web3_client_sol, neon_user, common_contrac
assert pending_trx[hex(tx.nonce)][0]["status"] in ("Done", "InProgress")
assert common_contract.functions.getNumber().call() == contract_data

@pytest.mark.eip_1559
def test_multiple_scheduled_trx(self, web3_client_sol, neon_user, common_contract, evm_loader, treasury_pool):
nonce = web3_client_sol.get_nonce(neon_user.checksum_address)
contract_data = 18
Expand Down Expand Up @@ -77,6 +78,7 @@ def test_multiple_scheduled_trx(self, web3_client_sol, neon_user, common_contrac
assert pending_trx[hex(nonce)][0]["status"] == "Done"
assert pending_trx[hex(nonce)][0]["hash"][2:] == trxs[0].hash().hex()

@pytest.mark.eip_1559
def test_multiple_scheduled_trx_with_failed_trx(
self, web3_client_sol, neon_user, treasury_pool, revert_contract_caller, event_caller_contract, evm_loader
):
Expand Down Expand Up @@ -225,6 +227,7 @@ def test_scheduled_trx_send_tokens_to_sol_chain_contract(
assert event_logs[0].args.value == value
assert event_logs[0].event == "IndexedArgs"

@pytest.mark.eip_1559
def test_scheduled_trx_with_timestamp(
self, block_timestamp_contract, web3_client_sol, neon_user, treasury_pool, evm_loader, json_rpc_client
):
Expand Down Expand Up @@ -277,6 +280,7 @@ def test_scheduled_trx_with_timestamp(
assert added_timestamp <= int(tx_block_timestamp, 16)
assert contract.functions.getDataFromMapping(added_timestamp).call() == [v1, v2]

@pytest.mark.eip_1559
def test_scheduled_trx_with_small_gas_limit(
self, block_timestamp_contract, web3_client_sol, neon_user, treasury_pool, evm_loader, event_caller_contract
):
Expand Down
Loading

0 comments on commit 7c3629a

Please sign in to comment.