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

Add two tests for address zero + EVM contract bug tests #81

Open
wants to merge 3 commits into
base: integration-more-tests
Choose a base branch
from
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ pub(crate) async fn test_2k_txs(
let info = telos_client.v1_chain.get_info().await.unwrap();
let nonce = get_nonce(&telos_client, &EOSIO_ADDR).await;
let tx = multi_raw_eth_tx(
500,
100,
&info,
name!("eosio"),
PermissionLevel::new(name!("eosio"), name!("active")),
Expand All @@ -73,11 +73,11 @@ pub(crate) async fn test_2k_txs(

let result = telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

debug!("({}/{}) 500 txs in block {}", i + 1, total_batches, result.processed.block_num);
debug!("({}/{}) 100 txs in block {}", i + 1, total_batches, result.processed.block_num);
tokio::time::sleep(Duration::from_secs(2)).await;
}

tokio::time::sleep(Duration::from_secs(3)).await;
let last_nonce = get_nonce(&telos_client, &EOSIO_ADDR).await;
assert_eq!(last_nonce - start_nonce, 500 * total_batches);
assert_eq!(last_nonce - start_nonce, 100 * total_batches);
}
315 changes: 311 additions & 4 deletions crates/telos/node/tests/integration/test_tx_types.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,30 @@
use std::str::FromStr;
use std::time::Duration;
use alloy_consensus::{Signed, TxLegacy};
use alloy_network::TransactionBuilder;
use alloy_primitives::{hex, keccak256, Address, Bytes, Signature, B256, U256};
use alloy_primitives::{hex, keccak256, Address, Bytes, Signature, TxKind, B256, U256};
use alloy_provider::Provider;
use alloy_rpc_types::{AccessList, AccessListItem, TransactionInput, TransactionRequest};
use alloy_rpc_types::BlockNumberOrTag::Latest;
use antelope::chain::checksum::Checksum256;
use alloy_sol_types::sol;
use alloy_sol_types::sol_data::Bool;
use antelope::api::system::structs::CreateAccountParams;
use antelope::api::system::SystemAPI;
use antelope::api::v1::structs::{GetTableRowsParams, IndexPosition, TableIndexType};
use antelope::chain::asset::Asset;
use antelope::chain::authority::{Authority, KeyWeight};
use antelope::chain::name::Name;
use antelope::chain::private_key::PrivateKey;
use antelope::name;
use telos_translator_rs::types::evm_types::AccountRow;
use telos_translator_rs::types::names::EOSIO;
use tracing::debug;
use crate::{APIClient, DefaultProvider, EOSIO_PKEY, sign_native_tx};
use antelope::chain::checksum::{Checksum160, Checksum256};
use num_bigint::{BigUint, ToBigUint};
use telos_translator_rs::rlp::telos_rlp_decode::TelosTxDecodable;
use tracing::log::info;
use crate::utils::cleos_evm::{TestProvider, EOSIO_ADDR, EVM_USER_ADDR};
use crate::utils::cleos_evm::{transfer_tx, TestProvider, EOSIO_ADDR, EVM_USER, EVM_USER_ADDR};

// test_1559_tx tests sending eip1559 transaction that has max_priority_fee_per_gas and max_fee_per_gas set
pub(crate) async fn test_1559_tx(provider: &TestProvider) {
Expand Down Expand Up @@ -133,7 +148,7 @@ pub(crate) async fn test_wrong_nonce(provider: &TestProvider) {
let err = tx_result.unwrap_err();
assert_eq!(
err.to_string(),
"server returned an error response: error code -32003: nonce too low: next nonce 8, tx nonce 0"
"server returned an error response: error code -32003: nonce too low: next nonce 10, tx nonce 0"
)
}

Expand Down Expand Up @@ -338,3 +353,295 @@ fn make_unique_vrs(
let s = U256::from_be_slice(&s_bytes);
Signature::from_rs_and_parity(r, s, v).expect("Failed to create signature")
}

pub(crate) async fn test_deposit_to_address_zero(provider: &TestProvider, telos_client: &APIClient<DefaultProvider>) {
info!("test deposit to address zero");

// Get address zero balance before deposit
let address_zero_balance_before = provider.get_balance(Address::ZERO).await.unwrap();

let sys_api = SystemAPI::new(telos_client.clone());
let info = telos_client.v1_chain.get_info().await.unwrap();

// Create a test native account for deposit
let acc = Name::new_from_str("testdepzero1");
let acc_key = PrivateKey::from_str("5KKvUgsrcgJCCCqYkPgWCr4pzT6awYG7wn95XCcv142X1uStnxe", false).unwrap();

sys_api.create_account(CreateAccountParams{
creator: name!("eosio"),
name: acc,
stake_net: Asset::from_string("0.1000 TLOS"),
stake_cpu: Asset::from_string("0.1000 TLOS"),
ram_bytes: 10_000_000,
owner: Authority {threshold: 1, keys: vec![KeyWeight{key: acc_key.to_public(), weight: 1}], accounts: vec![], waits: vec![]},
active: Authority {threshold: 1, keys: vec![KeyWeight{key: acc_key.to_public(), weight: 1}], accounts: vec![], waits: vec![]},
transfer: true
}, EOSIO_PKEY.clone()).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Transfer 0.0001 TLOS to the created test account
let tx = transfer_tx(&info, Name::from_u64(EOSIO), acc, 1, vec![]);
let signed_tx = sign_native_tx(&tx, &info, &EOSIO_PKEY);
telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Do openwallet for address zero if it is not created yet
let query_params_account = GetTableRowsParams {
code: name!("eosio.evm"),
table: name!("account"),
scope: None,
lower_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap())),
upper_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap())),
limit: Some(1),
reverse: None,
index_position: Some(IndexPosition::SECONDARY),
show_payer: None,
};
let account_rows = telos_client.v1_chain.get_table_rows::<AccountRow>(query_params_account).await;
if let Ok(account_rows) = account_rows {
if account_rows.rows.len() != 1 || account_rows.rows[0].address != Checksum160::from_hex("0000000000000000000000000000000000000000").unwrap() {
// Address zero doesn't exist
let create_tx = crate::utils::cleos_evm::openwallet_tx(&info, Name::from_u64(EOSIO), Address::ZERO);
let signed_create_tx = sign_native_tx(&create_tx, &info, &EOSIO_PKEY);
telos_client.v1_chain.send_transaction(signed_create_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;
}
}

// Deposit 0.0001 TLOS to address zero
let memo = vec![48, 120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48];
let tx = transfer_tx(&info, acc, name!("eosio.evm"), 1, memo);
let signed_tx = sign_native_tx(&tx, &info, &acc_key);
telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Get address balance after deposit
let address_zero_balance_after = provider.get_balance(Address::ZERO).await.unwrap();

// Check if the balance is increased by 0.0001 TLOS
assert_eq!(address_zero_balance_after-address_zero_balance_before,U256::from(100000000000000_u64));
}

