Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

consider contract address length for instantiate2 #97

Merged
merged 6 commits into from
May 31, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 23 additions & 10 deletions contracts/sg-ics721/src/testing/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ impl Test {
outgoing_proxy,
pauser: admin.clone(),
cw721_admin: admin,
contract_addr_length: None,
},
&[],
"sg-ics721",
Expand Down Expand Up @@ -464,6 +465,13 @@ impl Test {
.unwrap()
}

fn query_contract_addr_length(&mut self) -> Option<u32> {
self.app
.wrap()
.query_wasm_smart(self.ics721.clone(), &QueryMsg::ContractAddrLength {})
.unwrap()
}

fn query_nft_contracts(&mut self) -> Vec<(String, Addr)> {
self.app
.wrap()
Expand Down Expand Up @@ -2350,6 +2358,7 @@ fn test_pause() {
outgoing_proxy: None,
cw721_base_code_id: None,
cw721_admin: None,
contract_addr_length: None,
})
.unwrap(),
}
Expand Down Expand Up @@ -2404,6 +2413,7 @@ fn test_migration() {
outgoing_proxy: None,
cw721_base_code_id: Some(12345678),
cw721_admin: Some(admin.to_string()),
contract_addr_length: Some(20), // injective have 20 bytes addresses
})
.unwrap(),
}
Expand All @@ -2417,23 +2427,25 @@ fn test_migration() {
assert!(proxy.is_none());
let cw721_code_id = test.query_cw721_id();
assert_eq!(cw721_code_id, 12345678);
assert_eq!(test.query_cw721_admin(), Some(admin),);
assert_eq!(test.query_cw721_admin(), Some(admin));
assert_eq!(test.query_contract_addr_length(), Some(20),);

// migrate without changing code id
let msg = MigrateMsg::WithUpdate {
pauser: None,
incoming_proxy: None,
outgoing_proxy: None,
cw721_base_code_id: None,
cw721_admin: Some("".to_string()),
contract_addr_length: None,
};
test.app
.execute(
test.app.api().addr_make(ICS721_ADMIN_AND_PAUSER),
WasmMsg::Migrate {
contract_addr: test.ics721.to_string(),
new_code_id: test.ics721_id,
msg: to_json_binary(&MigrateMsg::WithUpdate {
pauser: None,
incoming_proxy: None,
outgoing_proxy: None,
cw721_base_code_id: None,
cw721_admin: Some("".to_string()),
})
.unwrap(),
msg: to_json_binary(&msg).unwrap(),
}
.into(),
)
Expand All @@ -2445,5 +2457,6 @@ fn test_migration() {
assert!(proxy.is_none());
let cw721_code_id = test.query_cw721_id();
assert_eq!(cw721_code_id, 12345678);
assert_eq!(test.query_cw721_admin(), None,);
assert_eq!(test.query_cw721_admin(), None);
assert_eq!(test.query_contract_addr_length(), None,);
}
33 changes: 33 additions & 0 deletions packages/ics721/schema/ics721.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@
"cw721_base_code_id"
],
"properties": {
"contract_addr_length": {
"description": "The optional contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"cw721_admin": {
"description": "The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": [
Expand Down Expand Up @@ -1047,6 +1056,20 @@
},
"additionalProperties": false
},
{
"description": "Gets the contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).",
"type": "object",
"required": [
"contract_addr_length"
],
"properties": {
"contract_addr_length": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Gets a list of classID as key (from NonFungibleTokenPacketData) and cw721 contract as value (instantiated for that classID).",
"type": "object",
Expand Down Expand Up @@ -1255,6 +1278,16 @@
}
}
},
"contract_addr_length": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nullable_uint32",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"cw721_admin": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nullable_Nullable_Addr",
Expand Down
9 changes: 9 additions & 0 deletions packages/ics721/schema/raw/instantiate.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
"cw721_base_code_id"
],
"properties": {
"contract_addr_length": {
"description": "The optional contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
},
"cw721_admin": {
"description": "The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": [
Expand Down
14 changes: 14 additions & 0 deletions packages/ics721/schema/raw/query.json
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,20 @@
},
"additionalProperties": false
},
{
"description": "Gets the contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).",
"type": "object",
"required": [
"contract_addr_length"
],
"properties": {
"contract_addr_length": {
"type": "object",
"additionalProperties": false
}
},
"additionalProperties": false
},
{
"description": "Gets a list of classID as key (from NonFungibleTokenPacketData) and cw721 contract as value (instantiated for that classID).",
"type": "object",
Expand Down
10 changes: 10 additions & 0 deletions packages/ics721/schema/raw/response_to_contract_addr_length.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nullable_uint32",
"type": [
"integer",
"null"
],
"format": "uint32",
"minimum": 0.0
}
26 changes: 25 additions & 1 deletion packages/ics721/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{
},
state::{
ClassIdInfo, CollectionData, UniversalAllNftInfoResponse, ADMIN_USED_FOR_CW721,
CLASS_ID_AND_NFT_CONTRACT_INFO, CLASS_ID_TO_CLASS, CW721_CODE_ID,
CLASS_ID_AND_NFT_CONTRACT_INFO, CLASS_ID_TO_CLASS, CONTRACT_ADDR_LENGTH, CW721_CODE_ID,
INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL,
OUTGOING_PROXY, PO, TOKEN_METADATA,
},
Expand Down Expand Up @@ -76,6 +76,13 @@ where
.transpose()?,
)?;

