diff --git a/gravity-restaking/src/events/mod.rs b/gravity-restaking/src/events/mod.rs new file mode 100644 index 0000000..db0e835 --- /dev/null +++ b/gravity-restaking/src/events/mod.rs @@ -0,0 +1,3 @@ +pub mod sov_events; +pub mod user_events; +pub mod validator_events; diff --git a/gravity-restaking/src/events/sov_events.rs b/gravity-restaking/src/events/sov_events.rs new file mode 100644 index 0000000..7ea10ee --- /dev/null +++ b/gravity-restaking/src/events/sov_events.rs @@ -0,0 +1,56 @@ +use crate::{unique_payments::PaymentsVec, user_actions::sovereign::SovereignInfo}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait SovEventsModule { + #[inline] + fn emit_sov_register_event( + &self, + sov_address: ManagedAddress, + sov_info: SovereignInfo, + ) { + self.sov_register_event(sov_address, sov_info); + } + + #[inline] + fn emit_sov_unregister_event(&self, sov_address: ManagedAddress) { + self.sov_unregister_event(sov_address); + } + + #[inline] + fn emit_sov_add_own_security_funds_event( + &self, + sov_address: ManagedAddress, + payments: PaymentsVec, + ) { + self.sov_add_own_security_funds_event(sov_address, payments); + } + + #[inline] + fn emit_sov_set_max_restaking_cap_event(&self, sov_address: ManagedAddress, max: BigUint) { + self.sov_set_max_restaking_cap_event(sov_address, max); + } + + // Events + + #[event("sovRegisterEvent")] + fn sov_register_event( + &self, + #[indexed] sov_address: ManagedAddress, + sov_info: SovereignInfo, + ); + + #[event("sovUnregisterEvent")] + fn sov_unregister_event(&self, #[indexed] sov_address: ManagedAddress); + + #[event("sovAddOwnSecurityFundsEvent")] + fn sov_add_own_security_funds_event( + &self, + #[indexed] sov_address: ManagedAddress, + payments: PaymentsVec, + ); + + #[event("sovSetMaxRestakingCapEvent")] + fn sov_set_max_restaking_cap_event(&self, #[indexed] sov_address: ManagedAddress, max: BigUint); +} diff --git a/gravity-restaking/src/events/user_events.rs b/gravity-restaking/src/events/user_events.rs new file mode 100644 index 0000000..1258e7a --- /dev/null +++ b/gravity-restaking/src/events/user_events.rs @@ -0,0 +1,142 @@ +use crate::unique_payments::{PaymentsVec, UniquePayments}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait UserEventsModule { + #[inline] + fn emit_user_deposit_event(&self, caller: ManagedAddress, payments: PaymentsVec) { + self.user_deposit_event(caller, payments); + } + + #[inline] + fn emit_move_stake_event( + &self, + caller: ManagedAddress, + delegation: ManagedAddress, + value: BigUint, + ) { + self.move_stake_event(caller, delegation, value); + } + + #[inline] + fn emit_delegate_validator_event( + &self, + caller: ManagedAddress, + validator: ManagedAddress, + payments: PaymentsVec, + ) { + self.delegate_validator_event(caller, validator, payments); + } + + #[inline] + fn emit_delgate_sov_event( + &self, + caller: ManagedAddress, + sov: ManagedAddress, + payments: PaymentsVec, + ) { + self.delegate_sov_event(caller, sov, payments); + } + + #[inline] + fn emit_revoke_validator_event( + &self, + caller: ManagedAddress, + validator: ManagedAddress, + payments: UniquePayments, + ) { + self.revoke_validator_event(caller, validator, payments); + } + + #[inline] + fn emit_revoke_sov_event( + &self, + caller: ManagedAddress, + sov: ManagedAddress, + payments: UniquePayments, + ) { + self.revoke_sov_event(caller, sov, payments); + } + + #[inline] + fn emit_unbond_tokens_caller_event( + &self, + caller: ManagedAddress, + payments: PaymentsVec, + ) { + self.unbond_tokens_caller_event(caller, payments); + } + + #[inline] + fn emit_unbond_tokens_gravity_restaking_event( + &self, + caller: ManagedAddress, + payments: PaymentsVec, + ) { + self.unbond_tokens_gravity_restaking_event(caller, payments); + } + + // Events + + #[event("userDepositEvent")] + fn user_deposit_event( + &self, + #[indexed] caller: ManagedAddress, + payments: PaymentsVec, + ); + + #[event("moveStakeEvent")] + fn move_stake_event( + &self, + #[indexed] caller: ManagedAddress, + #[indexed] delegation: ManagedAddress, + value: BigUint, + ); + + #[event("delegateValidatorEvent")] + fn delegate_validator_event( + &self, + #[indexed] caller: ManagedAddress, + #[indexed] validator: ManagedAddress, + payments: PaymentsVec, + ); + + #[event("delegateSovEvent")] + fn delegate_sov_event( + &self, + #[indexed] caller: ManagedAddress, + #[indexed] sov: ManagedAddress, + payments: PaymentsVec, + ); + + #[event("revokeValidatorEvent")] + fn revoke_validator_event( + &self, + #[indexed] caller: ManagedAddress, + #[indexed] validator: ManagedAddress, + payments: UniquePayments, + ); + + #[event("revokeSovEvent")] + fn revoke_sov_event( + &self, + #[indexed] caller: ManagedAddress, + #[indexed] sov: ManagedAddress, + payments: UniquePayments, + ); + + #[event("unbondTokensCallerEvent")] + fn unbond_tokens_caller_event( + &self, + #[indexed] caller: ManagedAddress, + payments: PaymentsVec, + ); + + #[event("unbondTokensGravityRestakingEvent")] + fn unbond_tokens_gravity_restaking_event( + &self, + #[indexed] caller: ManagedAddress, + payments: PaymentsVec, + ); +} diff --git a/gravity-restaking/src/events/validator_events.rs b/gravity-restaking/src/events/validator_events.rs new file mode 100644 index 0000000..e1ffc23 --- /dev/null +++ b/gravity-restaking/src/events/validator_events.rs @@ -0,0 +1,91 @@ +use crate::{ + unique_payments::PaymentsVec, + user_actions::validator::{BlsKey, Percent}, +}; + +multiversx_sc::imports!(); + +#[multiversx_sc::module] +pub trait ValidatorEventsModule { + #[inline] + fn emit_validator_register_event(&self, validator: ManagedAddress, name: ManagedBuffer) { + self.validator_register_event(validator, name); + } + + #[inline] + fn emit_validator_add_bls_keys_event( + &self, + validator: ManagedAddress, + bls_keys: ManagedVec>, + ) { + self.validator_add_bls_keys_event(validator, bls_keys); + } + + #[inline] + fn emit_validator_remove_bls_keys_event( + &self, + validator: ManagedAddress, + bls_keys: ManagedVec>, + ) { + self.validator_remove_bls_keys_event(validator, bls_keys); + } + + #[inline] + fn emit_validator_set_fee_event(&self, validator: ManagedAddress, fee_percent: Percent) { + self.validator_set_fee_event(validator, fee_percent); + } + + #[inline] + fn emit_validator_set_max_delegation_event( + &self, + validator: ManagedAddress, + max_delegation: BigUint, + ) { + self.validator_set_max_delegation_event(validator, max_delegation); + } + + #[inline] + fn emit_validator_add_own_delegation_event( + &self, + validator: ManagedAddress, + payments: PaymentsVec, + ) { + self.validator_add_own_delegation_event(validator, payments); + } + + // Events + + #[event("validatorRegisterEvent")] + fn validator_register_event(&self, #[indexed] validator: ManagedAddress, name: ManagedBuffer); + + #[event("validatorAddBlsKeysEvent")] + fn validator_add_bls_keys_event( + &self, + #[indexed] validator: ManagedAddress, + bls_keys: ManagedVec>, + ); + + #[event("validatorRemoveBlsKeysEvent")] + fn validator_remove_bls_keys_event( + &self, + #[indexed] validator: ManagedAddress, + bls_keys: ManagedVec>, + ); + + #[event("validatorSetFeeEvent")] + fn validator_set_fee_event(&self, #[indexed] validator: ManagedAddress, fee_percent: Percent); + + #[event("validatorSetMaxDelegationEvent")] + fn validator_set_max_delegation_event( + &self, + #[indexed] validator: ManagedAddress, + max_delegation: BigUint, + ); + + #[event("validatorAddOwnDelegationEvent")] + fn validator_add_own_delegation_event( + &self, + #[indexed] validator: ManagedAddress, + payments: PaymentsVec, + ); +} diff --git a/gravity-restaking/src/lib.rs b/gravity-restaking/src/lib.rs index b1df5e4..42270a8 100644 --- a/gravity-restaking/src/lib.rs +++ b/gravity-restaking/src/lib.rs @@ -4,6 +4,7 @@ use user_actions::sovereign::Epoch; multiversx_sc::imports!(); +pub mod events; pub mod token_whitelist; pub mod unique_payments; pub mod user_actions; @@ -18,6 +19,9 @@ pub trait GravityRestaking: + user_actions::common_actions::CommonActionsModule + user_actions::common_storage::CommonStorageModule + user_actions::unbond::UnbondModule + + events::user_events::UserEventsModule + + events::validator_events::ValidatorEventsModule + + events::sov_events::SovEventsModule + utils::UtilsModule { #[init] diff --git a/gravity-restaking/src/user_actions/call_delegation.rs b/gravity-restaking/src/user_actions/call_delegation.rs index 427b5d1..01b0208 100644 --- a/gravity-restaking/src/user_actions/call_delegation.rs +++ b/gravity-restaking/src/user_actions/call_delegation.rs @@ -28,6 +28,9 @@ pub trait CallDelegationModule: + super::unbond::UnbondModule + super::common_actions::CommonActionsModule + super::common_storage::CommonStorageModule + + crate::events::user_events::UserEventsModule + + crate::events::validator_events::ValidatorEventsModule + + crate::events::sov_events::SovEventsModule + utils::UtilsModule { #[endpoint(moveStakeToReStaking)] @@ -59,26 +62,30 @@ pub trait CallDelegationModule: original_value: BigUint, #[call_result] call_result: ManagedAsyncCallResult<()>, ) { - if let ManagedAsyncCallResult::Ok(()) = call_result { - let ids_mapper = self.user_ids(); - let mut caller_id = ids_mapper.get_id(&original_caller); - let mut user_tokens = if caller_id == NULL_ID { - caller_id = ids_mapper.insert_new(&original_caller); + if call_result.is_err() { + return; + } - UniquePayments::new() - } else { - self.user_tokens(caller_id).get() - }; + let ids_mapper = self.user_ids(); + let mut caller_id = ids_mapper.get_id(&original_caller); + let mut user_tokens = if caller_id == NULL_ID { + caller_id = ids_mapper.insert_new(&original_caller); - let egld_payment = EsdtTokenPayment::new( - TokenIdentifier::from_esdt_bytes(EGLD_TOKEN_ID), - 0, - original_value, - ); - user_tokens.add_payment(egld_payment); + UniquePayments::new() + } else { + self.user_tokens(caller_id).get() + }; - self.user_tokens(caller_id).set(user_tokens); - } + let egld_payment = EsdtTokenPayment::new( + TokenIdentifier::from_esdt_bytes(EGLD_TOKEN_ID), + 0, + original_value.clone(), + ); + user_tokens.add_payment(egld_payment); + self.user_tokens(caller_id).set(user_tokens); + + let delegation = self.blockchain().get_caller(); + self.emit_move_stake_event(original_caller, delegation, original_value); } #[proxy] diff --git a/gravity-restaking/src/user_actions/sovereign.rs b/gravity-restaking/src/user_actions/sovereign.rs index 666277d..26084a5 100644 --- a/gravity-restaking/src/user_actions/sovereign.rs +++ b/gravity-restaking/src/user_actions/sovereign.rs @@ -30,6 +30,7 @@ pub trait SovereignModule: crate::token_whitelist::TokenWhitelistModule + crate::user_actions::common_actions::CommonActionsModule + crate::user_actions::common_storage::CommonStorageModule + + crate::events::sov_events::SovEventsModule + utils::UtilsModule { #[endpoint(registerSov)] @@ -37,16 +38,16 @@ pub trait SovereignModule: self.require_not_empty_buffer(&name); let caller = self.blockchain().get_caller(); - let caller_id = self.sovereign_id().insert_new(&caller); + let caller_id = self.sov_id().insert_new(&caller); let id_for_name_mapper = self.sov_chain_for_name(&name); require!(id_for_name_mapper.is_empty(), "Name already taken"); - self.sovereign_info(caller_id) - .set(SovereignInfo::new(name, description)); + let sov_info = SovereignInfo::new(name, description); + self.sov_info(caller_id).set(&sov_info); id_for_name_mapper.set(caller_id); - // TODO: event + self.emit_sov_register_event(caller, sov_info); } #[endpoint(setUpRewards)] @@ -58,18 +59,20 @@ pub trait SovereignModule: /* _computation: ???, */ ) { let caller = self.blockchain().get_caller(); - let _caller_id = self.sovereign_id().get_id_non_zero(&caller); + let _caller_id = self.sov_id().get_id_non_zero(&caller); // TODO: Unsure what to do with all this info yet } #[endpoint(unRegister)] fn unregister(&self) { let caller = self.blockchain().get_caller(); - let caller_id = self.sovereign_id().remove_by_address(&caller); + let caller_id = self.sov_id().remove_by_address(&caller); require!(caller_id != NULL_ID, "Unknown sovereign chain"); - let sov_info = self.sovereign_info(caller_id).take(); + let sov_info = self.sov_info(caller_id).take(); self.sov_chain_for_name(&sov_info.name).clear(); + + self.emit_sov_unregister_event(caller); } #[payable("*")] @@ -82,8 +85,8 @@ pub trait SovereignModule: #[endpoint(addOwnSecurityFunds)] fn add_own_security_funds(&self) { let sov_chain = self.blockchain().get_caller(); - let sov_id = self.sovereign_id().get_id_non_zero(&sov_chain); - let sov_info = self.sovereign_info(sov_id).get(); + let sov_id = self.sov_id().get_id_non_zero(&sov_chain); + let sov_info = self.sov_info(sov_id).get(); let user_id_of_sov_chain = self.user_ids().get_id_or_insert(&sov_chain); let payments = self.get_non_empty_payments(); @@ -100,32 +103,34 @@ pub trait SovereignModule: all_delegators_mapper: &mut self.all_sov_delegators(sov_id), delegated_by_mapper: self.delegated_sov_by(user_id_of_sov_chain, sov_id), opt_max_delegation: sov_info.opt_max_restaking_cap, - payments_to_add: payments, + payments_to_add: payments.clone(), total_amount: total, caller_id: user_id_of_sov_chain, }; self.add_delegation(args); - // TODO: event + self.sov_add_own_security_funds_event(sov_chain, payments); } #[endpoint(setMaxReStakingCap)] fn set_max_restaking_cap(&self, max_cap: BigUint) { let caller = self.blockchain().get_caller(); - let sov_id = self.sovereign_id().get_id_non_zero(&caller); - self.sovereign_info(sov_id).update(|sov_info| { + let sov_id = self.sov_id().get_id_non_zero(&caller); + self.sov_info(sov_id).update(|sov_info| { let current_total = self.total_delegated_sov_amount(sov_id).get(); require!(max_cap >= current_total, INVALID_MAX_AMOUNT_ERR_MSG); - sov_info.opt_max_restaking_cap = Some(max_cap); + sov_info.opt_max_restaking_cap = Some(max_cap.clone()); }); + + self.emit_sov_set_max_restaking_cap_event(caller, max_cap); } #[view(getSovInfo)] fn get_sov_info(&self, sov_address: ManagedAddress) -> SovereignInfo { - let sov_id = self.sovereign_id().get_id_non_zero(&sov_address); + let sov_id = self.sov_id().get_id_non_zero(&sov_address); - self.sovereign_info(sov_id).get() + self.sov_info(sov_id).get() } fn require_valid_sov_id(&self, sov_id: AddressId) { @@ -133,10 +138,10 @@ pub trait SovereignModule: } #[storage_mapper("sovId")] - fn sovereign_id(&self) -> AddressToIdMapper; + fn sov_id(&self) -> AddressToIdMapper; #[storage_mapper("sovInfo")] - fn sovereign_info(&self, sov_id: AddressId) -> SingleValueMapper>; + fn sov_info(&self, sov_id: AddressId) -> SingleValueMapper>; #[storage_mapper("sovForName")] fn sov_chain_for_name(&self, name: &ManagedBuffer) -> SingleValueMapper; diff --git a/gravity-restaking/src/user_actions/user.rs b/gravity-restaking/src/user_actions/user.rs index c576a67..866283c 100644 --- a/gravity-restaking/src/user_actions/user.rs +++ b/gravity-restaking/src/user_actions/user.rs @@ -18,6 +18,9 @@ pub trait UserModule: + super::unbond::UnbondModule + super::common_actions::CommonActionsModule + super::common_storage::CommonStorageModule + + crate::events::user_events::UserEventsModule + + crate::events::validator_events::ValidatorEventsModule + + crate::events::sov_events::SovEventsModule + utils::UtilsModule { #[payable("*")] @@ -25,7 +28,9 @@ pub trait UserModule: fn deposit(&self) { let payments = self.get_non_empty_payments(); let caller = self.blockchain().get_caller(); - self.deposit_common(&caller, payments); + self.deposit_common(&caller, &payments); + + self.emit_user_deposit_event(caller, payments); } /// Pairs of (token_id, nonce, amount) @@ -120,13 +125,13 @@ pub trait UserModule: all_delegators_mapper: &mut self.all_delegators(validator_id), delegated_by_mapper: self.delegated_by(caller_id, validator_id), opt_max_delegation: validator_config.opt_max_delegation, - payments_to_add: output_payments, + payments_to_add: output_payments.clone(), total_amount: total, caller_id, }; self.add_delegation(args); - // TODO: event + self.emit_delegate_validator_event(caller, validator, output_payments); } #[endpoint(delegateForSovereignChain)] @@ -142,7 +147,7 @@ pub trait UserModule: let sov_id = self.sov_chain_for_name(&sov_name).get(); self.require_valid_sov_id(sov_id); - let sov_info = self.sovereign_info(sov_id).get(); + let sov_info = self.sov_info(sov_id).get(); let (output_payments, total) = self.before_add_delegation(self.user_tokens(caller_id), tokens); @@ -152,13 +157,14 @@ pub trait UserModule: all_delegators_mapper: &mut self.all_sov_delegators(sov_id), delegated_by_mapper: self.delegated_sov_by(caller_id, sov_id), opt_max_delegation: sov_info.opt_max_restaking_cap, - payments_to_add: output_payments, + payments_to_add: output_payments.clone(), total_amount: total, caller_id, }; self.add_delegation(args); - // TODO: event + let sov_address = unsafe { self.sov_id().get_address(sov_id).unwrap_unchecked() }; + self.emit_delgate_sov_event(caller, sov_address, output_payments); } #[endpoint(revokeDelegationFromValidator)] @@ -182,9 +188,9 @@ pub trait UserModule: caller_id, }; let output_unique_payments = self.remove_delegation(args); - self.add_unbond_tokens(caller_id, output_unique_payments); + self.add_unbond_tokens(caller_id, output_unique_payments.clone()); - // TODO: event + self.emit_revoke_validator_event(caller, validator, output_unique_payments); } #[endpoint(revokeDelegationFromSovereignChain)] @@ -209,34 +215,42 @@ pub trait UserModule: caller_id, }; let output_unique_payments = self.remove_delegation(args); - self.add_unbond_tokens(caller_id, output_unique_payments); + self.add_unbond_tokens(caller_id, output_unique_payments.clone()); - // TODO: event + let sov_address = unsafe { self.sov_id().get_address(sov_id).unwrap_unchecked() }; + self.emit_revoke_sov_event(caller, sov_address, output_unique_payments); } #[endpoint(unbondTokensCaller)] fn unbond_tokens_caller(&self) { let caller = self.blockchain().get_caller(); - let caller_id = self.user_ids().get_id_non_zero(&caller); - let output_unique_payments = self.unbond_tokens_common(caller_id); - let output_payments = output_unique_payments.into_payments(); + let output_payments = self.unbond_common(&caller); if !output_payments.is_empty() { self.send().direct_multi(&caller, &output_payments); + + self.emit_unbond_tokens_caller_event(caller, output_payments); } } #[endpoint(unbondTokensGravityRestaking)] fn unbond_tokens_gravity_restaking(&self) { let caller = self.blockchain().get_caller(); - let caller_id = self.user_ids().get_id_non_zero(&caller); - let output_unique_payments = self.unbond_tokens_common(caller_id); - let output_payments = output_unique_payments.into_payments(); + let output_payments = self.unbond_common(&caller); if !output_payments.is_empty() { - self.deposit_common(&caller, output_payments); + self.deposit_common(&caller, &output_payments); + + self.emit_unbond_tokens_gravity_restaking_event(caller, output_payments); } } - fn deposit_common(&self, caller: &ManagedAddress, payments: PaymentsVec) { + fn unbond_common(&self, caller: &ManagedAddress) -> PaymentsVec { + let caller_id = self.user_ids().get_id_non_zero(caller); + let output_unique_payments = self.unbond_tokens_common(caller_id); + + output_unique_payments.into_payments() + } + + fn deposit_common(&self, caller: &ManagedAddress, payments: &PaymentsVec) { let ids_mapper = self.user_ids(); let mut caller_id = ids_mapper.get_id(caller); let mut user_tokens = if caller_id == NULL_ID { @@ -247,7 +261,7 @@ pub trait UserModule: self.user_tokens(caller_id).get() }; - for payment in &payments { + for payment in payments { self.require_token_in_whitelist(&payment.token_identifier); user_tokens.add_payment(payment); diff --git a/gravity-restaking/src/user_actions/validator.rs b/gravity-restaking/src/user_actions/validator.rs index 154c52b..60bdd0c 100644 --- a/gravity-restaking/src/user_actions/validator.rs +++ b/gravity-restaking/src/user_actions/validator.rs @@ -39,6 +39,7 @@ pub trait ValidatorModule: crate::token_whitelist::TokenWhitelistModule + crate::user_actions::common_actions::CommonActionsModule + crate::user_actions::common_storage::CommonStorageModule + + crate::events::validator_events::ValidatorEventsModule + utils::UtilsModule { #[endpoint] @@ -52,10 +53,10 @@ pub trait ValidatorModule: require!(id_for_name_mapper.is_empty(), "Name already taken"); self.validator_config(caller_id) - .set(ValidatorConfig::new(name)); + .set(ValidatorConfig::new(name.clone())); id_for_name_mapper.set(caller_id); - // TODO: event + self.emit_validator_register_event(caller, name); } /// pairs of bls_key and signed message of own address @@ -80,11 +81,20 @@ pub trait ValidatorModule: new_bls_keys.push(bls_key); } + let keys_added = new_bls_keys.clone(); self.validator_config(caller_id).update(|config| { - config.bls_keys.extend(&new_bls_keys); + while !new_bls_keys.is_empty() { + let current_key = new_bls_keys.get(0); + for existing_key in &config.bls_keys { + require!(existing_key != *current_key, "Key already known"); + } + + config.bls_keys.push((*current_key).clone()); + new_bls_keys.remove(0); + } }); - // TODO: event + self.emit_validator_add_bls_keys_event(caller, keys_added); } #[endpoint(removeKeys)] @@ -94,17 +104,19 @@ pub trait ValidatorModule: let mapper = self.validator_config(caller_id); let mut config = mapper.get(); + let mut removed_keys = ManagedVec::new(); for key in keys { let opt_index = config.bls_keys.find(&key); require!(opt_index.is_some(), "Key not found"); let index = unsafe { opt_index.unwrap_unchecked() }; config.bls_keys.remove(index); + removed_keys.push(key); } mapper.set(config); - // TODO: event + self.emit_validator_remove_bls_keys_event(caller, removed_keys); } // TODO: validateFor@projectID@LIST@LISTOFStakeEGLDAssets @@ -118,7 +130,7 @@ pub trait ValidatorModule: self.validator_config(caller_id) .update(|config| config.fee = fee); - // TODO: event + self.emit_validator_set_fee_event(caller, fee); } #[endpoint(setMaxDelegation)] @@ -129,10 +141,10 @@ pub trait ValidatorModule: let current_total = self.total_delegated_amount(caller_id).get(); require!(max_delegation >= current_total, INVALID_MAX_AMOUNT_ERR_MSG); - config.opt_max_delegation = Some(max_delegation); + config.opt_max_delegation = Some(max_delegation.clone()); }); - // TODO: event + self.emit_validator_set_max_delegation_event(caller, max_delegation); } #[payable("*")] @@ -157,13 +169,13 @@ pub trait ValidatorModule: all_delegators_mapper: &mut self.all_delegators(validator_id), delegated_by_mapper: self.delegated_by(user_id_of_validator, validator_id), opt_max_delegation: validator_config.opt_max_delegation, - payments_to_add: payments, + payments_to_add: payments.clone(), total_amount: total, caller_id: user_id_of_validator, }; self.add_delegation(args); - // TODO: event + self.emit_validator_add_own_delegation_event(validator, payments); } #[view(getValidatorConfig)]