From a3ec8edc647aec966e0cb142f09a5e4ec3f8be07 Mon Sep 17 00:00:00 2001 From: Tiago Carvalho Date: Wed, 3 Jan 2024 14:27:43 +0000 Subject: [PATCH] Include validator avatar in their medatada --- apps/src/lib/cli.rs | 22 +++++++++++++ apps/src/lib/client/rpc.rs | 6 ++++ apps/src/lib/client/tx.rs | 4 +++ apps/src/lib/client/utils.rs | 2 ++ apps/src/lib/config/genesis.rs | 1 + apps/src/lib/config/genesis/transactions.rs | 4 +++ benches/txs.rs | 2 ++ core/src/types/transaction/pos.rs | 9 ++++++ light_sdk/src/transaction/pos.rs | 5 +++ proof_of_stake/src/lib.rs | 6 +++- proof_of_stake/src/storage.rs | 32 +++++++++++++++++++ proof_of_stake/src/storage_key.rs | 9 ++++++ proof_of_stake/src/types/mod.rs | 4 +++ sdk/src/args.rs | 6 ++++ sdk/src/lib.rs | 4 +++ sdk/src/queries/vp/pos.rs | 4 ++- sdk/src/tx.rs | 2 ++ tx_prelude/src/proof_of_stake.rs | 4 +++ .../src/tx_change_validator_metadata.rs | 2 ++ wasm/wasm_source/src/vp_user.rs | 4 +++ 20 files changed, 130 insertions(+), 2 deletions(-) diff --git a/apps/src/lib/cli.rs b/apps/src/lib/cli.rs index fca330ec48..ace4a025e3 100644 --- a/apps/src/lib/cli.rs +++ b/apps/src/lib/cli.rs @@ -2839,6 +2839,7 @@ pub mod args { pub const ALLOW_DUPLICATE_IP: ArgFlag = flag("allow-duplicate-ip"); pub const AMOUNT: Arg = arg("amount"); pub const ARCHIVE_DIR: ArgOpt = arg_opt("archive-dir"); + pub const AVATAR_OPT: ArgOpt = arg_opt("avatar"); pub const BALANCE_OWNER: ArgOpt = arg_opt("owner"); pub const BASE_DIR: ArgDefault = arg_default( "base-dir", @@ -4042,6 +4043,7 @@ pub mod args { description: self.description, website: self.website, discord_handle: self.discord_handle, + avatar: self.avatar, unsafe_dont_encrypt: self.unsafe_dont_encrypt, tx_code_path: self.tx_code_path.to_path_buf(), } @@ -4064,6 +4066,7 @@ pub mod args { let description = DESCRIPTION_OPT.parse(matches); let website = WEBSITE_OPT.parse(matches); let discord_handle = DISCORD_OPT.parse(matches); + let avatar = AVATAR_OPT.parse(matches); let unsafe_dont_encrypt = UNSAFE_DONT_ENCRYPT.parse(matches); let tx_code_path = PathBuf::from(TX_BECOME_VALIDATOR_WASM); Self { @@ -4080,6 +4083,7 @@ pub mod args { description, website, discord_handle, + avatar, unsafe_dont_encrypt, tx_code_path, } @@ -4128,6 +4132,7 @@ pub mod args { .arg(DESCRIPTION_OPT.def().help("The validator's description.")) .arg(WEBSITE_OPT.def().help("The validator's website.")) .arg(DISCORD_OPT.def().help("The validator's discord handle.")) + .arg(AVATAR_OPT.def().help("The validator's avatar.")) .arg(VALIDATOR_CODE_PATH.def().help( "The path to the validity predicate WASM code to be used \ for the validator account. Uses the default validator VP \ @@ -4163,6 +4168,7 @@ pub mod args { description: self.description, website: self.website, discord_handle: self.discord_handle, + avatar: self.avatar, validator_vp_code_path: self .validator_vp_code_path .to_path_buf(), @@ -4193,6 +4199,7 @@ pub mod args { let description = DESCRIPTION_OPT.parse(matches); let website = WEBSITE_OPT.parse(matches); let discord_handle = DISCORD_OPT.parse(matches); + let avatar = AVATAR_OPT.parse(matches); let validator_vp_code_path = VALIDATOR_CODE_PATH .parse(matches) .unwrap_or_else(|| PathBuf::from(VP_USER_WASM)); @@ -4216,6 +4223,7 @@ pub mod args { description, website, discord_handle, + avatar, validator_vp_code_path, unsafe_dont_encrypt, tx_init_account_code_path, @@ -4268,6 +4276,7 @@ pub mod args { .arg(DESCRIPTION_OPT.def().help("The validator's description.")) .arg(WEBSITE_OPT.def().help("The validator's website.")) .arg(DISCORD_OPT.def().help("The validator's discord handle.")) + .arg(AVATAR_OPT.def().help("The validator's avatar.")) .arg(VALIDATOR_CODE_PATH.def().help( "The path to the validity predicate WASM code to be used \ for the validator account. Uses the default validator VP \ @@ -5331,6 +5340,7 @@ pub mod args { description: self.description, website: self.website, discord_handle: self.discord_handle, + avatar: self.avatar, commission_rate: self.commission_rate, tx_code_path: self.tx_code_path.to_path_buf(), } @@ -5345,6 +5355,7 @@ pub mod args { let description = DESCRIPTION_OPT.parse(matches); let website = WEBSITE_OPT.parse(matches); let discord_handle = DISCORD_OPT.parse(matches); + let avatar = AVATAR_OPT.parse(matches); let commission_rate = COMMISSION_RATE_OPT.parse(matches); let tx_code_path = PathBuf::from(TX_CHANGE_METADATA_WASM); Self { @@ -5354,6 +5365,7 @@ pub mod args { description, website, discord_handle, + avatar, commission_rate, tx_code_path, } @@ -5382,6 +5394,10 @@ pub mod args { existing discord handle, pass an empty string to this \ argument.", )) + .arg(AVATAR_OPT.def().help( + "The desired new validator avatar url. To remove the \ + existing avatar, pass an empty string to this argument.", + )) .arg( COMMISSION_RATE_OPT .def() @@ -6707,6 +6723,7 @@ pub mod args { pub description: Option, pub website: Option, pub discord_handle: Option, + pub avatar: Option, pub address: EstablishedAddress, pub tx_path: PathBuf, } @@ -6726,6 +6743,7 @@ pub mod args { let description = DESCRIPTION_OPT.parse(matches); let website = WEBSITE_OPT.parse(matches); let discord_handle = DISCORD_OPT.parse(matches); + let avatar = AVATAR_OPT.parse(matches); let address = RAW_ADDRESS_ESTABLISHED.parse(matches); let tx_path = PATH.parse(matches); Self { @@ -6740,6 +6758,7 @@ pub mod args { description, website, discord_handle, + avatar, tx_path, address, } @@ -6797,6 +6816,9 @@ pub mod args { "The validator's discord handle. This is an optional \ parameter.", )) + .arg(AVATAR_OPT.def().help( + "The validator's avatar. This is an optional parameter.", + )) } } diff --git a/apps/src/lib/client/rpc.rs b/apps/src/lib/client/rpc.rs index bc57f58f14..9e2135382a 100644 --- a/apps/src/lib/client/rpc.rs +++ b/apps/src/lib/client/rpc.rs @@ -1992,6 +1992,7 @@ pub async fn query_and_print_metadata( description, website, discord_handle, + avatar, }) => { display_line!( context.io(), @@ -2018,6 +2019,11 @@ pub async fn query_and_print_metadata( } else { display_line!(context.io(), "No discord handle"); } + if let Some(avatar) = avatar { + display_line!(context.io(), "Avatar: {}", avatar); + } else { + display_line!(context.io(), "No avatar"); + } } None => display_line!( context.io(), diff --git a/apps/src/lib/client/tx.rs b/apps/src/lib/client/tx.rs index f57cddd4eb..d76b12a7b5 100644 --- a/apps/src/lib/client/tx.rs +++ b/apps/src/lib/client/tx.rs @@ -472,6 +472,7 @@ pub async fn submit_become_validator( website, description, discord_handle, + avatar, unsafe_dont_encrypt, tx_code_path, }: args::TxBecomeValidator, @@ -710,6 +711,7 @@ pub async fn submit_become_validator( description, website, discord_handle, + avatar, }; // Put together all the PKs that we have to sign with to verify ownership @@ -845,6 +847,7 @@ pub async fn submit_init_validator( website, description, discord_handle, + avatar, validator_vp_code_path, unsafe_dont_encrypt, tx_init_account_code_path, @@ -896,6 +899,7 @@ pub async fn submit_init_validator( description, website, discord_handle, + avatar, tx_code_path: tx_become_validator_code_path, unsafe_dont_encrypt, }, diff --git a/apps/src/lib/client/utils.rs b/apps/src/lib/client/utils.rs index d334a8281b..c1a96620dd 100644 --- a/apps/src/lib/client/utils.rs +++ b/apps/src/lib/client/utils.rs @@ -806,6 +806,7 @@ pub fn init_genesis_validator( description, website, discord_handle, + avatar, tx_path, address, }: args::InitGenesisValidator, @@ -884,6 +885,7 @@ pub fn init_genesis_validator( description, website, discord_handle, + avatar, }, &validator_wallet, ); diff --git a/apps/src/lib/config/genesis.rs b/apps/src/lib/config/genesis.rs index 8649d2a4d1..83963a7d38 100644 --- a/apps/src/lib/config/genesis.rs +++ b/apps/src/lib/config/genesis.rs @@ -468,6 +468,7 @@ pub fn make_dev_genesis( description: None, website: None, discord_handle: None, + avatar: None, }, net_address: SocketAddr::new( IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)), diff --git a/apps/src/lib/config/genesis/transactions.rs b/apps/src/lib/config/genesis/transactions.rs index ae8d892a29..210230b14e 100644 --- a/apps/src/lib/config/genesis/transactions.rs +++ b/apps/src/lib/config/genesis/transactions.rs @@ -144,6 +144,7 @@ pub struct GenesisValidatorData { pub description: Option, pub website: Option, pub discord_handle: Option, + pub avatar: Option, } /// Panics if given `txs.validator_accounts` is not empty, because validator @@ -269,6 +270,7 @@ pub fn init_validator( description, website, discord_handle, + avatar, }: GenesisValidatorData, validator_wallet: &ValidatorWallet, ) -> (Address, UnsignedTransactions) { @@ -302,6 +304,7 @@ pub fn init_validator( description, website, discord_handle, + avatar, }, }; let unsigned_validator_addr = @@ -613,6 +616,7 @@ impl TxToSign for ValidatorAccountTx { description: self.metadata.description.clone(), website: self.metadata.website.clone(), discord_handle: self.metadata.discord_handle.clone(), + avatar: self.metadata.avatar.clone(), }, ) } diff --git a/benches/txs.rs b/benches/txs.rs index 523cd48489..e6493d6bbf 100644 --- a/benches/txs.rs +++ b/benches/txs.rs @@ -627,6 +627,7 @@ fn become_validator(c: &mut Criterion) { description: None, website: None, discord_handle: None, + avatar: None, }; let tx = shell.generate_tx( TX_BECOME_VALIDATOR_WASM, @@ -722,6 +723,7 @@ fn change_validator_metadata(c: &mut Criterion) { description: Some("I will change this piece of data".to_string()), website: None, discord_handle: None, + avatar: None, commission_rate: None, }; diff --git a/core/src/types/transaction/pos.rs b/core/src/types/transaction/pos.rs index 1ac5fc8a38..c486a86263 100644 --- a/core/src/types/transaction/pos.rs +++ b/core/src/types/transaction/pos.rs @@ -44,6 +44,9 @@ pub struct BecomeValidator { pub website: Option, /// The validator's discord handle pub discord_handle: Option, + /// URL that points to a picture (e.g. PNG), + /// identifying the validator + pub avatar: Option, } /// A bond is a validator's self-bond or a delegation from non-validator to a @@ -183,6 +186,8 @@ pub struct MetaDataChange { pub website: Option, /// Validator's discord handle pub discord_handle: Option, + /// Validator's avatar url + pub avatar: Option, /// Validator's commission rate pub commission_rate: Option, } @@ -267,6 +272,7 @@ pub mod tests { description in option::of("[a-zA-Z0-9_]*"), website in option::of("[a-zA-Z0-9_]*"), discord_handle in option::of("[a-zA-Z0-9_]*"), + avatar in option::of("[a-zA-Z0-9_]*"), commission_rate in option::of(arb_dec()), ) -> MetaDataChange { MetaDataChange { @@ -275,6 +281,7 @@ pub mod tests { description, website, discord_handle, + avatar, commission_rate, } } @@ -307,6 +314,7 @@ pub mod tests { description in option::of("[a-zA-Z0-9_]*"), website in option::of("[a-zA-Z0-9_]*"), discord_handle in option::of("[a-zA-Z0-9_]*"), + avatar in option::of("[a-zA-Z0-9_]*"), ) -> BecomeValidator { BecomeValidator { address, @@ -320,6 +328,7 @@ pub mod tests { description, website, discord_handle, + avatar, } } } diff --git a/light_sdk/src/transaction/pos.rs b/light_sdk/src/transaction/pos.rs index a436e1588a..e042d80c5a 100644 --- a/light_sdk/src/transaction/pos.rs +++ b/light_sdk/src/transaction/pos.rs @@ -133,6 +133,7 @@ impl BecomeValidator { description: Option, website: Option, discord_handle: Option, + avatar: Option, args: GlobalArgs, ) -> Self { let update_account = @@ -148,6 +149,7 @@ impl BecomeValidator { description, website, discord_handle, + avatar, }; Self(transaction::build_tx( @@ -333,12 +335,14 @@ pub struct ChangeMetaData(Tx); impl ChangeMetaData { /// Build a raw ChangeMetadata transaction from the given parameters + #[allow(clippy::too_many_arguments)] pub fn new( validator: Address, email: Option, description: Option, website: Option, discord_handle: Option, + avatar: Option, commission_rate: Option, args: GlobalArgs, ) -> Self { @@ -349,6 +353,7 @@ impl ChangeMetaData { description, website, discord_handle, + avatar, commission_rate, }; diff --git a/proof_of_stake/src/lib.rs b/proof_of_stake/src/lib.rs index a390d6ec00..afdf94a39b 100644 --- a/proof_of_stake/src/lib.rs +++ b/proof_of_stake/src/lib.rs @@ -68,7 +68,7 @@ use crate::storage::{ validator_slashes_handle, validator_state_handle, validator_total_redelegated_bonded_handle, validator_total_redelegated_unbonded_handle, write_last_reward_claim_epoch, - write_pos_params, write_validator_address_raw_hash, + write_pos_params, write_validator_address_raw_hash, write_validator_avatar, write_validator_description, write_validator_discord_handle, write_validator_email, write_validator_max_commission_rate_change, write_validator_metadata, write_validator_website, @@ -2558,6 +2558,7 @@ pub fn change_validator_metadata( description: Option, website: Option, discord_handle: Option, + avatar: Option, commission_rate: Option, current_epoch: Epoch, ) -> storage_api::Result<()> @@ -2576,6 +2577,9 @@ where if let Some(discord) = discord_handle { write_validator_discord_handle(storage, validator, &discord)?; } + if let Some(avatar) = avatar { + write_validator_avatar(storage, validator, &avatar)?; + } if let Some(commission_rate) = commission_rate { change_validator_commission_rate( storage, diff --git a/proof_of_stake/src/storage.rs b/proof_of_stake/src/storage.rs index bab677b3a0..5aac88a041 100644 --- a/proof_of_stake/src/storage.rs +++ b/proof_of_stake/src/storage.rs @@ -753,6 +753,35 @@ where } } +/// Read PoS validator's avatar. +pub fn read_validator_avatar( + storage: &S, + validator: &Address, +) -> storage_api::Result> +where + S: StorageRead, +{ + storage.read(&storage_key::validator_avatar_key(validator)) +} + +/// Write PoS validator's avatar. If the provided arg is an empty +/// string, remove the data. +pub fn write_validator_avatar( + storage: &mut S, + validator: &Address, + avatar: &String, +) -> storage_api::Result<()> +where + S: StorageRead + StorageWrite, +{ + let key = storage_key::validator_avatar_key(validator); + if avatar.is_empty() { + storage.delete(&key) + } else { + storage.write(&key, avatar) + } +} + /// Write validator's metadata. pub fn write_validator_metadata( storage: &mut S, @@ -774,6 +803,9 @@ where if let Some(discord) = metadata.discord_handle.as_ref() { write_validator_discord_handle(storage, validator, discord)?; } + if let Some(avatar) = metadata.avatar.as_ref() { + write_validator_avatar(storage, validator, avatar)?; + } Ok(()) } diff --git a/proof_of_stake/src/storage_key.rs b/proof_of_stake/src/storage_key.rs index 2991526760..90e3506a70 100644 --- a/proof_of_stake/src/storage_key.rs +++ b/proof_of_stake/src/storage_key.rs @@ -54,6 +54,7 @@ const VALIDATOR_EMAIL_KEY: &str = "email"; const VALIDATOR_DESCRIPTION_KEY: &str = "description"; const VALIDATOR_WEBSITE_KEY: &str = "website"; const VALIDATOR_DISCORD_KEY: &str = "discord_handle"; +const VALIDATOR_AVATAR_KEY: &str = "avatar"; const LIVENESS_PREFIX: &str = "liveness"; const LIVENESS_MISSED_VOTES: &str = "missed_votes"; const LIVENESS_MISSED_VOTES_SUM: &str = "sum_missed_votes"; @@ -271,6 +272,7 @@ pub fn is_validator_metadata_key(key: &Key) -> Option<&Address> { | VALIDATOR_DESCRIPTION_KEY | VALIDATOR_WEBSITE_KEY | VALIDATOR_DISCORD_KEY + | VALIDATOR_AVATAR_KEY ) => { Some(validator) @@ -1015,6 +1017,13 @@ pub fn validator_discord_key(validator: &Address) -> Key { .expect("Cannot obtain a storage key") } +/// Storage key for a validator's avatar +pub fn validator_avatar_key(validator: &Address) -> Key { + validator_prefix(validator) + .push(&VALIDATOR_AVATAR_KEY.to_owned()) + .expect("Cannot obtain a storage key") +} + /// Storage prefix for the liveness data of the cosnensus validator set. pub fn liveness_data_prefix() -> Key { Key::from(ADDRESS.to_db_key()) diff --git a/proof_of_stake/src/types/mod.rs b/proof_of_stake/src/types/mod.rs index 2d297bd72f..eb3bbb45fb 100644 --- a/proof_of_stake/src/types/mod.rs +++ b/proof_of_stake/src/types/mod.rs @@ -362,6 +362,9 @@ pub struct ValidatorMetaData { pub website: Option, /// Validator's discord handle pub discord_handle: Option, + /// URL that points to a picture (e.g. PNG), + /// identifying the validator + pub avatar: Option, } #[cfg(any(test, feature = "testing"))] @@ -372,6 +375,7 @@ impl Default for ValidatorMetaData { description: Default::default(), website: Default::default(), discord_handle: Default::default(), + avatar: Default::default(), } } } diff --git a/sdk/src/args.rs b/sdk/src/args.rs index c12ecdf537..366e07f572 100644 --- a/sdk/src/args.rs +++ b/sdk/src/args.rs @@ -748,6 +748,8 @@ pub struct TxBecomeValidator { pub website: Option, /// The validator's discord handle pub discord_handle: Option, + /// The validator's avatar + pub avatar: Option, /// Path to the TX WASM code file pub tx_code_path: PathBuf, /// Don't encrypt the keypair @@ -785,6 +787,8 @@ pub struct TxInitValidator { pub website: Option, /// The validator's discord handle pub discord_handle: Option, + /// The validator's avatar + pub avatar: Option, /// Path to the VP WASM code file pub validator_vp_code_path: PathBuf, /// Path to the TX WASM code file @@ -1456,6 +1460,8 @@ pub struct MetaDataChange { pub website: Option, /// New validator discord handle pub discord_handle: Option, + /// New validator avatar url + pub avatar: Option, /// New validator commission rate pub commission_rate: Option, /// Path to the TX WASM code file diff --git a/sdk/src/lib.rs b/sdk/src/lib.rs index 65b4a45cf4..52a31b4ca5 100644 --- a/sdk/src/lib.rs +++ b/sdk/src/lib.rs @@ -346,6 +346,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { description: Option, website: Option, discord_handle: Option, + avatar: Option, commission_rate: Option, ) -> args::MetaDataChange { args::MetaDataChange { @@ -354,6 +355,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { description, website, discord_handle, + avatar, commission_rate, tx_code_path: PathBuf::from(TX_CHANGE_METADATA_WASM), tx: self.tx_builder(), @@ -384,6 +386,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { description: None, website: None, discord_handle: None, + avatar: None, } } @@ -415,6 +418,7 @@ pub trait Namada: Sized + MaybeSync + MaybeSend { description: None, website: None, discord_handle: None, + avatar: None, } } diff --git a/sdk/src/queries/vp/pos.rs b/sdk/src/queries/vp/pos.rs index ff1b073dc4..47a1d6bd0b 100644 --- a/sdk/src/queries/vp/pos.rs +++ b/sdk/src/queries/vp/pos.rs @@ -22,7 +22,7 @@ use namada_proof_of_stake::storage::{ bond_handle, read_all_validator_addresses, read_below_capacity_validator_set_addresses_with_stake, read_consensus_validator_set_addresses_with_stake, read_pos_params, - read_total_stake, read_validator_description, + read_total_stake, read_validator_avatar, read_validator_description, read_validator_discord_handle, read_validator_email, read_validator_last_slash_epoch, read_validator_max_commission_rate_change, read_validator_stake, read_validator_website, unbond_handle, @@ -266,6 +266,7 @@ where let website = read_validator_website(ctx.wl_storage, &validator)?; let discord_handle = read_validator_discord_handle(ctx.wl_storage, &validator)?; + let avatar = read_validator_avatar(ctx.wl_storage, &validator)?; // Email is the only required field for a validator in storage match email { @@ -274,6 +275,7 @@ where description, website, discord_handle, + avatar, })), _ => Ok(None), } diff --git a/sdk/src/tx.rs b/sdk/src/tx.rs index de0474615b..a53ac8f8bf 100644 --- a/sdk/src/tx.rs +++ b/sdk/src/tx.rs @@ -694,6 +694,7 @@ pub async fn build_validator_metadata_change( description, website, discord_handle, + avatar, commission_rate, tx_code_path, }: &args::MetaDataChange, @@ -797,6 +798,7 @@ pub async fn build_validator_metadata_change( website: website.clone(), description: description.clone(), discord_handle: discord_handle.clone(), + avatar: avatar.clone(), commission_rate: *commission_rate, }; diff --git a/tx_prelude/src/proof_of_stake.rs b/tx_prelude/src/proof_of_stake.rs index 3b7883361d..acaa86e1ae 100644 --- a/tx_prelude/src/proof_of_stake.rs +++ b/tx_prelude/src/proof_of_stake.rs @@ -127,6 +127,7 @@ impl Ctx { description, website, discord_handle, + avatar, }: BecomeValidator, ) -> EnvResult
{ let current_epoch = self.get_block_epoch()?; @@ -151,6 +152,7 @@ impl Ctx { description, website, discord_handle, + avatar, }, offset_opt: None, }, @@ -180,6 +182,7 @@ impl Ctx { description: Option, website: Option, discord_handle: Option, + avatar: Option, commission_rate: Option, ) -> TxResult { let current_epoch = self.get_block_epoch()?; @@ -190,6 +193,7 @@ impl Ctx { description, website, discord_handle, + avatar, commission_rate, current_epoch, ) diff --git a/wasm/wasm_source/src/tx_change_validator_metadata.rs b/wasm/wasm_source/src/tx_change_validator_metadata.rs index f2ba6a0267..0a0806fd2c 100644 --- a/wasm/wasm_source/src/tx_change_validator_metadata.rs +++ b/wasm/wasm_source/src/tx_change_validator_metadata.rs @@ -15,6 +15,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { description, website, discord_handle, + avatar, commission_rate, } = transaction::pos::MetaDataChange::try_from_slice(&data[..]) .wrap_err("failed to decode Dec value")?; @@ -24,6 +25,7 @@ fn apply_tx(ctx: &mut Ctx, tx_data: Tx) -> TxResult { description, website, discord_handle, + avatar, commission_rate, ) } diff --git a/wasm/wasm_source/src/vp_user.rs b/wasm/wasm_source/src/vp_user.rs index 29c861d04d..e9e148405f 100644 --- a/wasm/wasm_source/src/vp_user.rs +++ b/wasm/wasm_source/src/vp_user.rs @@ -703,6 +703,7 @@ mod tests { description: None, website: None, discord_handle: None, + avatar: None, }; tx::ctx().become_validator(args).unwrap(); }); @@ -792,6 +793,7 @@ mod tests { Some("desc".to_owned()), Some("website".to_owned()), Some("discord".to_owned()), + Some("avatar".to_owned()), Some(Dec::new(6, 2).unwrap()), ) .unwrap(); @@ -972,6 +974,7 @@ mod tests { description: None, website: None, discord_handle: None, + avatar: None, }; tx::ctx().become_validator(args).unwrap(); }); @@ -1076,6 +1079,7 @@ mod tests { Some("desc".to_owned()), Some("website".to_owned()), Some("discord".to_owned()), + Some("avatar".to_owned()), Some(Dec::new(6, 2).unwrap()), ) .unwrap();