let contract_addr_length = msg.contract_addr_length;
if let Some(contract_addr_length) = contract_addr_length {
CONTRACT_ADDR_LENGTH.save(deps.storage, &contract_addr_length)?;
} else {
CONTRACT_ADDR_LENGTH.remove(deps.storage);
}

Ok(Response::default()
.add_submessages(proxies_instantiate)
.add_attribute("method", "instantiate")
Expand All @@ -84,6 +91,10 @@ where
"cw721_admin",
msg.cw721_admin
.map_or_else(|| "immutable".to_string(), |or| or),
)
.add_attribute(
"contract_addr_length",
contract_addr_length.map_or_else(|| "none".to_string(), |or| or.to_string()),
))
}

Expand Down Expand Up @@ -704,13 +715,15 @@ where
_env: Env,
msg: MigrateMsg,
) -> Result<Response<T>, ContractError> {
println!(">>>>>>>> msg: {:?}", msg);
match msg {
MigrateMsg::WithUpdate {
pauser,
incoming_proxy,
outgoing_proxy,
cw721_base_code_id,
cw721_admin,
contract_addr_length,
} => {
// disables incoming proxy if none is provided!
INCOMING_PROXY.save(
Expand Down Expand Up @@ -741,6 +754,12 @@ where
}
}

if let Some(contract_addr_length) = contract_addr_length {
CONTRACT_ADDR_LENGTH.save(deps.storage, &contract_addr_length)?;
} else {
CONTRACT_ADDR_LENGTH.remove(deps.storage);
}

let response = Response::default()
.add_attribute("method", "migrate")
.add_attribute("pauser", pauser.map_or_else(|| "none".to_string(), |or| or))
Expand Down Expand Up @@ -768,6 +787,11 @@ where
}
},
),
)
.add_attribute(
"contract_addr_length",
contract_addr_length
.map_or_else(|| "none".to_string(), |or| or.to_string()),
);

self.migrate_legacy(deps, response)
Expand Down
16 changes: 13 additions & 3 deletions packages/ics721/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,11 @@ use cosmwasm_std::{
};
use serde::Deserialize;

