-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6d1c052
commit 4781d89
Showing
9 changed files
with
324 additions
and
2 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
[package] | ||
name = "linea" | ||
version = "0.1.0" | ||
edition = "2021" | ||
license = "MIT" | ||
repository = "https://github.com/analog-labs/chain-connectors" | ||
description = "linea rosetta test." | ||
|
||
[dependencies] | ||
alloy-sol-types = { version = "0.8" } | ||
anyhow = "1.0" | ||
ethers = { version = "2.0", default-features = true, features = ["abigen", "rustls", "ws"] } | ||
ethers-solc = "2.0" | ||
hex-literal = "0.4" | ||
rosetta-chain-testing = { path = "../rosetta-chain-testing" } | ||
rosetta-client.workspace = true | ||
rosetta-config-ethereum.workspace = true | ||
rosetta-core.workspace = true | ||
rosetta-server-ethereum.workspace = true | ||
sha3 = "0.10" | ||
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,254 @@ | ||
//! # Binance Rosetta Server Test Suite | ||
//! | ||
//! This module contains a test suite for an Ethereum Rosetta server implementation | ||
//! specifically designed for interacting with the Binance network. The code includes | ||
//! tests for network status, account management, and smart contract interaction. | ||
//! | ||
//! ## Features | ||
//! | ||
//! - Network status tests to ensure proper connection and consistency with the Binance network. | ||
//! - Account tests, including faucet funding, balance retrieval, and error handling. | ||
//! - Smart contract tests covering deployment, event emission, and view function calls. | ||
//! | ||
//! ## Dependencies | ||
//! | ||
//! - `anyhow`: For flexible error handling. | ||
//! - `alloy_sol_types`: Custom types and macros for interacting with Solidity contracts. | ||
//! - `ethers`: Ethereum library for interaction with Ethereum clients. | ||
//! - `ethers_solc`: Integration for compiling Solidity code using the Solc compiler. | ||
//! - `hex_literal`: Macro for creating byte array literals from hexadecimal strings. | ||
//! - `rosetta_client`: Client library for Rosetta API interactions. | ||
//! - `rosetta_config_ethereum`: Configuration for Ethereum Rosetta server. | ||
//! - `rosetta_server_ethereum`: Custom client implementation for interacting with Ethereum. | ||
//! - `sha3`: SHA-3 (Keccak) implementation for hashing. | ||
//! - `tokio`: Asynchronous runtime for running async functions. | ||
//! | ||
//! ## Usage | ||
//! | ||
//! To run the tests, execute the following command: | ||
//! | ||
//! ```sh | ||
//! cargo test --package rosetta-testing-linea --lib -- tests --nocapture | ||
//! ``` | ||
//! | ||
//! Note: The code assumes a local Binance RPC node running on `ws://127.0.0.1:8546`. Ensure | ||
//! that this endpoint is configured correctly. | ||
#[allow(clippy::ignored_unit_patterns, clippy::pub_underscore_fields)] | ||
#[cfg(test)] | ||
mod tests { | ||
use alloy_sol_types::{sol, SolCall}; | ||
use anyhow::Result; | ||
use ethers::types::H256; | ||
|
||
use ethers_solc::{artifacts::Source, CompilerInput, EvmVersion, Solc}; | ||
use hex_literal::hex; | ||
use rosetta_chain_testing::run_test; | ||
use rosetta_client::Wallet; | ||
use rosetta_config_ethereum::{AtBlock, CallResult}; | ||
use rosetta_core::BlockchainClient; | ||
use rosetta_server_ethereum::MaybeWsEthereumClient; | ||
use sha3::Digest; | ||
use std::{collections::BTreeMap, path::Path}; | ||
|
||
/// Binance rpc url | ||
const LINEA_RPC_WS_URL: &str = "http://localhost:8545"; | ||
|
||
sol! { | ||
interface TestContract { | ||
event AnEvent(); | ||
function emitEvent() external; | ||
|
||
function identity(bool a) external view returns (bool); | ||
} | ||
} | ||
|
||
#[tokio::test] | ||
async fn network_status() { | ||
run_test(async move { | ||
let client = MaybeWsEthereumClient::new("linea", "dev", LINEA_RPC_WS_URL, None) | ||
.await | ||
.expect("Error creating client"); | ||
// Check if the genesis is consistent | ||
let genesis_block = client.genesis_block(); | ||
assert_eq!(genesis_block.index, 0); | ||
|
||
// Check if the current block is consistent | ||
let current_block = client.current_block().await.unwrap(); | ||
if current_block.index > 0 { | ||
assert_ne!(current_block.hash, genesis_block.hash); | ||
} else { | ||
assert_eq!(current_block.hash, genesis_block.hash); | ||
} | ||
|
||
// Check if the finalized block is consistent | ||
let finalized_block = client.finalized_block().await.unwrap(); | ||
assert!(finalized_block.index >= genesis_block.index); | ||
}) | ||
.await; | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_account() { | ||
run_test(async move { | ||
let client = MaybeWsEthereumClient::new("linea", "dev", LINEA_RPC_WS_URL, None) | ||
.await | ||
.expect("Error creating LineaClient"); | ||
let wallet = | ||
Wallet::from_config(client.config().clone(), LINEA_RPC_WS_URL, None, None) | ||
.await | ||
.unwrap(); | ||
let value = 10 * u128::pow(10, client.config().currency_decimals); | ||
let _ = wallet.faucet(value, None).await; | ||
let amount = wallet.balance().await.unwrap(); | ||
assert_eq!(amount, value); | ||
}) | ||
.await; | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_construction() { | ||
run_test(async move { | ||
let client = MaybeWsEthereumClient::new("linea", "dev", LINEA_RPC_WS_URL, None) | ||
.await | ||
.expect("Error creating LineaClient"); | ||
let faucet = 100 * u128::pow(10, client.config().currency_decimals); | ||
let value = u128::pow(10, client.config().currency_decimals); | ||
let alice = | ||
Wallet::from_config(client.config().clone(), LINEA_RPC_WS_URL, None, None) | ||
.await | ||
.unwrap(); | ||
let bob = Wallet::from_config(client.config().clone(), LINEA_RPC_WS_URL, None, None) | ||
.await | ||
.unwrap(); | ||
assert_ne!(alice.public_key(), bob.public_key()); | ||
|
||
// Alice and bob have no balance | ||
let balance = alice.balance().await.unwrap(); | ||
assert_eq!(balance, 0); | ||
let balance = bob.balance().await.unwrap(); | ||
assert_eq!(balance, 0); | ||
|
||
// Transfer faucets to alice | ||
alice.faucet(faucet, None).await.unwrap(); | ||
let balance = alice.balance().await.unwrap(); | ||
assert_eq!(balance, faucet); | ||
|
||
// Alice transfers to bob | ||
alice.transfer(bob.account(), value, None, None).await.unwrap(); | ||
let amount = bob.balance().await.unwrap(); | ||
assert_eq!(amount, value); | ||
}) | ||
.await; | ||
} | ||
|
||
fn compile_snippet(source: &str) -> Result<Vec<u8>> { | ||
let solc = Solc::default(); | ||
let source = format!("contract Contract {{ {source} }}"); | ||
let mut sources = BTreeMap::new(); | ||
sources.insert(Path::new("contract.sol").into(), Source::new(source)); | ||
let input = CompilerInput::with_sources(sources)[0] | ||
.clone() | ||
.evm_version(EvmVersion::Homestead); | ||
let output = solc.compile_exact(&input)?; | ||
let file = output.contracts.get("contract.sol").unwrap(); | ||
let contract = file.get("Contract").unwrap(); | ||
let bytecode = contract | ||
.evm | ||
.as_ref() | ||
.unwrap() | ||
.bytecode | ||
.as_ref() | ||
.unwrap() | ||
.object | ||
.as_bytes() | ||
.unwrap() | ||
.to_vec(); | ||
Ok(bytecode) | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_smart_contract() { | ||
run_test(async move { | ||
let client = MaybeWsEthereumClient::new("linea", "dev", LINEA_RPC_WS_URL, None) | ||
.await | ||
.expect("Error creating LineaClient"); | ||
let faucet = 10 * u128::pow(10, client.config().currency_decimals); | ||
let wallet = | ||
Wallet::from_config(client.config().clone(), LINEA_RPC_WS_URL, None, None) | ||
.await | ||
.unwrap(); | ||
wallet.faucet(faucet, None).await.unwrap(); | ||
|
||
let bytes = compile_snippet( | ||
r" | ||
event AnEvent(); | ||
function emitEvent() public { | ||
emit AnEvent(); | ||
} | ||
", | ||
) | ||
.unwrap(); | ||
let tx_hash = wallet.eth_deploy_contract(bytes).await.unwrap().tx_hash().0; | ||
let receipt = wallet.eth_transaction_receipt(tx_hash).await.unwrap().unwrap(); | ||
let contract_address = receipt.contract_address.unwrap(); | ||
let tx_hash = { | ||
let call = TestContract::emitEventCall {}; | ||
wallet | ||
.eth_send_call(contract_address.0, call.abi_encode(), 0, None, None) | ||
.await | ||
.unwrap() | ||
.tx_hash() | ||
.0 | ||
}; | ||
let receipt = wallet.eth_transaction_receipt(tx_hash).await.unwrap().unwrap(); | ||
assert_eq!(receipt.logs.len(), 1); | ||
let topic = receipt.logs[0].topics[0]; | ||
let expected = H256(sha3::Keccak256::digest("AnEvent()").into()); | ||
assert_eq!(topic, expected); | ||
}) | ||
.await; | ||
} | ||
|
||
#[tokio::test] | ||
async fn test_smart_contract_view() { | ||
run_test(async move { | ||
let client = MaybeWsEthereumClient::new("linea", "dev", LINEA_RPC_WS_URL, None) | ||
.await | ||
.expect("Error creating LineaClient"); | ||
let faucet = 10 * u128::pow(10, client.config().currency_decimals); | ||
let wallet = | ||
Wallet::from_config(client.config().clone(), LINEA_RPC_WS_URL, None, None) | ||
.await | ||
.unwrap(); | ||
wallet.faucet(faucet, None).await.unwrap(); | ||
let bytes = compile_snippet( | ||
r" | ||
function identity(bool a) public view returns (bool) { | ||
return a; | ||
} | ||
", | ||
) | ||
.unwrap(); | ||
let tx_hash = wallet.eth_deploy_contract(bytes).await.unwrap().tx_hash().0; | ||
let receipt = wallet.eth_transaction_receipt(tx_hash).await.unwrap().unwrap(); | ||
let contract_address = receipt.contract_address.unwrap(); | ||
|
||
let response = { | ||
let call = TestContract::identityCall { a: true }; | ||
wallet | ||
.eth_view_call(contract_address.0, call.abi_encode(), AtBlock::Latest) | ||
.await | ||
.unwrap() | ||
}; | ||
assert_eq!( | ||
response, | ||
CallResult::Success( | ||
hex!("0000000000000000000000000000000000000000000000000000000000000001") | ||
.to_vec() | ||
) | ||
); | ||
}) | ||
.await; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters