1use std::str::FromStr;
2
3use crate::error::ElContractsError;
4use crate::reader::ELChainReader;
5use alloy::dyn_abi::DynSolValue;
6use alloy::primitives::{Address, Bytes, FixedBytes, Signature, TxHash, U256};
7use alloy::signers::local::PrivateKeySigner;
8use alloy::signers::Signer;
9use alloy::sol;
10use eigen_common::{get_provider, get_signer};
11use eigen_crypto_bls::{
12 alloy_g1_point_slashing_to_g1_affine, alloy_g1_point_to_g1_affine, convert_to_g1_point,
13 convert_to_g2_point, BlsKeyPair,
14};
15use eigen_types::operator::operator_id_from_g1_pub_key;
16pub use eigen_types::operator::Operator;
17
18use eigen_utils::convert_allocation_operator_set_to_rewards_operator_set;
19use eigen_utils::rewardsv2::core::delegation_manager::DelegationManager as RewardsV2DelegationManager;
20use eigen_utils::rewardsv2::core::delegation_manager::IDelegationManager::OperatorDetails;
21use eigen_utils::slashing::core::allocation_manager::AllocationManager::OperatorSet;
22
23use eigen_utils::slashing::middleware::registry_coordinator::BN254::{G1Point, G2Point};
24use eigen_utils::slashing::middleware::slashing_registry_coordinator::ISlashingRegistryCoordinatorTypes::OperatorKickParam;
25use eigen_utils::slashing::middleware::slashing_registry_coordinator::SlashingRegistryCoordinator;
26use eigen_utils::{
27 slashing::core::{
28 allocation_manager::{AllocationManager, IAllocationManagerTypes},
29 delegation_manager::DelegationManager,
30 i_rewards_coordinator::{IRewardsCoordinator, IRewardsCoordinatorTypes::RewardsMerkleClaim},
31 permission_controller::PermissionController,
32 strategy_manager::StrategyManager,
33 },
34 slashing::middleware::{ierc20::IERC20, registry_coordinator::RegistryCoordinator},
35};
36use tracing::info;
37
38pub const GAS_LIMIT_REGISTER_AS_OPERATOR_DELEGATION_MANAGER: u128 = 300000;
40
41sol! {
42 #[allow(missing_docs)]
43 #[derive(Debug)]
44 enum RegistrationType {
46 NORMAL,
47 CHURN,
48 }
49}
50#[derive(Debug, Clone)]
52pub struct ELChainWriter {
53 strategy_manager: Address,
54 rewards_coordinator: Address,
55 permission_controller: Option<Address>,
56 allocation_manager: Option<Address>,
57 registry_coordinator: Address,
58 el_chain_reader: ELChainReader,
59 provider: String,
60 signer: String,
61}
62
63impl ELChainWriter {
64 #[allow(clippy::too_many_arguments)]
65 pub fn new(
66 strategy_manager: Address,
67 rewards_coordinator: Address,
68 permission_controller: Option<Address>,
69 allocation_manager: Option<Address>,
70 registry_coordinator: Address,
71 el_chain_reader: ELChainReader,
72 provider: String,
73 signer: String,
74 ) -> Self {
75 Self {
76 strategy_manager,
77 rewards_coordinator,
78 permission_controller,
79 allocation_manager,
80 registry_coordinator,
81 el_chain_reader,
82 provider,
83 signer,
84 }
85 }
86
87 pub fn set_signer(&mut self, signer: String) {
94 self.signer = signer;
95 }
96
97 pub async fn register_as_operator_preslashing(
98 &self,
99 operator: Operator,
100 ) -> Result<TxHash, ElContractsError> {
101 info!("registering operator {:?} to EigenLayer", operator.address);
102 let provider = get_signer(&self.signer.clone(), &self.provider);
103
104 if let Some(staker_opt_out_blocks) = operator.staker_opt_out_window_blocks {
105 let contract_delegation_manager =
106 RewardsV2DelegationManager::new(self.el_chain_reader.delegation_manager, provider);
107 let operator_details = OperatorDetails {
108 __deprecated_earningsReceiver: operator
109 ._deprecated_earnings_receiver_address
110 .unwrap_or(Address::ZERO),
111 delegationApprover: operator.delegation_approver_address,
112 stakerOptOutWindowBlocks: staker_opt_out_blocks,
113 };
114 let binding = {
115 let contract_call = contract_delegation_manager
116 .registerAsOperator(operator_details, operator.metadata_url);
117 contract_call.gas(300000)
118 };
119 let binding_tx = binding
120 .send()
121 .await
122 .map_err(ElContractsError::AlloyContractError)?;
123
124 let receipt = binding_tx
125 .get_receipt()
126 .await
127 .map_err(ElContractsError::AlloyPendingTransactionError)?;
128
129 let tx_status = receipt.status();
130 let hash = receipt.transaction_hash;
131 if tx_status {
132 info!(tx_hash = %receipt.transaction_hash, "tx successfully included");
133 } else {
134 info!(tx_hash = %receipt.transaction_hash, "failed to register operator");
135 };
136 Ok(hash)
137 } else {
138 Err(ElContractsError::StakerOptOutWindowBlocksNotSet)
139 }
140 }
141
142 pub async fn register_as_operator(
156 &self,
157 operator: Operator,
158 ) -> Result<TxHash, ElContractsError> {
159 info!("registering operator {:?} to EigenLayer", operator.address);
160 let provider = get_signer(&self.signer.clone(), &self.provider);
161
162 let contract_delegation_manager =
163 DelegationManager::new(self.el_chain_reader.delegation_manager, provider);
164
165 if let Some(allocation_delay) = operator.allocation_delay {
166 let binding = {
167 let contract_call = contract_delegation_manager.registerAsOperator(
168 operator.address,
169 allocation_delay,
170 operator.metadata_url,
171 );
172 contract_call.gas(300000)
173 };
174
175 let binding_tx = binding
176 .send()
177 .await
178 .map_err(ElContractsError::AlloyContractError)?;
179
180 let receipt = binding_tx
181 .get_receipt()
182 .await
183 .map_err(ElContractsError::AlloyPendingTransactionError)?;
184
185 let tx_status = receipt.status();
186 let hash = receipt.transaction_hash;
187 if tx_status {
188 info!(tx_hash = %receipt.transaction_hash, "tx successfully included");
189 } else {
190 info!(tx_hash = %receipt.transaction_hash, "failed to register operator");
191 };
192 Ok(hash)
193 } else {
194 Err(ElContractsError::AllocationDelayNotSet)
195 }
196 }
197
198 pub async fn update_operator_details(
212 &self,
213 operator: Operator,
214 ) -> Result<TxHash, ElContractsError> {
215 info!(
216 "updating operator detils of operator {:?} to EigenLayer",
217 operator.address
218 );
219
220 let provider = get_signer(&self.signer.clone(), &self.provider);
221
222 let contract_delegation_manager =
223 DelegationManager::new(self.el_chain_reader.delegation_manager, provider);
224
225 let contract_call_modify_operator_details = contract_delegation_manager
226 .modifyOperatorDetails(operator.address, operator.delegation_approver_address);
227
228 let modify_operator_tx = contract_call_modify_operator_details
229 .send()
230 .await
231 .map_err(ElContractsError::AlloyContractError)?;
232
233 info!(tx_hash = %modify_operator_tx.tx_hash(), operator = %operator.address, "updated operator details tx");
234
235 let contract_call_update_metadata_uri = contract_delegation_manager
236 .updateOperatorMetadataURI(operator.address, operator.metadata_url);
237
238 let metadata_tx = contract_call_update_metadata_uri.send().await?;
239
240 Ok(*metadata_tx.tx_hash())
241 }
242
243 pub async fn deposit_erc20_into_strategy(
258 &self,
259 strategy_addr: Address,
260 amount: U256,
261 ) -> Result<TxHash, ElContractsError> {
262 info!("depositing {amount:?} tokens into strategy {strategy_addr:?}");
263 let (_strategy, token_address) = self
264 .el_chain_reader
265 .get_strategy_and_underlying_token(strategy_addr)
266 .await?;
267 let provider = get_signer(&self.signer.clone(), &self.provider);
268 let token_contract = IERC20::new(token_address, &provider);
269
270 let contract_call = token_contract.approve(self.strategy_manager, amount);
271
272 let _approve = contract_call.send().await?;
273
274 let contract_strategy_manager = StrategyManager::new(self.strategy_manager, &provider);
275
276 let deposit_contract_call =
277 contract_strategy_manager.depositIntoStrategy(strategy_addr, token_address, amount);
278
279 let tx = deposit_contract_call.send().await?;
280
281 info!("deposited {amount:?} tokens into strategy {strategy_addr:?}");
282 Ok(*tx.tx_hash())
283 }
284
285 pub async fn set_claimer_for(
299 &self,
300 claimer: Address,
301 ) -> Result<FixedBytes<32>, ElContractsError> {
302 let provider = get_signer(&self.signer, &self.provider);
303
304 let contract_rewards_coordinator =
305 IRewardsCoordinator::new(self.rewards_coordinator, &provider);
306
307 let set_claimer_for_call = contract_rewards_coordinator.setClaimerFor_0(claimer);
308
309 let tx = set_claimer_for_call.send().await?;
310 Ok(*tx.tx_hash())
311 }
312
313 pub async fn process_claim(
333 &self,
334 claim: RewardsMerkleClaim,
335 earner_address: Address,
336 ) -> Result<FixedBytes<32>, ElContractsError> {
337 let provider = get_signer(&self.signer, &self.provider);
338
339 let contract_rewards_coordinator =
340 IRewardsCoordinator::new(self.rewards_coordinator, &provider);
341
342 let process_claim_call = contract_rewards_coordinator.processClaim(claim, earner_address);
343
344 let tx = process_claim_call.send().await?;
345 Ok(*tx.tx_hash())
346 }
347
348 pub async fn process_claims(
368 &self,
369 claims: Vec<RewardsMerkleClaim>,
370 earner_address: Address,
371 ) -> Result<FixedBytes<32>, ElContractsError> {
372 let provider = get_signer(&self.signer, &self.provider);
373
374 let contract_rewards_coordinator =
375 IRewardsCoordinator::new(self.rewards_coordinator, &provider);
376
377 let process_claim_call = contract_rewards_coordinator.processClaims(claims, earner_address);
378
379 let tx = process_claim_call.send().await?;
380 Ok(*tx.tx_hash())
381 }
382
383 pub async fn set_operator_avs_split(
399 &self,
400 operator: Address,
401 avs: Address,
402 split: u16,
403 ) -> Result<FixedBytes<32>, ElContractsError> {
404 let signer = get_signer(&self.signer, &self.provider);
405
406 let rewards_coordinator = IRewardsCoordinator::new(self.rewards_coordinator, signer);
407
408 let tx = rewards_coordinator
409 .setOperatorAVSSplit(operator, avs, split)
410 .send()
411 .await
412 .map_err(ElContractsError::AlloyContractError)?;
413
414 Ok(*tx.tx_hash())
415 }
416
417 pub async fn set_operator_set_split(
433 &self,
434 operator: Address,
435 operator_set: OperatorSet,
436 split: u16,
437 ) -> Result<FixedBytes<32>, ElContractsError> {
438 let signer = get_signer(&self.signer, &self.provider);
439
440 let rewards_coordinator = IRewardsCoordinator::new(self.rewards_coordinator, signer);
441 let operator_set_rewards =
442 convert_allocation_operator_set_to_rewards_operator_set(operator_set);
443 let tx = rewards_coordinator
444 .setOperatorSetSplit(operator, operator_set_rewards, split)
445 .send()
446 .await
447 .map_err(ElContractsError::AlloyContractError)?;
448
449 Ok(*tx.tx_hash())
450 }
451
452 pub async fn set_operator_pi_split(
467 &self,
468 operator: Address,
469 split: u16,
470 ) -> Result<FixedBytes<32>, ElContractsError> {
471 let signer = get_signer(&self.signer, &self.provider);
472
473 let rewards_coordinator = IRewardsCoordinator::new(self.rewards_coordinator, signer);
474
475 let tx = rewards_coordinator
476 .setOperatorPISplit(operator, split)
477 .send()
478 .await
479 .map_err(ElContractsError::AlloyContractError)?;
480
481 Ok(*tx.tx_hash())
482 }
483
484 pub async fn remove_permission(
501 &self,
502 account_address: Address,
503 appointee_address: Address,
504 target: Address,
505 selector: FixedBytes<4>,
506 ) -> Result<TxHash, ElContractsError> {
507 let provider = get_signer(&self.signer, &self.provider);
508 let permission_controller_contract = PermissionController::new(
509 self.permission_controller
510 .ok_or(ElContractsError::MissingParameter)?,
511 provider,
512 );
513
514 let tx = permission_controller_contract
515 .removeAppointee(account_address, appointee_address, target, selector)
516 .send()
517 .await
518 .map_err(ElContractsError::AlloyContractError)?;
519
520 Ok(*tx.tx_hash())
521 }
522
523 pub async fn set_permission(
535 &self,
536 account_address: Address,
537 appointee_address: Address,
538 target: Address,
539 selector: FixedBytes<4>,
540 ) -> Result<TxHash, ElContractsError> {
541 let provider = get_signer(&self.signer, &self.provider);
542 let permission_controller_contract = PermissionController::new(
543 self.permission_controller
544 .ok_or(ElContractsError::MissingParameter)?,
545 provider,
546 );
547
548 let tx = permission_controller_contract
549 .setAppointee(account_address, appointee_address, target, selector)
550 .send()
551 .await
552 .map_err(ElContractsError::AlloyContractError)?;
553
554 Ok(*tx.tx_hash())
555 }
556
557 pub async fn remove_pending_admin(
568 &self,
569 account_address: Address,
570 admin_address: Address,
571 ) -> Result<TxHash, ElContractsError> {
572 let provider = get_signer(&self.signer, &self.provider);
573 let permission_controller_contract = PermissionController::new(
574 self.permission_controller
575 .ok_or(ElContractsError::MissingParameter)?,
576 provider,
577 );
578
579 let tx = permission_controller_contract
580 .removePendingAdmin(account_address, admin_address)
581 .send()
582 .await
583 .map_err(ElContractsError::AlloyContractError)?;
584
585 Ok(*tx.tx_hash())
586 }
587
588 pub async fn add_pending_admin(
600 &self,
601 account_address: Address,
602 admin_address: Address,
603 ) -> Result<TxHash, ElContractsError> {
604 let provider = get_signer(&self.signer, &self.provider);
605 let permission_controller_contract = PermissionController::new(
606 self.permission_controller
607 .ok_or(ElContractsError::MissingParameter)?,
608 provider,
609 );
610
611 let tx = permission_controller_contract
612 .addPendingAdmin(account_address, admin_address)
613 .send()
614 .await
615 .map_err(ElContractsError::AlloyContractError)?;
616
617 Ok(*tx.tx_hash())
618 }
619
620 pub async fn accept_admin(&self, account: Address) -> Result<TxHash, ElContractsError> {
634 let provider = get_signer(&self.signer, &self.provider);
635 let permission_controller_contract = PermissionController::new(
636 self.permission_controller
637 .ok_or(ElContractsError::MissingParameter)?,
638 provider,
639 );
640
641 let tx = permission_controller_contract
642 .acceptAdmin(account)
643 .send()
644 .await
645 .map_err(ElContractsError::AlloyContractError)?;
646
647 Ok(*tx.tx_hash())
648 }
649
650 pub async fn remove_admin(
665 &self,
666 account: Address,
667 admin: Address,
668 ) -> Result<TxHash, ElContractsError> {
669 let provider = get_signer(&self.signer, &self.provider);
670 let permission_controller_contract = PermissionController::new(
671 self.permission_controller
672 .ok_or(ElContractsError::MissingParameter)?,
673 provider,
674 );
675
676 let tx = permission_controller_contract
677 .removeAdmin(account, admin)
678 .send()
679 .await
680 .map_err(ElContractsError::AlloyContractError)?;
681
682 Ok(*tx.tx_hash())
683 }
684
685 pub async fn register_for_operator_sets(
702 &self,
703 operator_address: Address,
704 avs_address: Address,
705 operator_set_ids: Vec<u32>,
706 bls_key_pair: BlsKeyPair,
707 socket: &str,
708 ) -> Result<TxHash, ElContractsError> {
709 let provider = get_signer(&self.signer, &self.provider);
710 let contract_allocation_manager = AllocationManager::new(
711 self.allocation_manager
712 .ok_or(ElContractsError::MissingParameter)?,
713 provider.clone(),
714 );
715 let contract_registry_coordinator =
716 RegistryCoordinator::new(self.registry_coordinator, provider);
717
718 let g1_hashed_msg_to_sign = contract_registry_coordinator
719 .pubkeyRegistrationMessageHash(operator_address)
720 .call()
721 .await?;
722
723 let sig = bls_key_pair
724 .sign_hashed_to_curve_message(alloy_g1_point_to_g1_affine(g1_hashed_msg_to_sign))
725 .g1_point();
726 let alloy_g1_point_signed_msg =
727 convert_to_g1_point(sig.g1()).map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
728 let g1_pub_key_bn254 = convert_to_g1_point(bls_key_pair.public_key().g1())
729 .map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
730 let g2_pub_key_bn254 = convert_to_g2_point(bls_key_pair.public_key_g2().g2())
731 .map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
732
733 let g2_point_x: Vec<DynSolValue> = vec![
734 DynSolValue::Uint(g2_pub_key_bn254.X[0], 256),
735 DynSolValue::Uint(g2_pub_key_bn254.X[1], 256),
736 ];
737 let g2_point_y: Vec<DynSolValue> = vec![
738 DynSolValue::Uint(g2_pub_key_bn254.Y[0], 256),
739 DynSolValue::Uint(g2_pub_key_bn254.Y[1], 256),
740 ];
741 let encoded_params_with_socket = DynSolValue::Tuple(vec![
742 DynSolValue::Uint(U256::from(0), 256),
743 DynSolValue::String(socket.to_string()),
744 DynSolValue::Uint(alloy_g1_point_signed_msg.X, 256),
745 DynSolValue::Uint(alloy_g1_point_signed_msg.Y, 256),
746 DynSolValue::Uint(g1_pub_key_bn254.X, 256),
747 DynSolValue::Uint(g1_pub_key_bn254.Y, 256),
748 DynSolValue::FixedArray(g2_point_x),
749 DynSolValue::FixedArray(g2_point_y),
750 ])
751 .abi_encode_params();
752
753 let params = IAllocationManagerTypes::RegisterParams {
754 avs: avs_address,
755 operatorSetIds: operator_set_ids,
756 data: encoded_params_with_socket.into(),
757 };
758 let tx = contract_allocation_manager
759 .registerForOperatorSets(operator_address, params)
760 .send()
761 .await?;
762
763 Ok(*tx.tx_hash())
764 }
765
766 #[allow(clippy::too_many_arguments)]
795 pub async fn register_for_operator_sets_with_churn(
796 &self,
797 operator: Address,
798 bls_key_pair: BlsKeyPair,
799 avs_address: Address,
800 operator_set_ids: Vec<u32>,
801 socket: String,
802 quorum_numbers: Bytes,
803 operators_to_kick: Vec<Address>,
804 churn_signer_private_key: String,
805 churn_sig_salt: FixedBytes<32>,
806 churn_sig_expiry: U256,
807 ) -> Result<TxHash, ElContractsError> {
808 let provider = get_signer(&self.signer, &self.provider);
809
810 let allocation_manager = AllocationManager::new(
811 self.allocation_manager
812 .ok_or(ElContractsError::MissingParameter)?,
813 &provider,
814 );
815
816 let (alloy_g1_point_signed_msg, g1_pub_key_bn254, g2_pub_key_bn254) =
817 prepare_bls_keys_for_registration(
818 &self.provider,
819 self.registry_coordinator,
820 operator,
821 &bls_key_pair,
822 )
823 .await?;
824
825 let operators_to_kick_params =
826 build_operator_kick_params(&operators_to_kick, &quorum_numbers);
827
828 let churn_signature = sign_churn_digest(
829 &self.provider,
830 self.registry_coordinator,
831 &bls_key_pair,
832 operator,
833 &operators_to_kick_params,
834 churn_signer_private_key,
835 churn_sig_salt,
836 churn_sig_expiry,
837 )
838 .await?;
839
840 let encoded_data = encode_registration_data(
841 socket,
842 alloy_g1_point_signed_msg,
843 g1_pub_key_bn254,
844 g2_pub_key_bn254,
845 operators_to_kick_params,
846 churn_signature,
847 churn_sig_salt,
848 churn_sig_expiry,
849 );
850
851 let register_params = IAllocationManagerTypes::RegisterParams {
852 avs: avs_address,
853 operatorSetIds: operator_set_ids,
854 data: encoded_data.into(),
855 };
856
857 let tx = allocation_manager
858 .registerForOperatorSets(operator, register_params)
859 .send()
860 .await
861 .map_err(ElContractsError::AlloyContractError)?;
862
863 Ok(*tx.tx_hash())
864 }
865
866 pub async fn deregister_from_operator_sets(
883 &self,
884 operator_address: Address,
885 avs_address: Address,
886 operator_set_ids: Vec<u32>,
887 ) -> Result<TxHash, ElContractsError> {
888 let provider = get_signer(&self.signer, &self.provider);
889 let contract_allocation_manager = AllocationManager::new(
890 self.allocation_manager
891 .ok_or(ElContractsError::MissingParameter)?,
892 provider,
893 );
894
895 let params = IAllocationManagerTypes::DeregisterParams {
896 operator: operator_address,
897 avs: avs_address,
898 operatorSetIds: operator_set_ids,
899 };
900 let tx = contract_allocation_manager
901 .deregisterFromOperatorSets(params)
902 .send()
903 .await
904 .map_err(ElContractsError::AlloyContractError)?;
905
906 Ok(*tx.tx_hash())
907 }
908
909 pub async fn set_allocation_delay(
925 &self,
926 operator_address: Address,
927 delay: u32,
928 ) -> Result<TxHash, ElContractsError> {
929 let provider = get_signer(&self.signer, &self.provider);
930 let contract_allocation_manager = AllocationManager::new(
931 self.allocation_manager
932 .ok_or(ElContractsError::MissingParameter)?,
933 provider,
934 );
935
936 let tx = contract_allocation_manager
937 .setAllocationDelay(operator_address, delay)
938 .send()
939 .await
940 .map_err(ElContractsError::AlloyContractError)?;
941
942 Ok(*tx.tx_hash())
943 }
944
945 pub async fn modify_allocations(
954 &self,
955 operator_address: Address,
956 allocations: Vec<IAllocationManagerTypes::AllocateParams>,
957 ) -> Result<TxHash, ElContractsError> {
958 let provider = get_signer(&self.signer, &self.provider);
959 let contract_allocation_manager = AllocationManager::new(
960 self.allocation_manager
961 .ok_or(ElContractsError::MissingParameter)?,
962 provider,
963 );
964
965 let tx = contract_allocation_manager
966 .modifyAllocations(operator_address, allocations)
967 .send()
968 .await
969 .map_err(ElContractsError::AlloyContractError)?;
970
971 Ok(*tx.tx_hash())
972 }
973
974 pub async fn clear_deallocation_queue(
989 &self,
990 operator: Address,
991 strategies: Vec<Address>,
992 num_to_clear: Vec<u16>,
993 ) -> Result<TxHash, ElContractsError> {
994 let provider = get_signer(&self.signer, &self.provider);
995 let allocation_manager_contract = AllocationManager::new(
996 self.allocation_manager
997 .ok_or(ElContractsError::MissingParameter)?,
998 provider,
999 );
1000
1001 allocation_manager_contract
1002 .clearDeallocationQueue(operator, strategies, num_to_clear)
1003 .send()
1004 .await
1005 .map_err(ElContractsError::AlloyContractError)
1006 .map(|tx| *tx.tx_hash())
1007 }
1008}
1009
1010async fn prepare_bls_keys_for_registration(
1028 rpc_url: &str,
1029 registry_coordinator_address: Address,
1030 operator: Address,
1031 bls_key_pair: &BlsKeyPair,
1032) -> Result<(G1Point, G1Point, G2Point), ElContractsError> {
1033 let provider = get_provider(rpc_url);
1034 let contract_registry_coordinator =
1035 SlashingRegistryCoordinator::new(registry_coordinator_address, &provider);
1036
1037 let g1_hashed_msg_to_sign = contract_registry_coordinator
1038 .pubkeyRegistrationMessageHash(operator)
1039 .call()
1040 .await?;
1041
1042 let sig = bls_key_pair
1043 .sign_hashed_to_curve_message(alloy_g1_point_slashing_to_g1_affine(g1_hashed_msg_to_sign))
1044 .g1_point();
1045
1046 let alloy_g1_point_signed_msg =
1047 convert_to_g1_point(sig.g1()).map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
1048 let g1_pub_key_bn254 = convert_to_g1_point(bls_key_pair.public_key().g1())
1049 .map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
1050 let g2_pub_key_bn254 = convert_to_g2_point(bls_key_pair.public_key_g2().g2())
1051 .map_err(|_| ElContractsError::BLSKeyPairInvalid)?;
1052
1053 Ok((
1054 alloy_g1_point_signed_msg,
1055 g1_pub_key_bn254,
1056 g2_pub_key_bn254,
1057 ))
1058}
1059
1060fn build_operator_kick_params(
1072 operators_to_kick: &[Address],
1073 quorum_numbers: &Bytes,
1074) -> Vec<OperatorKickParam> {
1075 operators_to_kick
1076 .iter()
1077 .zip(quorum_numbers.iter())
1078 .map(|(address, &quorum_number)| OperatorKickParam {
1079 operator: *address,
1080 quorumNumber: quorum_number,
1081 })
1082 .collect()
1083}
1084
1085#[allow(clippy::too_many_arguments)]
1104async fn sign_churn_digest(
1105 rpc_url: &str,
1106 registry_coordinator_address: Address,
1107 bls_key_pair: &BlsKeyPair,
1108 operator: Address,
1109 operators_to_kick_params: &[OperatorKickParam],
1110 churn_signer_private_key: String,
1111 churn_sig_salt: FixedBytes<32>,
1112 churn_sig_expiry: U256,
1113) -> Result<Signature, ElContractsError> {
1114 let provider = get_provider(rpc_url);
1115 let contract_registry_coordinator =
1116 SlashingRegistryCoordinator::new(registry_coordinator_address, &provider);
1117
1118 let churn_wallet = PrivateKeySigner::from_str(&churn_signer_private_key)
1119 .map_err(|_| ElContractsError::InvalidSignature)?;
1120
1121 let operator_id = operator_id_from_g1_pub_key(bls_key_pair.public_key())
1122 .map_err(|_| ElContractsError::InvalidSignature)?;
1123
1124 let churn_digest_hash = contract_registry_coordinator
1125 .calculateOperatorChurnApprovalDigestHash(
1126 operator,
1127 operator_id,
1128 operators_to_kick_params.to_vec(),
1129 churn_sig_salt,
1130 churn_sig_expiry,
1131 )
1132 .call()
1133 .await?;
1134
1135 let signature = churn_wallet
1136 .sign_hash(&churn_digest_hash)
1137 .await
1138 .map_err(|_| ElContractsError::InvalidSignature)?;
1139
1140 Ok(signature)
1141}
1142
1143#[allow(clippy::too_many_arguments)]
1159fn encode_registration_data(
1160 socket: String,
1161 alloy_g1_point_signed_msg: G1Point,
1162 g1_pub_key_bn254: G1Point,
1163 g2_pub_key_bn254: G2Point,
1164 operators_to_kick_params: Vec<OperatorKickParam>,
1165 churn_signature: Signature,
1166 churn_sig_salt: FixedBytes<32>,
1167 churn_sig_expiry: U256,
1168) -> Vec<u8> {
1169 let g2_point_x = vec![
1170 DynSolValue::Uint(g2_pub_key_bn254.X[0], 256),
1171 DynSolValue::Uint(g2_pub_key_bn254.X[1], 256),
1172 ];
1173 let g2_point_y = vec![
1174 DynSolValue::Uint(g2_pub_key_bn254.Y[0], 256),
1175 DynSolValue::Uint(g2_pub_key_bn254.Y[1], 256),
1176 ];
1177
1178 let pubkey_registration_params = DynSolValue::Tuple(vec![
1179 DynSolValue::Tuple(vec![
1180 DynSolValue::Uint(alloy_g1_point_signed_msg.X, 256),
1181 DynSolValue::Uint(alloy_g1_point_signed_msg.Y, 256),
1182 ]),
1183 DynSolValue::Tuple(vec![
1184 DynSolValue::Uint(g1_pub_key_bn254.X, 256),
1185 DynSolValue::Uint(g1_pub_key_bn254.Y, 256),
1186 ]),
1187 DynSolValue::Tuple(vec![
1188 DynSolValue::FixedArray(g2_point_x),
1189 DynSolValue::FixedArray(g2_point_y),
1190 ]),
1191 ]);
1192
1193 let operator_kick_params = DynSolValue::Array(
1194 operators_to_kick_params
1195 .into_iter()
1196 .map(|param| {
1197 DynSolValue::Tuple(vec![
1198 DynSolValue::Uint(U256::from(param.quorumNumber), 8),
1199 DynSolValue::Address(param.operator),
1200 ])
1201 })
1202 .collect(),
1203 );
1204
1205 let signature_with_salt = DynSolValue::Tuple(vec![
1206 DynSolValue::Bytes(churn_signature.as_bytes().into()),
1207 DynSolValue::FixedBytes(churn_sig_salt, 32),
1208 DynSolValue::Uint(churn_sig_expiry, 256),
1209 ]);
1210
1211 DynSolValue::Tuple(vec![
1212 DynSolValue::Uint(U256::from(1), 8), DynSolValue::String(socket),
1214 pubkey_registration_params,
1215 operator_kick_params,
1216 signature_with_salt,
1217 ])
1218 .abi_encode_params()
1219}
1220
1221#[cfg(test)]
1222mod tests {
1223 use alloy::{
1224 primitives::{address, ruint::aliases::U256, Address, Bytes, FixedBytes},
1225 providers::{Provider, WalletProvider},
1226 };
1227 use eigen_common::{get_provider, get_signer};
1228 use eigen_crypto_bls::BlsKeyPair;
1229 use eigen_testing_utils::{
1230 anvil::{
1231 mine_anvil_blocks, set_account_balance, start_anvil_container, start_m2_anvil_container,
1232 },
1233 anvil_constants::{
1234 get_erc20_mock_strategy, get_registry_coordinator_address, get_service_manager_address,
1235 FIRST_ADDRESS, FIRST_PRIVATE_KEY, OPERATOR_BLS_KEY_2, SECOND_ADDRESS,
1236 SECOND_PRIVATE_KEY,
1237 },
1238 chain_clients::{
1239 build_el_chain_reader, create_operator_set, create_total_delegated_stake_operator_set,
1240 new_claim, new_test_writer, new_test_writer_preslashing, OPERATOR_ADDRESS,
1241 OPERATOR_PRIVATE_KEY,
1242 },
1243 transaction::wait_transaction,
1244 };
1245 use eigen_types::operator::Operator;
1246 use eigen_utils::{
1247 convert_allocation_operator_set_to_rewards_operator_set,
1248 slashing::{
1249 core::allocation_manager::{AllocationManager::OperatorSet, IAllocationManagerTypes},
1250 middleware::slashing_registry_coordinator::{
1251 ISlashingRegistryCoordinatorTypes::OperatorSetParam as OperatorSetParamSlashing,
1252 SlashingRegistryCoordinator,
1253 },
1254 },
1255 };
1256 use std::str::FromStr;
1257
1258 #[tokio::test]
1259 async fn test_register_operator() {
1260 let (container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1261
1262 let new_operator_sk = "0x7ff6d852bfd83bb0e21a575a765bc2f197efeb97f04cf9454d4078d5eca9a726";
1264 let new_operator_address = get_signer(new_operator_sk, &http_endpoint)
1265 .signer_addresses()
1266 .next()
1267 .unwrap();
1268
1269 set_account_balance(&container, &new_operator_address.to_string()).await;
1270
1271 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1272 let el_chain_writer =
1273 new_test_writer(http_endpoint.to_string(), new_operator_sk.to_string()).await;
1274
1275 let operator = Operator {
1276 address: new_operator_address,
1277 delegation_approver_address: new_operator_address,
1278 metadata_url: "metadata_uri".to_string(),
1279 allocation_delay: Some(1),
1280 _deprecated_earnings_receiver_address: None,
1281 staker_opt_out_window_blocks: None,
1282 };
1283
1284 let tx_hash = el_chain_writer
1285 .register_as_operator(operator)
1286 .await
1287 .unwrap();
1288
1289 let tx_status = wait_transaction(&http_endpoint, tx_hash)
1290 .await
1291 .unwrap()
1292 .status();
1293 assert!(tx_status);
1294
1295 let is_registered = el_chain_reader
1296 .is_operator_registered(FIRST_ADDRESS)
1297 .await
1298 .unwrap();
1299 assert!(is_registered);
1300 }
1301
1302 #[tokio::test]
1303 async fn test_register_operator_preslashing() {
1304 let (container, http_endpoint, _ws_endpoint) = start_m2_anvil_container().await;
1305
1306 let new_operator_sk = "0x7ff6d852bfd83bb0e21a575a765bc2f197efeb97f04cf9454d4078d5eca9a726";
1308 let new_operator_address = get_signer(new_operator_sk, &http_endpoint)
1309 .signer_addresses()
1310 .next()
1311 .unwrap();
1312
1313 set_account_balance(&container, &new_operator_address.to_string()).await;
1314
1315 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1316 let el_chain_writer =
1317 new_test_writer_preslashing(http_endpoint.to_string(), new_operator_sk.to_string())
1318 .await;
1319
1320 let operator = Operator {
1321 address: FIRST_ADDRESS, delegation_approver_address: FIRST_ADDRESS,
1323 metadata_url: "metadata_uri".to_string(),
1324 allocation_delay: None,
1325 _deprecated_earnings_receiver_address: None,
1326 staker_opt_out_window_blocks: Some(0u32),
1327 };
1328 let tx_hash = el_chain_writer
1329 .register_as_operator_preslashing(operator)
1330 .await
1331 .unwrap();
1332
1333 let tx_status = wait_transaction(&http_endpoint, tx_hash)
1334 .await
1335 .unwrap()
1336 .status();
1337 assert!(tx_status);
1338
1339 let is_registered = el_chain_reader
1340 .is_operator_registered(FIRST_ADDRESS)
1341 .await
1342 .unwrap();
1343 assert!(is_registered);
1344 }
1345
1346 #[tokio::test]
1347 async fn test_register_and_update_operator() {
1348 let (container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1349 let provider = get_provider(&http_endpoint);
1350
1351 let address_str = "009440d62dc85c73dbf889b7ad1f4da8b231d2ef";
1352 let private_key = "6b35c6d8110c888de06575b45181bf3f9e6c73451fa5cde812c95a6b31e66ddf";
1353 let el_chain_writer =
1354 new_test_writer(http_endpoint.to_string(), private_key.to_string()).await;
1355
1356 set_account_balance(&container, address_str).await;
1357 let address = Address::from_str(address_str).unwrap();
1358
1359 let operator = Operator {
1360 address,
1361 delegation_approver_address: Address::ZERO,
1362 metadata_url: "eigensdk-rs".to_string(),
1363 allocation_delay: Some(1),
1364 _deprecated_earnings_receiver_address: None,
1365 staker_opt_out_window_blocks: None,
1366 };
1367
1368 let tx_hash = el_chain_writer
1370 .register_as_operator(operator)
1371 .await
1372 .unwrap();
1373
1374 let receipt = provider.get_transaction_receipt(tx_hash).await.unwrap();
1375 assert!(receipt.unwrap().status());
1376
1377 let operator_modified = Operator {
1378 address,
1379 delegation_approver_address: Address::ZERO,
1380 metadata_url: "new-metadata".to_string(),
1381 allocation_delay: Some(1),
1382 staker_opt_out_window_blocks: None,
1383 _deprecated_earnings_receiver_address: None,
1384 };
1385
1386 let tx_hash = el_chain_writer
1388 .update_operator_details(operator_modified)
1389 .await
1390 .unwrap();
1391 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1392 assert!(receipt.status());
1393 }
1394
1395 #[tokio::test]
1396 async fn test_deposit_erc20_into_strategy() {
1397 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1398 let el_chain_writer =
1399 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1400
1401 let amount = U256::from_str("100").unwrap();
1402 let strategy_addr = get_erc20_mock_strategy(http_endpoint.clone()).await;
1403 let tx_hash = el_chain_writer
1404 .deposit_erc20_into_strategy(strategy_addr, amount)
1405 .await
1406 .unwrap();
1407
1408 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1409 assert!(receipt.status());
1410 }
1411
1412 #[tokio::test]
1413 async fn test_set_claimer_for() {
1414 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1415 let el_chain_writer =
1416 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1417
1418 let claimer = address!("5eb15C0992734B5e77c888D713b4FC67b3D679A2");
1419
1420 let tx_hash = el_chain_writer.set_claimer_for(claimer).await.unwrap();
1421
1422 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1423 assert!(receipt.status());
1424 }
1425
1426 #[tokio::test]
1427 async fn test_process_claim() {
1428 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1429 let el_chain_writer =
1430 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1431
1432 let (_root, claim) = new_claim(&http_endpoint, U256::from(42)).await;
1433
1434 let tx_hash = el_chain_writer
1435 .process_claim(claim, FIRST_ADDRESS)
1436 .await
1437 .unwrap();
1438
1439 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1440 assert!(receipt.status());
1441 }
1442
1443 #[tokio::test]
1444 async fn test_process_claims() {
1445 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1446 let el_chain_writer =
1447 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1448
1449 let (_root, claim0) = new_claim(&http_endpoint, U256::from(42)).await;
1450 let (_root, claim1) = new_claim(&http_endpoint, U256::from(4256)).await;
1451
1452 let tx_hash = el_chain_writer
1453 .process_claims(vec![claim0, claim1], FIRST_ADDRESS)
1454 .await
1455 .unwrap();
1456
1457 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1458 assert!(receipt.status());
1459 }
1460
1461 #[tokio::test]
1462 async fn test_add_and_remove_pending_admin() {
1463 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1464 let el_chain_writer =
1465 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1466 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1467
1468 let pending_admin = address!("009440d62dc85c73dbf889b7ad1f4da8b231d2ef");
1469 let tx_hash = el_chain_writer
1470 .add_pending_admin(FIRST_ADDRESS, pending_admin)
1471 .await
1472 .unwrap();
1473 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1474 assert!(receipt.status());
1475
1476 let is_pending_admin = el_chain_reader
1477 .is_pending_admin(FIRST_ADDRESS, pending_admin)
1478 .await
1479 .unwrap();
1480 assert!(is_pending_admin);
1481
1482 let tx_hash = el_chain_writer
1483 .remove_pending_admin(FIRST_ADDRESS, pending_admin)
1484 .await
1485 .unwrap();
1486 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1487 assert!(receipt.status());
1488
1489 let is_admin = el_chain_reader
1490 .is_pending_admin(FIRST_ADDRESS, pending_admin)
1491 .await
1492 .unwrap();
1493 assert!(!is_admin);
1494 }
1495
1496 #[tokio::test]
1497 async fn test_accept_admin() {
1498 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1499 let account_writer =
1500 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1501
1502 let pending_admin = address!("14dC79964da2C08b23698B3D3cc7Ca32193d9955");
1503 let pending_admin_key =
1504 "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356";
1505
1506 let tx_hash = account_writer
1507 .add_pending_admin(FIRST_ADDRESS, pending_admin)
1508 .await
1509 .unwrap();
1510
1511 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1512 assert!(receipt.status());
1513
1514 let admin_writer =
1515 new_test_writer(http_endpoint.to_string(), pending_admin_key.to_string()).await;
1516 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1517
1518 let tx_hash = admin_writer.accept_admin(FIRST_ADDRESS).await.unwrap();
1519
1520 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1521 assert!(receipt.status());
1522
1523 let is_admin = el_chain_reader
1524 .is_admin(FIRST_ADDRESS, pending_admin)
1525 .await
1526 .unwrap();
1527 assert!(is_admin);
1528 }
1529
1530 #[tokio::test]
1531 async fn test_remove_admin() {
1532 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1533 let el_chain_writer =
1534 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1535 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1536
1537 let pending_admin_1 = address!("14dC79964da2C08b23698B3D3cc7Ca32193d9955");
1538 let pending_admin_1_key =
1539 "0x4bbbf85ce3377467afe5d46f804f221813b2bb87f24d81f60f1fcdbf7cbf4356";
1540
1541 let pending_admin_2 = address!("23618e81E3f5cdF7f54C3d65f7FBc0aBf5B21E8f");
1542 let pending_admin_2_key =
1543 "0xdbda1821b80551c9d65939329250298aa3472ba22feea921c0cf5d620ea67b97";
1544
1545 let tx_hash = el_chain_writer
1547 .add_pending_admin(FIRST_ADDRESS, pending_admin_1)
1548 .await
1549 .unwrap();
1550 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1551 assert!(receipt.status());
1552
1553 let tx_hash = el_chain_writer
1554 .add_pending_admin(FIRST_ADDRESS, pending_admin_2)
1555 .await
1556 .unwrap();
1557 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1558 assert!(receipt.status());
1559
1560 let admin_1_writer =
1561 new_test_writer(http_endpoint.to_string(), pending_admin_1_key.to_string()).await;
1562 admin_1_writer.accept_admin(FIRST_ADDRESS).await.unwrap();
1563 let admin_2_writer =
1564 new_test_writer(http_endpoint.to_string(), pending_admin_2_key.to_string()).await;
1565 admin_2_writer.accept_admin(FIRST_ADDRESS).await.unwrap();
1566
1567 let tx_hash = admin_1_writer
1568 .remove_admin(FIRST_ADDRESS, pending_admin_2)
1569 .await
1570 .unwrap();
1571
1572 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1573 assert!(receipt.status());
1574
1575 let is_admin = el_chain_reader
1576 .is_admin(FIRST_ADDRESS, pending_admin_2)
1577 .await
1578 .unwrap();
1579 assert!(!is_admin);
1580 }
1581
1582 #[tokio::test]
1583 async fn test_set_and_remove_permission() {
1584 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1585 let account_address = FIRST_ADDRESS;
1586 let appointee_address = address!("009440d62dc85c73dbf889b7ad1f4da8b231d2ef");
1587 let target = address!("14dC79964da2C08b23698B3D3cc7Ca32193d9955");
1588 let selector = [0, 1, 2, 3].into();
1589
1590 let account_writer =
1592 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1593 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1594
1595 let tx_hash = account_writer
1597 .set_permission(account_address, appointee_address, target, selector)
1598 .await
1599 .unwrap();
1600 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1601 assert!(receipt.status());
1602
1603 let can_call = el_chain_reader
1605 .can_call(account_address, appointee_address, target, selector)
1606 .await
1607 .unwrap();
1608 assert!(can_call);
1609
1610 let el_chain_writer =
1612 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1613
1614 let tx_hash = el_chain_writer
1615 .remove_permission(account_address, appointee_address, target, selector)
1616 .await
1617 .unwrap();
1618
1619 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1620 assert!(receipt.status());
1621 }
1622
1623 #[tokio::test]
1624 async fn test_register_for_operator_sets() {
1625 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1626 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1627 let operator_set_id = 0;
1628 create_operator_set(http_endpoint.as_str(), avs_address).await;
1629
1630 let operator_addr = OPERATOR_ADDRESS;
1631 let operator_private_key = OPERATOR_PRIVATE_KEY;
1632 let el_chain_writer =
1633 new_test_writer(http_endpoint.clone(), operator_private_key.to_string()).await;
1634 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1635
1636 let bls_key = BlsKeyPair::new("1".to_string()).unwrap();
1637
1638 let tx_hash = el_chain_writer
1639 .register_for_operator_sets(
1640 operator_addr,
1641 avs_address,
1642 vec![operator_set_id],
1643 bls_key,
1644 "socket",
1645 )
1646 .await
1647 .unwrap();
1648
1649 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1650 assert!(receipt.status());
1651
1652 let operator_set = OperatorSet {
1653 avs: avs_address,
1654 id: operator_set_id,
1655 };
1656 let is_registered = el_chain_reader
1657 .is_operator_registered_with_operator_set(operator_addr, operator_set.clone())
1658 .await
1659 .unwrap();
1660 assert!(is_registered);
1661
1662 let tx_hash = el_chain_writer
1663 .deregister_from_operator_sets(operator_addr, avs_address, vec![operator_set_id])
1664 .await
1665 .unwrap();
1666 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1667 assert!(receipt.status());
1668
1669 let is_registered = el_chain_reader
1670 .is_operator_registered_with_operator_set(operator_addr, operator_set.clone())
1671 .await
1672 .unwrap();
1673 assert!(!is_registered);
1674 }
1675
1676 #[tokio::test]
1677 async fn test_set_allocation_delay() {
1678 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1679 let el_chain_writer =
1680 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1681 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1682
1683 let delay = 10;
1684
1685 let tx_hash = el_chain_writer
1686 .set_allocation_delay(FIRST_ADDRESS, delay)
1687 .await
1688 .unwrap();
1689 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1690 assert!(receipt.status());
1691 let current_block = get_provider(&http_endpoint)
1692 .get_block_number()
1693 .await
1694 .unwrap();
1695 mine_anvil_blocks(&_container, (current_block as u32) + 2).await;
1696 let allocation_delay = el_chain_reader
1697 .get_allocation_delay(FIRST_ADDRESS)
1698 .await
1699 .unwrap();
1700
1701 assert_eq!(allocation_delay, delay);
1702 }
1703
1704 #[tokio::test]
1705 async fn test_modify_allocations() {
1706 let (container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1707 let el_chain_writer =
1708 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1709 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1710
1711 let operator_address = FIRST_ADDRESS;
1712 let strategy_addr = get_erc20_mock_strategy(http_endpoint.clone()).await;
1713
1714 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1715 let operator_set_id = 0;
1716 create_operator_set(http_endpoint.as_str(), avs_address).await;
1717
1718 let new_allocation = 100;
1719 let allocate_params = IAllocationManagerTypes::AllocateParams {
1720 strategies: vec![strategy_addr],
1721 operatorSet:
1722 eigen_utils::slashing::core::allocation_manager::AllocationManager::OperatorSet {
1723 avs: avs_address,
1724 id: operator_set_id,
1725 },
1726 newMagnitudes: vec![new_allocation],
1727 };
1728 let tx_hash = el_chain_writer
1729 .modify_allocations(operator_address, vec![allocate_params])
1730 .await
1731 .unwrap();
1732 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1733 assert!(receipt.status());
1734
1735 let allocation_info = el_chain_reader
1736 .get_allocation_info(operator_address, strategy_addr)
1737 .await
1738 .unwrap();
1739
1740 assert_eq!(allocation_info[0].pending_diff, U256::from(new_allocation));
1742
1743 let allocation_delay = el_chain_reader
1744 .get_allocation_delay(FIRST_ADDRESS)
1745 .await
1746 .unwrap();
1747 mine_anvil_blocks(&container, allocation_delay).await;
1748
1749 let allocation_info = el_chain_reader
1750 .get_allocation_info(operator_address, strategy_addr)
1751 .await
1752 .unwrap();
1753
1754 assert_eq!(
1756 allocation_info[0].current_magnitude,
1757 U256::from(new_allocation)
1758 );
1759 }
1760
1761 #[tokio::test]
1762 async fn test_set_operator_avs_split() {
1763 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1764 let el_chain_writer =
1765 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1766 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1767 let new_split = 5;
1768 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1769
1770 let split = el_chain_reader
1771 .get_operator_avs_split(FIRST_ADDRESS, avs_address)
1772 .await
1773 .unwrap();
1774
1775 assert_eq!(split, 1); let tx_hash = el_chain_writer
1778 .set_operator_avs_split(FIRST_ADDRESS, avs_address, new_split)
1779 .await
1780 .unwrap();
1781
1782 let tx_status = wait_transaction(&http_endpoint, tx_hash)
1783 .await
1784 .unwrap()
1785 .status();
1786 assert!(tx_status);
1787
1788 let split = el_chain_reader
1789 .get_operator_avs_split(FIRST_ADDRESS, avs_address)
1790 .await
1791 .unwrap();
1792 assert_eq!(split, 5); }
1794
1795 #[tokio::test]
1796 async fn test_set_operator_set_split() {
1797 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1798 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1799 let operator_set_id = 0;
1800 create_operator_set(http_endpoint.as_str(), avs_address).await;
1801
1802 let operator_addr = OPERATOR_ADDRESS;
1803 let operator_private_key = OPERATOR_PRIVATE_KEY;
1804 let el_chain_writer =
1805 new_test_writer(http_endpoint.clone(), operator_private_key.to_string()).await;
1806 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1807 let bls_key = BlsKeyPair::new("1".to_string()).unwrap();
1808
1809 let tx_hash = el_chain_writer
1810 .register_for_operator_sets(
1811 operator_addr,
1812 avs_address,
1813 vec![operator_set_id],
1814 bls_key,
1815 "socket",
1816 )
1817 .await
1818 .unwrap();
1819
1820 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1821 assert!(receipt.status());
1822 let operator_set = OperatorSet {
1823 avs: avs_address,
1824 id: 0,
1825 };
1826
1827 let new_split = 5;
1828 let tx_hash = el_chain_writer
1829 .set_operator_set_split(OPERATOR_ADDRESS, operator_set.clone(), new_split)
1830 .await
1831 .unwrap();
1832 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1833 assert!(receipt.status());
1834 let rewards_operator_set =
1835 convert_allocation_operator_set_to_rewards_operator_set(operator_set.clone());
1836 let split = el_chain_reader
1837 .get_operator_set_split(OPERATOR_ADDRESS, rewards_operator_set.clone())
1838 .await
1839 .unwrap();
1840
1841 assert_eq!(split, new_split); }
1843
1844 #[tokio::test]
1845 async fn test_set_operator_pi_split() {
1846 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1847 let el_chain_writer =
1848 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1849 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1850 let new_split = 5;
1851
1852 let split = el_chain_reader
1853 .get_operator_pi_split(FIRST_ADDRESS)
1854 .await
1855 .unwrap();
1856
1857 assert_eq!(split, 1); let tx_hash = el_chain_writer
1860 .set_operator_pi_split(FIRST_ADDRESS, new_split)
1861 .await
1862 .unwrap();
1863
1864 let receipt = wait_transaction(&http_endpoint, tx_hash).await.unwrap();
1865 assert!(receipt.status());
1866
1867 let split = el_chain_reader
1868 .get_operator_pi_split(FIRST_ADDRESS)
1869 .await
1870 .unwrap();
1871
1872 assert_eq!(split, new_split);
1873 }
1874
1875 #[tokio::test]
1876 async fn test_clear_deallocation_queue() {
1877 let (_contianer, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1878 let el_chain_writer =
1879 new_test_writer(http_endpoint.to_string(), FIRST_PRIVATE_KEY.to_string()).await;
1880 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1881 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1882 create_operator_set(http_endpoint.as_str(), avs_address).await;
1883
1884 let operator_address = FIRST_ADDRESS;
1885 let strategy_addr = get_erc20_mock_strategy(http_endpoint.clone()).await;
1886 let operator_set_id = 0;
1887
1888 let new_allocation = 100;
1889 let allocate_params = IAllocationManagerTypes::AllocateParams {
1890 strategies: vec![strategy_addr],
1891 operatorSet: OperatorSet {
1892 avs: avs_address,
1893 id: operator_set_id,
1894 },
1895 newMagnitudes: vec![new_allocation],
1896 };
1897 let tx_hash_alloc = el_chain_writer
1898 .modify_allocations(operator_address, vec![allocate_params.clone()])
1899 .await
1900 .unwrap();
1901 let receipt_alloc = wait_transaction(&http_endpoint, tx_hash_alloc)
1902 .await
1903 .unwrap();
1904 assert!(receipt_alloc.status());
1905
1906 let allocation_info_before = el_chain_reader
1907 .get_allocation_info(operator_address, strategy_addr)
1908 .await
1909 .unwrap();
1910
1911 assert_eq!(
1912 allocation_info_before[0].pending_diff,
1913 U256::from(new_allocation)
1914 );
1915
1916 let tx_hash_clear = el_chain_writer
1917 .clear_deallocation_queue(
1918 operator_address,
1919 vec![strategy_addr],
1920 vec![new_allocation as u16],
1921 )
1922 .await
1923 .unwrap();
1924 let receipt_clear = wait_transaction(&http_endpoint, tx_hash_clear)
1925 .await
1926 .unwrap();
1927 assert!(receipt_clear.status(),);
1928
1929 let allocation_info_after = el_chain_reader
1930 .get_allocation_info(operator_address, strategy_addr)
1931 .await
1932 .unwrap();
1933
1934 assert_eq!(allocation_info_after[0].pending_diff, U256::ZERO);
1935 assert_eq!(
1936 allocation_info_after[0].current_magnitude,
1937 U256::from(new_allocation)
1938 );
1939 }
1940
1941 #[tokio::test]
1942 async fn test_register_for_operator_sets_with_churn() {
1943 let (_container, http_endpoint, _ws_endpoint) = start_anvil_container().await;
1944 let default_signer = get_signer(FIRST_PRIVATE_KEY, &http_endpoint);
1945 let avs_address = get_service_manager_address(http_endpoint.clone()).await;
1946 let operator_set_id = 0;
1947
1948 create_total_delegated_stake_operator_set(
1950 &http_endpoint,
1951 get_erc20_mock_strategy(http_endpoint.clone()).await,
1952 avs_address,
1953 )
1954 .await;
1955
1956 let el_chain_writer =
1958 new_test_writer(http_endpoint.clone(), FIRST_PRIVATE_KEY.to_string()).await;
1959 let el_chain_reader = build_el_chain_reader(http_endpoint.clone()).await;
1960 let bls_key = BlsKeyPair::new("1".to_string()).unwrap();
1961 let tx_hash = el_chain_writer
1962 .register_for_operator_sets_with_churn(
1963 FIRST_ADDRESS,
1964 bls_key,
1965 avs_address,
1966 vec![operator_set_id],
1967 "socket".to_string(),
1968 Bytes::from([0]),
1969 vec![FIRST_ADDRESS],
1970 FIRST_PRIVATE_KEY.to_string(),
1971 FixedBytes::from([0x03; 32]),
1972 U256::MAX,
1973 )
1974 .await
1975 .unwrap();
1976
1977 assert!(wait_transaction(&http_endpoint, tx_hash)
1978 .await
1979 .unwrap()
1980 .status());
1981
1982 assert!(el_chain_reader
1984 .is_operator_registered_with_operator_set(
1985 FIRST_ADDRESS,
1986 OperatorSet {
1987 avs: avs_address,
1988 id: operator_set_id
1989 }
1990 )
1991 .await
1992 .unwrap());
1993
1994 let slashing_registry_coordinator = SlashingRegistryCoordinator::new(
1996 get_registry_coordinator_address(http_endpoint.clone()).await,
1997 default_signer.clone(),
1998 );
1999 let operator_set_params = OperatorSetParamSlashing {
2000 maxOperatorCount: 1,
2001 kickBIPsOfOperatorStake: 10,
2002 kickBIPsOfTotalStake: 10000,
2003 };
2004 assert!(slashing_registry_coordinator
2005 .setOperatorSetParams(0, operator_set_params)
2006 .send()
2007 .await
2008 .unwrap()
2009 .get_receipt()
2010 .await
2011 .unwrap()
2012 .status());
2013
2014 let el_chain_writer_2 =
2016 new_test_writer(http_endpoint.clone(), SECOND_PRIVATE_KEY.to_string()).await;
2017 let tx_hash = el_chain_writer_2
2018 .register_for_operator_sets_with_churn(
2019 SECOND_ADDRESS,
2020 BlsKeyPair::new(OPERATOR_BLS_KEY_2.to_string()).unwrap(),
2021 avs_address,
2022 vec![operator_set_id],
2023 "socket".to_string(),
2024 Bytes::from([0]),
2025 vec![FIRST_ADDRESS],
2026 FIRST_PRIVATE_KEY.to_string(),
2027 FixedBytes::from([0x05; 32]),
2028 U256::MAX,
2029 )
2030 .await
2031 .unwrap();
2032
2033 assert!(wait_transaction(&http_endpoint, tx_hash)
2034 .await
2035 .unwrap()
2036 .status());
2037
2038 assert!(!el_chain_reader
2040 .is_operator_registered_with_operator_set(
2041 FIRST_ADDRESS,
2042 OperatorSet {
2043 avs: avs_address,
2044 id: operator_set_id
2045 }
2046 )
2047 .await
2048 .unwrap());
2049
2050 assert!(el_chain_reader
2052 .is_operator_registered_with_operator_set(
2053 SECOND_ADDRESS,
2054 OperatorSet {
2055 avs: avs_address,
2056 id: operator_set_id
2057 }
2058 )
2059 .await
2060 .unwrap());
2061 }
2062}