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

added tests for simulate_solana #467

Draft
wants to merge 1 commit into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion integration/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,7 @@ def events_checker_contract(web3_client, accounts) -> tp.Any:


@pytest.fixture(scope="class")
def counter_contract(web3_client, accounts):
def counter_contract(web3_client, accounts) -> Contract:
contract, _ = web3_client.deploy_and_get_contract("common/Counter", "0.8.10", account=accounts[0])
return contract

Expand Down
16 changes: 15 additions & 1 deletion integration/tests/neon_evm/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ def calculator_contract(
return deploy_contract(operator_keypair, session_user, "calculator", evm_loader, treasury_pool)


@pytest.fixture(scope="session")
def counter_contract(
evm_loader: EvmLoader, operator_keypair: Keypair, session_user: Caller, treasury_pool
) -> Contract:
return deploy_contract(
operator=operator_keypair,
user=session_user,
contract_file_name="common/Counter",
evm_loader=evm_loader,
treasury_pool=treasury_pool,
version="0.8.10",
)


@pytest.fixture(scope="session")
def calculator_caller_contract(
evm_loader: EvmLoader, operator_keypair: Keypair, session_user: Caller, treasury_pool, calculator_contract
Expand Down Expand Up @@ -245,7 +259,7 @@ def erc20_for_spl(


@pytest.fixture(scope="session")
def neon_api_client():
def neon_api_client() -> NeonApiClient:
client = NeonApiClient(url=NEON_CORE_API_URL)
return client

Expand Down
69 changes: 68 additions & 1 deletion integration/tests/neon_evm/test_execute_trx_from_instruction.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import os
import random
import string

Expand All @@ -12,11 +13,14 @@
from solana.rpc.core import RPCException as SolanaRPCException
from spl.token.instructions import get_associated_token_address

from utils.types import Caller, Contract
from utils.evm_loader import EvmLoader
from utils.instructions import TransactionWithComputeBudget, make_ExecuteTrxFromInstruction
from utils.types import Caller, Contract, TreasuryPool
from .utils.assert_messages import InstructionAsserts
from .utils.constants import NEON_TOKEN_MINT_ID
from .utils.contract import make_contract_call_trx
from .utils.ethereum import make_eth_transaction
from .utils.neon_api_client import NeonApiClient
from .utils.storage import create_holder
from .utils.transaction_checks import check_transaction_logs_have_text

Expand Down Expand Up @@ -462,3 +466,66 @@ def test_old_trx_type_with_leading_zeros(
],
)
check_transaction_logs_have_text(resp, "exit_status=0x12")

def test_simulate_solana_iterative(
self,
sender_with_tokens: Caller,
neon_api_client: NeonApiClient,
operator_keypair: Keypair,
evm_loader: EvmLoader,
holder_acc: Pubkey,
treasury_pool: TreasuryPool,
counter_contract: Contract,
):
# Create Neon transaction
neon_signed_tx = make_contract_call_trx(
evm_loader=evm_loader,
user=sender_with_tokens,
contract=counter_contract,
function_signature="moreInstructionWithLogs(uint,uint)",
params=[0, 1000],
)

# Create Solana transaction
sol_tx = TransactionWithComputeBudget(operator_keypair)
operator_balance = evm_loader.get_operator_balance_pubkey(operator_keypair)

sol_tx.add(
make_ExecuteTrxFromInstruction(
operator_keypair,
operator_balance,
holder_acc,
evm_loader.loader_id,
treasury_pool.account,
treasury_pool.buffer,
neon_signed_tx.rawTransaction,
[
sender_with_tokens.balance_account_address,
counter_contract.solana_address,
counter_contract.solana_address,
],
)
)

sol_tx.sign(operator_keypair)

# Simulate the transaction in Evm Loader
serialized_transaction = sol_tx.serialize()
hex_serialized_transaction = serialized_transaction.hex()

simulate_response = neon_api_client.simulate_solana(
blockhash=os.urandom(32).hex(),
transactions=[hex_serialized_transaction],
)

simulated_compute_units = sum(
[simulate_result["executed_units"] for simulate_result in simulate_response.json()["value"]["transactions"]]
)

# Execute the transaction in Evm Loader
executed_sol_tx = evm_loader.send_tx(sol_tx, operator_keypair)
actual_compute_units = executed_sol_tx.value.transaction.meta.compute_units_consumed

# Compare simulation and execution results
msg = f"Simulated: {simulated_compute_units}, executed: {actual_compute_units}"
assert simulated_compute_units == actual_compute_units, msg
8 changes: 8 additions & 0 deletions integration/tests/neon_evm/utils/neon_api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ def get_balance(self, ether, chain_id = CHAIN_ID):
}
return requests.post(url=f"{self.url}/balance", json=body, headers=self.headers).json()

def simulate_solana(self, blockhash: str, transactions: list[str]) -> requests.Response:
body = {
"blockhash": blockhash,
"transactions": transactions,
}
return requests.post(url=f"{self.url}/simulate_solana", json=body, headers=self.headers)


def call_contract_get_function(self, sender, contract, function_signature: str, args=None):
data = abi.function_signature_to_4byte_selector(function_signature)
if args is not None:
Expand Down
4 changes: 2 additions & 2 deletions utils/evm_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ def execute_trx_from_instruction(
signer: Keypair = None,
system_program=sp.ID,
compute_unit_price=None,
) -> SendTransactionResp:
) -> GetTransactionResp:
signer = operator if signer is None else signer
trx = TransactionWithComputeBudget(operator, compute_unit_price=compute_unit_price)
operator_balance = self.get_operator_balance_pubkey(operator)
Expand Down Expand Up @@ -233,7 +233,7 @@ def execute_trx_from_account(
additional_accounts,
signer: Keypair,
system_program=sp.ID,
) -> SendTransactionResp:
) -> GetTransactionResp:
operator_balance = self.get_operator_balance_pubkey(operator)

trx = TransactionWithComputeBudget(operator)
Expand Down
2 changes: 1 addition & 1 deletion utils/solana_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def send_tx_and_check_status_ok(self, tx, *signers):
sig_status = json.loads(statuses_resp.to_json())
assert sig_status["result"]["value"][0]["status"] == {"Ok": None}, f"error:{sig_status}"

def send_tx(self, trx: Transaction, *signers: Keypair, wait_status=Confirmed):
def send_tx(self, trx: Transaction, *signers: Keypair, wait_status=Confirmed) -> GetTransactionResp:
result = self.send_transaction(trx, *signers,
opts=TxOpts(skip_confirmation=True, preflight_commitment=wait_status))
self.confirm_transaction(result.value, commitment=Confirmed)
Expand Down
Loading