pub(crate) async fn test_deposit_lower_than_address_zero_balance(provider: &TestProvider, telos_client: &APIClient<DefaultProvider>) {
info!("test deposit lower than address zero balance");

// Get address zero balance before deposit
let address_zero_balance_before = provider.get_balance(Address::ZERO).await.unwrap();
let address_evm_user_balance_before = provider.get_balance(*EVM_USER_ADDR).await.unwrap();

let sys_api = SystemAPI::new(telos_client.clone());
let info = telos_client.v1_chain.get_info().await.unwrap();

// Create a test native account for deposit
let acc = Name::new_from_str("testdepzero2");
let acc_key = PrivateKey::from_str("5Hviu1MqZqBjrJ5EQyYBhn9xtQbxG8fYQWDX3ihN9n9D7DvXCqE", false).unwrap();

sys_api.create_account(CreateAccountParams{
creator: name!("eosio"),
name: acc,
stake_net: Asset::from_string("0.1000 TLOS"),
stake_cpu: Asset::from_string("0.1000 TLOS"),
ram_bytes: 10_000_000,
owner: Authority {threshold: 1, keys: vec![KeyWeight{key: acc_key.to_public(), weight: 1}], accounts: vec![], waits: vec![]},
active: Authority {threshold: 1, keys: vec![KeyWeight{key: acc_key.to_public(), weight: 1}], accounts: vec![], waits: vec![]},
transfer: true
}, EOSIO_PKEY.clone()).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Transfer 0.0003 TLOS to the created test account
let tx = transfer_tx(&info, Name::from_u64(EOSIO), acc, 3, vec![]);
let signed_tx = sign_native_tx(&tx, &info, &EOSIO_PKEY);
telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Do openwallet for address zero if it is not created yet
let query_params_account = GetTableRowsParams {
code: name!("eosio.evm"),
table: name!("account"),
scope: None,
lower_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap())),
upper_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap())),
limit: Some(1),
reverse: None,
index_position: Some(IndexPosition::SECONDARY),
show_payer: None,
};
let account_rows = telos_client.v1_chain.get_table_rows::<AccountRow>(query_params_account).await;
if let Ok(account_rows) = account_rows {
if account_rows.rows.len() != 1 || account_rows.rows[0].address != Checksum160::from_hex("0000000000000000000000000000000000000000").unwrap() {
// Address zero doesn't exist
let create_tx = crate::utils::cleos_evm::openwallet_tx(&info, Name::from_u64(EOSIO), Address::ZERO);
let signed_create_tx = sign_native_tx(&create_tx, &info, &EOSIO_PKEY);
telos_client.v1_chain.send_transaction(signed_create_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;
}
}

// Deposit 0.0002 TLOS to address zero
let memo = vec![48, 120, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48];
let tx = transfer_tx(&info, acc, name!("eosio.evm"), 2, memo);
let signed_tx = sign_native_tx(&tx, &info, &acc_key);
telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Deposit 0.0001 TLOS (less than address zero balance) to another address
let tx = transfer_tx(&info, acc, name!("eosio.evm"), 1, EVM_USER_ADDR.to_string().into_bytes());
let signed_tx = sign_native_tx(&tx, &info, &acc_key);
telos_client.v1_chain.send_transaction(signed_tx).await.unwrap();

tokio::time::sleep(Duration::from_secs(1)).await;

// Get address balance after deposit
let address_zero_balance_after = provider.get_balance(Address::ZERO).await.unwrap();
let address_evm_user_balance_after = provider.get_balance(*EVM_USER_ADDR).await.unwrap();

// Check if the balance of address zero is increased by 0.0002 TLOS
assert_eq!(address_zero_balance_after-address_zero_balance_before,U256::from(200000000000000_u64));

// Check if the balance of evm user address is increased by 0.0001 TLOS
assert_eq!(address_evm_user_balance_after-address_evm_user_balance_before,U256::from(100000000000000_u64));
}

