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

chore: update way anvil state dump is generated #222

Merged
merged 23 commits into from
Jan 17, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
11a9336
update deploy-contracts-save-anvil-state.sh script
ricomateo Jan 16, 2025
a6e6670
update deployment scripts to track add the RewardsCoordinator address…
ricomateo Jan 16, 2025
e6701cf
add updated anvil state
ricomateo Jan 16, 2025
d833150
fix: failing tests
ricomateo Jan 16, 2025
84aa49f
update addresses in eigen-cli tests
ricomateo Jan 16, 2025
35288b0
fix: test_process_claim test
ricomateo Jan 16, 2025
fd84c8c
remove unnecessary commands from deploy-contracts-save-anvil-state.sh…
ricomateo Jan 16, 2025
388a593
add doc comments
ricomateo Jan 16, 2025
24bbd0d
remove unnecessary flags from bash scripts forge commands
ricomateo Jan 16, 2025
deaa06d
re-add doc comment in utils.sh
ricomateo Jan 16, 2025
ccf44f9
docs: add docs for anvil constants
MegaRedHand Jan 16, 2025
140e7e9
Merge branch 'main' into update-anvil-state
MegaRedHand Jan 16, 2025
678490a
feat: add MockERC20 to generated bindings
MegaRedHand Jan 16, 2025
76c1671
fix: update imports
MegaRedHand Jan 16, 2025
e57d763
chore: regenerate bindings
MegaRedHand Jan 16, 2025
2e0f784
chore: remove commit from .gitmodules
MegaRedHand Jan 17, 2025
df99aeb
chore: remove old TODO
MegaRedHand Jan 17, 2025
f6f1731
chore: fix typo
MegaRedHand Jan 17, 2025
b5f2945
chore: remove old comments and unneeded exit handler
MegaRedHand Jan 17, 2025
2ede20b
fix: add second initialize parameter
MegaRedHand Jan 17, 2025
7713a16
refactor: use encodeCall
MegaRedHand Jan 17, 2025
dd4a520
chore: regenerate state dump
MegaRedHand Jan 17, 2025
b6c6e13
chore: fix typo
MegaRedHand Jan 17, 2025
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
1 change: 0 additions & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@
[submodule "crates/contracts/lib/eigenlayer-middleware"]
path = crates/contracts/lib/eigenlayer-middleware
url = https://github.com/Layr-labs/eigenlayer-middleware
commit = 512ce7326f35e8060b9d46e23f9c159c0000b546
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ lint:
__BINDINGS__: ##

