Skip to content

Commit

Permalink
Use anvil on tests (#129)
Browse files Browse the repository at this point in the history
Changed tests to use anvil from a docker container instead of depending
on anvil running externally. This will allow to run tests more easily,
removing foundry as a dependency. Also fix some flaky tests that fail
due to multiple tests running in parallel and making requests to the
same anvil instance.

---------

Co-authored-by: Pablo Deymonnaz <[email protected]>
  • Loading branch information
TomasArrachea and pablodeymo authored Sep 24, 2024
1 parent b394482 commit 3c0416e
Show file tree
Hide file tree
Showing 22 changed files with 595 additions and 425 deletions.
3 changes: 0 additions & 3 deletions .github/workflows/integration.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ jobs:
with:
cache-on-failure: true

- name: Install Foundry
run: cargo install --git https://github.com/foundry-rs/foundry --profile release --locked foundry-cast anvil

- name: docker
uses: docker-practice/actions-setup-docker@master

Expand Down
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 0 additions & 9 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,9 @@ reset-anvil:
-docker stop anvil
-docker rm anvil

pr:
$(MAKE) start-anvil > /dev/null &
sleep 4 # needed to wait for anvil setup to finish
cargo test --workspace
docker stop anvil

coverage:
$(MAKE) start-anvil > /dev/null &
sleep 4 # needed to wait for anvil setup to finish
cargo llvm-cov --lcov --output-path lcov.info --workspace --features fireblock-tests
cargo llvm-cov report --html
docker stop anvil

deps:
@if ! command -v cargo-llvm-cov &> /dev/null; then \
Expand Down
77 changes: 52 additions & 25 deletions crates/chainio/clients/avsregistry/src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,22 +330,28 @@ impl AvsRegistryChainWriter {
#[cfg(test)]
mod tests {
use super::AvsRegistryChainWriter;
use alloy_node_bindings::Anvil;
use alloy_primitives::{Address, Bytes, FixedBytes, U256};
use eigen_crypto_bls::BlsKeyPair;
use eigen_logging::get_test_logger;
use eigen_testing_utils::anvil::start_anvil_container;
use eigen_testing_utils::anvil_constants::{
get_operator_state_retriever_address, get_registry_coordinator_address, ANVIL_HTTP_URL,
get_operator_state_retriever_address, get_registry_coordinator_address,
};
use eigen_testing_utils::transaction::get_transaction_status;
use std::str::FromStr;

async fn build_avs_registry_chain_writer(private_key: String) -> AvsRegistryChainWriter {
let registry_coordinator_address = get_registry_coordinator_address().await;
let operator_state_retriever_address = get_operator_state_retriever_address().await;
async fn build_avs_registry_chain_writer(
http_endpoint: String,
private_key: String,
) -> AvsRegistryChainWriter {
let registry_coordinator_address =
get_registry_coordinator_address(http_endpoint.clone()).await;
let operator_state_retriever_address =
get_operator_state_retriever_address(http_endpoint.clone()).await;

AvsRegistryChainWriter::build_avs_registry_chain_writer(
get_test_logger(),
ANVIL_HTTP_URL.to_string(),
http_endpoint,
private_key,
registry_coordinator_address,
operator_state_retriever_address,
Expand All @@ -356,33 +362,48 @@ mod tests {

#[tokio::test]
async fn test_avs_writer_methods() {
let account_idx = 5;
let anvil = Anvil::new().try_spawn().unwrap();
let private_key = anvil.keys().get(account_idx).unwrap();
let private_key_hex = hex::encode(private_key.to_bytes());
let private_key_decimal = U256::from_be_bytes(private_key.to_bytes().into()).to_string();
let avs_writer = build_avs_registry_chain_writer(private_key_hex).await;
let operator_id = anvil.addresses().get(account_idx).unwrap();

let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;

let bls_key =
"1371012690269088913462269866874713266643928125698382731338806296762673180359922"
.to_string();
let private_key =
"8b3a350cf5c34c9194ca85829a2df0ec3153be0318b5e2d3348e872092edffba".to_string();
let avs_writer = build_avs_registry_chain_writer(http_endpoint.clone(), private_key).await;
let operator_addr = Address::from_str("9965507D1a55bcC2695C58ba16FB37d819B0A4dc").unwrap();
let quorum_nums = Bytes::from([0]);
test_register_operator(&avs_writer, private_key_decimal, quorum_nums.clone()).await;
test_update_stake_of_operator_subset(&avs_writer, *operator_id).await;
test_update_stake_of_entire_operator_set(&avs_writer, *operator_id, quorum_nums.clone())

test_register_operator(
&avs_writer,
bls_key,
quorum_nums.clone(),
http_endpoint.clone(),
)
.await;
test_update_stake_of_operator_subset(&avs_writer, operator_addr, http_endpoint.clone())
.await;
test_deregister_operator(&avs_writer, quorum_nums).await;
test_update_stake_of_entire_operator_set(
&avs_writer,
operator_addr,
quorum_nums.clone(),
http_endpoint.clone(),
)
.await;
test_deregister_operator(&avs_writer, quorum_nums, http_endpoint).await;
}

// this function is caller from test_avs_writer_methods
async fn test_update_stake_of_operator_subset(
avs_writer: &AvsRegistryChainWriter,
operator_id: Address,
operator_addr: Address,
http_url: String,
) {
let tx_hash = avs_writer
.update_stakes_of_operator_subset_for_all_quorums(vec![operator_id])
.update_stakes_of_operator_subset_for_all_quorums(vec![operator_addr])
.await
.unwrap();

let tx_status = get_transaction_status(tx_hash).await;
let tx_status = get_transaction_status(http_url, tx_hash).await;
assert!(tx_status);
}

Expand All @@ -391,13 +412,14 @@ mod tests {
avs_writer: &AvsRegistryChainWriter,
operator_id: Address,
quorum_nums: Bytes,
http_url: String,
) {
let tx_hash = avs_writer
.update_stakes_of_entire_operator_set_for_quorums(vec![vec![operator_id]], quorum_nums)
.await
.unwrap();

let tx_status = get_transaction_status(tx_hash).await;
let tx_status = get_transaction_status(http_url, tx_hash).await;
assert!(tx_status);
}

Expand All @@ -406,6 +428,7 @@ mod tests {
avs_writer: &AvsRegistryChainWriter,
private_key_decimal: String,
quorum_nums: Bytes,
http_url: String,
) {
let bls_key_pair = BlsKeyPair::new(private_key_decimal).unwrap();
let digest_hash: FixedBytes<32> = FixedBytes::from([0x02; 32]);
Expand All @@ -423,15 +446,19 @@ mod tests {
.await
.unwrap();

let tx_status = get_transaction_status(tx_hash).await;
let tx_status = get_transaction_status(http_url, tx_hash).await;
assert!(tx_status);
}

// this function is caller from test_avs_writer_methods
async fn test_deregister_operator(avs_writer: &AvsRegistryChainWriter, quorum_nums: Bytes) {
async fn test_deregister_operator(
avs_writer: &AvsRegistryChainWriter,
quorum_nums: Bytes,
http_url: String,
) {
let tx_hash = avs_writer.deregister_operator(quorum_nums).await.unwrap();

let tx_status = get_transaction_status(tx_hash).await;
let tx_status = get_transaction_status(http_url, tx_hash).await;
assert!(tx_status);
}
}
73 changes: 34 additions & 39 deletions crates/chainio/clients/elcontracts/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,35 +391,33 @@ mod tests {
use alloy_primitives::{address, keccak256, Address, FixedBytes, U256};
use alloy_provider::Provider;
use eigen_logging::get_test_logger;
use eigen_testing_utils::anvil_constants::{
self, get_erc20_mock_strategy, ANVIL_HTTP_URL, ANVIL_RPC_URL,
use eigen_testing_utils::{
anvil::start_anvil_container,
anvil_constants::{
get_delegation_manager_address, get_erc20_mock_strategy, get_service_manager_address,
},
};
use eigen_utils::binding::{
mockAvsServiceManager, AVSDirectory,
AVSDirectory::calculateOperatorAVSRegistrationDigestHashReturn, DelegationManager,
DelegationManager::calculateDelegationApprovalDigestHashReturn,
};
use serial_test::serial;
use std::str::FromStr;
use tokio::time::{sleep, Duration};

const OPERATOR_ADDRESS: &str = "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720";

async fn build_el_chain_reader() -> ELChainReader {
let delegation_manager_address = anvil_constants::get_delegation_manager_address().await;
let delegation_manager_contract = DelegationManager::new(
delegation_manager_address,
anvil_constants::ANVIL_RPC_URL.clone(),
);
async fn build_el_chain_reader(http_endpoint: String) -> ELChainReader {
let delegation_manager_address =
get_delegation_manager_address(http_endpoint.clone()).await;
let delegation_manager_contract =
DelegationManager::new(delegation_manager_address, get_provider(&http_endpoint));
let slasher_address_return = delegation_manager_contract.slasher().call().await.unwrap();
let DelegationManager::slasherReturn {
_0: slasher_address,
} = slasher_address_return;
let service_manager_address = anvil_constants::get_service_manager_address().await;
let service_manager_contract = mockAvsServiceManager::new(
service_manager_address,
get_provider("http://localhost:8545"),
);
let service_manager_address = get_service_manager_address(http_endpoint.clone()).await;
let service_manager_contract =
mockAvsServiceManager::new(service_manager_address, get_provider(&http_endpoint));
let avs_directory_address_return = service_manager_contract
.avsDirectory()
.call()
Expand All @@ -434,24 +432,24 @@ mod tests {
slasher_address,
delegation_manager_address,
avs_directory_address,
ANVIL_HTTP_URL.to_string(),
http_endpoint,
)
}

#[tokio::test]
#[serial]
async fn test_calculate_delegation_approval_digest_hash() {
let el_chain_reader = build_el_chain_reader().await;
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let provider = get_provider(&http_endpoint);
let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
let operator: Address = address!("5eb15C0992734B5e77c888D713b4FC67b3D679A2");

let staker = operator;

let delegation_approver = Address::ZERO;

let approve_salt: FixedBytes<32> = FixedBytes::from([0x02; 32]);
let current_block_number = ANVIL_RPC_URL.clone().get_block_number().await.unwrap();
let block_info = ANVIL_RPC_URL
.clone()
let current_block_number = provider.get_block_number().await.unwrap();
let block_info = provider
.get_block_by_number(Number(current_block_number), true)
.await
.unwrap();
Expand All @@ -471,11 +469,9 @@ mod tests {
.unwrap();

// Directly calling the function through bindings to compare with the sdk .
let delegation_manager_address = anvil_constants::get_delegation_manager_address().await;
let delegation_manager_contract = DelegationManager::new(
delegation_manager_address,
anvil_constants::ANVIL_RPC_URL.clone(),
);
let delegation_manager_address = get_delegation_manager_address(http_endpoint).await;
let delegation_manager_contract =
DelegationManager::new(delegation_manager_address, provider);

let hash = delegation_manager_contract
.calculateDelegationApprovalDigestHash(
Expand All @@ -495,16 +491,15 @@ mod tests {
}

#[tokio::test]
#[serial]
async fn test_calculate_operator_avs_registration_digest_hash() {
sleep(Duration::from_secs(2)).await;
let el_chain_reader = build_el_chain_reader().await;
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let provider = get_provider(&http_endpoint);
let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
let operator: Address = address!("5eb15C0992734B5e77c888D713b4FC67b3D679A2");
let avs = Address::from_slice(&keccak256("avs ")[0..20]);
let salt: FixedBytes<32> = FixedBytes::from([0x02; 32]);
let current_block_number = ANVIL_RPC_URL.clone().get_block_number().await.unwrap();
let block_info = ANVIL_RPC_URL
.clone()
let current_block_number = provider.get_block_number().await.unwrap();
let block_info = provider
.get_block_by_number(Number(current_block_number), true)
.await
.unwrap();
Expand All @@ -519,7 +514,7 @@ mod tests {

// Using bindings directly to compare with sdk's output
let avs_registry_contract =
AVSDirectory::new(el_chain_reader.avs_directory, ANVIL_RPC_URL.clone());
AVSDirectory::new(el_chain_reader.avs_directory, provider.clone());
let operator_hash_from_bindings = avs_registry_contract
.calculateOperatorAVSRegistrationDigestHash(operator, avs, salt, expiry)
.call()
Expand All @@ -533,12 +528,12 @@ mod tests {
}

#[tokio::test]
#[serial]
async fn check_strategy_shares_and_operator_frozen() {
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let operator_addr = Address::from_str(OPERATOR_ADDRESS).unwrap();
let strategy_addr = get_erc20_mock_strategy().await;
let strategy_addr = get_erc20_mock_strategy(http_endpoint.clone()).await;

let chain_reader = build_el_chain_reader().await;
let chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
let shares = chain_reader
.get_operator_shares_in_strategy(operator_addr, strategy_addr)
.await
Expand All @@ -554,7 +549,7 @@ mod tests {
.unwrap();
assert!(!frozen);

let service_manager_address = anvil_constants::get_service_manager_address().await;
let service_manager_address = get_service_manager_address(http_endpoint).await;
let ret_can_slash = chain_reader
.service_manager_can_slash_operator_until_block(operator_addr, service_manager_address)
.await
Expand All @@ -565,10 +560,10 @@ mod tests {
}

#[tokio::test]
#[serial]
async fn test_get_operator_details() {
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let operator_addr = Address::from_str(OPERATOR_ADDRESS).unwrap();
let chain_reader = build_el_chain_reader().await;
let chain_reader = build_el_chain_reader(http_endpoint).await;

let operator = chain_reader
.get_operator_details(operator_addr)
Expand Down
Loading

0 comments on commit 3c0416e

Please sign in to comment.