pub(crate) async fn test_get_account_bug(reth_provider: &TestProvider, telos_client: &APIClient<DefaultProvider>, expected_outcome: bool) {
info!("test get account bug, expected outcome: {}", expected_outcome);

let address1 = Address::random();
let address2 = Address::random();

let nonce = reth_provider.get_transaction_count(*EOSIO_ADDR).await.unwrap();
let chain_id = reth_provider.get_chain_id().await.unwrap();
let gas_price = reth_provider.get_gas_price().await.unwrap();

sol! {
#[sol(rpc, bytecode="608060405234801561001057600080fd5b50610226806100206000396000f3fe60806040526004361061001e5760003560e01c80633ab79a6f14610023575b600080fd5b61003d60048036038101906100389190610146565b61003f565b005b600060023461004e91906101bf565b90508273ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015610096573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f193505050501580156100dd573d6000803e3d6000fd5b50505050565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610113826100e8565b9050919050565b61012381610108565b811461012e57600080fd5b50565b6000813590506101408161011a565b92915050565b6000806040838503121561015d5761015c6100e3565b5b600061016b85828601610131565b925050602061017c85828601610131565b9150509250929050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006101ca82610186565b91506101d583610186565b9250826101e5576101e4610190565b5b82820490509291505056fea264697066735822122075ae86f5524f94936eaa0251c4a94d92a5b02e384606fa1685efc83200e6143164736f6c63430008130033")]
contract SplitPayment {
function splitTransfer(address payable recipient1, address payable recipient2) external payable {
uint256 half = msg.value / 2;
recipient1.transfer(half);
recipient2.transfer(half);
}
}
}

let legacy_tx = alloy_consensus::TxLegacy {
chain_id: Some(chain_id),
nonce,
gas_price: gas_price.into(),
gas_limit: 20_000_000,
to: TxKind::Create,
value: U256::ZERO,
input: SplitPayment::BYTECODE.to_vec().into(),
};

let legacy_tx_request = TransactionRequest {
from: Some(*EOSIO_ADDR),
to: Some(legacy_tx.to),
gas: Some(legacy_tx.gas_limit as u64),
gas_price: Some(legacy_tx.gas_price),
value: Some(legacy_tx.value),
input: TransactionInput::from(legacy_tx.input),
nonce: Some(legacy_tx.nonce),
chain_id: legacy_tx.chain_id,
..Default::default()
};

let deploy_result = reth_provider.send_transaction(legacy_tx_request.clone()).await.unwrap();

let deploy_tx_hash = deploy_result.tx_hash();
debug!("Deployed contract with tx hash: {deploy_tx_hash}");
let receipt = deploy_result.get_receipt().await.unwrap();
debug!("Receipt: {:?}", receipt);


let deployed_contract_address = receipt.contract_address.unwrap();
let split_payment = SplitPayment::new(deployed_contract_address, reth_provider.clone());

let legacy_tx_request = TransactionRequest::default()
.with_from(*EOSIO_ADDR)
.with_to(deployed_contract_address)
.with_gas_limit(20_000_000)
.with_gas_price(gas_price)
.with_input(split_payment.splitTransfer(address1, address2).calldata().clone())
.with_nonce(reth_provider.get_transaction_count(*EOSIO_ADDR).await.unwrap())
.with_chain_id(chain_id)
.with_value(U256::from_str("2").unwrap());

let call_result = reth_provider.send_transaction(legacy_tx_request.clone()).await.unwrap();

let call_tx_hash = call_result.tx_hash();
debug!("Called contract with tx hash: {call_tx_hash}");
let receipt = call_result.get_receipt().await.unwrap();
debug!("Receipt: {:?}", receipt);

let mut address1_256 = [0; 32];
address1_256[12..32].copy_from_slice(address1.as_slice());
let query_params_account = GetTableRowsParams {
code: name!("eosio.evm"),
table: name!("account"),
scope: None,
lower_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_bytes(&address1_256).unwrap())),
upper_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_bytes(&address1_256).unwrap())),
limit: Some(1),
reverse: None,
index_position: Some(IndexPosition::SECONDARY),
show_payer: None,
};
let account_rows = telos_client.v1_chain.get_table_rows::<AccountRow>(query_params_account).await;
if let Ok(account_rows) = account_rows {
assert_eq!(account_rows.rows.len(), 1);
assert_eq!(account_rows.rows[0].address, Checksum160::from_bytes(address1.as_slice()).unwrap());
if expected_outcome == true {
assert_eq!(account_rows.rows[0].balance, Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000002").unwrap());
} else {
assert_eq!(account_rows.rows[0].balance, Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap());
}
}

let mut address2_256 = [0; 32];
address2_256[12..32].copy_from_slice(address2.as_slice());
let query_params_account = GetTableRowsParams {
code: name!("eosio.evm"),
table: name!("account"),
scope: None,
lower_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_bytes(&address2_256).unwrap())),
upper_bound: Some(TableIndexType::CHECKSUM256(Checksum256::from_bytes(&address2_256).unwrap())),
limit: Some(1),
reverse: None,
index_position: Some(IndexPosition::SECONDARY),
show_payer: None,
};
let account_rows = telos_client.v1_chain.get_table_rows::<AccountRow>(query_params_account).await;
if let Ok(account_rows) = account_rows {
if expected_outcome == true {
assert_eq!(account_rows.rows.len(), 0);
} else {
assert_eq!(account_rows.rows.len(), 1);
assert_eq!(account_rows.rows[0].address, Checksum160::from_bytes(address2.as_slice()).unwrap());
assert_eq!(account_rows.rows[0].balance, Checksum256::from_hex("0000000000000000000000000000000000000000000000000000000000000001").unwrap());
}
}

let address1_balance = reth_provider.get_balance(address1).await.unwrap();
let address2_balance = reth_provider.get_balance(address2).await.unwrap();

if expected_outcome == true {
assert_eq!(address1_balance, U256::from_str("2").unwrap());
assert_eq!(address2_balance, U256::ZERO);
} else {
assert_eq!(address1_balance, U256::from_str("1").unwrap());
assert_eq!(address2_balance, U256::from_str("1").unwrap());
}


}

pub(crate) async fn test_delegate_call_bug(provider: &TestProvider, telos_client: &APIClient<DefaultProvider>, expected_outcome: Bool) {
}
Loading
Loading