### SDK bindings ###
SDK_CONTRACTS:="MockAvsServiceManager ContractsRegistry"
SDK_CONTRACTS:="MockAvsServiceManager ContractsRegistry MockERC20"
SDK_CONTRACTS_LOCATION:=crates/contracts
SDK_BINDINGS_PATH:=crates/utils/src/sdk
# The echo is to remove quotes, and the patsubst to make the regex match the full text only
Expand Down
167 changes: 146 additions & 21 deletions crates/chainio/clients/elcontracts/src/writer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,30 +328,34 @@ impl ELChainWriter {
mod tests {
use super::ELChainWriter;
use crate::reader::ELChainReader;
use alloy::providers::Provider;
use alloy_primitives::{address, Address, FixedBytes, U256};
use alloy::{providers::Provider, sol_types::SolValue};
use alloy_primitives::{address, keccak256, Address, FixedBytes, U256, U8};
use alloy_signer_local::PrivateKeySigner;
use anvil_constants::CONTRACTS_REGISTRY;
use eigen_common::get_provider;
use eigen_common::{get_provider, get_signer};
use eigen_logging::get_test_logger;
use eigen_testing_utils::{
anvil::{set_account_balance, start_anvil_container},
anvil_constants::{
self, get_delegation_manager_address, get_erc20_mock_strategy,
get_rewards_coordinator_address, get_service_manager_address,
get_strategy_manager_address,
get_strategy_manager_address, ANVIL_FIRST_ADDRESS, ANVIL_FIRST_PRIVATE_KEY,
},
transaction::wait_transaction,
};
use eigen_types::operator::Operator;
use eigen_utils::{
core::{
delegationmanager::DelegationManager,
irewardscoordinator::IRewardsCoordinator::{EarnerTreeMerkleLeaf, RewardsMerkleClaim},
irewardscoordinator::IRewardsCoordinator::{
self, getDistributionRootsLengthReturn, EarnerTreeMerkleLeaf, RewardsMerkleClaim,
TokenTreeMerkleLeaf,
},
},
sdk::{
contractsregistry::ContractsRegistry::{self, get_test_valuesReturn},
mockavsservicemanager::MockAvsServiceManager,
mockerc20::MockERC20,
},
};
use serial_test::serial;
Expand Down Expand Up @@ -567,30 +571,151 @@ mod tests {
assert!(receipt.status());
}

#[tokio::test]
#[serial]
async fn test_process_claim() {
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let el_chain_writer = new_test_writer(http_endpoint.clone()).await;
/// The claim can be submitted from [`ANVIL_FIRST_PRIVATE_KEY`]
/// This is taken from the slashing PR, it is slightly changed since
/// some chain reader functions are not available in this branch yet.
pub async fn new_claim(
http_endpoint: &str,
cumulative_earnings: U256,
) -> (FixedBytes<32>, RewardsMerkleClaim) {
let signer = get_signer(ANVIL_FIRST_PRIVATE_KEY, http_endpoint);
let rewards_coordinator_address =
get_rewards_coordinator_address(http_endpoint.to_string()).await;

let (el_chain_reader, _) = setup_el_chain_reader(http_endpoint.to_string()).await;
let mock_strategy = get_erc20_mock_strategy(http_endpoint.to_string()).await;
let (_, token_address, _) = el_chain_reader
.get_strategy_and_underlying_erc20_token(mock_strategy)
.await
.unwrap();

// Initialize the rewards coordinator bindings
let rewards_coordinator = IRewardsCoordinator::new(rewards_coordinator_address, &signer);

let earner_address = address!("5eb15C0992734B5e77c888D713b4FC67b3D679A2");
// Mint tokens for the rewards coordinator
let token = MockERC20::new(token_address, &signer);
let receipt = token
.mint(rewards_coordinator_address, cumulative_earnings)
.send()
.await
.unwrap()
.get_receipt()
.await
.unwrap();
assert!(receipt.status());

// Generate token tree leaf
// For the tree structure, see https://github.com/Layr-Labs/eigenlayer-contracts/blob/a888a1cd1479438dda4b138245a69177b125a973/docs/core/RewardsCoordinator.md#rewards-merkle-tree-structure
let earner_address = ANVIL_FIRST_ADDRESS;
let token_leaves = vec![TokenTreeMerkleLeaf {
token: token_address,
cumulativeEarnings: cumulative_earnings,
}];
// Hash token tree leaf to get root
let encoded_token_leaf = [
// uint8 internal constant TOKEN_LEAF_SALT = 1;
U8::from(1).to_be_bytes_vec(),
token_leaves[0].token.abi_encode_packed(),
token_leaves[0].cumulativeEarnings.abi_encode_packed(),
]
.concat();
let earner_token_root = keccak256(encoded_token_leaf);

// Generate earner tree leaf
let earner_leaf = EarnerTreeMerkleLeaf {
earner: earner_address,
earnerTokenRoot: earner_token_root,
};
// Hash earner tree leaf to get root
let encoded_earner_leaf = [
// uint8 internal constant EARNER_LEAF_SALT = 0;
U8::from(0).to_be_bytes_vec(),
earner_leaf.earner.abi_encode_packed(),
earner_leaf.earnerTokenRoot.abi_encode_packed(),
]
.concat();
let earner_tree_root = keccak256(encoded_earner_leaf);

// Fetch the next root index from contract
let distribution_roots_length_return = rewards_coordinator
.getDistributionRootsLength()
.call()
.await
.unwrap();
let getDistributionRootsLengthReturn {
_0: next_root_index,
} = distribution_roots_length_return;
// Construct the claim
let claim = RewardsMerkleClaim {
rootIndex: 0,
rootIndex: next_root_index.try_into().unwrap(),
earnerIndex: 0,
// Empty proof because leaf == root
earnerTreeProof: vec![].into(),
earnerLeaf: EarnerTreeMerkleLeaf {
earner: address!("5eb15C0992734B5e77c888D713b4FC67b3D679A2"),
earnerTokenRoot: FixedBytes::from([0; 32]),
},
tokenIndices: vec![],
tokenTreeProofs: vec![],
tokenLeaves: vec![],
earnerLeaf: earner_leaf,
tokenIndices: vec![0],
tokenTreeProofs: vec![
// Empty proof because leaf == root
vec![].into(),
],
tokenLeaves: token_leaves,
};

let tx_hash = el_chain_writer
.process_claim(earner_address, claim)
let root = earner_tree_root;

let activation_delay = 0;
// Set the activation delay to zero so that the claim can be processed
// right after setting the root
let set_activation_delay = rewards_coordinator
.setActivationDelay(activation_delay)
.send()
.await
.unwrap();

let receipt = set_activation_delay.get_receipt().await.unwrap();
assert!(receipt.status());

// Set the rewards updater so that we can submit the root
let rewards_updater = ANVIL_FIRST_ADDRESS;
let set_rewards_updater_tx = rewards_coordinator
.setRewardsUpdater(rewards_updater)
.send()
.await
.unwrap();
let receipt = set_rewards_updater_tx.get_receipt().await.unwrap();
assert!(receipt.status());

// Fetch the current timestamp to increase it
let curr_rewards_calculation_end_timestamp_return = rewards_coordinator
.currRewardsCalculationEndTimestamp()
.call()
.await
.unwrap();
let IRewardsCoordinator::currRewardsCalculationEndTimestampReturn {
_0: curr_rewards_calculation_end_timestamp,
} = curr_rewards_calculation_end_timestamp_return;

// Submit the root
let submit_tx = rewards_coordinator
.submitRoot(root, curr_rewards_calculation_end_timestamp + 1)
.send()
.await
.unwrap();
let submit_status = submit_tx.get_receipt().await.unwrap().status();
assert!(submit_status);

(root, claim)
}

#[tokio::test]
async fn test_process_claim() {
let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
let private_key = ANVIL_FIRST_PRIVATE_KEY.to_string();
let el_chain_writer =
new_test_writer_with_private_key(http_endpoint.to_string(), private_key).await;
let earnings = U256::from(42);
let (_root, claim) = new_claim(&http_endpoint, earnings).await;
let earner = ANVIL_FIRST_ADDRESS;
let tx_hash = el_chain_writer.process_claim(earner, claim).await.unwrap();

let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
assert!(receipt.status());
Expand Down
14 changes: 11 additions & 3 deletions crates/chainio/clients/eth/src/instrumented_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1011,11 +1011,18 @@ mod tests {

// build the transaction
let to = address!("a0Ee7A142d267C1f36714E4a8F75612F20a79720");
let from = address!("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266");
// retrieve the nonce to then plug it in the transaction
let nonce = instrumented_client
.nonce_at(from, BlockNumberOrTag::Latest)
.await
.unwrap();

let mut tx = TxLegacy {
to: Call(to),
value: U256::from(0),
gas_limit: 2_000_000,
nonce: 0x69, // nonce queried from the sender account
nonce,
gas_price: 21_000_000_000,
input: bytes!(),
chain_id: Some(31337),
Expand Down Expand Up @@ -1116,7 +1123,7 @@ mod tests {
// test call_contract
let expected_bytes = anvil.call(&tx_request).await.unwrap();
let bytes = instrumented_client
.call_contract(tx_request.clone(), BlockNumberOrTag::Earliest)
.call_contract(tx_request.clone(), BlockNumberOrTag::Latest)
.await
.unwrap();
assert_eq!(expected_bytes, bytes);
Expand Down Expand Up @@ -1155,8 +1162,9 @@ mod tests {
.await
.unwrap();

let block_number = instrumented_client.block_number().await.unwrap();
let storage = instrumented_client
.storage_at(account, U256::ZERO, U256::ZERO)
.storage_at(account, U256::ZERO, U256::from(block_number))
.await
.unwrap();

Expand Down

Large diffs are not rendered by default.

33 changes: 8 additions & 25 deletions crates/contracts/anvil/deploy-contracts-save-anvil-state.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,6 @@
# Enable the script to exit immediately if a command exits with a non-zero status
set -o errexit -o nounset -o pipefail

# Define your cleanup function
clean_up() {
echo "Executing cleanup function..."
set +e
pkill -f anvil

# Check if the exit status is non-zero
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "Script exited due to set -e on line $1 with command '$2'. Exit status: $exit_status"
fi
}
# Use trap to call the clean_up function when the script exits
trap 'clean_up $LINENO "$BASH_COMMAND"' EXIT

# cd to the directory of this script so that this can be run from anywhere
anvil_dir=$(
cd "$(dirname "${BASH_SOURCE[0]}")"
Expand All @@ -40,19 +25,17 @@ CHAIN_ID=$(cast chain-id)

# DEPLOY CONTRACT REGISTRY
cd $root_dir/contracts
forge create src/ContractsRegistry.sol:ContractsRegistry --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY
forge create src/ContractsRegistry.sol:ContractsRegistry --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast


# DEPLOY EIGENLAYER
EIGEN_CONTRACTS_DIR=$root_dir/contracts/lib/eigenlayer-middleware/lib/eigenlayer-contracts
DEVNET_OUTPUT_DIR=$EIGEN_CONTRACTS_DIR/script/output/devnet
# deployment overwrites this file, so we save it as backup, because we want that output in our local files, and not in the eigenlayer-contracts submodule files
mv $DEVNET_OUTPUT_DIR/M2_from_scratch_deployment_data.json $DEVNET_OUTPUT_DIR/M2_from_scratch_deployment_data.json.bak
cd $EIGEN_CONTRACTS_DIR
forge script script/deploy/devnet/M2_Deploy_From_Scratch.s.sol --rpc-url $ETH_HTTP_URL \
forge script script/deploy/local/Deploy_From_Scratch.s.sol:DeployFromScratch --rpc-url $ETH_HTTP_URL \
--private-key $DEPLOYER_PRIVATE_KEY --broadcast \
--sig "run(string memory configFileName)" -- M2_deploy_from_scratch.anvil.config.json
mv $DEVNET_OUTPUT_DIR/M2_from_scratch_deployment_data.json $root_dir/contracts/script/output/${CHAIN_ID:?}/eigenlayer_deployment_output.json
mv $DEVNET_OUTPUT_DIR/M2_from_scratch_deployment_data.json.bak $DEVNET_OUTPUT_DIR/M2_from_scratch_deployment_data.json
--sig "run(string memory configFileName)" -- local/deploy_from_scratch.anvil.config.json
mv $DEVNET_OUTPUT_DIR/local_from_scratch_deployment_data.json $root_dir/contracts/script/output/${CHAIN_ID:?}/eigenlayer_deployment_output.json

# DEPLOY MOCKAVS
cd $root_dir/contracts
Expand All @@ -61,15 +44,15 @@ forge script script/DeployMockAvs.s.sol --rpc-url $ETH_HTTP_URL --private-key $D
# DEPLOY TOKENS AND STRATEGIES
cd $root_dir/contracts
# DO NOT REMOVE THE SLOW DIRECTIVE FROM THIS SCRIPT INVOCATION
# slow ensures that the transaction reciept is successful and recieved before sending the next transaction
# slow ensures that the transaction receipt is successful and received before sending the next transaction
# this should prevent the strategies deploying/registering in a flakey manner,
forge script script/DeployTokensStrategiesCreateQuorums.s.sol --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast --slow

# REGISTER OPERATORS WITH EIGENLAYER
cd $root_dir/contracts
# DO NOT REMOVE THE SLOW DIRECTIVE FROM THIS SCRIPT INVOCATION
# slow ensures that the transaction receipt is successful and recieved before sending the next transaction
# slow ensures that the transaction receipt is successful and received before sending the next transaction
# this should prevent the operators registering in a flakey manner, the operators registered will change from run to run without this
forge script script/RegisterOperatorsWithEigenlayer.s.sol --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast --slow

forge script script/UpdateOperators.s.sol --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast --slow
forge script script/UpdateOperators.s.sol --rpc-url $ETH_HTTP_URL --private-key $DEPLOYER_PRIVATE_KEY --broadcast --slow
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,9 @@ set -a
source ./utils.sh
set +a

cleanup() {
echo "Executing cleanup function..."
set +e
docker rm -f anvil
exit_status=$?
if [ $exit_status -ne 0 ]; then
echo "Script exited due to set -e on line $1 with command '$2'. Exit status: $exit_status"
fi
}
trap 'cleanup $LINENO "$BASH_COMMAND"' EXIT

# start an anvil instance in the background that has eigenlayer contracts deployed
# we start anvil in the background so that we can run the below script
# anvil --load-state avs-and-eigenlayer-deployed-anvil-state.json &
# FIXME: bug in latest foundry version, so we use this pinned version instead of latest
start_anvil_docker $parent_path/contracts_deployed_anvil_state.json ""

cd ../../contracts
Expand Down
16 changes: 3 additions & 13 deletions crates/contracts/anvil/utils.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
#!/bin/bash


# pinning at old foundry commit because of https://github.com/foundry-rs/foundry/issues/7502
FOUNDRY_IMAGE=ghcr.io/foundry-rs/foundry:nightly-5b7e4cb3c882b28f3c32ba580de27ce7381f415a
FOUNDRY_IMAGE=ghcr.io/foundry-rs/foundry:stable@sha256:daeeaaf4383ee0cbfc9f31f079a04ffb0123e49e5f67f2a20b5ce1ac1959a4d6

set -e -o nounset

Expand All @@ -11,6 +9,7 @@ parent_path=$(
pwd -P
)


clean_up() {
# Check if the exit status is non-zero
exit_status=$?
Expand All @@ -32,18 +31,9 @@ start_anvil_docker() {
DUMP_STATE_ANVIL_ARG=$([[ -z $DUMP_STATE_FILE ]] && echo "" || echo "--dump-state /dump-state.json")

trap 'docker stop anvil 2>/dev/null || true' EXIT
docker run -d --name anvil -p 8545:8545 $LOAD_STATE_VOLUME_DOCKER_ARG $DUMP_STATE_VOLUME_DOCKER_ARG \
docker run --rm -d --name anvil -p 8545:8545 $LOAD_STATE_VOLUME_DOCKER_ARG $DUMP_STATE_VOLUME_DOCKER_ARG \
--entrypoint anvil \
$FOUNDRY_IMAGE \
$LOAD_STATE_ANVIL_ARG $DUMP_STATE_ANVIL_ARG --host 0.0.0.0
sleep 2
}









Loading
Loading