Skip to content

Commit

Permalink
Integration tests (#71)
Browse files Browse the repository at this point in the history
* Add test for eip1559 and eip2930 transaction types.

* Add double approve test.

* Improve approve test.

---------

Co-authored-by: lesa-telos <lesa-telos@telos.net>
  • Loading branch information
lesa-telos and lesa-telos authored Nov 21, 2024
1 parent 000f430 commit 0f9605a
Showing 1 changed file with 129 additions and 8 deletions.
137 changes: 129 additions & 8 deletions crates/telos/node/tests/live_test_runner.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,21 @@
use alloy_network::{ReceiptResponse, TransactionBuilder};
use alloy_primitives::U256;
use std::fmt::Debug;
use std::str::FromStr;
use alloy_contract::private::Transport;
use alloy_network::{Ethereum, ReceiptResponse, TransactionBuilder};
use alloy_primitives::{keccak256, Address, B256, U256};
use alloy_provider::network::EthereumWallet;
use alloy_provider::{Provider, ProviderBuilder};
use alloy_rpc_types::TransactionRequest;
use alloy_rpc_types::{TransactionRequest};
use alloy_signer_local::PrivateKeySigner;
use alloy_sol_types::private::primitives::TxKind::Create;
use alloy_sol_types::private::primitives::TxKind::{Create};
use alloy_sol_types::{sol, SolEvent};
use reqwest::Url;
use reth::primitives::BlockId;
use reth::rpc::types::{BlockTransactionsKind, TransactionInput};
use std::str::FromStr;
use reqwest::{Url};
use tracing::info;
use reth::primitives::BlockId;
use reth::primitives::BlockNumberOrTag::Latest;
use reth::primitives::revm_primitives::bytes::Bytes;
use reth::revm::primitives::{AccessList, AccessListItem};

#[tokio::test]
pub async fn run_local() {
Expand Down Expand Up @@ -92,7 +97,7 @@ pub async fn test_blocknum_onchain(url: &str, private_key: &str) {
..Default::default()
};

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

let deploy_tx_hash = deploy_result.tx_hash();
info!("Deployed contract with tx hash: {deploy_tx_hash}");
Expand Down Expand Up @@ -125,10 +130,126 @@ pub async fn test_blocknum_onchain(url: &str, private_key: &str) {
assert_eq!(U256::from(rpc_block_num), block_num_event.number);
info!("Block numbers match inside transaction event");

// test eip1559 transaction which is not supported
test_1559_tx(provider.clone(), address).await;
// test eip2930 transaction which is not supported
test_2930_tx(provider.clone(), address).await;
// test double approve erc20 call
test_double_approve_erc20(provider.clone(), address).await;
// The below needs to be done using LegacyTransaction style call... with the current code it's including base_fee_per_gas and being rejected by reth
// let block_num_latest = block_num_checker.getBlockNum().call().await.unwrap();
// assert!(block_num_latest._0 > U256::from(rpc_block_num), "Latest block number via call to getBlockNum is not greater than the block number in the previous log event");
//
// let block_num_five_back = block_num_checker.getBlockNum().call().block(BlockId::number(rpc_block_num - 5)).await.unwrap();
// assert!(block_num_five_back._0 == U256::from(rpc_block_num - 5), "Block number 5 blocks back via historical eth_call is not correct");

}

// test_1559_tx tests sending eip1559 transaction that has max_priority_fee_per_gas and max_fee_per_gas set
pub async fn test_1559_tx<T>(provider: impl Provider<T, Ethereum> + Send + Sync, sender_address: Address)
where
T: Transport + Clone + Debug,
{
let nonce = provider.get_transaction_count(sender_address).await.unwrap();
let chain_id = provider.get_chain_id().await.unwrap();
let to_address: Address = Address::from_str("0x23CB6AE34A13a0977F4d7101eBc24B87Bb23F0d4").unwrap();

let tx = TransactionRequest::default()
.with_to(to_address)
.with_nonce(nonce)
.with_chain_id(chain_id)
.with_value(U256::from(100))
.with_gas_limit(21_000)
.with_max_priority_fee_per_gas(1_000_000_000)
.with_max_fee_per_gas(20_000_000_000);

let tx_result = provider.send_transaction(tx).await;
assert!(tx_result.is_err());
}

// test_2930_tx tests sending eip2930 transaction which has access_list provided
pub async fn test_2930_tx<T>(provider: impl Provider<T, Ethereum> + Send + Sync, sender_address: Address)
where
T: Transport + Clone + Debug,

{
let nonce = provider.get_transaction_count(sender_address).await.unwrap();
let chain_id = provider.get_chain_id().await.unwrap();
let gas_price = provider.get_gas_price().await.unwrap();

let to_address: Address = Address::from_str("0x23CB6AE34A13a0977F4d7101eBc24B87Bb23F0d4").unwrap();
let tx = TransactionRequest::default()
.to(to_address)
.nonce(nonce)
.value(U256::from(1e17))
.with_chain_id(chain_id)
.with_gas_price(gas_price)
.with_gas_limit(20_000_000)
.max_priority_fee_per_gas(1e11 as u128)
.with_access_list(AccessList::from(vec![AccessListItem { address: to_address, storage_keys: vec![B256::ZERO] }]))
.max_fee_per_gas(2e9 as u128);
let tx_result = provider.send_transaction(tx).await;
assert!(tx_result.is_err());
}


// test_double_approve_erc20 sends 2 transactions for approve on the ERC20 token and asserts that only once it is success
pub async fn test_double_approve_erc20<T>(
provider: impl Provider<T, Ethereum> + Send + Sync,
sender_address: Address,
) where
T: Transport + Clone + Debug,
{
let nonce = provider.get_transaction_count(sender_address).await.unwrap();
let chain_id = provider.get_chain_id().await.unwrap();
let gas_price = provider.get_gas_price().await.unwrap();

let erc20_contract_address: Address =
"0x49f54c5e2301eb9256438123e80762470c2c7ec2".parse().unwrap();
let spender: Address = "0x23CB6AE34A13a0977F4d7101eBc24B87Bb23F0d4".parse().unwrap();
let function_signature = "approve(address,uint256)";
let amount: U256 = U256::from(0);
let selector = &keccak256(function_signature.as_bytes())[..4];
let amount_bytes: [u8; 32] = amount.to_be_bytes();
let mut encoded_data = Vec::new();
encoded_data.extend_from_slice(selector);
encoded_data.extend_from_slice(spender.as_ref());
encoded_data.extend_from_slice(&amount_bytes);
let input_data = Bytes::from(encoded_data);

// Build approve transaction
let mut tx = TransactionRequest::default()
.to(erc20_contract_address)
.with_input(input_data)
.nonce(nonce)
.value(U256::from(10))
.with_chain_id(chain_id)
.with_gas_price(gas_price)
.with_gas_limit(20_000_000);

// call approve
let tx_result = provider.send_transaction(tx.clone()).await;
assert!(tx_result.is_ok());
let receipt1 = tx_result.unwrap().get_receipt().await;
assert!(receipt1.is_ok());

let nonce = provider.get_transaction_count(sender_address).await.unwrap();
tx.nonce = Some(nonce);

// repeat approve
let tx_result = provider.send_transaction(tx.clone()).await;
assert!(tx_result.is_ok());

let receipt2 = tx_result.unwrap().get_receipt().await;
assert!(receipt2.is_ok());

let block_number = receipt2.unwrap().block_number.unwrap();

// make sure the block is included
while let Some(block) = provider.get_block_by_number(Latest, false).await.unwrap() {
if block.header.number == block_number {
break;
}
}
}

0 comments on commit 0f9605a

Please sign in to comment.