From 7eb44d23bb41b042c9344309b0545935429ec6d7 Mon Sep 17 00:00:00 2001 From: varun-doshi Date: Fri, 14 Mar 2025 14:42:25 +0530 Subject: [PATCH] feat: use Uint256 for Coin --- packages/std/src/coin.rs | 33 ++++++++++++++---------- packages/std/src/coins.rs | 26 +++++++++---------- packages/std/src/math/uint256.rs | 8 ++++++ packages/std/src/testing/message_info.rs | 2 +- packages/std/src/testing/mock.rs | 12 +++++---- packages/std/src/traits.rs | 4 +-- packages/vm/src/instance.rs | 12 ++++----- 7 files changed, 56 insertions(+), 41 deletions(-) diff --git a/packages/std/src/coin.rs b/packages/std/src/coin.rs index c0c055b37d..1c87ed86ce 100644 --- a/packages/std/src/coin.rs +++ b/packages/std/src/coin.rs @@ -4,16 +4,16 @@ use serde::{Deserialize, Serialize}; use crate::prelude::*; use crate::CoinFromStrError; -use crate::Uint128; +use crate::Uint256; #[derive(Serialize, Deserialize, Clone, Default, PartialEq, Eq, JsonSchema)] pub struct Coin { pub denom: String, - pub amount: Uint128, + pub amount: Uint256, } impl Coin { - pub fn new(amount: impl Into, denom: impl Into) -> Self { + pub fn new(amount: impl Into, denom: impl Into) -> Self { Coin { amount: amount.into(), denom: denom.into(), @@ -113,12 +113,14 @@ pub fn has_coins(coins: &[Coin], required: &Coin) -> bool { #[cfg(test)] mod tests { + use crate::uint256; + use super::*; #[test] fn coin_implements_display() { let a = Coin { - amount: Uint128::new(123), + amount: Uint256::new(123), denom: "ucosm".to_string(), }; @@ -133,7 +135,7 @@ mod tests { assert_eq!( a, Coin { - amount: Uint128::new(123), + amount: Uint256::new(123), denom: "ucosm".to_string() } ); @@ -142,7 +144,7 @@ mod tests { assert_eq!( zero, Coin { - amount: Uint128::new(0), + amount: Uint256::new(0), denom: "ucosm".to_string() } ); @@ -151,7 +153,7 @@ mod tests { assert_eq!( string_denom, Coin { - amount: Uint128::new(42), + amount: Uint256::new(42), denom: "ucosm".to_string() } ); @@ -163,7 +165,7 @@ mod tests { assert_eq!( a, vec![Coin { - amount: Uint128::new(123), + amount: Uint256::new(123), denom: "ucosm".to_string() }] ); @@ -172,7 +174,7 @@ mod tests { assert_eq!( zero, vec![Coin { - amount: Uint128::new(0), + amount: Uint256::new(0), denom: "ucosm".to_string() }] ); @@ -181,7 +183,7 @@ mod tests { assert_eq!( string_denom, vec![Coin { - amount: Uint128::new(42), + amount: Uint256::new(42), denom: "ucosm".to_string() }] ); @@ -197,16 +199,19 @@ mod tests { #[test] fn parse_coin() { - let expected = Coin::new(123u128, "ucosm"); + let expected = Coin::new(uint256!(123u128), "ucosm"); assert_eq!("123ucosm".parse::().unwrap(), expected); // leading zeroes should be ignored assert_eq!("00123ucosm".parse::().unwrap(), expected); // 0 amount parses correctly - assert_eq!("0ucosm".parse::().unwrap(), Coin::new(0u128, "ucosm")); + assert_eq!( + "0ucosm".parse::().unwrap(), + Coin::new(uint256!(0u128), "ucosm") + ); // ibc denom should work let ibc_str = "11111ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2"; let ibc_coin = Coin::new( - 11111u128, + uint256!(11111u128), "ibc/27394FB092D2ECCD56123C74F36E4C1F926001CEADA9CA97EA622B25F41E5EB2", ); assert_eq!(ibc_str.parse::().unwrap(), ibc_coin); @@ -246,7 +251,7 @@ mod tests { #[test] fn debug_coin() { - let coin = Coin::new(123u128, "ucosm"); + let coin = Coin::new(uint256!(123u128), "ucosm"); assert_eq!(format!("{coin:?}"), r#"Coin { 123 "ucosm" }"#); } } diff --git a/packages/std/src/coins.rs b/packages/std/src/coins.rs index 530bdbcfd3..6d2e09e194 100644 --- a/packages/std/src/coins.rs +++ b/packages/std/src/coins.rs @@ -2,7 +2,7 @@ use alloc::collections::BTreeMap; use core::fmt; use core::str::FromStr; -use crate::prelude::*; +use crate::{prelude::*, Uint256}; use crate::{Coin, CoinsError, OverflowError, OverflowOperation, StdError, StdResult, Uint128}; /// A collection of coins, similar to Cosmos SDK's `sdk.Coins` struct. @@ -133,11 +133,11 @@ impl Coins { } /// Returns the amount of the given denom or zero if the denom is not present. - pub fn amount_of(&self, denom: &str) -> Uint128 { + pub fn amount_of(&self, denom: &str) -> Uint256 { self.0 .get(denom) .map(|c| c.amount) - .unwrap_or_else(Uint128::zero) + .unwrap_or_else(Uint256::zero) } /// Returns the amount of the given denom if and only if this collection contains only @@ -159,7 +159,7 @@ impl Coins { /// let coins: Coins = [coin(100, "uatom"), coin(200, "uusd")].try_into().unwrap(); /// assert_eq!(coins.contains_only("uatom"), None); /// ``` - pub fn contains_only(&self, denom: &str) -> Option { + pub fn contains_only(&self, denom: &str) -> Option { if self.len() == 1 { self.0.get(denom).map(|c| c.amount) } else { @@ -398,14 +398,14 @@ mod tests { fn handling_zero_amount() { // create a Vec that contains zero amounts let mut vec = mock_vec(); - vec[0].amount = Uint128::zero(); + vec[0].amount = Uint256::zero(); let coins = Coins::try_from(vec).unwrap(); assert_eq!(coins.len(), 2); - assert_ne!(coins.amount_of("ibc/1234ABCD"), Uint128::zero()); + assert_ne!(coins.amount_of("ibc/1234ABCD"), Uint256::zero()); assert_ne!( coins.amount_of("factory/osmo1234abcd/subdenom"), - Uint128::zero() + Uint256::zero() ); // adding a coin with zero amount should not be added @@ -432,7 +432,7 @@ mod tests { // existing denom coins.add(coin(12345, "uatom")).unwrap(); assert_eq!(coins.len(), 3); - assert_eq!(coins.amount_of("uatom").u128(), 24690); + assert_eq!(coins.amount_of("uatom"), Uint256::new(24690)); // new denom coins.add(coin(123, "uusd")).unwrap(); @@ -440,7 +440,7 @@ mod tests { // zero amount coins.add(coin(0, "uusd")).unwrap(); - assert_eq!(coins.amount_of("uusd").u128(), 123); + assert_eq!(coins.amount_of("uusd"), Uint256::new(123)); // zero amount, new denom coins.add(coin(0, "utest")).unwrap(); @@ -462,7 +462,7 @@ mod tests { // partial sub coins.sub(coin(1, "uatom")).unwrap(); assert_eq!(coins.len(), 1); - assert_eq!(coins.amount_of("uatom").u128(), 12344); + assert_eq!(coins.amount_of("uatom"), Uint256::new(12344)); // full sub coins.sub(coin(12344, "uatom")).unwrap(); @@ -476,7 +476,7 @@ mod tests { // sub zero, non-existent denom coins.sub(coin(0, "uatom")).unwrap(); assert_eq!(coins.len(), 1); - assert_eq!(coins.amount_of("uatom").u128(), 12345); + assert_eq!(coins.amount_of("uatom"), Uint256::new(12345)); } #[test] @@ -488,7 +488,7 @@ mod tests { // happy path let coins = Coins::from(coin(12345, "uatom")); assert_eq!(coins.len(), 1); - assert_eq!(coins.amount_of("uatom").u128(), 12345); + assert_eq!(coins.amount_of("uatom"), Uint256::new(12345)); } #[test] @@ -524,6 +524,6 @@ mod tests { .eq(coins.to_vec().iter().map(|c| &c.denom))); // can still use the coins afterwards - assert_eq!(coins.amount_of("uatom").u128(), 12345); + assert_eq!(coins.amount_of("uatom"), Uint256::new(12345)); } } diff --git a/packages/std/src/math/uint256.rs b/packages/std/src/math/uint256.rs index e59e5de524..a7b29d560f 100644 --- a/packages/std/src/math/uint256.rs +++ b/packages/std/src/math/uint256.rs @@ -52,6 +52,14 @@ pub struct Uint256(#[schemars(with = "String")] pub(crate) U256); impl_int_serde!(Uint256); forward_ref_partial_eq!(Uint256, Uint256); +#[macro_export] +macro_rules! uint256 { + ($val:expr) => { + Uint256::from($val) + }; +} + + impl Uint256 { pub const MAX: Uint256 = Uint256(U256::MAX); pub const MIN: Uint256 = Uint256(U256::ZERO); diff --git a/packages/std/src/testing/message_info.rs b/packages/std/src/testing/message_info.rs index 39178ba8a4..a272d7d4e3 100644 --- a/packages/std/src/testing/message_info.rs +++ b/packages/std/src/testing/message_info.rs @@ -72,7 +72,7 @@ mod tests { MessageInfo { sender: addr.clone(), funds: vec![Coin { - amount: Uint128::new(123), + amount: crate::Uint256::new(123), denom: "foo".to_string(), }], } diff --git a/packages/std/src/testing/mock.rs b/packages/std/src/testing/mock.rs index ccb3bbe8ac..50ba81ec00 100644 --- a/packages/std/src/testing/mock.rs +++ b/packages/std/src/testing/mock.rs @@ -1,5 +1,7 @@ use crate::prelude::*; +use crate::uint256; use crate::HashFunction; +use crate::Uint256; use crate::{Addr, CanonicalAddr, Timestamp}; use alloc::collections::BTreeMap; #[cfg(feature = "cosmwasm_1_3")] @@ -757,7 +759,7 @@ impl Default for WasmQuerier { pub struct BankQuerier { #[allow(dead_code)] /// BTreeMap - supplies: BTreeMap, + supplies: BTreeMap, /// A map from address to balance. The address is the String conversion of `Addr`, /// i.e. the bech32 encoded address. balances: BTreeMap>, @@ -798,7 +800,7 @@ impl BankQuerier { .collect(); } - fn calculate_supplies(balances: &BTreeMap>) -> BTreeMap { + fn calculate_supplies(balances: &BTreeMap>) -> BTreeMap { let mut supplies = BTreeMap::new(); let all_coins = balances.iter().flat_map(|(_, coins)| coins); @@ -806,7 +808,7 @@ impl BankQuerier { for coin in all_coins { *supplies .entry(coin.denom.clone()) - .or_insert_with(Uint128::zero) += coin.amount; + .or_insert_with(Uint256::zero) += coin.amount; } supplies @@ -820,10 +822,10 @@ impl BankQuerier { .supplies .get(denom) .cloned() - .unwrap_or_else(Uint128::zero); + .unwrap_or_else(Uint256::zero); let bank_res = SupplyResponse { amount: Coin { - amount, + amount: uint256!(amount), denom: denom.to_string(), }, }; diff --git a/packages/std/src/traits.rs b/packages/std/src/traits.rs index aaadaaba81..79136221ad 100644 --- a/packages/std/src/traits.rs +++ b/packages/std/src/traits.rs @@ -665,7 +665,7 @@ mod tests { use super::*; use crate::testing::MockQuerier; - use crate::{coins, Uint128}; + use crate::{coins, Uint128, Uint256}; // this is a simple demo helper to prove we can use it fn demo_helper(_querier: &dyn Querier) -> u64 { @@ -702,7 +702,7 @@ mod tests { .unwrap() .unwrap(); let balance: BalanceResponse = from_json(raw).unwrap(); - assert_eq!(balance.amount.amount, Uint128::new(5)); + assert_eq!(balance.amount.amount, Uint256::new(5)); } #[cfg(feature = "cosmwasm_1_1")] diff --git a/packages/vm/src/instance.rs b/packages/vm/src/instance.rs index 1850dfced0..c39acd8271 100644 --- a/packages/vm/src/instance.rs +++ b/packages/vm/src/instance.rs @@ -542,7 +542,7 @@ mod tests { mock_instance_with_options, MockInstanceOptions, }; use cosmwasm_std::{ - coin, coins, from_json, AllBalanceResponse, BalanceResponse, BankQuery, Empty, QueryRequest, + coin, coins, from_json, AllBalanceResponse, BalanceResponse, BankQuery, Empty, QueryRequest, Uint256, }; use wasmer::FunctionEnvMut; @@ -1000,7 +1000,7 @@ mod tests { .unwrap() .unwrap(); let BalanceResponse { amount, .. } = from_json(response).unwrap(); - assert_eq!(amount.amount.u128(), 8000); + assert_eq!(amount.amount, Uint256::new(8000)); assert_eq!(amount.denom, "silver"); Ok(()) }) @@ -1022,9 +1022,9 @@ mod tests { .unwrap(); let AllBalanceResponse { amount, .. } = from_json(response).unwrap(); assert_eq!(amount.len(), 2); - assert_eq!(amount[0].amount.u128(), 10000); + assert_eq!(amount[0].amount, Uint256::new(10000)); assert_eq!(amount[0].denom, "gold"); - assert_eq!(amount[1].amount.u128(), 8000); + assert_eq!(amount[1].amount, Uint256::new(8000)); assert_eq!(amount[1].denom, "silver"); Ok(()) @@ -1056,7 +1056,7 @@ mod tests { .unwrap() .unwrap(); let BalanceResponse { amount, .. } = from_json(response).unwrap(); - assert_eq!(amount.amount.u128(), 500); + assert_eq!(amount.amount, Uint256::new(500)); Ok(()) }) .unwrap(); @@ -1085,7 +1085,7 @@ mod tests { .unwrap() .unwrap(); let BalanceResponse { amount, .. } = from_json(response).unwrap(); - assert_eq!(amount.amount.u128(), 8000); + assert_eq!(amount.amount, Uint256::new(8000)); Ok(()) }) .unwrap();