33992542b1
* updated contracts to cosmwasm2.2 and fixed build issues * removed old coconut contract code + additional dkg fixes * replace deprecated to_binary and from_binary functions * mixnet contract tests compiling some are failing due to incorrect addresses * made other contract tests compile * fixed remaining tests * allow usage of manually dispatching contract replies * nym-api test fixes * removed old toolchain from contracts CI * linter fixes * regenerated contract schema * fixed easy_addr * further license fixes * post rebase fixes + update to 2.2.2 * change ci runner * minor CI adjustments * change wallet CI to use node 20 * more CI changes... * run cosmwasm-check against release contracts * test ci changes * wip...
237 lines
7.5 KiB
Rust
237 lines
7.5 KiB
Rust
use cosmwasm_std::{Addr, Api, Storage, Uint128};
|
|
use cosmwasm_std::{Coin, Order};
|
|
use cw_storage_plus::{Item, Map};
|
|
use mixnet_contract_common::{IdentityKey, NodeId};
|
|
use vesting_contract_common::account::VestingAccountStorageKey;
|
|
use vesting_contract_common::{Account, PledgeData, VestingContractError};
|
|
|
|
pub(crate) type BlockTimestampSecs = u64;
|
|
|
|
/// Counter for the unique, monotonically increasing storage key id for the vesting account data.
|
|
pub const KEY: Item<VestingAccountStorageKey> = Item::new("key");
|
|
|
|
/// Storage map containing vesting account information associated with particular owner address.
|
|
pub const ACCOUNTS: Map<Addr, Account> = Map::new("acc");
|
|
|
|
/// Storage map containing information about amount of tokens associated with particular vesting account
|
|
/// that are currently present in the contract (and have not been withdrawn or staked in the mixnet contract)
|
|
// note: this assumes I understood the intent behind this correctly
|
|
const BALANCES: Map<VestingAccountStorageKey, Uint128> = Map::new("blc");
|
|
|
|
/// Storage map containing information about amount of tokens withdrawn from the contract by a particular vesting account.
|
|
const WITHDRAWNS: Map<VestingAccountStorageKey, Uint128> = Map::new("wthd");
|
|
|
|
/// Storage map containing information about amount of tokens pledged towards bonding mixnodes
|
|
/// in the mixnet contract using a particular vesting account.
|
|
const BOND_PLEDGES: Map<VestingAccountStorageKey, PledgeData> = Map::new("bnd");
|
|
|
|
/// Storage map containing information about amount of tokens pledged towards bonding gateways
|
|
/// in the mixnet contract using a particular vesting account.
|
|
const GATEWAY_PLEDGES: Map<VestingAccountStorageKey, PledgeData> = Map::new("gtw");
|
|
|
|
/// Old, pre-v2 migration, storage map that used to contain information about tokens delegated
|
|
/// towards particular mixnodes in the mixnet contract with given vesting account.
|
|
/// It should be completely empty.
|
|
pub const _OLD_DELEGATIONS: Map<
|
|
(VestingAccountStorageKey, IdentityKey, BlockTimestampSecs),
|
|
Uint128,
|
|
> = Map::new("dlg");
|
|
|
|
/// Storage map containing information about tokens delegated towards particular mixnodes
|
|
/// in the mixnet contract with given vesting account.
|
|
pub const DELEGATIONS: Map<(VestingAccountStorageKey, NodeId, BlockTimestampSecs), Uint128> =
|
|
Map::new("dlg_v2");
|
|
|
|
/// Explicit contract admin that is allowed, among other things, to create new vesting accounts.
|
|
pub const ADMIN: Item<Addr> = Item::new("adm");
|
|
|
|
/// Address of the mixnet contract.
|
|
pub const MIXNET_CONTRACT_ADDRESS: Item<Addr> = Item::new("mix");
|
|
|
|
/// The denomination of coin used for staking.
|
|
pub const MIX_DENOM: Item<String> = Item::new("den");
|
|
|
|
pub fn save_delegation(
|
|
key: (VestingAccountStorageKey, NodeId, BlockTimestampSecs),
|
|
amount: Uint128,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
let existing_delegation_amount = if let Some(delegation) = DELEGATIONS.may_load(storage, key)? {
|
|
delegation
|
|
} else {
|
|
Uint128::zero()
|
|
};
|
|
let new_delegations_amount = existing_delegation_amount + amount;
|
|
DELEGATIONS.save(storage, key, &new_delegations_amount)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn remove_delegation(
|
|
key: (VestingAccountStorageKey, NodeId, BlockTimestampSecs),
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
DELEGATIONS.remove(storage, key);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_delegation_timestamps(
|
|
prefix: (VestingAccountStorageKey, NodeId),
|
|
storage: &dyn Storage,
|
|
) -> Result<Vec<BlockTimestampSecs>, VestingContractError> {
|
|
let block_timestamps = DELEGATIONS
|
|
.prefix(prefix)
|
|
.keys(storage, None, None, Order::Ascending)
|
|
.collect::<Result<Vec<_>, _>>()?;
|
|
Ok(block_timestamps)
|
|
}
|
|
|
|
pub fn count_subdelegations_for_mix(
|
|
prefix: (VestingAccountStorageKey, NodeId),
|
|
storage: &dyn Storage,
|
|
) -> u32 {
|
|
DELEGATIONS
|
|
.prefix(prefix)
|
|
.keys(storage, None, None, Order::Ascending)
|
|
.count() as u32
|
|
}
|
|
|
|
pub fn load_withdrawn(
|
|
key: VestingAccountStorageKey,
|
|
storage: &dyn Storage,
|
|
) -> Result<Uint128, VestingContractError> {
|
|
Ok(WITHDRAWNS
|
|
.may_load(storage, key)
|
|
.unwrap_or(None)
|
|
.unwrap_or_else(Uint128::zero))
|
|
}
|
|
|
|
pub fn load_balance(
|
|
key: VestingAccountStorageKey,
|
|
storage: &dyn Storage,
|
|
) -> Result<Uint128, VestingContractError> {
|
|
Ok(BALANCES
|
|
.may_load(storage, key)
|
|
.unwrap_or(None)
|
|
.unwrap_or_else(Uint128::zero))
|
|
}
|
|
|
|
pub fn save_balance(
|
|
key: VestingAccountStorageKey,
|
|
value: Uint128,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
BALANCES.save(storage, key, &value)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn save_withdrawn(
|
|
key: VestingAccountStorageKey,
|
|
value: Uint128,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
WITHDRAWNS.save(storage, key, &value)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_bond_pledge(
|
|
key: VestingAccountStorageKey,
|
|
storage: &dyn Storage,
|
|
) -> Result<Option<PledgeData>, VestingContractError> {
|
|
Ok(BOND_PLEDGES.may_load(storage, key).unwrap_or(None))
|
|
}
|
|
|
|
pub fn remove_bond_pledge(
|
|
key: VestingAccountStorageKey,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
BOND_PLEDGES.remove(storage, key);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn save_bond_pledge(
|
|
key: VestingAccountStorageKey,
|
|
value: &PledgeData,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
BOND_PLEDGES.save(storage, key, value)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn decrease_bond_pledge(
|
|
key: VestingAccountStorageKey,
|
|
amount: Coin,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
let mut existing = BOND_PLEDGES.load(storage, key)?;
|
|
if existing.amount.amount <= amount.amount {
|
|
// this shouldn't be possible!
|
|
// (but check for it anyway... just in case)
|
|
return Err(VestingContractError::InvalidBondPledgeReduction {
|
|
current: existing.amount,
|
|
decrease_by: amount,
|
|
});
|
|
}
|
|
existing.amount.amount -= amount.amount;
|
|
save_bond_pledge(key, &existing, storage)
|
|
}
|
|
|
|
pub fn load_gateway_pledge(
|
|
key: VestingAccountStorageKey,
|
|
storage: &dyn Storage,
|
|
) -> Result<Option<PledgeData>, VestingContractError> {
|
|
Ok(GATEWAY_PLEDGES.may_load(storage, key).unwrap_or(None))
|
|
}
|
|
|
|
pub fn save_gateway_pledge(
|
|
key: VestingAccountStorageKey,
|
|
value: &PledgeData,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
GATEWAY_PLEDGES.save(storage, key, value)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn remove_gateway_pledge(
|
|
key: VestingAccountStorageKey,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
GATEWAY_PLEDGES.remove(storage, key);
|
|
Ok(())
|
|
}
|
|
|
|
pub fn save_account(
|
|
account: &Account,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
ACCOUNTS.save(storage, account.owner_address(), account)?;
|
|
Ok(())
|
|
}
|
|
|
|
pub fn load_account(
|
|
address: Addr,
|
|
storage: &dyn Storage,
|
|
) -> Result<Option<Account>, VestingContractError> {
|
|
Ok(ACCOUNTS.may_load(storage, address).unwrap_or(None))
|
|
}
|
|
|
|
pub fn delete_account(
|
|
address: Addr,
|
|
storage: &mut dyn Storage,
|
|
) -> Result<(), VestingContractError> {
|
|
ACCOUNTS.remove(storage, address);
|
|
Ok(())
|
|
}
|
|
|
|
fn validate_account(address: Addr, storage: &dyn Storage) -> Result<Account, VestingContractError> {
|
|
load_account(address.clone(), storage)?
|
|
.ok_or_else(|| VestingContractError::NoAccountForAddress(address.into_string()))
|
|
}
|
|
|
|
pub fn account_from_address(
|
|
address: &str,
|
|
storage: &dyn Storage,
|
|
api: &dyn Api,
|
|
) -> Result<Account, VestingContractError> {
|
|
validate_account(api.addr_validate(address)?, storage)
|
|
}
|