use crate::{ibc::ACK_CALLBACK_REPLY_ID, state::INCOMING_PROXY, ContractError};
use crate::{
ibc::ACK_CALLBACK_REPLY_ID,
state::{CONTRACT_ADDR_LENGTH, INCOMING_PROXY},
ContractError,
};
use ics721_types::{
ibc_types::NonFungibleTokenPacketData,
types::{
Expand Down Expand Up @@ -147,8 +151,14 @@ pub fn get_instantiate2_address(
let CodeInfoResponse { checksum, .. } = deps.querier.query_wasm_code_info(code_id)?;

let canonical_cw721_addr = instantiate2_address(&checksum, &canonical_creator, salt)?;

Ok(deps.api.addr_humanize(&canonical_cw721_addr)?)
if let Some(contract_addr_length) = CONTRACT_ADDR_LENGTH.may_load(deps.storage)? {
let contract_addr_length = contract_addr_length as usize;
Ok(deps
.api
.addr_humanize(&canonical_cw721_addr[..contract_addr_length].into())?)
} else {
Ok(deps.api.addr_humanize(&canonical_cw721_addr)?)
}
}

mod test {
Expand Down
8 changes: 8 additions & 0 deletions packages/ics721/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pub struct InstantiateMsg {
pub pauser: Option<String>,
/// The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.
pub cw721_admin: Option<String>,
/// The optional contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).
pub contract_addr_length: Option<u32>,
}

#[cw_serde]
Expand Down Expand Up @@ -162,6 +164,10 @@ pub enum QueryMsg {
#[returns(Option<Option<::cosmwasm_std::Addr>>)]
Cw721Admin {},

/// Gets the contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).
#[returns(Option<u32>)]
ContractAddrLength {},

/// Gets a list of classID as key (from
/// NonFungibleTokenPacketData) and cw721 contract as value
/// (instantiated for that classID).
Expand Down Expand Up @@ -212,5 +218,7 @@ pub enum MigrateMsg {
cw721_base_code_id: Option<u64>,
/// The admin address for instantiating new cw721 contracts. In case of "", contract is immutable.
cw721_admin: Option<String>,
/// The optional contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).
contract_addr_length: Option<u32>,
},
}
7 changes: 5 additions & 2 deletions packages/ics721/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ use crate::{
msg::QueryMsg,
state::{
UniversalAllNftInfoResponse, ADMIN_USED_FOR_CW721, CLASS_ID_AND_NFT_CONTRACT_INFO,
CLASS_ID_TO_CLASS, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL, INCOMING_PROXY,
OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA,
CLASS_ID_TO_CLASS, CONTRACT_ADDR_LENGTH, CW721_CODE_ID, INCOMING_CLASS_TOKEN_TO_CHANNEL,
INCOMING_PROXY, OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA,
},
};
use ics721_types::token_types::{Class, ClassId, ClassToken, Token, TokenId};
Expand Down Expand Up @@ -35,6 +35,9 @@ pub trait Ics721Query {
QueryMsg::IncomingProxy {} => to_json_binary(&INCOMING_PROXY.load(deps.storage)?),
QueryMsg::Cw721CodeId {} => to_json_binary(&query_cw721_code_id(deps)?),
QueryMsg::Cw721Admin {} => to_json_binary(&ADMIN_USED_FOR_CW721.load(deps.storage)?),
QueryMsg::ContractAddrLength {} => {
to_json_binary(&CONTRACT_ADDR_LENGTH.may_load(deps.storage)?)
}
QueryMsg::NftContracts { start_after, limit } => {
to_json_binary(&query_nft_contracts(deps, start_after, limit)?)
}
Expand Down
7 changes: 7 additions & 0 deletions packages/ics721/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,15 +38,22 @@ pub const CLASS_ID_TO_CLASS: Map<ClassId, Class> = Map::new("g");
pub const OUTGOING_CLASS_TOKEN_TO_CHANNEL: Map<(ClassId, TokenId), String> = Map::new("h");
/// Same as above, but for NFTs arriving at this contract.
pub const INCOMING_CLASS_TOKEN_TO_CHANNEL: Map<(ClassId, TokenId), String> = Map::new("i");

/// Maps (class ID, token ID) -> token metadata. Used to store
/// on-chain metadata for tokens that have arrived from other
/// chains. When a token arrives, it's metadata (regardless of if it
/// is `None`) is stored in this map. When the token is returned to
/// it's source chain, the metadata is removed from the map.
pub const TOKEN_METADATA: Map<(ClassId, TokenId), Option<Binary>> = Map::new("j");

/// The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.
pub const ADMIN_USED_FOR_CW721: Item<Option<Addr>> = Item::new("l");

/// The optional contract address length being used for instantiate2. In case of None, default length is 32 (standard in cosmwasm).
/// So length must be shorter than 32. For example, Injective has 20 length address.
/// Bug: https://github.com/CosmWasm/cosmwasm/issues/2155
pub const CONTRACT_ADDR_LENGTH: Item<u32> = Item::new("n");

#[derive(Deserialize)]
pub struct UniversalAllNftInfoResponse {
pub access: UniversalOwnerOfResponse,
Expand Down
Loading
Loading