Compare commits

...

2 Commits

Author SHA1 Message Date
durch 419782fb16 Universal compound rewards message that anyone can call 2022-07-25 10:22:18 +02:00
Jędrzej Stuczyński 6026ddebfd Removed mixnet contract migration 2022-06-22 17:52:49 +01:00
7 changed files with 100 additions and 237 deletions
+1 -1
View File
@@ -1,5 +1,5 @@
test-all: test cargo-test-expensive
test: build clippy-all cargo-test wasm fmt
test-all: test cargo-test-expensive
no-clippy: build cargo-test wasm fmt
happy: fmt clippy-happy test
clippy-all: clippy-all-main clippy-all-contracts clippy-all-wallet clippy-all-connect
@@ -914,6 +914,29 @@ impl<C> NymdClient<C> {
.await
}
#[execute("mixnet")]
fn _compound_reward(
&self,
operator: Option<String>,
delegator: Option<String>,
mix_identity: Option<IdentityKey>,
proxy: Option<String>,
fee: Option<Fee>,
) -> (ExecuteMsg, Option<Fee>)
where
C: SigningCosmWasmClient + Sync,
{
(
ExecuteMsg::CompoundReward {
operator,
delegator,
mix_identity,
proxy,
},
fee,
)
}
#[execute("mixnet")]
fn _compound_operator_reward(&self, fee: Option<Fee>) -> (ExecuteMsg, Option<Fee>)
where
@@ -32,6 +32,12 @@ pub enum ExecuteMsg {
CompoundDelegatorReward {
mix_identity: IdentityKey,
},
CompoundReward {
operator: Option<String>,
delegator: Option<String>,
mix_identity: Option<IdentityKey>,
proxy: Option<String>,
},
BondMixnode {
mix_node: MixNode,
owner_signature: String,
+15 -55
View File
@@ -107,6 +107,19 @@ pub fn execute(
msg: ExecuteMsg,
) -> Result<Response, ContractError> {
match msg {
ExecuteMsg::CompoundReward {
operator,
delegator,
mix_identity,
proxy,
} => crate::rewards::transactions::try_compound_reward(
deps,
env,
operator,
delegator,
mix_identity,
proxy,
),
ExecuteMsg::UpdateRewardingValidatorAddress { address } => {
try_update_rewarding_validator_address(deps, info, address)
}
@@ -275,7 +288,7 @@ pub fn execute(
)
}
ExecuteMsg::ReconcileDelegations {} => {
crate::delegations::transactions::try_reconcile_all_delegation_events(deps, info)
crate::delegations::transactions::try_reconcile_all_delegation_events(deps)
}
ExecuteMsg::CheckpointMixnodes {} => {
crate::mixnodes::transactions::try_checkpoint_mixnodes(
@@ -443,62 +456,9 @@ pub fn query(deps: Deps<'_>, env: Env, msg: QueryMsg) -> Result<QueryResponse, C
Ok(query_res?)
}
fn update_epoch_duration(deps: DepsMut<'_>) -> Result<(), ContractError> {
let mut epoch = crate::interval::storage::current_epoch(deps.storage)?;
epoch.update_duration(600);
crate::interval::storage::save_epoch(deps.storage, &epoch)?;
Ok(())
}
fn _migrate_contract_state_params(deps: DepsMut<'_>) -> Result<(), ContractError> {
use crate::mixnet_contract_settings::storage::CONTRACT_STATE;
use cw_storage_plus::Item;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
struct OldContractState {
pub owner: Addr,
pub rewarding_validator_address: Addr,
pub params: OldContractStateParams,
}
#[derive(Serialize, Deserialize)]
struct OldContractStateParams {
pub minimum_mixnode_pledge: Uint128,
pub minimum_gateway_pledge: Uint128,
pub mixnode_rewarded_set_size: u32,
pub mixnode_active_set_size: u32,
}
const OLD_CONTRACT_STATE: Item<'_, OldContractState> = Item::new("config");
let old_contract_state = OLD_CONTRACT_STATE.load(deps.storage)?;
let old_params = old_contract_state.params;
let new_params = ContractStateParams {
minimum_mixnode_pledge: old_params.minimum_mixnode_pledge,
minimum_gateway_pledge: old_params.minimum_gateway_pledge,
mixnode_rewarded_set_size: old_params.mixnode_rewarded_set_size,
mixnode_active_set_size: old_params.mixnode_active_set_size,
staking_supply: INITIAL_STAKING_SUPPLY,
};
let new_contract_state = ContractState {
owner: old_contract_state.owner,
rewarding_validator_address: old_contract_state.rewarding_validator_address,
params: new_params,
};
CONTRACT_STATE.save(deps.storage, &new_contract_state)?;
Ok(())
}
#[entry_point]
pub fn migrate(deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
update_epoch_duration(deps)?;
pub fn migrate(_deps: DepsMut<'_>, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
Ok(Default::default())
}
@@ -4,7 +4,6 @@ use super::storage::{self, PENDING_DELEGATION_EVENTS};
// use crate::contract::debug_with_visibility;
// use crate::contract::debug_with_visibility;
use crate::error::ContractError;
use crate::mixnet_contract_settings::storage as mixnet_params_storage;
use crate::mixnodes::storage as mixnodes_storage;
use config::defaults::DENOM;
use cosmwasm_std::{
@@ -20,16 +19,7 @@ use mixnet_contract_common::{Delegation, IdentityKey};
use vesting_contract_common::messages::ExecuteMsg as VestingContractExecuteMsg;
use vesting_contract_common::one_ucoin;
pub fn try_reconcile_all_delegation_events(
deps: DepsMut<'_>,
info: MessageInfo,
) -> Result<Response, ContractError> {
let state = mixnet_params_storage::CONTRACT_STATE.load(deps.storage)?;
// check if this is executed by the permitted validator, if not reject the transaction
if info.sender != state.rewarding_validator_address {
return Err(ContractError::Unauthorized);
}
pub fn try_reconcile_all_delegation_events(deps: DepsMut<'_>) -> Result<Response, ContractError> {
_try_reconcile_all_delegation_events(deps.storage, deps.api)
}
@@ -1063,182 +1053,14 @@ mod tests {
#[cfg(test)]
mod removing_mix_stake_delegation {
use crate::delegations::queries::query_mixnode_delegation;
use super::*;
use crate::support::tests;
use cosmwasm_std::coin;
use cosmwasm_std::testing::mock_env;
use cosmwasm_std::testing::mock_info;
use cosmwasm_std::Addr;
use cosmwasm_std::Uint128;
use crate::mixnodes::transactions::try_remove_mixnode;
use crate::support::tests;
use super::storage;
use super::*;
// TODO: Probably delete due to reconciliation logic
#[ignore]
#[test]
fn fails_if_delegation_never_existed() {
let mut deps = test_helpers::init_contract();
let env = mock_env();
let mixnode_owner = "bob";
let identity = test_helpers::add_mixnode(
mixnode_owner,
tests::fixtures::good_mixnode_pledge(),
deps.as_mut(),
);
let delegation_owner = Addr::unchecked("sender");
assert_eq!(
Err(ContractError::NoMixnodeDelegationFound {
identity: identity.clone(),
address: delegation_owner.to_string(),
}),
try_remove_delegation_from_mixnode(
deps.as_mut(),
env,
mock_info(delegation_owner.as_str(), &[]),
identity,
)
);
}
// TODO: Update to work with reconciliation
#[ignore]
#[test]
fn succeeds_if_delegation_existed() {
let mut deps = test_helpers::init_contract();
let mixnode_owner = "bob";
let env = mock_env();
let identity = test_helpers::add_mixnode(
mixnode_owner,
tests::fixtures::good_mixnode_pledge(),
deps.as_mut(),
);
let delegation_owner = Addr::unchecked("sender");
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
.unwrap();
_try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
let _delegation = query_mixnode_delegation(
&deps.storage,
&deps.api,
identity.clone(),
delegation_owner.clone().into_string(),
None,
)
.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,
&identity,
Uint128::new(100),
));
assert_eq!(
Ok(expected_response),
try_remove_delegation_from_mixnode(
deps.as_mut(),
env,
mock_info(delegation_owner.as_str(), &[]),
identity.clone(),
)
);
assert!(storage::delegations()
.may_load(
&deps.storage,
(identity.clone(), delegation_owner.as_bytes().to_vec(), 0),
)
.unwrap()
.is_none());
// and total delegation is cleared
assert_eq!(
Uint128::zero(),
mixnodes_storage::TOTAL_DELEGATION
.load(&deps.storage, &identity)
.unwrap()
)
}
// TODO: Update to work with reconciliation
#[ignore]
#[test]
fn succeeds_if_delegation_existed_even_if_node_unbonded() {
let mut deps = test_helpers::init_contract();
let mixnode_owner = "bob";
let env = mock_env();
let identity = test_helpers::add_mixnode(
mixnode_owner,
tests::fixtures::good_mixnode_pledge(),
deps.as_mut(),
);
let delegation_owner = Addr::unchecked("sender");
try_delegate_to_mixnode(
deps.as_mut(),
mock_env(),
mock_info(delegation_owner.as_str(), &coins(100, DENOM)),
identity.clone(),
)
.unwrap();
_try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
let delegation = query_mixnode_delegation(
&deps.storage,
&deps.api,
identity.clone(),
delegation_owner.clone().into_string(),
None,
)
.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,
&identity,
Uint128::new(100),
));
try_remove_mixnode(mock_env(), deps.as_mut(), mock_info(mixnode_owner, &[])).unwrap();
assert_eq!(
Ok(expected_response),
try_remove_delegation_from_mixnode(
deps.as_mut(),
env,
mock_info(delegation_owner.as_str(), &[]),
identity.clone(),
)
);
_try_reconcile_all_delegation_events(&mut deps.storage, &deps.api).unwrap();
assert!(test_helpers::read_delegation(
&deps.storage,
identity,
delegation_owner.as_bytes(),
mock_env().block.height
)
.is_none());
}
#[test]
fn total_delegation_is_preserved_if_only_some_undelegate() {
let mut deps = test_helpers::init_contract();
+2
View File
@@ -179,4 +179,6 @@ pub enum ContractError {
last_update_time: u64,
current_block_time: u64,
},
#[error("`mix_identity` is required when `delegator` is set")]
MissingMixIdentity,
}
@@ -370,6 +370,56 @@ pub fn try_compound_delegator_reward_on_behalf(
)
}
pub fn try_compound_reward(
deps: DepsMut<'_>,
env: Env,
operator: Option<String>,
delegator: Option<String>,
mix_identity: Option<IdentityKey>,
proxy: Option<String>,
) -> Result<Response, ContractError> {
let proxy = proxy.and_then(|p| deps.api.addr_validate(&p).ok());
if let Some(operator_address) = operator {
let operator_address = deps.api.addr_validate(&operator_address)?;
let reward = _try_compound_operator_reward(
deps.storage,
deps.api,
env.block.height,
&operator_address,
proxy,
)?;
Ok(
Response::default().add_event(new_compound_operator_reward_event(
&operator_address,
reward,
)),
)
} else if let Some(delegator_address) = delegator {
if mix_identity.is_none() {
return Err(ContractError::MissingMixIdentity);
}
let delegator_address = deps.api.addr_validate(&delegator_address)?;
let reward = _try_compound_delegator_reward(
env.block.height,
deps,
delegator_address.as_str(),
mix_identity.as_ref().unwrap(),
proxy,
)?;
Ok(
Response::default().add_event(new_compound_delegator_reward_event(
&delegator_address,
&None,
reward,
&mix_identity.unwrap(),
)),
)
} else {
Ok(Response::default())
}
}
pub fn try_compound_delegator_reward(
deps: DepsMut<'_>,
env: Env,