use cosmwasm_std::testing::MockApi; use cosmwasm_std::{Addr, Api, Empty, Storage}; use cw_multi_test::error::AnyResult; use cw_multi_test::{no_init, AddressGenerator, AppBuilder, Executor, WasmKeeper}; use crate::test_contracts; #[test] fn contract_address_should_work() { // prepare application with custom API let mut app = AppBuilder::default() .with_api(MockApi::default().with_prefix("purple")) .build(no_init); // prepare user addresses let creator_addr = app.api().addr_make("creator"); // store contract's code let code_id = app.store_code_with_creator(creator_addr, test_contracts::counter::contract()); let owner = app.api().addr_make("owner"); let contract_addr_1 = app .instantiate_contract(code_id, owner.clone(), &Empty {}, &[], "Counter", None) .unwrap(); let contract_addr_2 = app .instantiate_contract(code_id, owner, &Empty {}, &[], "Counter", None) .unwrap(); // addresses of the two contract instances should be different assert_ne!(contract_addr_1, contract_addr_2); // make sure that generated addresses are in valid Bech32 encoding assert_eq!( contract_addr_1.to_string(), "purple1mzdhwvvh22wrt07w59wxyd58822qavwkx5lcej7aqfkpqqlhaqfs5efvjk" ); assert_eq!( contract_addr_2.to_string(), "purple14hj2tavq8fpesdwxxcu44rty3hh90vhujrvcmstl4zr3txmfvw9smc2vxm" ); } #[test] fn custom_address_generator_should_work() { // prepare custom address generator struct CustomAddressGenerator; impl AddressGenerator for CustomAddressGenerator { fn contract_address( &self, _api: &dyn Api, _storage: &mut dyn Storage, _code_id: u64, _instance_id: u64, ) -> AnyResult { Ok(MockApi::default() .with_prefix("osmo") .addr_make("test_addr")) } } // prepare wasm module with custom address generator let wasm_keeper = WasmKeeper::new().with_address_generator(CustomAddressGenerator); // prepare application with custom wasm keeper let mut app = AppBuilder::default().with_wasm(wasm_keeper).build(no_init); // prepare user addresses let owner_addr = app.api().addr_make("owner"); // store contract's code let code_id = app.store_code(test_contracts::counter::contract()); let contract_addr = app .instantiate_contract(code_id, owner_addr, &Empty {}, &[], "Counter", None) .unwrap(); // make sure that contract address equals to value generated by custom address generator assert_eq!( contract_addr.as_str(), MockApi::default() .with_prefix("osmo") .addr_make("test_addr") .as_str() ); } #[test] fn predictable_contract_address_should_work() { // prepare application with custom api let mut app = AppBuilder::default() .with_api(MockApi::default().with_prefix("juno")) .build(no_init); let creator = app.api().addr_make("creator"); // store contract's code let code_id = app.store_code_with_creator(creator.clone(), test_contracts::counter::contract()); let contract_addr_1 = app .instantiate2_contract( code_id, creator.clone(), &Empty {}, &[], "Counter", None, [1, 2, 3, 4, 5, 6], ) .unwrap(); let contract_addr_2 = app .instantiate2_contract( code_id, creator.clone(), &Empty {}, &[], "Counter", None, [11, 12, 13, 14, 15, 16], ) .unwrap(); // addresses of the two contract instances should be different assert_ne!(contract_addr_1, contract_addr_2); // instantiating a contract with the same salt should fail app.instantiate2_contract( code_id, creator, &Empty {}, &[], "Counter", None, [1, 2, 3, 4, 5, 6], ) .unwrap_err(); } #[test] fn creating_contract_with_the_same_predictable_address_should_fail() { // prepare application with custom api let mut app = AppBuilder::default() .with_api(MockApi::default().with_prefix("juno")) .build(no_init); let creator = app.api().addr_make("creator"); // store contract's code let code_id = app.store_code_with_creator(creator.clone(), test_contracts::counter::contract()); // instantiating for the first time should work app.instantiate2_contract( code_id, creator.clone(), &Empty {}, &[], "Counter", None, [1, 2, 3, 4, 5, 6], ) .unwrap(); // this instantiating should fail, // the same address is generated for a contract instance app.instantiate2_contract( code_id, creator, &Empty {}, &[], "Counter", None, [1, 2, 3, 4, 5, 6], ) .unwrap_err(); }