From daccce42f1c32100808baa9804facf5a21a6451b Mon Sep 17 00:00:00 2001 From: Noah Saso Date: Thu, 31 Oct 2024 13:12:12 -0400 Subject: [PATCH] added legacy NFT claim test --- .../src/testing/execute.rs | 25 +++ .../src/testing/tests.rs | 169 ++++++++++++++++- .../src/testing/execute.rs | 29 +++ .../src/testing/tests.rs | 172 +++++++++++++++++- 4 files changed, 392 insertions(+), 3 deletions(-) diff --git a/contracts/voting/dao-voting-cw721-staked/src/testing/execute.rs b/contracts/voting/dao-voting-cw721-staked/src/testing/execute.rs index 08a1b397a..a80b0b90c 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/testing/execute.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/testing/execute.rs @@ -117,6 +117,31 @@ pub fn claim_nfts(app: &mut App, module: &Addr, sender: &str) -> AnyResult AnyResult { + app.execute_contract( + addr!(sender), + module.clone(), + &ExecuteMsg::ClaimNfts { + token_ids: Some(token_ids.to_vec()), + }, + &[], + ) +} + +pub fn claim_legacy_nfts(app: &mut App, module: &Addr, sender: &str) -> AnyResult { + app.execute_contract( + addr!(sender), + module.clone(), + &ExecuteMsg::ClaimNfts { token_ids: None }, + &[], + ) +} + pub fn add_hook(app: &mut App, module: &Addr, sender: &str, hook: &str) -> AnyResult { app.execute_contract( addr!(sender), diff --git a/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs b/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs index b16fdbf43..7b690933a 100644 --- a/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs +++ b/contracts/voting/dao-voting-cw721-staked/src/testing/tests.rs @@ -1,8 +1,12 @@ +use cosmwasm_std::storage_keys::to_length_prefixed_nested; use cosmwasm_std::testing::{mock_dependencies, mock_env}; -use cosmwasm_std::{to_json_binary, Addr, Coin, Decimal, Empty, Uint128, WasmMsg}; +use cosmwasm_std::{ + to_json_binary, to_json_vec, Addr, Coin, Decimal, Empty, Storage, Uint128, WasmMsg, +}; use cw721_base::msg::{ExecuteMsg as Cw721ExecuteMsg, InstantiateMsg as Cw721InstantiateMsg}; use cw721_controllers::{NftClaim, NftClaimsResponse}; use cw_multi_test::{next_block, App, BankSudo, Executor, SudoMsg}; +use cw_storage_plus::Map; use cw_utils::Duration; use dao_interface::voting::IsActiveResponse; use dao_testing::contracts::{ @@ -10,6 +14,7 @@ use dao_testing::contracts::{ }; use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse}; +use crate::testing::execute::{claim_legacy_nfts, claim_specific_nfts}; use crate::{ contract::{migrate, CONTRACT_NAME, CONTRACT_VERSION}, msg::{ExecuteMsg, InstantiateMsg, MigrateMsg, NftContract, QueryMsg}, @@ -300,6 +305,168 @@ fn test_claims() -> anyhow::Result<()> { Ok(()) } +// I can query and claim my pending legacy claims and non-legacy claims. +#[test] +pub fn test_legacy_claims_work() -> anyhow::Result<()> { + let CommonTest { + mut app, + module, + nft, + } = setup_test(Some(Duration::Height(1))); + + mint_and_stake_nft(&mut app, &nft, &module, CREATOR_ADDR, "1")?; + mint_and_stake_nft(&mut app, &nft, &module, CREATOR_ADDR, "2")?; + mint_and_stake_nft(&mut app, &nft, &module, CREATOR_ADDR, "3")?; + mint_and_stake_nft(&mut app, &nft, &module, CREATOR_ADDR, "4")?; + mint_and_stake_nft(&mut app, &nft, &module, CREATOR_ADDR, "5")?; + + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!(claims.nft_claims, vec![]); + + let res = claim_legacy_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + + // insert legacy claims manually + + // taken from cw-multi-test's WasmKeeper::contract_storage in wasm.rs + let mut module_namespace = b"contract_data/".to_vec(); + module_namespace.extend_from_slice(module.as_bytes()); + let prefix = to_length_prefixed_nested(&[b"wasm", &module_namespace]); + let key = Map::<&Addr, Vec>::new("nft_claims").key(&Addr::unchecked(CREATOR_ADDR)); + let mut legacy_nft_claims_key = prefix; + legacy_nft_claims_key.extend_from_slice(&key); + + let block = app.block_info(); + app.storage_mut().set( + &legacy_nft_claims_key, + &to_json_vec(&vec![cw721_controllers_v250::NftClaim { + token_id: "4".to_string(), + release_at: Duration::Height(1).after(&block), + }]) + .unwrap(), + ); + + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "4".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + // claim now exists, but is not yet expired. Nothing to claim. + let res = claim_legacy_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + + app.update_block(next_block); + + // no non-legacy claims + let res = claim_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + + // legacy claim works + claim_legacy_nfts(&mut app, &module, CREATOR_ADDR).unwrap(); + let owner = query_nft_owner(&app, &nft, "4")?; + assert_eq!(owner.owner, CREATOR_ADDR.to_string()); + + // unstake non-legacy + unstake_nfts(&mut app, &module, CREATOR_ADDR, &["2"])?; + + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "2".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + // Claim now exists, but is not yet expired. Nothing to claim. + let res = claim_legacy_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + + app.update_block(next_block); + + // no legacy claims + let res = claim_legacy_nfts(&mut app, &module, CREATOR_ADDR); + is_error!(res => "Nothing to claim"); + + claim_nfts(&mut app, &module, CREATOR_ADDR)?; + + let owner = query_nft_owner(&app, &nft, "2")?; + assert_eq!(owner.owner, CREATOR_ADDR.to_string()); + + // unstake another non-legacy + unstake_nfts(&mut app, &module, CREATOR_ADDR, &["3"])?; + + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "3".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + app.update_block(next_block); + + claim_specific_nfts(&mut app, &module, CREATOR_ADDR, &["3".to_string()])?; + let owner = query_nft_owner(&app, &nft, "3")?; + assert_eq!(owner.owner, CREATOR_ADDR.to_string()); + + // unstake legacy + let block = app.block_info(); + app.storage_mut().set( + &legacy_nft_claims_key, + &to_json_vec(&vec![cw721_controllers_v250::NftClaim { + token_id: "5".to_string(), + release_at: Duration::Height(1).after(&block), + }]) + .unwrap(), + ); + // unstake non-legacy + unstake_nfts(&mut app, &module, CREATOR_ADDR, &["1"])?; + + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!( + claims.nft_claims, + vec![ + NftClaim { + token_id: "5".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }, + NftClaim { + token_id: "1".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + } + ] + ); + + app.update_block(next_block); + + // both claims should be ready to claim + claim_legacy_nfts(&mut app, &module, CREATOR_ADDR)?; + claim_nfts(&mut app, &module, CREATOR_ADDR)?; + + let owner = query_nft_owner(&app, &nft, "1")?; + assert_eq!(owner.owner, CREATOR_ADDR.to_string()); + let owner = query_nft_owner(&app, &nft, "5")?; + assert_eq!(owner.owner, CREATOR_ADDR.to_string()); + + // no claims left + let claims = query_claims(&app, &module, CREATOR_ADDR)?; + assert_eq!(claims.nft_claims, vec![]); + + Ok(()) +} + // I can list all of the currently staked NFTs for an address. #[test] fn test_list_staked_nfts() -> anyhow::Result<()> { diff --git a/contracts/voting/dao-voting-onft-staked/src/testing/execute.rs b/contracts/voting/dao-voting-onft-staked/src/testing/execute.rs index bef18ff42..2936f8fb7 100644 --- a/contracts/voting/dao-voting-onft-staked/src/testing/execute.rs +++ b/contracts/voting/dao-voting-onft-staked/src/testing/execute.rs @@ -205,6 +205,35 @@ pub fn claim_nfts(app: &mut OmniflixApp, module: &Addr, sender: &str) -> AnyResu ) } +pub fn claim_specific_nfts( + app: &mut OmniflixApp, + module: &Addr, + sender: &str, + token_ids: &[String], +) -> AnyResult { + app.execute_contract( + addr!(sender), + module.clone(), + &ExecuteMsg::ClaimNfts { + token_ids: Some(token_ids.to_vec()), + }, + &[], + ) +} + +pub fn claim_legacy_nfts( + app: &mut OmniflixApp, + module: &Addr, + sender: &str, +) -> AnyResult { + app.execute_contract( + addr!(sender), + module.clone(), + &ExecuteMsg::ClaimNfts { token_ids: None }, + &[], + ) +} + pub fn add_hook( app: &mut OmniflixApp, module: &Addr, diff --git a/contracts/voting/dao-voting-onft-staked/src/testing/tests.rs b/contracts/voting/dao-voting-onft-staked/src/testing/tests.rs index a906771db..2f120403a 100644 --- a/contracts/voting/dao-voting-onft-staked/src/testing/tests.rs +++ b/contracts/voting/dao-voting-onft-staked/src/testing/tests.rs @@ -1,13 +1,18 @@ +use cosmwasm_std::storage_keys::to_length_prefixed_nested; use cosmwasm_std::testing::{mock_dependencies, mock_env}; -use cosmwasm_std::{Addr, Decimal, Uint128}; +use cosmwasm_std::{to_json_vec, Addr, Decimal, Storage, Uint128}; use cw721_controllers::{NftClaim, NftClaimsResponse}; use cw_multi_test::{next_block, Executor}; +use cw_storage_plus::Map; use cw_utils::Duration; use dao_interface::voting::IsActiveResponse; use dao_voting::threshold::{ActiveThreshold, ActiveThresholdResponse}; use crate::msg::OnftCollection; -use crate::testing::execute::{cancel_stake, confirm_stake_nft, prepare_stake_nft, send_nft}; +use crate::testing::execute::{ + cancel_stake, claim_legacy_nfts, claim_specific_nfts, confirm_stake_nft, prepare_stake_nft, + send_nft, +}; use crate::testing::queries::query_dao; use crate::testing::DAO; use crate::{ @@ -293,6 +298,169 @@ fn test_claims() -> anyhow::Result<()> { Ok(()) } +// I can query and claim my pending legacy claims and non-legacy claims. +#[test] +pub fn test_legacy_claims_work() -> anyhow::Result<()> { + let CommonTest { + mut app, + module, + nft, + .. + } = setup_test(Some(Duration::Height(1)), None); + + mint_and_stake_nft(&mut app, &nft, &module, STAKER, "1")?; + mint_and_stake_nft(&mut app, &nft, &module, STAKER, "2")?; + mint_and_stake_nft(&mut app, &nft, &module, STAKER, "3")?; + mint_and_stake_nft(&mut app, &nft, &module, STAKER, "4")?; + mint_and_stake_nft(&mut app, &nft, &module, STAKER, "5")?; + + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!(claims.nft_claims, vec![]); + + let res = claim_legacy_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + + // insert legacy claims manually + + // taken from cw-multi-test's WasmKeeper::contract_storage in wasm.rs + let mut module_namespace = b"contract_data/".to_vec(); + module_namespace.extend_from_slice(module.as_bytes()); + let prefix = to_length_prefixed_nested(&[b"wasm", &module_namespace]); + let key = Map::<&Addr, Vec>::new("nft_claims").key(&Addr::unchecked(STAKER)); + let mut legacy_nft_claims_key = prefix; + legacy_nft_claims_key.extend_from_slice(&key); + + let block = app.block_info(); + app.storage_mut().set( + &legacy_nft_claims_key, + &to_json_vec(&vec![cw721_controllers_v250::NftClaim { + token_id: "4".to_string(), + release_at: Duration::Height(1).after(&block), + }]) + .unwrap(), + ); + + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "4".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + // claim now exists, but is not yet expired. Nothing to claim. + let res = claim_legacy_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + + app.update_block(next_block); + + // no non-legacy claims + let res = claim_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + + // legacy claim works + claim_legacy_nfts(&mut app, &module, STAKER).unwrap(); + let owner = query_nft_owner(&app, &nft, "4")?; + assert_eq!(owner, STAKER.to_string()); + + // unstake non-legacy + unstake_nfts(&mut app, &module, STAKER, &["2"])?; + + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "2".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + // Claim now exists, but is not yet expired. Nothing to claim. + let res = claim_legacy_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + let res = claim_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + + app.update_block(next_block); + + // no legacy claims + let res = claim_legacy_nfts(&mut app, &module, STAKER); + is_error!(res => "Nothing to claim"); + + claim_nfts(&mut app, &module, STAKER)?; + + let owner = query_nft_owner(&app, &nft, "2")?; + assert_eq!(owner, STAKER.to_string()); + + // unstake another non-legacy + unstake_nfts(&mut app, &module, STAKER, &["3"])?; + + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!( + claims.nft_claims, + vec![NftClaim { + token_id: "3".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }] + ); + + app.update_block(next_block); + + claim_specific_nfts(&mut app, &module, STAKER, &["3".to_string()])?; + let owner = query_nft_owner(&app, &nft, "3")?; + assert_eq!(owner, STAKER.to_string()); + + // unstake legacy + let block = app.block_info(); + app.storage_mut().set( + &legacy_nft_claims_key, + &to_json_vec(&vec![cw721_controllers_v250::NftClaim { + token_id: "5".to_string(), + release_at: Duration::Height(1).after(&block), + }]) + .unwrap(), + ); + // unstake non-legacy + unstake_nfts(&mut app, &module, STAKER, &["1"])?; + + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!( + claims.nft_claims, + vec![ + NftClaim { + token_id: "5".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + }, + NftClaim { + token_id: "1".to_string(), + release_at: cw_utils::Expiration::AtHeight(app.block_info().height + 1) + } + ] + ); + + app.update_block(next_block); + + // both claims should be ready to claim + claim_legacy_nfts(&mut app, &module, STAKER)?; + claim_nfts(&mut app, &module, STAKER)?; + + let owner = query_nft_owner(&app, &nft, "1")?; + assert_eq!(owner, STAKER.to_string()); + let owner = query_nft_owner(&app, &nft, "5")?; + assert_eq!(owner, STAKER.to_string()); + + // no claims left + let claims = query_claims(&app, &module, STAKER)?; + assert_eq!(claims.nft_claims, vec![]); + + Ok(()) +} + // I can list all of the currently staked NFTs for an address. #[test] fn test_list_staked_nfts() -> anyhow::Result<()> {