From 6b3700aefebf558df7b78b751753f0ae313acc06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C4=99drzej=20Stuczy=C5=84ski?= Date: Tue, 11 Jan 2022 16:56:12 +0000 Subject: [PATCH] Feature/expanded events (#1015) * Expanded emitted events for delegation-related transactions * Expanded emitted events for gateway-related transactions * Expanded emitted events for mixnode-related transactions * Expanded emitted events for settings update transaction * Expanded emitted events for rewarding-related transactions * Fixed attribute look up in tests * Making linter happier * Reorganised cosmwasm contract-related modules * Introduced similar event handling to the vesting contract --- Cargo.lock | 30 +- Cargo.toml | 4 +- .../client-libs/validator-client/Cargo.toml | 2 +- .../validator-client/src/client.rs | 12 +- .../validator-client/src/nymd/mod.rs | 4 +- .../src/nymd/traits/vesting_signing_client.rs | 2 +- .../validator-client/src/validator_api/mod.rs | 2 +- .../contracts-common/Cargo.toml | 10 + .../contracts-common/src/events.rs | 30 ++ .../contracts-common/src/lib.rs | 4 + .../mixnet-contract/Cargo.toml | 6 +- .../mixnet-contract/src/delegation.rs | 0 .../mixnet-contract/src/error.rs | 0 .../mixnet-contract/src/events.rs | 353 ++++++++++++++++++ .../mixnet-contract/src/gateway.rs | 0 .../mixnet-contract/src/lib.rs | 1 + .../mixnet-contract/src/mixnode.rs | 12 +- .../mixnet-contract/src/msg.rs | 0 .../mixnet-contract/src/types.rs | 0 .../vesting-contract/Cargo.toml | 9 + .../vesting-contract/src/events.rs | 133 +++++++ .../vesting-contract/src/lib.rs | 4 + common/nymsphinx/Cargo.toml | 2 +- common/nymsphinx/src/receiver.rs | 2 +- common/topology/Cargo.toml | 2 +- common/topology/src/gateway.rs | 2 +- common/topology/src/lib.rs | 4 +- common/topology/src/mix.rs | 2 +- contracts/Cargo.lock | 50 ++- contracts/mixnet/Cargo.toml | 4 +- contracts/mixnet/examples/schema.rs | 2 +- contracts/mixnet/src/contract.rs | 14 +- contracts/mixnet/src/delegations/queries.rs | 22 +- contracts/mixnet/src/delegations/storage.rs | 14 +- .../mixnet/src/delegations/transactions.rs | 80 +++- contracts/mixnet/src/error.rs | 2 +- contracts/mixnet/src/gateways/queries.rs | 4 +- contracts/mixnet/src/gateways/storage.rs | 8 +- contracts/mixnet/src/gateways/transactions.rs | 65 ++-- .../src/mixnet_contract_settings/models.rs | 2 +- .../src/mixnet_contract_settings/queries.rs | 4 +- .../src/mixnet_contract_settings/storage.rs | 3 +- .../mixnet_contract_settings/transactions.rs | 35 +- .../mixnet/src/mixnodes/bonding_queries.rs | 4 +- .../mixnet/src/mixnodes/layer_queries.rs | 2 +- contracts/mixnet/src/mixnodes/storage.rs | 7 +- contracts/mixnet/src/mixnodes/transactions.rs | 66 ++-- contracts/mixnet/src/rewards/helpers.rs | 4 +- contracts/mixnet/src/rewards/queries.rs | 35 +- contracts/mixnet/src/rewards/storage.rs | 2 +- contracts/mixnet/src/rewards/transactions.rs | 306 ++++++++------- contracts/mixnet/src/support/helpers.rs | 2 +- .../mixnet/src/support/tests/fixtures.rs | 4 +- .../mixnet/src/support/tests/messages.rs | 2 +- contracts/mixnet/src/support/tests/mod.rs | 2 +- contracts/mixnet/src/support/tests/queries.rs | 2 +- contracts/vesting/Cargo.toml | 3 +- contracts/vesting/src/contract.rs | 51 ++- contracts/vesting/src/errors.rs | 2 +- contracts/vesting/src/messages.rs | 3 +- contracts/vesting/src/traits/bonding.rs | 2 +- .../vesting/src/traits/delegating_account.rs | 2 +- .../src/vesting/account/delegating_account.rs | 15 +- .../account/gateway_bonding_account.rs | 13 +- .../account/mixnode_bonding_account.rs | 13 +- contracts/vesting/src/vesting/account/mod.rs | 2 +- contracts/vesting/src/vesting/mod.rs | 2 +- explorer-api/Cargo.toml | 2 +- explorer-api/src/mix_node/http.rs | 2 +- explorer-api/src/mix_node/models.rs | 2 +- explorer-api/src/mix_nodes/delegations.rs | 2 +- explorer-api/src/mix_nodes/models.rs | 2 +- explorer-api/src/mix_nodes/tasks.rs | 2 +- explorer-api/src/ping/http.rs | 2 +- explorer-api/src/state.rs | 2 +- nym-wallet/Cargo.lock | 24 +- nym-wallet/src-tauri/Cargo.toml | 6 +- nym-wallet/src-tauri/src/main.rs | 6 +- .../src-tauri/src/operations/mixnet/admin.rs | 2 +- .../src-tauri/src/operations/mixnet/bond.rs | 2 +- .../src/operations/mixnet/delegate.rs | 2 +- validator-api/Cargo.toml | 2 +- validator-api/src/cache/mod.rs | 2 +- validator-api/src/cache/routes.rs | 2 +- .../src/network_monitor/monitor/preparer.rs | 2 +- validator-api/src/nymd_client.rs | 4 +- validator-api/src/rewarding/mod.rs | 4 +- 87 files changed, 1147 insertions(+), 414 deletions(-) create mode 100644 common/cosmwasm-smart-contracts/contracts-common/Cargo.toml create mode 100644 common/cosmwasm-smart-contracts/contracts-common/src/events.rs create mode 100644 common/cosmwasm-smart-contracts/contracts-common/src/lib.rs rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/Cargo.toml (77%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/delegation.rs (100%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/error.rs (100%) create mode 100644 common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/gateway.rs (100%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/lib.rs (97%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/mixnode.rs (98%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/msg.rs (100%) rename common/{ => cosmwasm-smart-contracts}/mixnet-contract/src/types.rs (100%) create mode 100644 common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml create mode 100644 common/cosmwasm-smart-contracts/vesting-contract/src/events.rs create mode 100644 common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 0f31900699..c3af75358c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -788,6 +788,13 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "contracts-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -1795,7 +1802,7 @@ dependencies = [ "humantime-serde", "isocountry", "log", - "mixnet-contract", + "mixnet-contract-common", "network-defaults", "okapi", "pretty_env_logger", @@ -3395,10 +3402,11 @@ dependencies = [ ] [[package]] -name = "mixnet-contract" +name = "mixnet-contract-common" version = "0.1.0" dependencies = [ "az", + "contracts-common", "cosmwasm-std", "fixed", "log", @@ -3865,7 +3873,7 @@ dependencies = [ "getset", "humantime-serde", "log", - "mixnet-contract", + "mixnet-contract-common", "nymsphinx", "pin-project", "pretty_env_logger", @@ -3916,7 +3924,7 @@ name = "nymsphinx" version = "0.1.0" dependencies = [ "crypto", - "mixnet-contract", + "mixnet-contract-common", "nymsphinx-acknowledgements", "nymsphinx-addressing", "nymsphinx-anonymous-replies", @@ -7087,7 +7095,7 @@ dependencies = [ "bs58", "crypto", "log", - "mixnet-contract", + "mixnet-contract-common", "nymsphinx-addressing", "nymsphinx-types", "rand 0.7.3", @@ -7341,7 +7349,7 @@ dependencies = [ "flate2", "itertools", "log", - "mixnet-contract", + "mixnet-contract-common", "network-defaults", "prost", "reqwest", @@ -7416,10 +7424,18 @@ dependencies = [ "config", "cosmwasm-std", "cw-storage-plus", - "mixnet-contract", + "mixnet-contract-common", "schemars", "serde", "thiserror", + "vesting-contract-common", +] + +[[package]] +name = "vesting-contract-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 0d2ed7a3c4..90a214fe8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,9 @@ members = [ "common/credentials", "common/crypto", "common/bandwidth-claim-contract", - "common/mixnet-contract", + "common/cosmwasm-smart-contracts/contracts-common", + "common/cosmwasm-smart-contracts/mixnet-contract", + "common/cosmwasm-smart-contracts/vesting-contract", "common/mixnode-common", "common/network-defaults", "common/nonexhaustive-delayqueue", diff --git a/common/client-libs/validator-client/Cargo.toml b/common/client-libs/validator-client/Cargo.toml index 205f3f198a..e5f831efbe 100644 --- a/common/client-libs/validator-client/Cargo.toml +++ b/common/client-libs/validator-client/Cargo.toml @@ -9,7 +9,7 @@ rust-version = "1.56" [dependencies] base64 = "0.13" -mixnet-contract = { path="../../../common/mixnet-contract" } +mixnet-contract-common = { path= "../../cosmwasm-smart-contracts/mixnet-contract" } vesting-contract = { path="../../../contracts/vesting" } serde = { version="1", features=["derive"] } serde_json = "1" diff --git a/common/client-libs/validator-client/src/client.rs b/common/client-libs/validator-client/src/client.rs index 1cd25c71c1..4a3653fb21 100644 --- a/common/client-libs/validator-client/src/client.rs +++ b/common/client-libs/validator-client/src/client.rs @@ -6,15 +6,15 @@ use crate::nymd::{ error::NymdError, CosmWasmClient, NymdClient, QueryNymdClient, SigningNymdClient, }; #[cfg(feature = "nymd-client")] -use mixnet_contract::ContractStateParams; +use mixnet_contract_common::ContractStateParams; use crate::{validator_api, ValidatorClientError}; use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse}; #[cfg(feature = "nymd-client")] -use mixnet_contract::{ +use mixnet_contract_common::{ Delegation, MixnetContractVersion, MixnodeRewardingStatusResponse, RewardingIntervalResponse, }; -use mixnet_contract::{GatewayBond, IdentityKeyRef, MixNodeBond}; +use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond}; #[cfg(feature = "nymd-client")] use std::str::FromStr; @@ -212,7 +212,7 @@ impl Client { pub async fn get_rewarding_status( &self, - mix_identity: mixnet_contract::IdentityKey, + mix_identity: mixnet_contract_common::IdentityKey, rewarding_interval_nonce: u32, ) -> Result where @@ -301,8 +301,8 @@ impl Client { pub async fn get_all_nymd_single_mixnode_delegations( &self, - identity: mixnet_contract::IdentityKey, - ) -> Result, ValidatorClientError> + identity: mixnet_contract_common::IdentityKey, + ) -> Result, ValidatorClientError> where C: CosmWasmClient + Sync, { diff --git a/common/client-libs/validator-client/src/nymd/mod.rs b/common/client-libs/validator-client/src/nymd/mod.rs index 71c8766cf7..dfaa1abbb8 100644 --- a/common/client-libs/validator-client/src/nymd/mod.rs +++ b/common/client-libs/validator-client/src/nymd/mod.rs @@ -13,7 +13,7 @@ use cosmrs::rpc::{Error as TendermintRpcError, HttpClientUrl}; use cosmwasm_std::{Coin, Uint128}; pub use fee::gas_price::GasPrice; use fee::helpers::Operation; -use mixnet_contract::{ +use mixnet_contract_common::{ ContractStateParams, Delegation, ExecuteMsg, Gateway, GatewayBond, GatewayOwnershipResponse, IdentityKey, LayerDistribution, MixNode, MixNodeBond, MixOwnershipResponse, MixnetContractVersion, MixnodeRewardingStatusResponse, PagedAllDelegationsResponse, @@ -289,7 +289,7 @@ impl NymdClient { pub async fn get_rewarding_status( &self, - mix_identity: mixnet_contract::IdentityKey, + mix_identity: mixnet_contract_common::IdentityKey, rewarding_interval_nonce: u32, ) -> Result where diff --git a/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs b/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs index 558a5af2ba..8c862f0851 100644 --- a/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs +++ b/common/client-libs/validator-client/src/nymd/traits/vesting_signing_client.rs @@ -8,7 +8,7 @@ use crate::nymd::fee::helpers::Operation; use crate::nymd::{cosmwasm_coin_to_cosmos_coin, NymdClient}; use async_trait::async_trait; use cosmwasm_std::Coin; -use mixnet_contract::{Gateway, IdentityKey, IdentityKeyRef, MixNode}; +use mixnet_contract_common::{Gateway, IdentityKey, IdentityKeyRef, MixNode}; use vesting_contract::messages::ExecuteMsg as VestingExecuteMsg; #[async_trait] diff --git a/common/client-libs/validator-client/src/validator_api/mod.rs b/common/client-libs/validator-client/src/validator_api/mod.rs index 0374a4885e..6511b1157c 100644 --- a/common/client-libs/validator-client/src/validator_api/mod.rs +++ b/common/client-libs/validator-client/src/validator_api/mod.rs @@ -4,7 +4,7 @@ use crate::validator_api::error::ValidatorAPIError; use crate::validator_api::routes::{CORE_STATUS_COUNT, SINCE_ARG}; use coconut_interface::{BlindSignRequestBody, BlindedSignatureResponse, VerificationKeyResponse}; -use mixnet_contract::{GatewayBond, IdentityKeyRef, MixNodeBond}; +use mixnet_contract_common::{GatewayBond, IdentityKeyRef, MixNodeBond}; use serde::{Deserialize, Serialize}; use url::Url; use validator_api_requests::models::{ diff --git a/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml new file mode 100644 index 0000000000..26c0b3d4af --- /dev/null +++ b/common/cosmwasm-smart-contracts/contracts-common/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "contracts-common" +version = "0.1.0" +authors = ["Jędrzej Stuczyński "] +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cosmwasm-std = "1.0.0-beta3" diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/events.rs b/common/cosmwasm-smart-contracts/contracts-common/src/events.rs new file mode 100644 index 0000000000..d9b5b363ca --- /dev/null +++ b/common/cosmwasm-smart-contracts/contracts-common/src/events.rs @@ -0,0 +1,30 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use cosmwasm_std::Event; + +/// Looks up value of particular attribute in the provided event. If it fails to find it, +/// the function panics. +/// +/// # Arguments +/// +/// * `event`: event to search through. +/// * `key`: key associated with the particular attribute +pub fn must_find_attribute(event: &Event, key: &str) -> String { + may_find_attribute(event, key).unwrap() +} + +/// Looks up value of particular attribute in the provided event. Returns None if it does not exist. +/// +/// # Arguments +/// +/// * `event`: event to search through. +/// * `key`: key associated with the particular attribute +pub fn may_find_attribute(event: &Event, key: &str) -> Option { + for attr in &event.attributes { + if attr.key == key { + return Some(attr.value.clone()); + } + } + None +} diff --git a/common/cosmwasm-smart-contracts/contracts-common/src/lib.rs b/common/cosmwasm-smart-contracts/contracts-common/src/lib.rs new file mode 100644 index 0000000000..58d367a2f5 --- /dev/null +++ b/common/cosmwasm-smart-contracts/contracts-common/src/lib.rs @@ -0,0 +1,4 @@ +// Copyright 2021 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod events; diff --git a/common/mixnet-contract/Cargo.toml b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml similarity index 77% rename from common/mixnet-contract/Cargo.toml rename to common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml index 6f17d0e879..ba0edd57b1 100644 --- a/common/mixnet-contract/Cargo.toml +++ b/common/cosmwasm-smart-contracts/mixnet-contract/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mixnet-contract" +name = "mixnet-contract-common" version = "0.1.0" authors = ["Jędrzej Stuczyński "] edition = "2018" @@ -14,10 +14,12 @@ serde_repr = "0.1" schemars = "0.8" ts-rs = { version = "5.1", optional = true } thiserror = "1.0" -network-defaults = { path = "../network-defaults" } +network-defaults = { path = "../../network-defaults" } fixed = { version = "1.1", features = ["serde"] } az = "1.1" log = "0.4.14" +contracts-common = { path = "../contracts-common" } + [features] default = [] diff --git a/common/mixnet-contract/src/delegation.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs similarity index 100% rename from common/mixnet-contract/src/delegation.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/delegation.rs diff --git a/common/mixnet-contract/src/error.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs similarity index 100% rename from common/mixnet-contract/src/error.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/error.rs diff --git a/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs new file mode 100644 index 0000000000..d464e96acf --- /dev/null +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/events.rs @@ -0,0 +1,353 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use crate::mixnode::NodeRewardResult; +use crate::{ContractStateParams, Delegation, IdentityKeyRef, Layer}; +use cosmwasm_std::{Addr, Coin, Event, Uint128}; + +pub use contracts_common::events::*; + +// event types +pub const DELEGATION_EVENT_TYPE: &str = "delegation"; +pub const UNDELEGATION_EVENT_TYPE: &str = "undelegation"; +pub const GATEWAY_BONDING_EVENT_TYPE: &str = "gateway_bonding"; +pub const GATEWAY_UNBONDING_EVENT_TYPE: &str = "gateway_unbonding"; +pub const MIXNODE_BONDING_EVENT_TYPE: &str = "mixnode_bonding"; +pub const MIXNODE_UNBONDING_EVENT_TYPE: &str = "mixnode_unbonding"; +pub const SETTINGS_UPDATE_EVENT_TYPE: &str = "settings_update"; +pub const BEGIN_REWARDING_EVENT_TYPE: &str = "begin_rewarding"; +pub const OPERATOR_REWARDING_EVENT_TYPE: &str = "mix_rewarding"; +pub const MIX_DELEGATORS_REWARDING_EVENT_TYPE: &str = "mix_delegators_rewarding"; +pub const FINISH_REWARDING_EVENT_TYPE: &str = "finish_rewarding"; + +// attributes that are used in multiple places +pub const OWNER_KEY: &str = "owner"; +pub const AMOUNT_KEY: &str = "amount"; +pub const PROXY_KEY: &str = "proxy"; + +// event-specific attributes + +// delegation/undelegation +pub const DELEGATOR_KEY: &str = "delegator"; +pub const DELEGATION_TARGET_KEY: &str = "delegation_target"; +pub const DELEGATION_HEIGHT_KEY: &str = "delegation_latest_block_height"; + +// bonding/unbonding +pub const NODE_IDENTITY_KEY: &str = "identity"; +pub const ASSIGNED_LAYER_KEY: &str = "assigned_layer"; + +// settings change +pub const OLD_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "old_minimum_mixnode_pledge"; +pub const OLD_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "old_minimum_gateway_pledge"; +pub const OLD_MIXNODE_REWARDED_SET_SIZE_KEY: &str = "old_mixnode_rewarded_set_size"; +pub const OLD_MIXNODE_ACTIVE_SET_SIZE_KEY: &str = "old_mixnode_active_set_size"; +pub const OLD_ACTIVE_SET_WORK_FACTOR_KEY: &str = "old_active_set_work_factor"; + +pub const NEW_MINIMUM_MIXNODE_PLEDGE_KEY: &str = "new_minimum_mixnode_pledge"; +pub const NEW_MINIMUM_GATEWAY_PLEDGE_KEY: &str = "new_minimum_gateway_pledge"; +pub const NEW_MIXNODE_REWARDED_SET_SIZE_KEY: &str = "new_mixnode_rewarded_set_size"; +pub const NEW_MIXNODE_ACTIVE_SET_SIZE_KEY: &str = "new_mixnode_active_set_size"; +pub const NEW_ACTIVE_SET_WORK_FACTOR_KEY: &str = "new_active_set_work_factor"; + +// rewarding +pub const REWARDING_INTERVAL_NONCE_KEY: &str = "rewarding_interval_nonce"; +pub const TOTAL_MIXNODE_REWARD_KEY: &str = "total_node_reward"; +pub const OPERATOR_REWARD_KEY: &str = "operator_reward"; +pub const LAMBDA_KEY: &str = "lambda"; +pub const SIGMA_KEY: &str = "sigma"; +pub const DISTRIBUTED_DELEGATION_REWARDS_KEY: &str = "distributed_delegation_rewards"; +pub const FURTHER_DELEGATIONS_TO_REWARD_KEY: &str = "further_delegations"; +pub const NO_REWARD_REASON_KEY: &str = "no_reward_reason"; +pub const BOND_NOT_FOUND_VALUE: &str = "bond_not_found"; +pub const BOND_TOO_FRESH_VALUE: &str = "bond_too_fresh"; +pub const ZERO_UPTIME_VALUE: &str = "zero_uptime"; + +pub fn new_delegation_event( + delegator: &Addr, + proxy: &Option, + amount: &Coin, + mix_identity: IdentityKeyRef, +) -> Event { + let mut event = Event::new(DELEGATION_EVENT_TYPE).add_attribute(DELEGATOR_KEY, delegator); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event + .add_attribute(AMOUNT_KEY, amount.to_string()) + .add_attribute(DELEGATION_TARGET_KEY, mix_identity) +} + +pub fn new_undelegation_event( + delegator: &Addr, + proxy: &Option, + old_delegation: &Delegation, + mix_identity: IdentityKeyRef, +) -> Event { + let mut event = Event::new(UNDELEGATION_EVENT_TYPE).add_attribute(DELEGATOR_KEY, delegator); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event + .add_attribute(AMOUNT_KEY, old_delegation.amount.to_string()) + .add_attribute( + DELEGATION_HEIGHT_KEY, + old_delegation.block_height.to_string(), + ) + .add_attribute(DELEGATION_TARGET_KEY, mix_identity) +} + +pub fn new_gateway_bonding_event( + owner: &Addr, + proxy: &Option, + amount: &Coin, + identity: IdentityKeyRef, +) -> Event { + let mut event = Event::new(GATEWAY_BONDING_EVENT_TYPE) + .add_attribute(OWNER_KEY, owner) + .add_attribute(NODE_IDENTITY_KEY, identity); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event.add_attribute(AMOUNT_KEY, amount.to_string()) +} + +pub fn new_gateway_unbonding_event( + owner: &Addr, + proxy: &Option, + amount: &Coin, + identity: IdentityKeyRef, +) -> Event { + let mut event = Event::new(GATEWAY_UNBONDING_EVENT_TYPE) + .add_attribute(OWNER_KEY, owner) + .add_attribute(NODE_IDENTITY_KEY, identity); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event.add_attribute(AMOUNT_KEY, amount.to_string()) +} + +pub fn new_mixnode_bonding_event( + owner: &Addr, + proxy: &Option, + amount: &Coin, + identity: IdentityKeyRef, + assigned_layer: Layer, +) -> Event { + let mut event = Event::new(MIXNODE_BONDING_EVENT_TYPE) + .add_attribute(OWNER_KEY, owner) + .add_attribute(NODE_IDENTITY_KEY, identity); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event + .add_attribute(ASSIGNED_LAYER_KEY, assigned_layer) + .add_attribute(AMOUNT_KEY, amount.to_string()) +} + +pub fn new_mixnode_unbonding_event( + owner: &Addr, + proxy: &Option, + amount: &Coin, + identity: IdentityKeyRef, +) -> Event { + let mut event = Event::new(MIXNODE_UNBONDING_EVENT_TYPE) + .add_attribute(OWNER_KEY, owner) + .add_attribute(NODE_IDENTITY_KEY, identity); + + if let Some(proxy) = proxy { + event = event.add_attribute(PROXY_KEY, proxy) + } + + // coin implements Display trait and we use that implementation here + event.add_attribute(AMOUNT_KEY, amount.to_string()) +} + +pub fn new_settings_update_event( + old_params: &ContractStateParams, + new_params: &ContractStateParams, +) -> Event { + let mut event = Event::new(SETTINGS_UPDATE_EVENT_TYPE); + + if old_params.minimum_mixnode_pledge != new_params.minimum_mixnode_pledge { + event = event + .add_attribute( + OLD_MINIMUM_MIXNODE_PLEDGE_KEY, + old_params.minimum_mixnode_pledge, + ) + .add_attribute( + NEW_MINIMUM_MIXNODE_PLEDGE_KEY, + new_params.minimum_mixnode_pledge, + ) + } + + if old_params.minimum_gateway_pledge != new_params.minimum_gateway_pledge { + event = event + .add_attribute( + OLD_MINIMUM_GATEWAY_PLEDGE_KEY, + old_params.minimum_gateway_pledge, + ) + .add_attribute( + NEW_MINIMUM_GATEWAY_PLEDGE_KEY, + new_params.minimum_gateway_pledge, + ) + } + + if old_params.mixnode_rewarded_set_size != new_params.mixnode_rewarded_set_size { + event = event + .add_attribute( + OLD_MIXNODE_REWARDED_SET_SIZE_KEY, + old_params.mixnode_rewarded_set_size.to_string(), + ) + .add_attribute( + NEW_MIXNODE_REWARDED_SET_SIZE_KEY, + new_params.mixnode_rewarded_set_size.to_string(), + ) + } + + if old_params.mixnode_active_set_size != new_params.mixnode_active_set_size { + event = event + .add_attribute( + OLD_MIXNODE_ACTIVE_SET_SIZE_KEY, + old_params.mixnode_active_set_size.to_string(), + ) + .add_attribute( + NEW_MIXNODE_ACTIVE_SET_SIZE_KEY, + new_params.mixnode_active_set_size.to_string(), + ) + } + + if old_params.active_set_work_factor != new_params.active_set_work_factor { + event = event + .add_attribute( + OLD_ACTIVE_SET_WORK_FACTOR_KEY, + old_params.active_set_work_factor.to_string(), + ) + .add_attribute( + NEW_ACTIVE_SET_WORK_FACTOR_KEY, + new_params.active_set_work_factor.to_string(), + ) + } + + event +} + +pub fn new_begin_rewarding_event(rewarding_interval_nonce: u32) -> Event { + Event::new(BEGIN_REWARDING_EVENT_TYPE).add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) +} + +pub fn new_finish_rewarding_event(rewarding_interval_nonce: u32) -> Event { + Event::new(FINISH_REWARDING_EVENT_TYPE).add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) +} + +pub fn new_not_found_mix_operator_rewarding_event( + rewarding_interval_nonce: u32, + identity: IdentityKeyRef, +) -> Event { + Event::new(OPERATOR_REWARDING_EVENT_TYPE) + .add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) + .add_attribute(NODE_IDENTITY_KEY, identity) + .add_attribute(NO_REWARD_REASON_KEY, BOND_NOT_FOUND_VALUE) +} + +pub fn new_too_fresh_bond_mix_operator_rewarding_event( + rewarding_interval_nonce: u32, + identity: IdentityKeyRef, +) -> Event { + Event::new(OPERATOR_REWARDING_EVENT_TYPE) + .add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) + .add_attribute(NODE_IDENTITY_KEY, identity) + .add_attribute(NO_REWARD_REASON_KEY, BOND_TOO_FRESH_VALUE) +} + +pub fn new_zero_uptime_mix_operator_rewarding_event( + rewarding_interval_nonce: u32, + identity: IdentityKeyRef, +) -> Event { + Event::new(OPERATOR_REWARDING_EVENT_TYPE) + .add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) + .add_attribute(NODE_IDENTITY_KEY, identity) + .add_attribute(NO_REWARD_REASON_KEY, ZERO_UPTIME_VALUE) +} + +pub fn new_mix_operator_rewarding_event( + rewarding_interval_nonce: u32, + identity: IdentityKeyRef, + node_reward_result: NodeRewardResult, + operator_reward: Uint128, + delegation_rewards_distributed: Uint128, + further_delegations: bool, +) -> Event { + Event::new(OPERATOR_REWARDING_EVENT_TYPE) + .add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) + .add_attribute(NODE_IDENTITY_KEY, identity) + .add_attribute( + TOTAL_MIXNODE_REWARD_KEY, + node_reward_result.reward().to_string(), + ) + .add_attribute(LAMBDA_KEY, node_reward_result.lambda().to_string()) + .add_attribute(SIGMA_KEY, node_reward_result.sigma().to_string()) + .add_attribute(OPERATOR_REWARD_KEY, operator_reward) + .add_attribute( + DISTRIBUTED_DELEGATION_REWARDS_KEY, + delegation_rewards_distributed, + ) + .add_attribute( + FURTHER_DELEGATIONS_TO_REWARD_KEY, + further_delegations.to_string(), + ) +} + +pub fn new_mix_delegators_rewarding_event( + rewarding_interval_nonce: u32, + identity: IdentityKeyRef, + delegation_rewards_distributed: Uint128, + further_delegations: bool, +) -> Event { + Event::new(MIX_DELEGATORS_REWARDING_EVENT_TYPE) + .add_attribute( + REWARDING_INTERVAL_NONCE_KEY, + rewarding_interval_nonce.to_string(), + ) + .add_attribute(NODE_IDENTITY_KEY, identity) + .add_attribute( + DISTRIBUTED_DELEGATION_REWARDS_KEY, + delegation_rewards_distributed, + ) + .add_attribute( + FURTHER_DELEGATIONS_TO_REWARD_KEY, + further_delegations.to_string(), + ) +} diff --git a/common/mixnet-contract/src/gateway.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs similarity index 100% rename from common/mixnet-contract/src/gateway.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/gateway.rs diff --git a/common/mixnet-contract/src/lib.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs similarity index 97% rename from common/mixnet-contract/src/lib.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs index 813fa3b894..6f1854cc12 100644 --- a/common/mixnet-contract/src/lib.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/lib.rs @@ -3,6 +3,7 @@ mod delegation; pub mod error; +pub mod events; mod gateway; pub mod mixnode; mod msg; diff --git a/common/mixnet-contract/src/mixnode.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs similarity index 98% rename from common/mixnet-contract/src/mixnode.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs index 59923598ed..ff77ec628a 100644 --- a/common/mixnet-contract/src/mixnode.rs +++ b/common/cosmwasm-smart-contracts/mixnet-contract/src/mixnode.rs @@ -53,6 +53,16 @@ pub enum Layer { Three = 3, } +impl From for String { + fn from(layer: Layer) -> Self { + if layer == Layer::Gateway { + "gateway".to_string() + } else { + (layer as u8).to_string() + } + } +} + #[derive(Debug, Clone, JsonSchema, PartialEq, Serialize, Deserialize, Copy)] pub struct NodeRewardParams { period_reward_pool: Uint128, @@ -243,7 +253,7 @@ impl DelegatorRewardParams { } } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] pub struct NodeRewardResult { reward: U128, lambda: U128, diff --git a/common/mixnet-contract/src/msg.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs similarity index 100% rename from common/mixnet-contract/src/msg.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/msg.rs diff --git a/common/mixnet-contract/src/types.rs b/common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs similarity index 100% rename from common/mixnet-contract/src/types.rs rename to common/cosmwasm-smart-contracts/mixnet-contract/src/types.rs diff --git a/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml new file mode 100644 index 0000000000..278244b8f0 --- /dev/null +++ b/common/cosmwasm-smart-contracts/vesting-contract/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "vesting-contract-common" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +cosmwasm-std = "1.0.0-beta3" diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/events.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/events.rs new file mode 100644 index 0000000000..946383b7e4 --- /dev/null +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/events.rs @@ -0,0 +1,133 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +use cosmwasm_std::{Addr, Coin, Event, Timestamp}; + +// event types +pub const WITHDRAW_EVENT_TYPE: &str = "vested_coins_withdraw"; +pub const OWNERSHIP_TRANSFER_EVENT_TYPE: &str = "ownership_transfer"; +pub const STAKING_ADDRESS_UPDATE_EVENT_TYPE: &str = "staking_address_update"; +pub const NEW_PERIODIC_VESTING_ACCOUNT_EVENT_TYPE: &str = "new_periodic_vesting_account"; + +pub const VESTING_DELEGATION_EVENT_TYPE: &str = "vesting_delegation"; +pub const VESTING_UNDELEGATION_EVENT_TYPE: &str = "vesting_undelegation"; +pub const VESTING_GATEWAY_BONDING_EVENT_TYPE: &str = "vesting_gateway_bonding"; +pub const VESTING_GATEWAY_UNBONDING_EVENT_TYPE: &str = "vesting_gateway_unbonding"; +pub const VESTING_MIXNODE_BONDING_EVENT_TYPE: &str = "vesting_mixnode_bonding"; +pub const VESTING_MIXNODE_UNBONDING_EVENT_TYPE: &str = "vesting_mixnode_unbonding"; + +pub const TRACK_MIXNODE_UNBOND_EVENT_TYPE: &str = "track_mixnode_unbond"; +pub const TRACK_GATEWAY_UNBOND_EVENT_TYPE: &str = "track_gateway_unbond"; +pub const TRACK_UNDELEGATION_EVENT_TYPE: &str = "track_undelegation"; + +// attributes that are used in multiple places +pub const OWNER_KEY: &str = "owner"; +pub const AMOUNT_KEY: &str = "amount"; + +// event-specific attributes + +// withdraw +pub const REMAINING_SPENDABLE_KEY: &str = "remaining_spendable"; + +// ownership transfer +pub const FROM_ACCOUNT_KEY: &str = "from"; +pub const TO_ACCOUNT_KEY: &str = "to"; +pub const NO_VALUE_VALUE: &str = "none"; + +// new vesting account +pub const START_TIME_KEY: &str = "start_time"; +pub const STAKING_ADDRESS_KEY: &str = "staking_address"; + +// OPEN QUESTION: would it make sense to also emit amount of vesting/locked coins here? +// however, then it would require additional storage reads. +pub fn new_vested_coins_withdraw_event( + address: &Addr, + amount: &Coin, + remaining_spendable: &Coin, +) -> Event { + Event::new(WITHDRAW_EVENT_TYPE) + .add_attribute(OWNER_KEY, address) + .add_attribute(AMOUNT_KEY, amount.to_string()) + .add_attribute(REMAINING_SPENDABLE_KEY, remaining_spendable.to_string()) +} + +pub fn new_ownership_transfer_event(from: &Addr, to: &Addr) -> Event { + Event::new(OWNERSHIP_TRANSFER_EVENT_TYPE) + .add_attribute(FROM_ACCOUNT_KEY, from) + .add_attribute(TO_ACCOUNT_KEY, to) +} + +pub fn new_staking_address_update_event(from: &Option, to: &Option) -> Event { + let mut event = Event::new(OWNERSHIP_TRANSFER_EVENT_TYPE); + + if let Some(from) = from { + event = event.add_attribute(FROM_ACCOUNT_KEY, from) + } else { + event = event.add_attribute(FROM_ACCOUNT_KEY, NO_VALUE_VALUE); + } + + if let Some(to) = to { + event = event.add_attribute(TO_ACCOUNT_KEY, to) + } else { + event = event.add_attribute(TO_ACCOUNT_KEY, NO_VALUE_VALUE); + } + + event +} + +pub fn new_periodic_vesting_account_event( + owner_address: &Addr, + amount: &Coin, + staking_address: &Option, + start_time: Timestamp, +) -> Event { + let mut event = Event::new(NEW_PERIODIC_VESTING_ACCOUNT_EVENT_TYPE) + .add_attribute(OWNER_KEY, owner_address) + .add_attribute(AMOUNT_KEY, amount.to_string()); + + if let Some(staking_address) = staking_address { + event = event.add_attribute(STAKING_ADDRESS_KEY, staking_address); + } + + event.add_attribute(START_TIME_KEY, start_time.to_string()) +} + +// In most cases the events are rather barebone as there's no point in attaching +// bunch of data to them as it would be redundant. It is because in most cases when the event is emitted +// a call to the mixnet contract is made that throws another event with relevant attributes already attached. + +pub fn new_vesting_gateway_bonding_event() -> Event { + Event::new(VESTING_GATEWAY_BONDING_EVENT_TYPE) +} + +pub fn new_vesting_gateway_unbonding_event() -> Event { + Event::new(VESTING_GATEWAY_UNBONDING_EVENT_TYPE) +} + +pub fn new_vesting_mixnode_bonding_event() -> Event { + Event::new(VESTING_MIXNODE_BONDING_EVENT_TYPE) +} + +pub fn new_vesting_mixnode_unbonding_event() -> Event { + Event::new(VESTING_MIXNODE_UNBONDING_EVENT_TYPE) +} + +pub fn new_vesting_delegation_event() -> Event { + Event::new(VESTING_DELEGATION_EVENT_TYPE) +} + +pub fn new_vesting_undelegation_event() -> Event { + Event::new(VESTING_UNDELEGATION_EVENT_TYPE) +} + +pub fn new_track_mixnode_unbond_event() -> Event { + Event::new(TRACK_MIXNODE_UNBOND_EVENT_TYPE) +} + +pub fn new_track_gateway_unbond_event() -> Event { + Event::new(TRACK_GATEWAY_UNBOND_EVENT_TYPE) +} + +pub fn new_track_undelegation_event() -> Event { + Event::new(TRACK_UNDELEGATION_EVENT_TYPE) +} diff --git a/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs new file mode 100644 index 0000000000..002130e5fd --- /dev/null +++ b/common/cosmwasm-smart-contracts/vesting-contract/src/lib.rs @@ -0,0 +1,4 @@ +// Copyright 2022 - Nym Technologies SA +// SPDX-License-Identifier: Apache-2.0 + +pub mod events; diff --git a/common/nymsphinx/Cargo.toml b/common/nymsphinx/Cargo.toml index 4c2feb78a3..ce94c101b0 100644 --- a/common/nymsphinx/Cargo.toml +++ b/common/nymsphinx/Cargo.toml @@ -25,7 +25,7 @@ crypto = { path = "../crypto" } topology = { path = "../topology" } [dev-dependencies] -mixnet-contract = { path = "../mixnet-contract" } +mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } # do not include this when compiling into wasm as it somehow when combined together with reqwest, it will require # net2 via tokio-util -> tokio -> mio -> net2 diff --git a/common/nymsphinx/src/receiver.rs b/common/nymsphinx/src/receiver.rs index c3e9aebd9d..d06afa9a91 100644 --- a/common/nymsphinx/src/receiver.rs +++ b/common/nymsphinx/src/receiver.rs @@ -186,7 +186,7 @@ impl Default for MessageReceiver { mod message_receiver { use super::*; use crypto::asymmetric::identity; - use mixnet_contract::Layer; + use mixnet_contract_common::Layer; use nymsphinx_addressing::clients::Recipient; use rand::rngs::OsRng; use std::collections::HashMap; diff --git a/common/topology/Cargo.toml b/common/topology/Cargo.toml index 199505b83f..7d7bb7ecc3 100644 --- a/common/topology/Cargo.toml +++ b/common/topology/Cargo.toml @@ -13,7 +13,7 @@ rand = { version = "0.7.3", features = ["wasm-bindgen"] } ## internal crypto = { path = "../crypto" } -mixnet-contract = { path = "../mixnet-contract" } +mixnet-contract-common = { path = "../cosmwasm-smart-contracts/mixnet-contract" } nymsphinx-addressing = { path = "../nymsphinx/addressing" } nymsphinx-types = { path = "../nymsphinx/types" } version-checker = { path = "../version-checker" } diff --git a/common/topology/src/gateway.rs b/common/topology/src/gateway.rs index a0c068bfd6..70284f1c3e 100644 --- a/common/topology/src/gateway.rs +++ b/common/topology/src/gateway.rs @@ -3,7 +3,7 @@ use crate::{filter, NetworkAddress}; use crypto::asymmetric::{encryption, identity}; -use mixnet_contract::GatewayBond; +use mixnet_contract_common::GatewayBond; use nymsphinx_addressing::nodes::{NodeIdentity, NymNodeRoutingAddress}; use nymsphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; diff --git a/common/topology/src/lib.rs b/common/topology/src/lib.rs index eb32901f18..c14256512a 100644 --- a/common/topology/src/lib.rs +++ b/common/topology/src/lib.rs @@ -3,7 +3,7 @@ use crate::filter::VersionFilterable; use log::warn; -use mixnet_contract::{GatewayBond, MixNodeBond}; +use mixnet_contract_common::{GatewayBond, MixNodeBond}; use nymsphinx_addressing::nodes::NodeIdentity; use nymsphinx_types::Node as SphinxNode; use rand::Rng; @@ -272,7 +272,7 @@ mod converting_mixes_to_vec { use crypto::asymmetric::{encryption, identity}; use super::*; - use mixnet_contract::Layer; + use mixnet_contract_common::Layer; #[test] fn returns_a_vec_with_hashmap_values() { diff --git a/common/topology/src/mix.rs b/common/topology/src/mix.rs index 2f2faf5a4d..f28c9175b1 100644 --- a/common/topology/src/mix.rs +++ b/common/topology/src/mix.rs @@ -3,7 +3,7 @@ use crate::{filter, NetworkAddress}; use crypto::asymmetric::{encryption, identity}; -use mixnet_contract::{Layer, MixNodeBond}; +use mixnet_contract_common::{Layer, MixNodeBond}; use nymsphinx_addressing::nodes::NymNodeRoutingAddress; use nymsphinx_types::Node as SphinxNode; use std::convert::{TryFrom, TryInto}; diff --git a/contracts/Cargo.lock b/contracts/Cargo.lock index d1e0a14153..f374cb6199 100644 --- a/contracts/Cargo.lock +++ b/contracts/Cargo.lock @@ -236,6 +236,13 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "contracts-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", +] + [[package]] name = "cosmwasm-crypto" version = "1.0.0-beta3" @@ -831,21 +838,6 @@ checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "mixnet-contract" version = "0.1.0" -dependencies = [ - "az", - "cosmwasm-std", - "fixed", - "log", - "network-defaults", - "schemars", - "serde", - "serde_repr", - "thiserror", -] - -[[package]] -name = "mixnet-contracts" -version = "0.1.0" dependencies = [ "bs58", "config", @@ -855,7 +847,7 @@ dependencies = [ "crypto", "cw-storage-plus", "fixed", - "mixnet-contract", + "mixnet-contract-common", "rand", "rand_chacha", "schemars", @@ -865,6 +857,22 @@ dependencies = [ "vesting-contract", ] +[[package]] +name = "mixnet-contract-common" +version = "0.1.0" +dependencies = [ + "az", + "contracts-common", + "cosmwasm-std", + "fixed", + "log", + "network-defaults", + "schemars", + "serde", + "serde_repr", + "thiserror", +] + [[package]] name = "network-defaults" version = "0.1.0" @@ -1525,10 +1533,18 @@ dependencies = [ "config", "cosmwasm-std", "cw-storage-plus", - "mixnet-contract", + "mixnet-contract-common", "schemars", "serde", "thiserror", + "vesting-contract-common", +] + +[[package]] +name = "vesting-contract-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", ] [[package]] diff --git a/contracts/mixnet/Cargo.toml b/contracts/mixnet/Cargo.toml index 25de04f9db..5fc7aba1f0 100644 --- a/contracts/mixnet/Cargo.toml +++ b/contracts/mixnet/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "mixnet-contracts" +name = "mixnet-contract" version = "0.1.0" authors = ["Dave Hrycyszyn "] edition = "2018" @@ -16,7 +16,7 @@ exclude = [ crate-type = ["cdylib", "rlib"] [dependencies] -mixnet-contract = { path = "../../common/mixnet-contract" } +mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } config = { path = "../../common/config"} vesting-contract = { path = "../vesting" } diff --git a/contracts/mixnet/examples/schema.rs b/contracts/mixnet/examples/schema.rs index 0059dfb5a4..8f390777ca 100644 --- a/contracts/mixnet/examples/schema.rs +++ b/contracts/mixnet/examples/schema.rs @@ -4,7 +4,7 @@ extern crate mixnet_contract; use cosmwasm_schema::{export_schema, remove_schemas, schema_for}; -use mixnet_contract::{ExecuteMsg, InstantiateMsg, MixNodeBond, QueryMsg}; +use mixnet_contract_common::{ExecuteMsg, InstantiateMsg, MixNodeBond, QueryMsg}; use std::env::current_dir; use std::fs::create_dir_all; diff --git a/contracts/mixnet/src/contract.rs b/contracts/mixnet/src/contract.rs index c4d33b337e..badd8d12c6 100644 --- a/contracts/mixnet/src/contract.rs +++ b/contracts/mixnet/src/contract.rs @@ -23,7 +23,9 @@ use crate::rewards::storage as rewards_storage; use cosmwasm_std::{ entry_point, to_binary, Addr, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, Uint128, }; -use mixnet_contract::{ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg}; +use mixnet_contract_common::{ + ContractStateParams, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, +}; /// Constant specifying minimum of coin required to bond a gateway pub const INITIAL_GATEWAY_PLEDGE: Uint128 = Uint128::new(100_000_000); @@ -292,11 +294,11 @@ pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> Result Result { #[derive(serde::Serialize, serde::Deserialize, Clone)] pub struct StoredMixnodeBondOld { - pub pledge_amount: mixnet_contract::Coin, + pub pledge_amount: mixnet_contract_common::Coin, pub owner: Addr, - pub layer: mixnet_contract::Layer, + pub layer: mixnet_contract_common::Layer, pub block_height: u64, - pub mix_node: mixnet_contract::MixNode, + pub mix_node: mixnet_contract_common::MixNode, pub profit_margin_percent: Option, pub proxy: Option, } @@ -314,7 +316,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result() -> cw_storage_plus::IndexedMap< 'a, - mixnet_contract::IdentityKeyRef<'a>, + mixnet_contract_common::IdentityKeyRef<'a>, StoredMixnodeBondOld, MixnodeBondIndexOld<'a>, > { @@ -354,7 +356,7 @@ pub mod tests { use config::defaults::DENOM; use cosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}; use cosmwasm_std::{coins, from_binary}; - use mixnet_contract::PagedMixnodeResponse; + use mixnet_contract_common::PagedMixnodeResponse; #[test] fn initialize_contract() { diff --git a/contracts/mixnet/src/delegations/queries.rs b/contracts/mixnet/src/delegations/queries.rs index 4bc9ceed71..258f1d548d 100644 --- a/contracts/mixnet/src/delegations/queries.rs +++ b/contracts/mixnet/src/delegations/queries.rs @@ -7,10 +7,10 @@ use cosmwasm_std::Deps; use cosmwasm_std::Order; use cosmwasm_std::StdResult; use cw_storage_plus::{Bound, PrimaryKey}; -use mixnet_contract::PagedAllDelegationsResponse; -use mixnet_contract::PagedDelegatorDelegationsResponse; -use mixnet_contract::PagedMixDelegationsResponse; -use mixnet_contract::{Delegation, IdentityKey}; +use mixnet_contract_common::{ + Delegation, IdentityKey, PagedAllDelegationsResponse, PagedDelegatorDelegationsResponse, + PagedMixDelegationsResponse, +}; pub(crate) fn query_all_network_delegations_paged( deps: Deps, @@ -140,7 +140,7 @@ pub(crate) mod tests { #[cfg(test)] mod querying_for_mixnode_delegations_paged { use super::*; - use mixnet_contract::IdentityKey; + use mixnet_contract_common::IdentityKey; #[test] fn retrieval_obeys_limits() { @@ -281,7 +281,7 @@ pub(crate) mod tests { mod querying_for_all_mixnode_delegations_paged { use super::*; use crate::support::tests::test_helpers; - use mixnet_contract::IdentityKey; + use mixnet_contract_common::IdentityKey; #[test] fn retrieval_obeys_limits() { @@ -444,7 +444,7 @@ pub(crate) mod tests { // add delegation from a different address let delegation = Delegation::new( - delegation_owner2.clone(), + delegation_owner2, node_identity1.clone(), coin(1234, DENOM), 1234, @@ -474,7 +474,7 @@ pub(crate) mod tests { // add delegation for a different node let delegation = Delegation::new( delegation_owner1.clone(), - node_identity2.clone(), + node_identity2, coin(1234, DENOM), 1234, None, @@ -493,11 +493,7 @@ pub(crate) mod tests { identity: node_identity1.clone(), address: Addr::unchecked(delegation_owner1.clone()) }), - query_mixnode_delegation( - deps.as_ref(), - node_identity1.clone(), - delegation_owner1.to_string() - ) + query_mixnode_delegation(deps.as_ref(), node_identity1, delegation_owner1.to_string()) ) } diff --git a/contracts/mixnet/src/delegations/storage.rs b/contracts/mixnet/src/delegations/storage.rs index 46fd0cc7fd..8e4f3cedcb 100644 --- a/contracts/mixnet/src/delegations/storage.rs +++ b/contracts/mixnet/src/delegations/storage.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use cw_storage_plus::{Index, IndexList, IndexedMap, MultiIndex}; -use mixnet_contract::{Addr, Delegation, IdentityKey}; +use mixnet_contract_common::{Addr, Delegation, IdentityKey}; // storage prefixes const DELEGATION_PK_NAMESPACE: &str = "dl"; @@ -64,7 +64,7 @@ pub(crate) fn delegations<'a>() -> IndexedMap<'a, PrimaryKey, Delegation, Delega mod tests { use crate::delegations::storage; use cosmwasm_std::Addr; - use mixnet_contract::IdentityKey; + use mixnet_contract_common::IdentityKey; #[cfg(test)] mod reverse_mix_delegations { @@ -74,7 +74,7 @@ mod tests { use cosmwasm_std::testing::mock_env; use cosmwasm_std::{coin, Order}; use cw_storage_plus::PrimaryKey; - use mixnet_contract::Delegation; + use mixnet_contract_common::Delegation; #[test] fn reverse_mix_delegation_exists() { @@ -94,7 +94,7 @@ mod tests { storage::delegations() .save( &mut deps.storage, - (node_identity.clone(), delegation_owner.clone()).joined_key(), + (node_identity, delegation_owner.clone()).joined_key(), &dummy_data, ) .unwrap(); @@ -131,7 +131,7 @@ mod tests { // add delegation for a different node let dummy_data = Delegation::new( delegation_owner1.clone(), - node_identity2.clone(), + node_identity2, delegation.clone(), mock_env().block.height, None, @@ -156,14 +156,14 @@ mod tests { let dummy_data = Delegation::new( delegation_owner2.clone(), node_identity1.clone(), - delegation.clone(), + delegation, mock_env().block.height, None, ); storage::delegations() .save( &mut deps.storage, - (node_identity1.clone(), delegation_owner2.clone()).joined_key(), + (node_identity1.clone(), delegation_owner2).joined_key(), &dummy_data, ) .unwrap(); diff --git a/contracts/mixnet/src/delegations/transactions.rs b/contracts/mixnet/src/delegations/transactions.rs index 5de8764e93..9d060e891c 100644 --- a/contracts/mixnet/src/delegations/transactions.rs +++ b/contracts/mixnet/src/delegations/transactions.rs @@ -7,8 +7,8 @@ use crate::support::helpers::generate_storage_key; use config::defaults::DENOM; use cosmwasm_std::{coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response}; use cw_storage_plus::PrimaryKey; -use mixnet_contract::Delegation; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::events::{new_delegation_event, new_undelegation_event}; +use mixnet_contract_common::{Delegation, IdentityKey}; use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg; fn validate_delegation_stake(mut delegation: Vec) -> Result { @@ -113,16 +113,21 @@ pub(crate) fn _try_delegate_to_mixnode( } None => Delegation::new( delegate.to_owned(), - mix_identity, - amount, + mix_identity.clone(), + amount.clone(), env.block.height, - proxy, + proxy.clone(), ), }) }, )?; - Ok(Response::default()) + Ok(Response::new().add_event(new_delegation_event( + &delegate, + &proxy, + &amount, + &mix_identity, + ))) } pub(crate) fn try_remove_delegation_from_mixnode( @@ -204,14 +209,19 @@ pub(crate) fn _try_remove_delegation_from_mixnode( let msg = Some(VestingContractExecuteMsg::TrackUndelegation { owner: delegate.as_str().to_string(), mix_identity: mix_identity.clone(), - amount: old_delegation.amount, + amount: old_delegation.amount.clone(), }); let track_undelegation_msg = wasm_execute(proxy, &msg, coins(0, DENOM))?; response = response.add_message(track_undelegation_msg); } - Ok(response) + Ok(response.add_event(new_undelegation_event( + &delegate, + &proxy, + &old_delegation, + &mix_identity, + ))) } } } @@ -530,7 +540,7 @@ mod tests { try_delegate_to_mixnode( deps.as_mut(), env1, - mock_info(delegation_owner1.as_str(), &[delegation1.clone()]), + mock_info(delegation_owner1.as_str(), &[delegation1]), identity.clone(), ) .unwrap(); @@ -544,7 +554,7 @@ mod tests { try_delegate_to_mixnode( deps.as_mut(), env2, - mock_info(delegation_owner2.as_str(), &[delegation2.clone()]), + mock_info(delegation_owner2.as_str(), &[delegation2]), identity.clone(), ) .unwrap(); @@ -699,7 +709,7 @@ mod tests { try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info(delegation_owner.as_str(), &vec![delegation_amount.clone()]), + mock_info(delegation_owner.as_str(), &[delegation_amount.clone()]), identity.clone(), ) .unwrap(); @@ -722,6 +732,7 @@ mod tests { #[cfg(test)] mod removing_mix_stake_delegation { + use crate::delegations::queries::query_mixnode_delegation; use cosmwasm_std::coin; use cosmwasm_std::testing::mock_env; use cosmwasm_std::testing::mock_info; @@ -774,11 +785,27 @@ mod tests { identity.clone(), ) .unwrap(); - assert_eq!( - Ok(Response::new().add_message(BankMsg::Send { + let delegation = query_mixnode_delegation( + deps.as_ref(), + identity.clone(), + delegation_owner.clone().into_string(), + ) + .unwrap(); + + let expected_response = Response::new() + .add_message(BankMsg::Send { to_address: delegation_owner.clone().into(), amount: coins(100, DENOM), - })), + }) + .add_event(new_undelegation_event( + &delegation_owner, + &None, + &delegation, + &identity, + )); + + assert_eq!( + Ok(expected_response), try_remove_delegation_from_mixnode( deps.as_mut(), mock_info(delegation_owner.as_str(), &[]), @@ -819,12 +846,27 @@ mod tests { identity.clone(), ) .unwrap(); - try_remove_mixnode(deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap(); - assert_eq!( - Ok(Response::new().add_message(BankMsg::Send { + let delegation = query_mixnode_delegation( + deps.as_ref(), + identity.clone(), + delegation_owner.clone().into_string(), + ) + .unwrap(); + let expected_response = Response::new() + .add_message(BankMsg::Send { to_address: delegation_owner.clone().into(), amount: coins(100, DENOM), - })), + }) + .add_event(new_undelegation_event( + &delegation_owner, + &None, + &delegation, + &identity, + )); + + try_remove_mixnode(deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap(); + assert_eq!( + Ok(expected_response), try_remove_delegation_from_mixnode( deps.as_mut(), mock_info(delegation_owner.as_str(), &[]), @@ -853,7 +895,7 @@ mod tests { assert!(try_delegate_to_mixnode( deps.as_mut(), mock_env(), - mock_info(delegation_owner1.as_str(), &[delegation1.clone()]), + mock_info(delegation_owner1.as_str(), &[delegation1]), identity.clone(), ) .is_ok()); diff --git a/contracts/mixnet/src/error.rs b/contracts/mixnet/src/error.rs index 3cdccc1f13..46e85e9de0 100644 --- a/contracts/mixnet/src/error.rs +++ b/contracts/mixnet/src/error.rs @@ -3,7 +3,7 @@ use config::defaults::DENOM; use cosmwasm_std::{Addr, StdError}; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::IdentityKey; use thiserror::Error; /// Custom errors for contract failure conditions. diff --git a/contracts/mixnet/src/gateways/queries.rs b/contracts/mixnet/src/gateways/queries.rs index 2305f470c6..4125ca2143 100644 --- a/contracts/mixnet/src/gateways/queries.rs +++ b/contracts/mixnet/src/gateways/queries.rs @@ -5,7 +5,9 @@ use super::storage; use crate::mixnodes::storage::{BOND_PAGE_DEFAULT_LIMIT, BOND_PAGE_MAX_LIMIT}; // Keeps gateway and mixnode retrieval in sync by re-using the constant. Could be split into its own constant. use cosmwasm_std::{Deps, Order, StdResult}; use cw_storage_plus::Bound; -use mixnet_contract::{GatewayBond, GatewayOwnershipResponse, IdentityKey, PagedGatewayResponse}; +use mixnet_contract_common::{ + GatewayBond, GatewayOwnershipResponse, IdentityKey, PagedGatewayResponse, +}; pub(crate) fn query_gateways_paged( deps: Deps, diff --git a/contracts/mixnet/src/gateways/storage.rs b/contracts/mixnet/src/gateways/storage.rs index 33b5ef9ab0..723a8c6ea0 100644 --- a/contracts/mixnet/src/gateways/storage.rs +++ b/contracts/mixnet/src/gateways/storage.rs @@ -3,7 +3,7 @@ use cosmwasm_std::Addr; use cw_storage_plus::{Index, IndexList, IndexedMap, UniqueIndex}; -use mixnet_contract::{GatewayBond, IdentityKeyRef}; +use mixnet_contract_common::{GatewayBond, IdentityKeyRef}; // storage prefixes const GATEWAYS_PK_NAMESPACE: &str = "gt"; @@ -41,9 +41,7 @@ mod tests { use cosmwasm_std::StdResult; use cosmwasm_std::Storage; use cosmwasm_std::{coin, Addr, Uint128}; - use mixnet_contract::GatewayBond; - use mixnet_contract::IdentityKey; - use mixnet_contract::{Gateway, IdentityKeyRef}; + use mixnet_contract_common::{Gateway, GatewayBond, IdentityKey, IdentityKeyRef}; // currently this is only used in tests but may become useful later on pub(crate) fn read_gateway_pledge_amount( @@ -87,7 +85,7 @@ mod tests { let gateway_bond = GatewayBond { pledge_amount: coin(pledge_amount, DENOM), - owner: node_owner.clone(), + owner: node_owner, block_height: 12_345, gateway: Gateway { identity_key: node_identity.clone(), diff --git a/contracts/mixnet/src/gateways/transactions.rs b/contracts/mixnet/src/gateways/transactions.rs index 14cd6881c6..6426b44357 100644 --- a/contracts/mixnet/src/gateways/transactions.rs +++ b/contracts/mixnet/src/gateways/transactions.rs @@ -9,7 +9,8 @@ use config::defaults::DENOM; use cosmwasm_std::{ coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128, }; -use mixnet_contract::{Gateway, GatewayBond, Layer}; +use mixnet_contract_common::events::{new_gateway_bonding_event, new_gateway_unbonding_event}; +use mixnet_contract_common::{Gateway, GatewayBond, Layer}; use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg; pub fn try_add_gateway( @@ -97,12 +98,24 @@ pub(crate) fn _try_add_gateway( &gateway.identity_key, )?; - let bond = GatewayBond::new(pledge, owner, env.block.height, gateway, proxy); + let gateway_identity = gateway.identity_key.clone(); + let bond = GatewayBond::new( + pledge.clone(), + owner.clone(), + env.block.height, + gateway, + proxy.clone(), + ); storage::gateways().save(deps.storage, bond.identity(), &bond)?; mixnet_params_storage::increment_layer_count(deps.storage, Layer::Gateway)?; - Ok(Response::new()) + Ok(Response::new().add_event(new_gateway_bonding_event( + &owner, + &proxy, + &pledge, + &gateway_identity, + ))) } pub fn try_remove_gateway_on_behalf( @@ -155,23 +168,24 @@ pub(crate) fn _try_remove_gateway( // decrement layer count mixnet_params_storage::decrement_layer_count(deps.storage, Layer::Gateway)?; - let mut response = Response::new() - .add_message(return_tokens) - .add_attribute("action", "unbond") - .add_attribute("address", owner.clone()) - .add_attribute("gateway_bond", gateway_bond.to_string()); + let mut response = Response::new().add_message(return_tokens); if let Some(proxy) = &proxy { let msg = VestingContractExecuteMsg::TrackUnbondGateway { owner: owner.as_str().to_string(), - amount: gateway_bond.pledge_amount, + amount: gateway_bond.pledge_amount(), }; let track_unbond_message = wasm_execute(proxy, &msg, coins(0, DENOM))?; response = response.add_message(track_unbond_message); } - Ok(response) + Ok(response.add_event(new_gateway_unbonding_event( + &owner, + &proxy, + &gateway_bond.pledge_amount, + gateway_bond.identity(), + ))) } fn validate_gateway_pledge( @@ -212,12 +226,10 @@ pub mod tests { use crate::support::tests; use crate::support::tests::test_helpers; use config::defaults::DENOM; - use cosmwasm_std::attr; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, BankMsg, Response}; use cosmwasm_std::{from_binary, Addr, Uint128}; - use mixnet_contract::Gateway; - use mixnet_contract::{ExecuteMsg, PagedGatewayResponse, QueryMsg}; + use mixnet_contract_common::{ExecuteMsg, Gateway, PagedGatewayResponse, QueryMsg}; #[test] fn gateway_add() { @@ -454,19 +466,6 @@ pub mod tests { let msg = ExecuteMsg::UnbondGateway {}; let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); - // we should see log messages come back showing an unbond message - let expected_attributes = vec![ - attr("action", "unbond"), - attr("address", "fred"), - attr( - "gateway_bond", - format!( - "amount: {} {}, owner: fred, identity: {}", - INITIAL_GATEWAY_PLEDGE, DENOM, fred_identity - ), - ), - ]; - // we should see a funds transfer from the contract back to fred let expected_message = BankMsg::Send { to_address: String::from(info.sender), @@ -474,11 +473,17 @@ pub mod tests { }; // run the executor and check that we got back the correct results - let expected = Response::new() - .add_attributes(expected_attributes) - .add_message(expected_message); + let expected_response = + Response::new() + .add_message(expected_message) + .add_event(new_gateway_unbonding_event( + &Addr::unchecked("fred"), + &None, + &tests::fixtures::good_gateway_pledge()[0], + &fred_identity, + )); - assert_eq!(remove_fred, expected); + assert_eq!(expected_response, remove_fred); // only 1 node now exists, owned by bob: let gateway_bonds = tests::queries::get_gateways(&mut deps); diff --git a/contracts/mixnet/src/mixnet_contract_settings/models.rs b/contracts/mixnet/src/mixnet_contract_settings/models.rs index 0e5dcd8cb4..6b9d5d73f9 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/models.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/models.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use cosmwasm_std::Addr; -use mixnet_contract::ContractStateParams; +use mixnet_contract_common::ContractStateParams; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/contracts/mixnet/src/mixnet_contract_settings/queries.rs b/contracts/mixnet/src/mixnet_contract_settings/queries.rs index 2178ed8930..68427a8173 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/queries.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/queries.rs @@ -3,7 +3,9 @@ use super::storage; use cosmwasm_std::{Deps, StdResult}; -use mixnet_contract::{ContractStateParams, MixnetContractVersion, RewardingIntervalResponse}; +use mixnet_contract_common::{ + ContractStateParams, MixnetContractVersion, RewardingIntervalResponse, +}; pub(crate) fn query_contract_settings_params(deps: Deps) -> StdResult { storage::CONTRACT_STATE diff --git a/contracts/mixnet/src/mixnet_contract_settings/storage.rs b/contracts/mixnet/src/mixnet_contract_settings/storage.rs index 3ec217c352..2f2bd48664 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/storage.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/storage.rs @@ -5,8 +5,7 @@ use crate::mixnet_contract_settings::models::ContractState; use cosmwasm_std::StdResult; use cosmwasm_std::Storage; use cw_storage_plus::Item; -use mixnet_contract::Layer; -use mixnet_contract::LayerDistribution; +use mixnet_contract_common::{Layer, LayerDistribution}; pub(crate) const CONTRACT_STATE: Item = Item::new("config"); pub(crate) const LAYERS: Item = Item::new("layers"); diff --git a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs index 21bd496be6..e087584c4d 100644 --- a/contracts/mixnet/src/mixnet_contract_settings/transactions.rs +++ b/contracts/mixnet/src/mixnet_contract_settings/transactions.rs @@ -6,7 +6,8 @@ use crate::error::ContractError; use cosmwasm_std::DepsMut; use cosmwasm_std::MessageInfo; use cosmwasm_std::Response; -use mixnet_contract::ContractStateParams; +use mixnet_contract_common::events::new_settings_update_event; +use mixnet_contract_common::ContractStateParams; pub(crate) fn try_update_contract_settings( deps: DepsMut, @@ -34,10 +35,12 @@ pub(crate) fn try_update_contract_settings( return Err(ContractError::InvalidActiveSetSize); } + let response = Response::new().add_event(new_settings_update_event(&state.params, ¶ms)); + state.params = params; storage::CONTRACT_STATE.save(deps.storage, &state)?; - Ok(Response::default()) + Ok(response) } #[cfg(test)] @@ -49,7 +52,7 @@ pub mod tests { use crate::support::tests::test_helpers; use cosmwasm_std::testing::mock_info; use cosmwasm_std::Response; - use mixnet_contract::ContractStateParams; + use mixnet_contract_common::ContractStateParams; #[test] fn updating_contract_settings() { @@ -63,14 +66,13 @@ pub mod tests { active_set_work_factor: 10, }; + let initial_params = storage::CONTRACT_STATE + .load(deps.as_ref().storage) + .unwrap() + .params; + // sanity check to ensure new_params are different than the default ones - assert_ne!( - new_params, - storage::CONTRACT_STATE - .load(deps.as_ref().storage) - .unwrap() - .params - ); + assert_ne!(new_params, initial_params); // cannot be updated from non-owner account let info = mock_info("not-the-creator", &[]); @@ -80,7 +82,10 @@ pub mod tests { // but works fine from the creator account let info = mock_info("creator", &[]); let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone()); - assert_eq!(res, Ok(Response::default())); + assert_eq!( + res, + Ok(Response::new().add_event(new_settings_update_event(&initial_params, &new_params))) + ); // and the state is actually updated let current_state = storage::CONTRACT_STATE.load(deps.as_ref().storage).unwrap(); @@ -90,21 +95,21 @@ pub mod tests { let info = mock_info("creator", &[]); let mut new_params = current_state.params.clone(); new_params.mixnode_rewarded_set_size = new_params.mixnode_active_set_size - 1; - let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone()); + let res = try_update_contract_settings(deps.as_mut(), info, new_params); assert_eq!(Err(ContractError::InvalidActiveSetSize), res); // error is thrown for 0 size rewarded set let info = mock_info("creator", &[]); let mut new_params = current_state.params.clone(); new_params.mixnode_rewarded_set_size = 0; - let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone()); + let res = try_update_contract_settings(deps.as_mut(), info, new_params); assert_eq!(Err(ContractError::ZeroRewardedSet), res); // error is thrown for 0 size active set let info = mock_info("creator", &[]); - let mut new_params = current_state.params.clone(); + let mut new_params = current_state.params; new_params.mixnode_active_set_size = 0; - let res = try_update_contract_settings(deps.as_mut(), info, new_params.clone()); + let res = try_update_contract_settings(deps.as_mut(), info, new_params); assert_eq!(Err(ContractError::ZeroActiveSet), res); } } diff --git a/contracts/mixnet/src/mixnodes/bonding_queries.rs b/contracts/mixnet/src/mixnodes/bonding_queries.rs index 4e485f1b77..e916e7263e 100644 --- a/contracts/mixnet/src/mixnodes/bonding_queries.rs +++ b/contracts/mixnet/src/mixnodes/bonding_queries.rs @@ -4,7 +4,9 @@ use super::storage; use cosmwasm_std::{Deps, Order, StdResult}; use cw_storage_plus::Bound; -use mixnet_contract::{IdentityKey, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse}; +use mixnet_contract_common::{ + IdentityKey, MixNodeBond, MixOwnershipResponse, PagedMixnodeResponse, +}; pub fn query_mixnodes_paged( deps: Deps, diff --git a/contracts/mixnet/src/mixnodes/layer_queries.rs b/contracts/mixnet/src/mixnodes/layer_queries.rs index 2ce21648f3..7a45c58167 100644 --- a/contracts/mixnet/src/mixnodes/layer_queries.rs +++ b/contracts/mixnet/src/mixnodes/layer_queries.rs @@ -3,7 +3,7 @@ use crate::mixnet_contract_settings::storage as mixnet_params_storage; use cosmwasm_std::{Deps, StdResult}; -use mixnet_contract::LayerDistribution; +use mixnet_contract_common::LayerDistribution; pub(crate) fn query_layer_distribution(deps: Deps) -> StdResult { mixnet_params_storage::LAYERS.load(deps.storage) diff --git a/contracts/mixnet/src/mixnodes/storage.rs b/contracts/mixnet/src/mixnodes/storage.rs index 45a90cfc3e..15d365f0d9 100644 --- a/contracts/mixnet/src/mixnodes/storage.rs +++ b/contracts/mixnet/src/mixnodes/storage.rs @@ -4,7 +4,7 @@ use config::defaults::DENOM; use cosmwasm_std::{StdResult, Storage, Uint128}; use cw_storage_plus::{Index, IndexList, IndexedMap, Map, UniqueIndex}; -use mixnet_contract::{Addr, Coin, IdentityKeyRef, Layer, MixNode, MixNodeBond}; +use mixnet_contract_common::{Addr, Coin, IdentityKeyRef, Layer, MixNode, MixNodeBond}; use serde::{Deserialize, Serialize}; use std::fmt::{Display, Formatter}; @@ -138,8 +138,7 @@ mod tests { use config::defaults::DENOM; use cosmwasm_std::testing::MockStorage; use cosmwasm_std::{coin, Addr, Uint128}; - use mixnet_contract::IdentityKey; - use mixnet_contract::MixNode; + use mixnet_contract_common::{IdentityKey, MixNode}; #[test] fn mixnode_single_read_retrieval() { @@ -170,7 +169,7 @@ mod tests { let mixnode_bond = StoredMixnodeBond { pledge_amount: coin(pledge_value, DENOM), - owner: node_owner.clone(), + owner: node_owner, layer: Layer::One, block_height: 12_345, mix_node: MixNode { diff --git a/contracts/mixnet/src/mixnodes/transactions.rs b/contracts/mixnet/src/mixnodes/transactions.rs index 4bd4420ef9..252128324a 100644 --- a/contracts/mixnet/src/mixnodes/transactions.rs +++ b/contracts/mixnet/src/mixnodes/transactions.rs @@ -11,7 +11,8 @@ use config::defaults::DENOM; use cosmwasm_std::{ coins, wasm_execute, Addr, BankMsg, Coin, DepsMut, Env, MessageInfo, Response, Uint128, }; -use mixnet_contract::MixNode; +use mixnet_contract_common::events::{new_mixnode_bonding_event, new_mixnode_unbonding_event}; +use mixnet_contract_common::MixNode; use vesting_contract::messages::ExecuteMsg as VestingContractExecuteMsg; pub fn try_add_mixnode( @@ -109,12 +110,12 @@ fn _try_add_mixnode( let layer = layer_distribution.choose_with_fewest(); let stored_bond = StoredMixnodeBond::new( - pledge_amount, - owner, + pledge_amount.clone(), + owner.clone(), layer, env.block.height, mix_node, - proxy, + proxy.clone(), ); // technically we don't have to set the total_delegation bucket, but it makes things easier @@ -132,7 +133,13 @@ fn _try_add_mixnode( mixnet_params_storage::increment_layer_count(deps.storage, stored_bond.layer)?; - Ok(Response::new()) + Ok(Response::new().add_event(new_mixnode_bonding_event( + &owner, + &proxy, + &pledge_amount, + identity, + stored_bond.layer, + ))) } pub fn try_remove_mixnode_on_behalf( @@ -185,22 +192,24 @@ pub(crate) fn _try_remove_mixnode( // decrement layer count mixnet_params_storage::decrement_layer_count(deps.storage, mixnode_bond.layer)?; - let mut response = Response::new() - .add_message(return_tokens) - .add_attribute("action", "unbond") - .add_attribute("mixnode_bond", mixnode_bond.to_string()); + let mut response = Response::new().add_message(return_tokens); if let Some(proxy) = &proxy { let msg = VestingContractExecuteMsg::TrackUnbondMixnode { owner: owner.as_str().to_string(), - amount: mixnode_bond.pledge_amount, + amount: mixnode_bond.pledge_amount(), }; let track_unbond_message = wasm_execute(proxy, &msg, coins(0, DENOM))?; response = response.add_message(track_unbond_message); } - Ok(response) + Ok(response.add_event(new_mixnode_unbonding_event( + &owner, + &proxy, + &mixnode_bond.pledge_amount, + mixnode_bond.identity(), + ))) } pub(crate) fn try_update_mixnode_config( @@ -277,13 +286,12 @@ pub mod tests { use crate::support::tests; use crate::support::tests::test_helpers; use config::defaults::DENOM; - use cosmwasm_std::attr; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, BankMsg, Response}; use cosmwasm_std::{from_binary, Addr, Uint128}; - use mixnet_contract::Layer; - use mixnet_contract::MixNode; - use mixnet_contract::{ExecuteMsg, LayerDistribution, PagedMixnodeResponse, QueryMsg}; + use mixnet_contract_common::{ + ExecuteMsg, Layer, LayerDistribution, MixNode, PagedMixnodeResponse, QueryMsg, + }; #[test] fn mixnode_add() { @@ -542,18 +550,6 @@ pub mod tests { let msg = ExecuteMsg::UnbondMixnode {}; let remove_fred = execute(deps.as_mut(), mock_env(), info.clone(), msg).unwrap(); - // we should see log messages come back showing an unbond message - let expected_attributes = vec![ - attr("action", "unbond"), - attr( - "mixnode_bond", - format!( - "amount: {}{}, owner: fred, identity: {}", - INITIAL_MIXNODE_PLEDGE, DENOM, fred_identity - ), - ), - ]; - // we should see a funds transfer from the contract back to fred let expected_message = BankMsg::Send { to_address: String::from(info.sender), @@ -561,11 +557,17 @@ pub mod tests { }; // run the executor and check that we got back the correct results - let expected = Response::new() - .add_attributes(expected_attributes) - .add_message(expected_message); + let expected_response = + Response::new() + .add_message(expected_message) + .add_event(new_mixnode_unbonding_event( + &Addr::unchecked("fred"), + &None, + &tests::fixtures::good_gateway_pledge()[0], + &fred_identity, + )); - assert_eq!(remove_fred, expected); + assert_eq!(expected_response, remove_fred); // only 1 node now exists, owned by bob: let mix_node_bonds = tests::queries::get_mix_nodes(&mut deps); @@ -755,6 +757,6 @@ pub mod tests { assert_eq!(alice_node.mix_node.identity_key, alice_identity); assert_eq!(alice_node.layer, Layer::One); assert_eq!(bob_node.mix_node.identity_key, bob_identity); - assert_eq!(bob_node.layer, mixnet_contract::Layer::Two); + assert_eq!(bob_node.layer, mixnet_contract_common::Layer::Two); } } diff --git a/contracts/mixnet/src/rewards/helpers.rs b/contracts/mixnet/src/rewards/helpers.rs index 593e2eb7f9..c363cb5e39 100644 --- a/contracts/mixnet/src/rewards/helpers.rs +++ b/contracts/mixnet/src/rewards/helpers.rs @@ -5,8 +5,8 @@ use super::storage; use crate::error::ContractError; use crate::mixnodes::storage as mixnodes_storage; use cosmwasm_std::{Addr, Storage, Uint128}; -use mixnet_contract::mixnode::DelegatorRewardParams; -use mixnet_contract::{ +use mixnet_contract_common::mixnode::DelegatorRewardParams; +use mixnet_contract_common::{ IdentityKey, IdentityKeyRef, PendingDelegatorRewarding, RewardingResult, RewardingStatus, }; diff --git a/contracts/mixnet/src/rewards/queries.rs b/contracts/mixnet/src/rewards/queries.rs index 7d643c073d..a52f74dcf0 100644 --- a/contracts/mixnet/src/rewards/queries.rs +++ b/contracts/mixnet/src/rewards/queries.rs @@ -4,7 +4,7 @@ use super::storage; use cosmwasm_std::Uint128; use cosmwasm_std::{Deps, StdResult}; -use mixnet_contract::{IdentityKey, MixnodeRewardingStatusResponse}; +use mixnet_contract_common::{IdentityKey, MixnodeRewardingStatusResponse}; pub(crate) fn query_reward_pool(deps: Deps) -> StdResult { storage::REWARD_POOL.load(deps.storage) @@ -46,7 +46,9 @@ pub(crate) mod tests { }; use config::defaults::DENOM; use cosmwasm_std::{coin, Addr}; - use mixnet_contract::{RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT}; + use mixnet_contract_common::{ + RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT, + }; #[test] fn returns_empty_status_for_unrewarded_nodes() { @@ -75,14 +77,14 @@ pub(crate) mod tests { try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 1).unwrap(); try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info.clone(), node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), 1, ) .unwrap(); - try_finish_mixnode_rewarding(deps.as_mut(), info.clone(), 1).unwrap(); + try_finish_mixnode_rewarding(deps.as_mut(), info, 1).unwrap(); assert!(query_rewarding_status(deps.as_ref(), node_identity, 2) .unwrap() @@ -120,7 +122,7 @@ pub(crate) mod tests { 1, ) .unwrap(); - try_finish_mixnode_rewarding(deps.as_mut(), info.clone(), 1).unwrap(); + try_finish_mixnode_rewarding(deps.as_mut(), info, 1).unwrap(); let res = query_rewarding_status(deps.as_ref(), node_identity, 1).unwrap(); assert!(matches!(res.status, Some(RewardingStatus::Complete(..)))); @@ -151,10 +153,7 @@ pub(crate) mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info( - &*format!("delegator{:04}", i), - &vec![coin(200_000000, DENOM)], - ), + mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]), node_identity.clone(), ) .unwrap(); @@ -167,7 +166,7 @@ pub(crate) mod tests { try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info.clone(), node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), @@ -176,13 +175,8 @@ pub(crate) mod tests { .unwrap(); // rewards all pending - try_reward_next_mixnode_delegators( - deps.as_mut(), - info.clone(), - node_identity.to_string(), - 2, - ) - .unwrap(); + try_reward_next_mixnode_delegators(deps.as_mut(), info, node_identity.to_string(), 2) + .unwrap(); let res = query_rewarding_status(deps.as_ref(), node_identity, 2).unwrap(); assert!(matches!(res.status, Some(RewardingStatus::Complete(..)))); @@ -222,10 +216,7 @@ pub(crate) mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info( - &*format!("delegator{:04}", i), - &vec![coin(200_000000, DENOM)], - ), + mock_info(&*format!("delegator{:04}", i), &[coin(200_000000, DENOM)]), node_identity.clone(), ) .unwrap(); @@ -238,7 +229,7 @@ pub(crate) mod tests { try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), diff --git a/contracts/mixnet/src/rewards/storage.rs b/contracts/mixnet/src/rewards/storage.rs index 56ce6a4964..7f8e1765c9 100644 --- a/contracts/mixnet/src/rewards/storage.rs +++ b/contracts/mixnet/src/rewards/storage.rs @@ -5,7 +5,7 @@ use crate::error::ContractError; use config::defaults::TOTAL_SUPPLY; use cosmwasm_std::{StdResult, Storage, Uint128}; use cw_storage_plus::{Item, Map, U32Key}; -use mixnet_contract::{IdentityKey, RewardingStatus}; +use mixnet_contract_common::{IdentityKey, RewardingStatus}; pub(crate) const REWARD_POOL: Item = Item::new("pool"); pub(crate) const REWARDING_STATUS: Map<(U32Key, IdentityKey), RewardingStatus> = Map::new("rm"); diff --git a/contracts/mixnet/src/rewards/transactions.rs b/contracts/mixnet/src/rewards/transactions.rs index 44f17d3e70..438ad9504d 100644 --- a/contracts/mixnet/src/rewards/transactions.rs +++ b/contracts/mixnet/src/rewards/transactions.rs @@ -9,8 +9,13 @@ use crate::mixnodes::storage as mixnodes_storage; use crate::rewards::helpers; use cosmwasm_std::{Addr, DepsMut, Env, MessageInfo, Response, StdResult, Storage, Uint128}; use cw_storage_plus::{Bound, PrimaryKey}; -use mixnet_contract::mixnode::{DelegatorRewardParams, NodeRewardParams}; -use mixnet_contract::{ +use mixnet_contract_common::events::{ + new_begin_rewarding_event, new_finish_rewarding_event, new_mix_delegators_rewarding_event, + new_mix_operator_rewarding_event, new_not_found_mix_operator_rewarding_event, + new_too_fresh_bond_mix_operator_rewarding_event, new_zero_uptime_mix_operator_rewarding_event, +}; +use mixnet_contract_common::mixnode::{DelegatorRewardParams, NodeRewardParams}; +use mixnet_contract_common::{ IdentityKey, RewardingResult, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT, }; @@ -106,10 +111,7 @@ pub(crate) fn try_begin_mixnode_rewarding( mixnet_params_storage::CONTRACT_STATE.save(deps.storage, &state)?; - Ok(Response::new().add_attribute( - "rewarding interval nonce", - rewarding_interval_nonce.to_string(), - )) + Ok(Response::new().add_event(new_begin_rewarding_event(rewarding_interval_nonce))) } fn reward_mix_delegators( @@ -232,21 +234,26 @@ pub(crate) fn try_reward_next_mixnode_delegators( let mut rewarding_results = next_page_info.running_results; rewarding_results.total_delegator_reward += delegation_rewarding_result.total_rewarded; - let round_increase = delegation_rewarding_result.total_rewarded.to_string(); + let round_increase = delegation_rewarding_result.total_rewarded; let more_delegators = delegation_rewarding_result.start_next.is_some(); helpers::update_rewarding_status( deps.storage, rewarding_interval_nonce, - mix_identity, + mix_identity.clone(), rewarding_results, delegation_rewarding_result.start_next, next_page_info.rewarding_params, )?; - Ok(Response::new() - .add_attribute("current round delegation increase", round_increase) - .add_attribute("more delegators to reward", more_delegators.to_string())) + Ok( + Response::new().add_event(new_mix_delegators_rewarding_event( + rewarding_interval_nonce, + &mix_identity, + round_increase, + more_delegators, + )), + ) } } } @@ -283,68 +290,91 @@ pub(crate) fn try_reward_mixnode( let current_bond = match mixnodes_storage::read_full_mixnode_bond(deps.storage, &mix_identity)? { Some(bond) => bond, - None => return Ok(Response::new().add_attribute("result", "bond not found")), + None => { + return Ok( + Response::new().add_event(new_not_found_mix_operator_rewarding_event( + rewarding_interval_nonce, + &mix_identity, + )), + ) + } }; - let mut node_reward = "0".to_string(); - let mut operator_reward = Uint128::zero(); - let mut total_delegation_increase = Uint128::zero(); - let mut more_delegators = false; - - // check if node is old enough for rewarding and if its uptime is non-zero - if current_bond.block_height + storage::MINIMUM_BLOCK_AGE_FOR_REWARDING <= env.block.height - && params.uptime() > 0 - { - let mut node_reward_params = params; - node_reward_params.set_reward_blockstamp(env.block.height); - - let operator_reward_result = current_bond.reward(&node_reward_params); - node_reward = operator_reward_result.reward().to_string(); - - // Omitting the price per packet function now, it follows that base operator reward is the node_reward - operator_reward = Uint128::new(current_bond.operator_reward(&node_reward_params)); - - let delegator_params = DelegatorRewardParams::new(¤t_bond, node_reward_params); - let delegation_rewarding_result = - reward_mix_delegators(deps.storage, mix_identity.clone(), None, delegator_params)?; - - helpers::update_post_rewarding_storage( - deps.storage, - &mix_identity, - operator_reward, - delegation_rewarding_result.total_rewarded, - )?; - - let rewarding_results = RewardingResult { - operator_reward, - total_delegator_reward: delegation_rewarding_result.total_rewarded, - }; - - total_delegation_increase = rewarding_results.total_delegator_reward; - more_delegators = delegation_rewarding_result.start_next.is_some(); - - helpers::update_rewarding_status( - deps.storage, - rewarding_interval_nonce, - mix_identity, - rewarding_results, - delegation_rewarding_result.start_next, - delegator_params, - )?; - } else { - // node is not eligible for rewarding, so we're done immediately + // check if node is old enough for rewarding + if current_bond.block_height + storage::MINIMUM_BLOCK_AGE_FOR_REWARDING > env.block.height { storage::REWARDING_STATUS.save( deps.storage, - (rewarding_interval_nonce.into(), mix_identity), + (rewarding_interval_nonce.into(), mix_identity.clone()), &RewardingStatus::Complete(Default::default()), )?; + + return Ok( + Response::new().add_event(new_too_fresh_bond_mix_operator_rewarding_event( + rewarding_interval_nonce, + &mix_identity, + )), + ); } - Ok(Response::new() - .add_attribute("node reward", node_reward) - .add_attribute("operator reward", operator_reward) - .add_attribute("total delegation increase", total_delegation_increase) - .add_attribute("more delegators to reward", more_delegators.to_string())) + // check if it has non-zero uptime + if params.uptime() == 0 { + storage::REWARDING_STATUS.save( + deps.storage, + (rewarding_interval_nonce.into(), mix_identity.clone()), + &RewardingStatus::Complete(Default::default()), + )?; + + return Ok( + Response::new().add_event(new_zero_uptime_mix_operator_rewarding_event( + rewarding_interval_nonce, + &mix_identity, + )), + ); + } + + let mut node_reward_params = params; + node_reward_params.set_reward_blockstamp(env.block.height); + + let node_reward_result = current_bond.reward(&node_reward_params); + + // Omitting the price per packet function now, it follows that base operator reward is the node_reward + let operator_reward = Uint128::new(current_bond.operator_reward(&node_reward_params)); + + let delegator_params = DelegatorRewardParams::new(¤t_bond, node_reward_params); + let delegation_rewarding_result = + reward_mix_delegators(deps.storage, mix_identity.clone(), None, delegator_params)?; + + helpers::update_post_rewarding_storage( + deps.storage, + &mix_identity, + operator_reward, + delegation_rewarding_result.total_rewarded, + )?; + + let rewarding_results = RewardingResult { + operator_reward, + total_delegator_reward: delegation_rewarding_result.total_rewarded, + }; + let total_delegator_reward = rewarding_results.total_delegator_reward; + let further_delegations = delegation_rewarding_result.start_next.is_some(); + + helpers::update_rewarding_status( + deps.storage, + rewarding_interval_nonce, + mix_identity.clone(), + rewarding_results, + delegation_rewarding_result.start_next, + delegator_params, + )?; + + Ok(Response::new().add_event(new_mix_operator_rewarding_event( + rewarding_interval_nonce, + &mix_identity, + node_reward_result, + operator_reward, + total_delegator_reward, + further_delegations, + ))) } pub(crate) fn try_finish_mixnode_rewarding( @@ -374,7 +404,7 @@ pub(crate) fn try_finish_mixnode_rewarding( state.rewarding_in_progress = false; mixnet_params_storage::CONTRACT_STATE.save(deps.storage, &state)?; - Ok(Response::new()) + Ok(Response::new().add_event(new_finish_rewarding_event(rewarding_interval_nonce))) } #[cfg(test)] @@ -394,11 +424,15 @@ pub mod tests { use config::defaults::DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::Coin; - use cosmwasm_std::{attr, Order}; + use cosmwasm_std::Order; use cosmwasm_std::{coin, coins, Addr, Uint128}; - use mixnet_contract::mixnode::NodeRewardParams; - use mixnet_contract::{Delegation, MixNode}; - use mixnet_contract::{IdentityKey, Layer}; + use mixnet_contract_common::events::{ + must_find_attribute, BOND_TOO_FRESH_VALUE, DISTRIBUTED_DELEGATION_REWARDS_KEY, + FURTHER_DELEGATIONS_TO_REWARD_KEY, NO_REWARD_REASON_KEY, OPERATOR_REWARDING_EVENT_TYPE, + OPERATOR_REWARD_KEY, TOTAL_MIXNODE_REWARD_KEY, + }; + use mixnet_contract_common::mixnode::NodeRewardParams; + use mixnet_contract_common::{Delegation, IdentityKey, Layer, MixNode}; #[cfg(test)] mod beginning_mixnode_rewarding { @@ -426,7 +460,7 @@ pub mod tests { let res = try_begin_mixnode_rewarding( deps.as_mut(), - env.clone(), + env, mock_info(rewarding_validator_address.as_ref(), &[]), 1, ); @@ -452,7 +486,7 @@ pub mod tests { let res = try_begin_mixnode_rewarding( deps.as_mut(), - env.clone(), + env, mock_info(rewarding_validator_address.as_ref(), &[]), 2, ); @@ -547,7 +581,7 @@ pub mod tests { let res = try_begin_mixnode_rewarding( deps.as_mut(), - env.clone(), + env, mock_info(rewarding_validator_address.as_ref(), &[]), 43, ); @@ -774,9 +808,9 @@ pub mod tests { let res = try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, - node_identity.clone(), + node_identity, tests::fixtures::node_rewarding_params_fixture(100), 1, ); @@ -836,9 +870,9 @@ pub mod tests { let res = try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, - node_identity.clone(), + node_identity, tests::fixtures::node_rewarding_params_fixture(100), 1, ); @@ -900,7 +934,7 @@ pub mod tests { deps.as_mut(), env, info, - node_identity.clone(), + node_identity, tests::fixtures::node_rewarding_params_fixture(100), 2, ); @@ -923,7 +957,7 @@ pub mod tests { let initial_delegation = 20000_000000; let mixnode_bond = StoredMixnodeBond { pledge_amount: coin(initial_bond, DENOM), - owner: node_owner.clone(), + owner: node_owner, layer: Layer::One, block_height: env.block.height, mix_node: MixNode { @@ -987,13 +1021,11 @@ pub mod tests { .unwrap() .u128() ); - - assert_eq!(res.attributes[0], attr("node reward", "0")); - assert_eq!(res.attributes[1], attr("operator reward", "0")); - assert_eq!(res.attributes[2], attr("total delegation increase", "0")); + assert_eq!(1, res.events.len()); + assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, res.events[0].ty); assert_eq!( - res.attributes[3], - attr("more delegators to reward", false.to_string()) + BOND_TOO_FRESH_VALUE, + must_find_attribute(&res.events[0], NO_REWARD_REASON_KEY) ); // reward can happen now, but only for bonded node @@ -1026,12 +1058,18 @@ pub mod tests { .u128() ); - assert_ne!(res.attributes[0], attr("node reward", "0")); - assert_ne!(res.attributes[1], attr("operator reward", "0")); - assert_eq!(res.attributes[2], attr("total delegation increase", "0")); + assert_eq!(1, res.events.len()); + let event = &res.events[0]; + assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, event.ty); + assert_ne!("0", must_find_attribute(event, TOTAL_MIXNODE_REWARD_KEY)); + assert_ne!("0", must_find_attribute(event, OPERATOR_REWARD_KEY)); assert_eq!( - res.attributes[3], - attr("more delegators to reward", false.to_string()) + "0", + must_find_attribute(event, DISTRIBUTED_DELEGATION_REWARDS_KEY) + ); + assert_eq!( + false.to_string(), + must_find_attribute(event, FURTHER_DELEGATIONS_TO_REWARD_KEY) ); // reward happens now, both for node owner and delegators @@ -1046,7 +1084,7 @@ pub mod tests { try_begin_mixnode_rewarding(deps.as_mut(), env.clone(), info.clone(), 3).unwrap(); let res = try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info.clone(), node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), @@ -1069,12 +1107,18 @@ pub mod tests { > initial_delegation ); - assert_ne!(res.attributes[0], attr("node reward", "0")); - assert_ne!(res.attributes[1], attr("operator reward", "0")); - assert_ne!(res.attributes[2], attr("total delegation increase", "0")); + assert_eq!(1, res.events.len()); + let event = &res.events[0]; + assert_eq!(OPERATOR_REWARDING_EVENT_TYPE, event.ty); + assert_ne!("0", must_find_attribute(event, TOTAL_MIXNODE_REWARD_KEY)); + assert_ne!("0", must_find_attribute(event, OPERATOR_REWARD_KEY)); + assert_ne!( + "0", + must_find_attribute(event, DISTRIBUTED_DELEGATION_REWARDS_KEY) + ); assert_eq!( - res.attributes[3], - attr("more delegators to reward", false.to_string()) + false.to_string(), + must_find_attribute(event, FURTHER_DELEGATIONS_TO_REWARD_KEY) ); } @@ -1197,7 +1241,7 @@ pub mod tests { ); assert_eq!( mixnodes_storage::TOTAL_DELEGATION - .load(&deps.storage, &node_identity.clone()) + .load(&deps.storage, &node_identity) .unwrap() .u128(), pre_reward_delegation + mix1_delegator1_reward + mix1_delegator2_reward @@ -1213,7 +1257,7 @@ pub mod tests { // it's all correctly saved match storage::REWARDING_STATUS - .load(deps.as_ref().storage, (1.into(), node_identity.clone())) + .load(deps.as_ref().storage, (1.into(), node_identity)) .unwrap() { RewardingStatus::Complete(result) => assert_eq!( @@ -1243,6 +1287,7 @@ pub mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; + #[allow(clippy::inconsistent_digit_grouping)] let mix_bond = Uint128::new(10000_000_000); let delegation_value = 2000_000000; @@ -1262,7 +1307,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{}", i), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -1290,8 +1335,8 @@ pub mod tests { ) .unwrap(); assert_eq!( - res.attributes[3], - attr("more delegators to reward", false.to_string()) + false.to_string(), + must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY) ); try_finish_mixnode_rewarding( @@ -1324,6 +1369,7 @@ pub mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; + #[allow(clippy::inconsistent_digit_grouping)] let mix_bond = Uint128::new(10000_000_000); let delegation_value = 2000_000000; @@ -1343,7 +1389,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{}", i), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -1371,8 +1417,8 @@ pub mod tests { ) .unwrap(); assert_eq!( - res.attributes[3], - attr("more delegators to reward", false.to_string()) + false.to_string(), + must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY) ); try_finish_mixnode_rewarding( @@ -1405,6 +1451,7 @@ pub mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; + #[allow(clippy::inconsistent_digit_grouping)] let mix_bond = Uint128::new(10000_000_000); let delegation_value = 2000_000000; @@ -1424,7 +1471,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", i), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -1452,8 +1499,8 @@ pub mod tests { ) .unwrap(); assert_eq!( - res.attributes[3], - attr("more delegators to reward", true.to_string()) + true.to_string(), + must_find_attribute(&res.events[0], FURTHER_DELEGATIONS_TO_REWARD_KEY) ); try_finish_mixnode_rewarding( @@ -1476,7 +1523,7 @@ pub mod tests { let delegation = test_helpers::read_delegation( &deps.storage, - node_identity.clone(), + node_identity, format!("delegator{:04}", MIXNODE_DELEGATORS_PAGE_LIMIT), ) .unwrap(); @@ -1492,6 +1539,8 @@ pub mod tests { let mut env = mock_env(); let node_owner: Addr = Addr::unchecked("bob"); + + #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), coins(10000_000_000, DENOM), @@ -1511,7 +1560,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", i), - &vec![coin(base_delegation, DENOM)], + &[coin(base_delegation, DENOM)], ), node_identity.clone(), ) @@ -1530,7 +1579,7 @@ pub mod tests { for delegation in delegations_storage::delegations() .idx .mixnode - .prefix(node_identity.clone()) + .prefix(node_identity) .range(deps.as_ref().storage, None, None, Order::Ascending) { actual_reward += @@ -1545,6 +1594,8 @@ pub mod tests { // with paging let node_owner: Addr = Addr::unchecked("alice"); + + #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), coins(10000_000_000, DENOM), @@ -1564,7 +1615,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", i), - &vec![coin(base_delegation, DENOM)], + &[coin(base_delegation, DENOM)], ), node_identity.clone(), ) @@ -1628,7 +1679,7 @@ pub mod tests { for delegation in delegations_storage::delegations() .idx .mixnode - .prefix(node_identity.clone()) + .prefix(node_identity) .range(deps.as_ref().storage, Some(start), None, Order::Ascending) { actual_reward += @@ -1685,7 +1736,7 @@ pub mod tests { try_begin_mixnode_rewarding( deps.as_mut(), - env.clone(), + env, mock_info(rewarding_validator_address.as_ref(), &[]), 1, ) @@ -1717,6 +1768,8 @@ pub mod tests { let rewarding_validator_address = current_state.rewarding_validator_address; let node_owner: Addr = Addr::unchecked("alice"); + + #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), coins(10000_000_000, DENOM), @@ -1752,7 +1805,7 @@ pub mod tests { assert_eq!( Err(ContractError::MixnodeAlreadyRewarded { - identity: node_identity.clone() + identity: node_identity }), res ); @@ -1766,6 +1819,8 @@ pub mod tests { // there was another page of delegators, but they were already dealt with let node_owner: Addr = Addr::unchecked("bob"); + + #[allow(clippy::inconsistent_digit_grouping)] let node_identity = test_helpers::add_mixnode( node_owner.as_str(), coins(10000_000_000, DENOM), @@ -1776,10 +1831,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info( - &*format!("delegator{:04}", i), - &vec![coin(2000_000000, DENOM)], - ), + mock_info(&*format!("delegator{:04}", i), &[coin(2000_000000, DENOM)]), node_identity.clone(), ) .unwrap(); @@ -1798,7 +1850,7 @@ pub mod tests { try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), @@ -1824,7 +1876,7 @@ pub mod tests { assert_eq!( Err(ContractError::MixnodeAlreadyRewarded { - identity: node_identity.clone() + identity: node_identity }), res ); @@ -1847,6 +1899,7 @@ pub mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; + #[allow(clippy::inconsistent_digit_grouping)] let mix_bond = Uint128::new(10000_000_000); let delegation_value = 2000_000000; @@ -1868,7 +1921,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", i), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -1888,7 +1941,7 @@ pub mod tests { try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), @@ -1944,6 +1997,7 @@ pub mod tests { .unwrap(); let rewarding_validator_address = current_state.rewarding_validator_address; + #[allow(clippy::inconsistent_digit_grouping)] let mix_bond = Uint128::new(10000_000_000); let delegation_value = 2000_000000; @@ -1965,7 +2019,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", i), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -1978,7 +2032,7 @@ pub mod tests { try_delegate_to_mixnode( deps.as_mut(), env.clone(), - mock_info("delegator0123", &vec![coin(delegation_value, DENOM)]), + mock_info("delegator0123", &[coin(delegation_value, DENOM)]), node_identity.clone(), ) .unwrap(); @@ -1988,7 +2042,7 @@ pub mod tests { env.clone(), mock_info( &*format!("delegator{:04}", 123 + MIXNODE_DELEGATORS_PAGE_LIMIT), - &vec![coin(delegation_value, DENOM)], + &[coin(delegation_value, DENOM)], ), node_identity.clone(), ) @@ -2007,7 +2061,7 @@ pub mod tests { try_reward_mixnode( deps.as_mut(), - env.clone(), + env, info, node_identity.clone(), tests::fixtures::node_rewarding_params_fixture(100), diff --git a/contracts/mixnet/src/support/helpers.rs b/contracts/mixnet/src/support/helpers.rs index a5994b42d2..94c273879e 100644 --- a/contracts/mixnet/src/support/helpers.rs +++ b/contracts/mixnet/src/support/helpers.rs @@ -5,7 +5,7 @@ use crate::error::ContractError; use crate::gateways::storage as gateways_storage; use crate::mixnodes::storage as mixnodes_storage; use cosmwasm_std::{Addr, Deps, Storage}; -use mixnet_contract::IdentityKeyRef; +use mixnet_contract_common::IdentityKeyRef; pub fn generate_storage_key(address: &Addr, proxy: Option<&Addr>) -> Vec { if let Some(proxy) = &proxy { diff --git a/contracts/mixnet/src/support/tests/fixtures.rs b/contracts/mixnet/src/support/tests/fixtures.rs index f71040b4d7..cd1861e344 100644 --- a/contracts/mixnet/src/support/tests/fixtures.rs +++ b/contracts/mixnet/src/support/tests/fixtures.rs @@ -6,8 +6,8 @@ use crate::mixnodes::storage as mixnodes_storage; use crate::{mixnodes::storage::StoredMixnodeBond, support::tests}; use config::defaults::{DENOM, TOTAL_SUPPLY}; use cosmwasm_std::{coin, Addr, Coin}; -use mixnet_contract::mixnode::NodeRewardParams; -use mixnet_contract::{Gateway, GatewayBond, Layer, MixNode}; +use mixnet_contract_common::mixnode::NodeRewardParams; +use mixnet_contract_common::{Gateway, GatewayBond, Layer, MixNode}; pub fn mix_node_fixture() -> MixNode { MixNode { diff --git a/contracts/mixnet/src/support/tests/messages.rs b/contracts/mixnet/src/support/tests/messages.rs index e7f8af7a91..fabea69ad4 100644 --- a/contracts/mixnet/src/support/tests/messages.rs +++ b/contracts/mixnet/src/support/tests/messages.rs @@ -1,4 +1,4 @@ -use mixnet_contract::{ExecuteMsg, Gateway, IdentityKey, MixNode}; +use mixnet_contract_common::{ExecuteMsg, Gateway, IdentityKey, MixNode}; use rand::thread_rng; use crate::support::tests; diff --git a/contracts/mixnet/src/support/tests/mod.rs b/contracts/mixnet/src/support/tests/mod.rs index 7b0b99fff8..3218b72162 100644 --- a/contracts/mixnet/src/support/tests/mod.rs +++ b/contracts/mixnet/src/support/tests/mod.rs @@ -28,7 +28,7 @@ pub mod test_helpers { use cosmwasm_std::{Addr, StdResult, Storage}; use cosmwasm_std::{Empty, MemoryStorage}; use cw_storage_plus::PrimaryKey; - use mixnet_contract::{Delegation, Gateway, IdentityKeyRef, InstantiateMsg, MixNode}; + use mixnet_contract_common::{Delegation, Gateway, IdentityKeyRef, InstantiateMsg, MixNode}; use rand::thread_rng; pub fn add_mixnode(sender: &str, stake: Vec, deps: DepsMut) -> String { diff --git a/contracts/mixnet/src/support/tests/queries.rs b/contracts/mixnet/src/support/tests/queries.rs index 4c8d00195e..9a9900501b 100644 --- a/contracts/mixnet/src/support/tests/queries.rs +++ b/contracts/mixnet/src/support/tests/queries.rs @@ -4,7 +4,7 @@ use cosmwasm_std::{ testing::{mock_env, MockApi, MockQuerier, MockStorage}, Addr, Coin, OwnedDeps, }; -use mixnet_contract::{ +use mixnet_contract_common::{ GatewayBond, MixNodeBond, PagedGatewayResponse, PagedMixnodeResponse, QueryMsg, }; diff --git a/contracts/vesting/Cargo.toml b/contracts/vesting/Cargo.toml index 55e731443c..069d31ae3e 100644 --- a/contracts/vesting/Cargo.toml +++ b/contracts/vesting/Cargo.toml @@ -14,7 +14,8 @@ exclude = [ crate-type = ["cdylib", "rlib"] [dependencies] -mixnet-contract = { path = "../../common/mixnet-contract" } +mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } +vesting-contract-common = { path = "../../common/cosmwasm-smart-contracts/vesting-contract" } config = { path = "../../common/config" } cosmwasm-std = { version = "1.0.0-beta3"} diff --git a/contracts/vesting/src/contract.rs b/contracts/vesting/src/contract.rs index 999f2eb95b..89f469f1b5 100644 --- a/contracts/vesting/src/contract.rs +++ b/contracts/vesting/src/contract.rs @@ -7,10 +7,15 @@ use crate::traits::{ use crate::vesting::{populate_vesting_periods, Account}; use config::defaults::{DEFAULT_MIXNET_CONTRACT_ADDRESS, DENOM}; use cosmwasm_std::{ - entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse, + coin, entry_point, to_binary, BankMsg, Coin, Deps, DepsMut, Env, MessageInfo, QueryResponse, Response, Timestamp, Uint128, }; -use mixnet_contract::{Gateway, IdentityKey, MixNode}; +use mixnet_contract_common::{Gateway, IdentityKey, MixNode}; +use vesting_contract_common::events::{ + new_ownership_transfer_event, new_periodic_vesting_account_event, + new_staking_address_update_event, new_track_gateway_unbond_event, + new_track_mixnode_unbond_event, new_track_undelegation_event, new_vested_coins_withdraw_event, +}; // We're using a 24 month vesting period with 3 months sub-periods. // There are 8 three month periods in two years @@ -115,12 +120,16 @@ pub fn try_withdraw_vested_coins( let send_tokens = BankMsg::Send { to_address: account.owner_address().as_str().to_string(), - amount: vec![amount], + amount: vec![amount.clone()], }; Ok(Response::new() - .add_attribute("action", "whitdraw") - .add_message(send_tokens)) + .add_message(send_tokens) + .add_event(new_vested_coins_withdraw_event( + &address, + &amount, + &coin(new_balance, &amount.denom), + ))) } else { Err(ContractError::InsufficientSpendable( account.owner_address().as_str().to_string(), @@ -139,7 +148,7 @@ fn try_transfer_ownership( let mut account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?; if address == account.owner_address() { account.transfer_ownership(&to_address, deps.storage)?; - Ok(Response::default()) + Ok(Response::new().add_event(new_ownership_transfer_event(&address, &to_address))) } else { Err(ContractError::NotOwner(account.owner_address().to_string())) } @@ -154,8 +163,9 @@ fn try_update_staking_address( let to_address = to_address.and_then(|x| deps.api.addr_validate(&x).ok()); let mut account = account_from_address(info.sender.as_str(), deps.storage, deps.api)?; if address == account.owner_address() { - account.update_staking_address(to_address, deps.storage)?; - Ok(Response::default()) + let old = account.staking_address().cloned(); + account.update_staking_address(to_address.clone(), deps.storage)?; + Ok(Response::new().add_event(new_staking_address_update_event(&old, &to_address))) } else { Err(ContractError::NotOwner(account.owner_address().to_string())) } @@ -190,7 +200,7 @@ pub fn try_track_unbond_gateway( } let account = account_from_address(owner, deps.storage, deps.api)?; account.try_track_unbond_gateway(amount, deps.storage)?; - Ok(Response::default()) + Ok(Response::new().add_event(new_track_gateway_unbond_event())) } pub fn try_bond_mixnode( @@ -221,7 +231,7 @@ pub fn try_track_unbond_mixnode( } let account = account_from_address(owner, deps.storage, deps.api)?; account.try_track_unbond_mixnode(amount, deps.storage)?; - Ok(Response::default()) + Ok(Response::new().add_event(new_track_mixnode_unbond_event())) } fn try_track_undelegation( @@ -236,7 +246,7 @@ fn try_track_undelegation( } let account = account_from_address(address, deps.storage, deps.api)?; account.track_undelegation(mix_identity, amount, deps.storage)?; - Ok(Response::default()) + Ok(Response::new().add_event(new_track_undelegation_event())) } fn try_delegate_to_mixnode( @@ -279,15 +289,24 @@ fn try_create_periodic_vesting_account( }; let start_time = start_time.unwrap_or_else(|| env.block.time.seconds()); let periods = populate_vesting_periods(start_time, NUM_VESTING_PERIODS); + + let start_time = Timestamp::from_seconds(start_time); Account::new( - owner_address, - staking_address, - coin, - Timestamp::from_seconds(start_time), + owner_address.clone(), + staking_address.clone(), + coin.clone(), + start_time, periods, deps.storage, )?; - Ok(Response::default()) + Ok( + Response::new().add_event(new_periodic_vesting_account_event( + &owner_address, + &coin, + &staking_address, + start_time, + )), + ) } #[entry_point] diff --git a/contracts/vesting/src/errors.rs b/contracts/vesting/src/errors.rs index c9faef420a..fa1b8fc5f7 100644 --- a/contracts/vesting/src/errors.rs +++ b/contracts/vesting/src/errors.rs @@ -1,5 +1,5 @@ use cosmwasm_std::{Addr, StdError}; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::IdentityKey; use thiserror::Error; #[derive(Error, Debug, PartialEq)] diff --git a/contracts/vesting/src/messages.rs b/contracts/vesting/src/messages.rs index fffec2ca15..f32661818a 100644 --- a/contracts/vesting/src/messages.rs +++ b/contracts/vesting/src/messages.rs @@ -1,6 +1,5 @@ use cosmwasm_std::{Coin, Timestamp}; -use mixnet_contract::IdentityKey; -use mixnet_contract::{Gateway, MixNode}; +use mixnet_contract_common::{Gateway, IdentityKey, MixNode}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/contracts/vesting/src/traits/bonding.rs b/contracts/vesting/src/traits/bonding.rs index 73ec75024b..9ab5066d72 100644 --- a/contracts/vesting/src/traits/bonding.rs +++ b/contracts/vesting/src/traits/bonding.rs @@ -1,6 +1,6 @@ use crate::errors::ContractError; use cosmwasm_std::{Coin, Env, Response, Storage}; -use mixnet_contract::{Gateway, MixNode}; +use mixnet_contract_common::{Gateway, MixNode}; pub trait MixnodeBondingAccount { fn try_bond_mixnode( diff --git a/contracts/vesting/src/traits/delegating_account.rs b/contracts/vesting/src/traits/delegating_account.rs index bc133911d9..c2d7104893 100644 --- a/contracts/vesting/src/traits/delegating_account.rs +++ b/contracts/vesting/src/traits/delegating_account.rs @@ -1,6 +1,6 @@ use crate::errors::ContractError; use cosmwasm_std::{Coin, Env, Response, Storage, Timestamp, Uint128}; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::IdentityKey; pub trait DelegatingAccount { fn try_delegate_to_mixnode( diff --git a/contracts/vesting/src/vesting/account/delegating_account.rs b/contracts/vesting/src/vesting/account/delegating_account.rs index 20b67c971e..c39ae4a870 100644 --- a/contracts/vesting/src/vesting/account/delegating_account.rs +++ b/contracts/vesting/src/vesting/account/delegating_account.rs @@ -3,8 +3,11 @@ use crate::traits::DelegatingAccount; use config::defaults::{DEFAULT_MIXNET_CONTRACT_ADDRESS, DENOM}; use cosmwasm_std::{wasm_execute, Coin, Env, Order, Response, Storage, Timestamp, Uint128}; use cw_storage_plus::Map; -use mixnet_contract::ExecuteMsg as MixnetExecuteMsg; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::ExecuteMsg as MixnetExecuteMsg; +use mixnet_contract_common::IdentityKey; +use vesting_contract_common::events::{ + new_vesting_delegation_event, new_vesting_undelegation_event, +}; use super::Account; @@ -34,8 +37,8 @@ impl DelegatingAccount for Account { self.track_delegation(env.block.time, mix_identity, current_balance, coin, storage)?; Ok(Response::new() - .add_attribute("action", "delegate to mixnode on behalf") - .add_message(delegate_to_mixnode)) + .add_message(delegate_to_mixnode) + .add_event(new_vesting_delegation_event())) } fn try_undelegate_from_mixnode( @@ -64,8 +67,8 @@ impl DelegatingAccount for Account { )?; Ok(Response::new() - .add_attribute("action", "undelegate to mixnode on behalf") - .add_message(undelegate_from_mixnode)) + .add_message(undelegate_from_mixnode) + .add_event(new_vesting_undelegation_event())) } fn track_delegation( diff --git a/contracts/vesting/src/vesting/account/gateway_bonding_account.rs b/contracts/vesting/src/vesting/account/gateway_bonding_account.rs index b4100557b2..ce54d8ab60 100644 --- a/contracts/vesting/src/vesting/account/gateway_bonding_account.rs +++ b/contracts/vesting/src/vesting/account/gateway_bonding_account.rs @@ -3,7 +3,10 @@ use crate::errors::ContractError; use crate::traits::GatewayBondingAccount; use config::defaults::DEFAULT_MIXNET_CONTRACT_ADDRESS; use cosmwasm_std::{wasm_execute, Coin, Env, Response, Storage, Uint128}; -use mixnet_contract::{ExecuteMsg as MixnetExecuteMsg, Gateway}; +use mixnet_contract_common::{ExecuteMsg as MixnetExecuteMsg, Gateway}; +use vesting_contract_common::events::{ + new_vesting_gateway_bonding_event, new_vesting_gateway_unbonding_event, +}; use super::Account; @@ -50,8 +53,8 @@ impl GatewayBondingAccount for Account { self.save_gateway_pledge(pledge_data, storage)?; Ok(Response::new() - .add_attribute("action", "bond gateway on behalf") - .add_message(bond_gateway_msg)) + .add_message(bond_gateway_msg) + .add_event(new_vesting_gateway_bonding_event())) } fn try_unbond_gateway(&self, storage: &dyn Storage) -> Result { @@ -63,8 +66,8 @@ impl GatewayBondingAccount for Account { let unbond_msg = wasm_execute(DEFAULT_MIXNET_CONTRACT_ADDRESS, &msg, vec![])?; Ok(Response::new() - .add_attribute("action", "unbond gateway on behalf") - .add_message(unbond_msg)) + .add_message(unbond_msg) + .add_event(new_vesting_gateway_unbonding_event())) } else { Err(ContractError::NoBondFound( self.owner_address().as_str().to_string(), diff --git a/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs b/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs index e62f9fea00..ea78f580e1 100644 --- a/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs +++ b/contracts/vesting/src/vesting/account/mixnode_bonding_account.rs @@ -3,7 +3,10 @@ use crate::errors::ContractError; use crate::traits::MixnodeBondingAccount; use config::defaults::DEFAULT_MIXNET_CONTRACT_ADDRESS; use cosmwasm_std::{wasm_execute, Coin, Env, Response, Storage, Uint128}; -use mixnet_contract::{ExecuteMsg as MixnetExecuteMsg, MixNode}; +use mixnet_contract_common::{ExecuteMsg as MixnetExecuteMsg, MixNode}; +use vesting_contract_common::events::{ + new_vesting_mixnode_bonding_event, new_vesting_mixnode_unbonding_event, +}; use super::Account; @@ -50,8 +53,8 @@ impl MixnodeBondingAccount for Account { self.save_mixnode_pledge(pledge_data, storage)?; Ok(Response::new() - .add_attribute("action", "bond mixnode on behalf") - .add_message(bond_mixnode_mag)) + .add_message(bond_mixnode_mag) + .add_event(new_vesting_mixnode_bonding_event())) } fn try_unbond_mixnode(&self, storage: &dyn Storage) -> Result { @@ -63,8 +66,8 @@ impl MixnodeBondingAccount for Account { let unbond_msg = wasm_execute(DEFAULT_MIXNET_CONTRACT_ADDRESS, &msg, vec![])?; Ok(Response::new() - .add_attribute("action", "unbond mixnode on behalf") - .add_message(unbond_msg)) + .add_message(unbond_msg) + .add_event(new_vesting_mixnode_unbonding_event())) } else { Err(ContractError::NoBondFound( self.owner_address().as_str().to_string(), diff --git a/contracts/vesting/src/vesting/account/mod.rs b/contracts/vesting/src/vesting/account/mod.rs index 4156630147..2ce20122ee 100644 --- a/contracts/vesting/src/vesting/account/mod.rs +++ b/contracts/vesting/src/vesting/account/mod.rs @@ -4,7 +4,7 @@ use crate::errors::ContractError; use crate::storage::{save_account, KEY}; use cosmwasm_std::{Addr, Coin, Order, Storage, Timestamp, Uint128}; use cw_storage_plus::{Item, Map}; -use mixnet_contract::IdentityKey; +use mixnet_contract_common::IdentityKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/contracts/vesting/src/vesting/mod.rs b/contracts/vesting/src/vesting/mod.rs index 1c4b0a6ca5..b0a0f6e71a 100644 --- a/contracts/vesting/src/vesting/mod.rs +++ b/contracts/vesting/src/vesting/mod.rs @@ -46,7 +46,7 @@ mod tests { use config::defaults::DENOM; use cosmwasm_std::testing::{mock_env, mock_info}; use cosmwasm_std::{coins, Addr, Coin, Timestamp, Uint128}; - use mixnet_contract::{Gateway, MixNode}; + use mixnet_contract_common::{Gateway, MixNode}; #[test] fn test_account_creation() { diff --git a/explorer-api/Cargo.toml b/explorer-api/Cargo.toml index 3719d89d7a..24a9357530 100644 --- a/explorer-api/Cargo.toml +++ b/explorer-api/Cargo.toml @@ -22,6 +22,6 @@ log = "0.4.0" pretty_env_logger = "0.4.0" thiserror = "1.0.29" -mixnet-contract = { path = "../common/mixnet-contract" } +mixnet-contract-common = { path = "../common/cosmwasm-smart-contracts/mixnet-contract" } network-defaults = { path = "../common/network-defaults" } validator-client = { path = "../common/client-libs/validator-client", features=["nymd-client"] } diff --git a/explorer-api/src/mix_node/http.rs b/explorer-api/src/mix_node/http.rs index a663f594c5..c3888f393e 100644 --- a/explorer-api/src/mix_node/http.rs +++ b/explorer-api/src/mix_node/http.rs @@ -4,7 +4,7 @@ use crate::mix_node::models::{NodeDescription, NodeStats}; use crate::mix_nodes::delegations::{get_mixnode_delegations, get_single_mixnode_delegations}; use crate::state::ExplorerApiStateContext; -use mixnet_contract::Delegation; +use mixnet_contract_common::Delegation; use reqwest::Error as ReqwestError; use rocket::serde::json::Json; use rocket::{Route, State}; diff --git a/explorer-api/src/mix_node/models.rs b/explorer-api/src/mix_node/models.rs index 323946a47f..835bfe3991 100644 --- a/explorer-api/src/mix_node/models.rs +++ b/explorer-api/src/mix_node/models.rs @@ -3,7 +3,7 @@ use crate::mix_node::cache::Cache; use crate::mix_nodes::location::Location; -use mixnet_contract::{Addr, Coin, Layer, MixNode}; +use mixnet_contract_common::{Addr, Coin, Layer, MixNode}; use serde::Deserialize; use serde::Serialize; use std::sync::Arc; diff --git a/explorer-api/src/mix_nodes/delegations.rs b/explorer-api/src/mix_nodes/delegations.rs index 17f15989a7..a6f0ee1c05 100644 --- a/explorer-api/src/mix_nodes/delegations.rs +++ b/explorer-api/src/mix_nodes/delegations.rs @@ -1,7 +1,7 @@ // Copyright 2022 - Nym Technologies SA // SPDX-License-Identifier: Apache-2.0 -use mixnet_contract::Delegation; +use mixnet_contract_common::Delegation; pub(crate) async fn get_single_mixnode_delegations(pubkey: &str) -> Vec { let client = super::utils::new_nymd_client(); diff --git a/explorer-api/src/mix_nodes/models.rs b/explorer-api/src/mix_nodes/models.rs index 7ccd179f86..7a07131fc1 100644 --- a/explorer-api/src/mix_nodes/models.rs +++ b/explorer-api/src/mix_nodes/models.rs @@ -4,7 +4,7 @@ use crate::mix_node::models::{MixnodeStatus, PrettyDetailedMixNodeBond}; use crate::mix_nodes::location::{Location, LocationCache, LocationCacheItem}; use crate::mix_nodes::MIXNODES_CACHE_ENTRY_TTL; -use mixnet_contract::MixNodeBond; +use mixnet_contract_common::MixNodeBond; use std::collections::{HashMap, HashSet}; use std::sync::Arc; use std::time::{Duration, SystemTime}; diff --git a/explorer-api/src/mix_nodes/tasks.rs b/explorer-api/src/mix_nodes/tasks.rs index d1580a832c..b6257c1660 100644 --- a/explorer-api/src/mix_nodes/tasks.rs +++ b/explorer-api/src/mix_nodes/tasks.rs @@ -3,7 +3,7 @@ use crate::mix_nodes::MIXNODES_CACHE_REFRESH_RATE; use crate::state::ExplorerApiStateContext; -use mixnet_contract::MixNodeBond; +use mixnet_contract_common::MixNodeBond; use reqwest::Url; use std::future::Future; use validator_client::ValidatorClientError; diff --git a/explorer-api/src/ping/http.rs b/explorer-api/src/ping/http.rs index 006938bec6..67a2730bb7 100644 --- a/explorer-api/src/ping/http.rs +++ b/explorer-api/src/ping/http.rs @@ -8,7 +8,7 @@ use rocket_okapi::okapi::openapi3::OpenApi; use rocket_okapi::openapi_get_routes_spec; use rocket_okapi::settings::OpenApiSettings; -use mixnet_contract::MixNodeBond; +use mixnet_contract_common::MixNodeBond; use crate::ping::models::PingResponse; use crate::state::ExplorerApiStateContext; diff --git a/explorer-api/src/state.rs b/explorer-api/src/state.rs index d6be0e3f70..676c4f9423 100644 --- a/explorer-api/src/state.rs +++ b/explorer-api/src/state.rs @@ -5,7 +5,7 @@ use chrono::{DateTime, Utc}; use log::info; use serde::{Deserialize, Serialize}; -use mixnet_contract::MixNodeBond; +use mixnet_contract_common::MixNodeBond; use crate::country_statistics::country_nodes_distribution::{ ConcurrentCountryNodesDistribution, CountryNodesDistribution, diff --git a/nym-wallet/Cargo.lock b/nym-wallet/Cargo.lock index 43eb2fbad4..3be5369708 100644 --- a/nym-wallet/Cargo.lock +++ b/nym-wallet/Cargo.lock @@ -575,6 +575,13 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +[[package]] +name = "contracts-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -2589,10 +2596,11 @@ dependencies = [ ] [[package]] -name = "mixnet-contract" +name = "mixnet-contract-common" version = "0.1.0" dependencies = [ "az", + "contracts-common", "cosmwasm-std", "fixed", "log", @@ -2797,7 +2805,7 @@ dependencies = [ "credentials", "dirs", "eyre", - "mixnet-contract", + "mixnet-contract-common", "rand 0.6.5", "serde", "serde_json", @@ -5283,7 +5291,7 @@ dependencies = [ "flate2", "itertools", "log", - "mixnet-contract", + "mixnet-contract-common", "network-defaults", "prost", "reqwest", @@ -5328,10 +5336,18 @@ dependencies = [ "config", "cosmwasm-std", "cw-storage-plus", - "mixnet-contract", + "mixnet-contract-common", "schemars", "serde", "thiserror", + "vesting-contract-common", +] + +[[package]] +name = "vesting-contract-common" +version = "0.1.0" +dependencies = [ + "cosmwasm-std", ] [[package]] diff --git a/nym-wallet/src-tauri/Cargo.toml b/nym-wallet/src-tauri/Cargo.toml index fff7095a05..457444a2c1 100644 --- a/nym-wallet/src-tauri/Cargo.toml +++ b/nym-wallet/src-tauri/Cargo.toml @@ -35,7 +35,7 @@ cosmwasm-std = "1.0.0-beta3" validator-client = { path = "../../common/client-libs/validator-client", features = [ "nymd-client", ] } -mixnet-contract = { path = "../../common/mixnet-contract" } +mixnet-contract-common = { path = "../../common/cosmwasm-smart-contracts/mixnet-contract" } config = { path = "../../common/config" } coconut-interface = { path = "../../common/coconut-interface" } credentials = { path = "../../common/credentials" } @@ -43,8 +43,8 @@ credentials = { path = "../../common/credentials" } [dev-dependencies] ts-rs = "5.1" -[dev-dependencies.mixnet-contract] -path = "../../common/mixnet-contract" +[dev-dependencies.mixnet-contract-common] +path = "../../common/cosmwasm-smart-contracts/mixnet-contract" features = ["ts-rs"] [dev-dependencies.validator-client] diff --git a/nym-wallet/src-tauri/src/main.rs b/nym-wallet/src-tauri/src/main.rs index 00d158b82c..d2e873a297 100644 --- a/nym-wallet/src-tauri/src/main.rs +++ b/nym-wallet/src-tauri/src/main.rs @@ -3,7 +3,7 @@ windows_subsystem = "windows" )] -use mixnet_contract::{Gateway, MixNode}; +use mixnet_contract_common::{Gateway, MixNode}; use std::sync::Arc; use tauri::Menu; use tokio::sync::RwLock; @@ -78,10 +78,10 @@ fn main() { #[cfg(test)] mod test { ts_rs::export! { - mixnet_contract::MixNode => "../src/types/rust/mixnode.ts", + mixnet_contract_common::MixNode => "../src/types/rust/mixnode.ts", crate::coin::Coin => "../src/types/rust/coin.ts", crate::mixnet::account::Balance => "../src/types/rust/balance.ts", - mixnet_contract::Gateway => "../src/types/rust/gateway.ts", + mixnet_contract_common::Gateway => "../src/types/rust/gateway.ts", crate::mixnet::send::TauriTxResult => "../src/types/rust/tauritxresult.ts", crate::mixnet::send::TransactionDetails => "../src/types/rust/transactiondetails.ts", validator_client::nymd::fee::helpers::Operation => "../src/types/rust/operation.ts", diff --git a/nym-wallet/src-tauri/src/operations/mixnet/admin.rs b/nym-wallet/src-tauri/src/operations/mixnet/admin.rs index 4413ea1efc..14bf378378 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/admin.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/admin.rs @@ -2,7 +2,7 @@ use crate::error::BackendError; use crate::nymd_client; use crate::state::State; use cosmwasm_std::Uint128; -use mixnet_contract::ContractStateParams; +use mixnet_contract_common::ContractStateParams; use serde::{Deserialize, Serialize}; use std::convert::{TryFrom, TryInto}; use std::sync::Arc; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs index c7da0fa4d5..9a2cf0cb30 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/bond.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/bond.rs @@ -3,7 +3,7 @@ use crate::error::BackendError; use crate::nymd_client; use crate::state::State; use crate::{Gateway, MixNode}; -use mixnet_contract::{GatewayBond, MixNodeBond}; +use mixnet_contract_common::{GatewayBond, MixNodeBond}; use std::convert::TryInto; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs index 842ed3fb59..dbf56cc0ad 100644 --- a/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs +++ b/nym-wallet/src-tauri/src/operations/mixnet/delegate.rs @@ -4,7 +4,7 @@ use crate::nymd_client; use crate::state::State; use crate::utils::DelegationResult; use cosmwasm_std::Coin as CosmWasmCoin; -use mixnet_contract::PagedDelegatorDelegationsResponse; +use mixnet_contract_common::PagedDelegatorDelegationsResponse; use std::convert::TryInto; use std::sync::Arc; use tokio::sync::RwLock; diff --git a/validator-api/Cargo.toml b/validator-api/Cargo.toml index a419e47fa1..2e12d321ab 100644 --- a/validator-api/Cargo.toml +++ b/validator-api/Cargo.toml @@ -47,7 +47,7 @@ sqlx = { version = "0.5", features = ["runtime-tokio-rustls", "sqlite", "macros" config = { path = "../common/config" } crypto = { path="../common/crypto" } gateway-client = { path="../common/client-libs/gateway-client" } -mixnet-contract = { path="../common/mixnet-contract" } +mixnet-contract-common = { path= "../common/cosmwasm-smart-contracts/mixnet-contract" } nymsphinx = { path="../common/nymsphinx" } topology = { path="../common/topology" } validator-api-requests = { path = "validator-api-requests" } diff --git a/validator-api/src/cache/mod.rs b/validator-api/src/cache/mod.rs index 9596aef2b9..865af46966 100644 --- a/validator-api/src/cache/mod.rs +++ b/validator-api/src/cache/mod.rs @@ -6,7 +6,7 @@ use crate::rewarding::EpochRewardParams; use ::time::OffsetDateTime; use anyhow::Result; use config::defaults::VALIDATOR_API_VERSION; -use mixnet_contract::{ +use mixnet_contract_common::{ ContractStateParams, GatewayBond, IdentityKey, IdentityKeyRef, MixNodeBond, RewardingIntervalResponse, }; diff --git a/validator-api/src/cache/routes.rs b/validator-api/src/cache/routes.rs index cf59be469e..be902cd311 100644 --- a/validator-api/src/cache/routes.rs +++ b/validator-api/src/cache/routes.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 use crate::cache::ValidatorCache; -use mixnet_contract::{GatewayBond, MixNodeBond}; +use mixnet_contract_common::{GatewayBond, MixNodeBond}; use rocket::serde::json::Json; use rocket::State; diff --git a/validator-api/src/network_monitor/monitor/preparer.rs b/validator-api/src/network_monitor/monitor/preparer.rs index 160e5e8eda..6fed3f643a 100644 --- a/validator-api/src/network_monitor/monitor/preparer.rs +++ b/validator-api/src/network_monitor/monitor/preparer.rs @@ -8,7 +8,7 @@ use crate::network_monitor::test_packet::{NodeType, TestPacket}; use crate::network_monitor::test_route::TestRoute; use crypto::asymmetric::{encryption, identity}; use log::info; -use mixnet_contract::{Addr, GatewayBond, Layer, MixNodeBond}; +use mixnet_contract_common::{Addr, GatewayBond, Layer, MixNodeBond}; use nymsphinx::addressing::clients::Recipient; use nymsphinx::forwarding::packet::MixPacket; use rand::seq::SliceRandom; diff --git a/validator-api/src/nymd_client.rs b/validator-api/src/nymd_client.rs index f74476f6b5..1481ad2682 100644 --- a/validator-api/src/nymd_client.rs +++ b/validator-api/src/nymd_client.rs @@ -4,7 +4,7 @@ use crate::config::Config; use crate::rewarding::{error::RewardingError, EpochRewardParams, MixnodeToReward}; use config::defaults::DEFAULT_VALIDATOR_API_PORT; -use mixnet_contract::{ +use mixnet_contract_common::{ ContractStateParams, Delegation, ExecuteMsg, GatewayBond, IdentityKey, MixNodeBond, MixnodeRewardingStatusResponse, RewardingIntervalResponse, MIXNODE_DELEGATORS_PAGE_LIMIT, }; @@ -157,7 +157,7 @@ impl Client { pub(crate) async fn get_rewarding_status( &self, - mix_identity: mixnet_contract::IdentityKey, + mix_identity: mixnet_contract_common::IdentityKey, rewarding_interval_nonce: u32, ) -> Result where diff --git a/validator-api/src/rewarding/mod.rs b/validator-api/src/rewarding/mod.rs index 4e5561e083..74222bb16b 100644 --- a/validator-api/src/rewarding/mod.rs +++ b/validator-api/src/rewarding/mod.rs @@ -12,8 +12,8 @@ use crate::storage::models::{ use crate::storage::ValidatorApiStorage; use config::defaults::DENOM; use log::{error, info}; -use mixnet_contract::mixnode::NodeRewardParams; -use mixnet_contract::{ +use mixnet_contract_common::mixnode::NodeRewardParams; +use mixnet_contract_common::{ ExecuteMsg, IdentityKey, MixNodeBond, RewardingStatus, MIXNODE_DELEGATORS_PAGE_LIMIT, }; use std::convert::TryInto;