Files
nym/contracts/vesting/src/storage.rs
T
Jędrzej Stuczyński 33992542b1 feature: upgrade cosmwasm to 2.2 (#5479)
* 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...
2025-03-21 13:43:35 +00:00

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)
}