diff --git a/Cargo.lock b/Cargo.lock index b03ada80e..5896180de 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -589,10 +589,11 @@ dependencies = [ "astroport 4.0.0", "cosmwasm-schema", "cosmwasm-std", + "cw-multi-test 0.20.0 (git+https://github.com/astroport-fi/cw-multi-test?branch=feat/bank_with_send_hooks)", "cw-storage-plus 1.2.0", "cw2 1.1.2", - "osmosis-std", - "osmosis-test-tube", + "neutron-sdk", + "neutron-test-tube", "test-tube", "thiserror", ] @@ -1152,7 +1153,7 @@ dependencies = [ [[package]] name = "cw-multi-test" version = "0.20.0" -source = "git+https://github.com/astroport-fi/cw-multi-test?branch=feat/bank_with_send_hooks#80ebf1aff909d5438fff093b6243c5d7cbf924b3" +source = "git+https://github.com/astroport-fi/cw-multi-test?branch=feat/bank_with_send_hooks#3220f4cd126b5a8da2ce8b00152afef046a9b391" dependencies = [ "anyhow", "bech32 0.9.1", @@ -2017,15 +2018,6 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" -dependencies = [ - "either", -] - [[package]] name = "itertools" version = "0.12.1" @@ -2188,6 +2180,23 @@ dependencies = [ "thiserror", ] +[[package]] +name = "neutron-test-tube" +version = "0.1.0" +source = "git+https://github.com/j0nl1/neutron-test-tube#7b478ebc5e8bd4a6fb5df8655a5d4028d90d00d9" +dependencies = [ + "base64", + "bindgen", + "cosmrs", + "cosmwasm-std", + "neutron-sdk", + "prost 0.12.3", + "serde", + "serde_json", + "test-tube", + "thiserror", +] + [[package]] name = "nom" version = "7.1.3" @@ -2352,24 +2361,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "osmosis-test-tube" -version = "21.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a528c942d25d3159634f77953ca0e16c5a450fc44578ad922320128e4025fd" -dependencies = [ - "base64", - "bindgen", - "cosmrs", - "cosmwasm-std", - "osmosis-std", - "prost 0.12.3", - "serde", - "serde_json", - "test-tube", - "thiserror", -] - [[package]] name = "parking_lot" version = "0.12.1" @@ -2589,7 +2580,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" dependencies = [ "anyhow", - "itertools 0.11.0", + "itertools 0.10.5", "proc-macro2", "quote", "syn 2.0.48", @@ -3597,14 +3588,12 @@ dependencies = [ [[package]] name = "test-tube" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17f30e7fea966bde5f9933a4cb2db79dd272115ea19d1656da2aac7ce0700fa" +version = "0.5.0" +source = "git+https://github.com/j0nl1/neutron-test-tube#7b478ebc5e8bd4a6fb5df8655a5d4028d90d00d9" dependencies = [ "base64", "cosmrs", "cosmwasm-std", - "osmosis-std", "prost 0.12.3", "serde", "serde_json", diff --git a/contracts/periphery/tokenfactory_tracker/Cargo.toml b/contracts/periphery/tokenfactory_tracker/Cargo.toml index b0a5463ef..8001b0be8 100644 --- a/contracts/periphery/tokenfactory_tracker/Cargo.toml +++ b/contracts/periphery/tokenfactory_tracker/Cargo.toml @@ -11,13 +11,14 @@ crate-type = ["cdylib", "rlib"] [dependencies] cw2.workspace = true -cosmwasm-std.workspace = true +cosmwasm-std = { workspace = true, features = ["cosmwasm_1_1"] } cw-storage-plus.workspace = true cosmwasm-schema.workspace = true thiserror.workspace = true astroport = { path = "../../../packages/astroport", version = "4" } [dev-dependencies] -osmosis-std = "0.21" -osmosis-test-tube = "21.0.0" -test-tube = "0.3.0" +cw-multi-test = { git = "https://github.com/astroport-fi/cw-multi-test", branch = "feat/bank_with_send_hooks", features = ["cosmwasm_1_1"] } +neutron-sdk = "0.8.0" +neutron-test-tube = { git = "https://github.com/j0nl1/neutron-test-tube" } +test-tube = { git = "https://github.com/j0nl1/neutron-test-tube" } diff --git a/contracts/periphery/tokenfactory_tracker/src/contract.rs b/contracts/periphery/tokenfactory_tracker/src/contract.rs index 241b39928..591d74a3b 100644 --- a/contracts/periphery/tokenfactory_tracker/src/contract.rs +++ b/contracts/periphery/tokenfactory_tracker/src/contract.rs @@ -1,6 +1,6 @@ #[cfg(not(feature = "library"))] use cosmwasm_std::entry_point; -use cosmwasm_std::{DepsMut, Env, MessageInfo, Response, StdError, Storage, Uint128}; +use cosmwasm_std::{DepsMut, Env, MessageInfo, Response, Uint128}; use cw2::set_contract_version; use astroport::asset::validate_native_denom; @@ -59,7 +59,7 @@ pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result Result Result { - // If the token is minted directly to an address, we don't need to subtract - // as the sender is the module address - if from.ne(&config.m) { - BALANCES.update::<_, StdError>(storage, &from, block_seconds, |balance| { - Ok(balance.unwrap_or_default().checked_sub(amount)?) - })?; - } else { - // Minted new tokens - TOTAL_SUPPLY_HISTORY.update::<_, StdError>(storage, block_seconds, |balance| { - Ok(balance.unwrap_or_default().checked_add(amount)?) - })?; - } + if from != to { + if from != config.m { + let from_balance = deps.querier.query_balance(&from, &config.d)?.amount; + BALANCES.save( + deps.storage, + &from, + &from_balance.checked_sub(amount)?, + block_seconds, + )?; + } - // When burning tokens, the receiver is the token factory module address - // Sending tokens to the module address isn't allowed by the chain - if to.ne(&config.m) { - BALANCES.update::<_, StdError>(storage, &to, block_seconds, |balance| { - Ok(balance.unwrap_or_default().checked_add(amount)?) - })?; - } else { - // Burned tokens - TOTAL_SUPPLY_HISTORY.update::<_, StdError>(storage, block_seconds, |balance| { - Ok(balance.unwrap_or_default().checked_sub(amount)?) - })?; + if to != config.m { + let to_balance = deps.querier.query_balance(&to, &config.d)?.amount; + BALANCES.save( + deps.storage, + &to, + &to_balance.checked_add(amount)?, + block_seconds, + )?; + } } + let total_supply = deps.querier.query_supply(&config.d)?.amount; + TOTAL_SUPPLY_HISTORY.save(deps.storage, &total_supply, block_seconds)?; + Ok(Response::default()) } @@ -131,10 +128,11 @@ pub fn track_balances( mod tests { use cosmwasm_std::testing::mock_dependencies; use cosmwasm_std::{ - from_json, + coins, testing::{mock_env, mock_info}, - to_json_binary, Coin, Uint128, + to_json_binary, Addr, BankMsg, Coin, Uint128, }; + use cw_multi_test::{App, BankSudo, ContractWrapper, Executor}; use astroport::tokenfactory_tracker::QueryMsg; @@ -155,9 +153,12 @@ mod tests { #[test] fn track_token_balances() { - let mut deps = mock_dependencies(); - let mut env = mock_env(); - let info = mock_info(OWNER, &[]); + let mut app = App::new(|router, _, store| { + router + .bank + .init_balance(store, &Addr::unchecked(MODULE_ADDRESS), coins(200, DENOM)) + .unwrap(); + }); let operations = vec![ // Simulate a mint @@ -201,110 +202,135 @@ mod tests { let expected_user4_balance = Uint128::from(1u128); let expected_total_supply = Uint128::from(101u128); - instantiate( - deps.as_mut(), - env.clone(), - info, - InstantiateMsg { - tokenfactory_module_address: MODULE_ADDRESS.to_string(), - tracked_denom: DENOM.to_string(), - }, + // setup tracker contract + let tracker_code_id = app.store_code(Box::new( + ContractWrapper::new_with_empty(instantiate, instantiate, query).with_sudo_empty(sudo), + )); + let tracker_contract = app + .instantiate_contract( + tracker_code_id, + Addr::unchecked(OWNER), + &InstantiateMsg { + tokenfactory_module_address: MODULE_ADDRESS.to_string(), + tracked_denom: DENOM.to_string(), + }, + &[], + "label", + None, + ) + .unwrap(); + app.sudo( + BankSudo::SetHook { + denom: DENOM.to_string(), + contract_addr: tracker_contract.to_string(), + } + .into(), ) .unwrap(); for TestOperation { from, to, amount } in operations { - sudo( - deps.as_mut(), - env.clone(), - SudoMsg::BlockBeforeSend { - from, - to, - amount: Coin { - denom: DENOM.to_string(), - amount, - }, - }, + app.send_tokens( + Addr::unchecked(&from), + Addr::unchecked(&to), + &coins(amount.u128(), DENOM), ) .unwrap(); } - env.block.time = env.block.time.plus_seconds(10); - - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::BalanceAt { - address: "user1".to_string(), - timestamp: Some(env.block.time.seconds()), - }, - ) - .unwrap(); - assert_eq!(balance, to_json_binary(&expected_user1_balance).unwrap()); - - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::BalanceAt { - address: "user2".to_string(), - timestamp: Some(env.block.time.seconds()), - }, - ) - .unwrap(); - assert_eq!(balance, to_json_binary(&expected_user2_balance).unwrap()); - - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::BalanceAt { - address: "user3".to_string(), - timestamp: Some(env.block.time.seconds()), - }, + // burn everything from module balance + let amount = app.wrap().query_all_balances(MODULE_ADDRESS).unwrap(); + app.execute( + Addr::unchecked(MODULE_ADDRESS), + BankMsg::Burn { amount }.into(), ) .unwrap(); - assert_eq!(balance, to_json_binary(&expected_user3_balance).unwrap()); - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::BalanceAt { - address: "user3".to_string(), - timestamp: None, - }, - ) - .unwrap(); - assert_eq!(balance, to_json_binary(&expected_user3_balance).unwrap()); + // send coin to trigger total supply update + let user = Addr::unchecked("user4"); + app.send_tokens(user.clone(), user, &coins(1, DENOM)) + .unwrap(); - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::BalanceAt { - address: "user4".to_string(), - timestamp: None, - }, - ) - .unwrap(); - assert_eq!(balance, to_json_binary(&expected_user4_balance).unwrap()); + let query_at_ts = app.block_info().time.seconds() + 10; - let balance = query( - deps.as_ref(), - env.clone(), - QueryMsg::TotalSupplyAt { - timestamp: Some(env.block.time.seconds()), - }, - ) - .unwrap(); - assert_eq!( - from_json::(&balance).unwrap(), - expected_total_supply - ); + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::BalanceAt { + address: "user1".to_string(), + timestamp: Some(query_at_ts), + }, + ) + .unwrap(); + assert_eq!(balance, expected_user1_balance); + + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::BalanceAt { + address: "user2".to_string(), + timestamp: Some(query_at_ts), + }, + ) + .unwrap(); + assert_eq!(balance, expected_user2_balance); + + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::BalanceAt { + address: "user3".to_string(), + timestamp: Some(query_at_ts), + }, + ) + .unwrap(); + assert_eq!(balance, expected_user3_balance); + + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::BalanceAt { + address: "user3".to_string(), + timestamp: None, + }, + ) + .unwrap(); + assert_eq!(balance, expected_user3_balance); + + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::BalanceAt { + address: "user4".to_string(), + timestamp: None, + }, + ) + .unwrap(); + assert_eq!(balance, expected_user4_balance); + + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::TotalSupplyAt { + timestamp: Some(query_at_ts), + }, + ) + .unwrap(); + assert_eq!(balance, expected_total_supply); - let balance = query( - deps.as_ref(), - env, - QueryMsg::TotalSupplyAt { timestamp: None }, - ) - .unwrap(); - assert_eq!(balance, to_json_binary(&expected_total_supply).unwrap()); + let balance: Uint128 = app + .wrap() + .query_wasm_smart( + &tracker_contract, + &QueryMsg::TotalSupplyAt { timestamp: None }, + ) + .unwrap(); + assert_eq!(balance, expected_total_supply); } #[test] diff --git a/contracts/periphery/tokenfactory_tracker/src/error.rs b/contracts/periphery/tokenfactory_tracker/src/error.rs index f207b03f2..c44944c34 100644 --- a/contracts/periphery/tokenfactory_tracker/src/error.rs +++ b/contracts/periphery/tokenfactory_tracker/src/error.rs @@ -1,4 +1,4 @@ -use cosmwasm_std::StdError; +use cosmwasm_std::{OverflowError, StdError}; use thiserror::Error; #[derive(Error, Debug, PartialEq)] @@ -6,6 +6,9 @@ pub enum ContractError { #[error("{0}")] Std(#[from] StdError), + #[error("{0}")] + OverflowError(#[from] OverflowError), + #[error("Invalid denom, expected {expected_denom}")] InvalidDenom { expected_denom: String }, } diff --git a/contracts/periphery/tokenfactory_tracker/tests/test_data/astroport_tokenfactory_tracker.wasm b/contracts/periphery/tokenfactory_tracker/tests/test_data/astroport_tokenfactory_tracker.wasm index 94673544b..14aad91d3 100644 Binary files a/contracts/periphery/tokenfactory_tracker/tests/test_data/astroport_tokenfactory_tracker.wasm and b/contracts/periphery/tokenfactory_tracker/tests/test_data/astroport_tokenfactory_tracker.wasm differ diff --git a/contracts/periphery/tokenfactory_tracker/tests/tube-based-e2e.rs b/contracts/periphery/tokenfactory_tracker/tests/tube-based-e2e.rs index a50b99fa7..25c7e5d73 100644 --- a/contracts/periphery/tokenfactory_tracker/tests/tube-based-e2e.rs +++ b/contracts/periphery/tokenfactory_tracker/tests/tube-based-e2e.rs @@ -1,41 +1,50 @@ use std::collections::HashMap; use cosmwasm_std::{coin, Uint128}; -use osmosis_std::types::cosmos::auth::v1beta1::{ - ModuleAccount, QueryModuleAccountByNameRequest, QueryModuleAccountByNameResponse, +use neutron_sdk::proto_types::osmosis::tokenfactory::v1beta1::{ + MsgBurn, MsgCreateDenom, MsgMint, MsgSetBeforeSendHook, MsgSetBeforeSendHookResponse, +}; +use neutron_test_tube::cosmrs::proto::cosmos::bank::v1beta1::{ + MsgSend, MsgSendResponse, QueryBalanceRequest, }; -use osmosis_std::types::cosmos::bank::v1beta1::{MsgSend, QueryBalanceRequest}; -use osmosis_std::types::cosmos::base::v1beta1::Coin; -use osmosis_std::types::osmosis::tokenfactory::v1beta1::{ - MsgBurn, MsgMint, MsgSetBeforeSendHook, MsgSetBeforeSendHookResponse, +use neutron_test_tube::cosmrs::proto::prost::Message; +use neutron_test_tube::{Bank, NeutronTestApp, TokenFactory, Wasm}; +use test_tube::cosmrs::proto::cosmos::auth::v1beta1::{ + ModuleAccount, QueryModuleAccountByNameRequest, QueryModuleAccountByNameResponse, }; -use osmosis_test_tube::osmosis_std::types::osmosis::tokenfactory::v1beta1::MsgCreateDenom; -use osmosis_test_tube::{OsmosisTestApp, TokenFactory}; -use test_tube::{Account, Bank, Module, Runner, RunnerResult, SigningAccount, Wasm}; +use test_tube::cosmrs::proto::cosmos::base::v1beta1::Coin; +use test_tube::{Account, Module, Runner, RunnerExecuteResult, RunnerResult, SigningAccount}; use astroport::tokenfactory_tracker::{InstantiateMsg, QueryMsg}; const TRACKER_WASM: &str = "./tests/test_data/astroport_tokenfactory_tracker.wasm"; +fn proto_coin(amount: u128, denom: &str) -> Coin { + Coin { + denom: denom.to_string(), + amount: amount.to_string(), + } +} + struct TestSuite<'a> { - wasm: Wasm<'a, OsmosisTestApp>, - bank: Bank<'a, OsmosisTestApp>, - tf: TokenFactory<'a, OsmosisTestApp>, + wasm: Wasm<'a, NeutronTestApp>, + bank: Bank<'a, NeutronTestApp>, + tf: TokenFactory<'a, NeutronTestApp>, owner: SigningAccount, tokenfactory_module_address: String, } impl<'a> TestSuite<'a> { - fn new(app: &'a OsmosisTestApp) -> Self { + fn new(app: &'a NeutronTestApp) -> Self { let wasm = Wasm::new(app); let bank = Bank::new(app); let tf = TokenFactory::new(app); let signer = app - .init_account(&[coin(1_500_000e6 as u128, "uosmo")]) + .init_account(&[coin(1_500_000e6 as u128, "untrn")]) .unwrap(); - let ModuleAccount { base_account, .. } = app - .query::( + let module_account = ModuleAccount::decode( + app.query::( "/cosmos.auth.v1beta1.Query/ModuleAccountByName", &QueryModuleAccountByNameRequest { name: "tokenfactory".to_string(), @@ -44,15 +53,17 @@ impl<'a> TestSuite<'a> { .unwrap() .account .unwrap() - .try_into() - .unwrap(); + .value + .as_slice(), + ) + .unwrap(); Self { wasm, bank, tf, owner: signer, - tokenfactory_module_address: base_account.unwrap().address, + tokenfactory_module_address: module_account.base_account.unwrap().address, } } @@ -75,6 +86,8 @@ impl<'a> TestSuite<'a> { fn mint(&self, denom: &str, amount: impl Into, to: &str) { let amount: Uint128 = amount.into(); + + // Pass through minter self.tf .mint( MsgMint { @@ -83,11 +96,54 @@ impl<'a> TestSuite<'a> { denom: denom.to_string(), amount: amount.to_string(), }), - mint_to_address: to.to_string(), + mint_to_address: self.owner.address(), }, &self.owner, ) .unwrap(); + + // Send to user + self.send( + &self.owner, + to.to_string(), + proto_coin(amount.u128(), denom), + ) + .unwrap(); + } + + fn burn(&self, denom: &str, amount: impl Into) { + let amount: Uint128 = amount.into(); + + self.tf + .burn( + MsgBurn { + sender: self.owner.address(), + amount: Some(proto_coin(amount.u128(), &denom)), + burn_from_address: self.owner.address(), + }, + &self.owner, + ) + .unwrap(); + + // Trigger hook + self.send(&self.owner, self.owner.address(), proto_coin(1, denom)) + .unwrap(); + } + + fn send( + &self, + signer: &SigningAccount, + to_address: String, + amount: Coin, + ) -> RunnerExecuteResult { + self.bank.send( + MsgSend { + from_address: signer.address(), + to_address, + amount: vec![amount], + }, + signer, + ) } fn instantiate_tracker(&self, denom: &str) -> String { @@ -112,15 +168,15 @@ impl<'a> TestSuite<'a> { tracker_addr } - fn set_before_send_hook(&self, denom: &str, tracker_addr: &str, app: &OsmosisTestApp) { + fn set_before_send_hook(&self, denom: &str, tracker_addr: &str, app: &NeutronTestApp) { let set_hook_msg = MsgSetBeforeSendHook { sender: self.owner.address(), denom: denom.to_string(), - cosmwasm_address: tracker_addr.to_string(), + contract_addr: tracker_addr.to_string(), }; app.execute::<_, MsgSetBeforeSendHookResponse>( set_hook_msg, - MsgSetBeforeSendHook::TYPE_URL, + "/osmosis.tokenfactory.v1beta1.MsgSetBeforeSendHook", &self.owner, ) .unwrap(); @@ -149,7 +205,7 @@ impl<'a> TestSuite<'a> { #[test] fn ensure_tracking_on_mint() { - let app = OsmosisTestApp::new(); + let app = NeutronTestApp::new(); let ts = TestSuite::new(&app); let denom = ts.create_denom("test"); @@ -190,7 +246,7 @@ fn ensure_tracking_on_mint() { #[test] fn ensure_tracking_on_send() { - let app = OsmosisTestApp::new(); + let app = NeutronTestApp::new(); let ts = TestSuite::new(&app); let denom = ts.create_denom("test"); let tracker_addr = ts.instantiate_tracker(&denom); @@ -205,15 +261,7 @@ fn ensure_tracking_on_send() { assert_eq!(balance_before.u128(), 0u128); // Send owner -> user - ts.bank - .send( - MsgSend { - from_address: ts.owner.address(), - to_address: user.address(), - amount: vec![coin(1000u128, &denom).into()], - }, - &ts.owner, - ) + ts.send(&ts.owner, user.address(), proto_coin(1000u128, &denom)) .unwrap(); app.increase_time(10); @@ -238,47 +286,44 @@ fn ensure_tracking_on_send() { #[test] fn ensure_tracking_on_burn() { - let app = OsmosisTestApp::new(); + let app = NeutronTestApp::new(); let ts = TestSuite::new(&app); let denom = ts.create_denom("test"); let tracker_addr = ts.instantiate_tracker(&denom); ts.set_before_send_hook(&denom, &tracker_addr, &app); - // Mint tokens to owner - ts.mint(&denom, 1000u128, &ts.owner.address()); + let user = app + .init_account(&[coin(1_500_000e6 as u128, "untrn")]) + .unwrap(); + + // Mint tokens to user + ts.mint(&denom, 1000u128, &user.address()); + + // Mint 1 token to owner to be able to trigger hook on burn + ts.mint(&denom, 1u128, &ts.owner.address()); app.increase_time(10); - let balance_before = ts - .balance_at(&tracker_addr, &ts.owner.address(), None) - .unwrap(); + let balance_before = ts.balance_at(&tracker_addr, &user.address(), None).unwrap(); assert_eq!(balance_before.u128(), 1000u128); - // Burn from owner - ts.tf - .burn( - MsgBurn { - sender: ts.owner.address(), - amount: Some(coin(1000u128, &denom).into()), - burn_from_address: ts.owner.address(), - }, - &ts.owner, - ) + // Send back to minter + ts.send(&user, ts.owner.address(), proto_coin(1000u128, &denom)) .unwrap(); + // Burn from minter + ts.burn(&denom, 1000u128); app.increase_time(10); - let balance_after = ts - .balance_at(&tracker_addr, &ts.owner.address(), None) - .unwrap(); + let balance_after = ts.balance_at(&tracker_addr, &user.address(), None).unwrap(); assert_eq!(balance_after.u128(), 0u128); let supply_after = ts.supply_at(&tracker_addr, None).unwrap(); - assert_eq!(supply_after.u128(), 0u128); + assert_eq!(supply_after.u128(), 1u128); } #[test] fn ensure_sending_to_module_prohibited() { - let app = OsmosisTestApp::new(); + let app = NeutronTestApp::new(); let ts = TestSuite::new(&app); let denom = ts.create_denom("test"); let tracker_addr = ts.instantiate_tracker(&denom); @@ -289,14 +334,10 @@ fn ensure_sending_to_module_prohibited() { // Send owner -> tokenfactory module address let err = ts - .bank .send( - MsgSend { - from_address: ts.owner.address(), - to_address: ts.tokenfactory_module_address.clone(), - amount: vec![coin(1000u128, &denom).into()], - }, &ts.owner, + ts.tokenfactory_module_address.clone(), + proto_coin(1000u128, &denom), ) .unwrap_err(); @@ -311,7 +352,7 @@ fn ensure_sending_to_module_prohibited() { #[test] fn test_historical_queries() { - let app = OsmosisTestApp::new(); + let app = NeutronTestApp::new(); let ts = TestSuite::new(&app); let denom = ts.create_denom("test"); diff --git a/contracts/tokenomics/staking/src/contract.rs b/contracts/tokenomics/staking/src/contract.rs index e3cedaf68..a33a0fd53 100644 --- a/contracts/tokenomics/staking/src/contract.rs +++ b/contracts/tokenomics/staking/src/contract.rs @@ -304,18 +304,27 @@ fn execute_leave(deps: DepsMut, env: Env, info: MessageInfo) -> Result = vec![ + // Burn the received xASTRO tokens + MsgBurn { + sender: env.contract.address.to_string(), + amount: Some(coin(amount.u128(), &config.xastro_denom).into()), + burn_from_address: "".to_string(), // This needs to be "" for now + } + .into(), + // Send ASTRO to the sender + BankMsg::Send { + to_address: info.sender.to_string(), + amount: vec![coin(return_amount.u128(), config.astro_denom)], + } + .into(), + // Send xASTRO to itself to trigger total supply snapshot in tracker contract + BankMsg::Send { + to_address: env.contract.address.to_string(), + amount: vec![coin(1, &config.xastro_denom)], + } + .into(), + ]; // Set the data to be returned in set_data to easy integration with // other contracts @@ -325,8 +334,7 @@ fn execute_leave(deps: DepsMut, env: Env, info: MessageInfo) -> Result