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

new CW721_ADMIN store #81

Merged
merged 3 commits into from
Jan 23, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 19 additions & 4 deletions contracts/sg-ics721/src/testing/integration_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ impl Test {
false => None,
};

let admin = admin_and_pauser
.clone()
.map(|p| app.api().addr_make(&p).to_string());
let ics721 = app
.instantiate_contract(
ics721_id,
Expand All @@ -346,9 +349,8 @@ impl Test {
cw721_base_code_id: source_cw721_id,
incoming_proxy,
outgoing_proxy,
pauser: admin_and_pauser
.clone()
.map(|p| app.api().addr_make(&p).to_string()),
pauser: admin.clone(),
cw721_admin: admin,
},
&[],
"sg-ics721",
Expand Down Expand Up @@ -452,6 +454,13 @@ impl Test {
.unwrap()
}

fn query_cw721_admin(&mut self) -> Option<Addr> {
self.app
.wrap()
.query_wasm_smart(self.ics721.clone(), &QueryMsg::Cw721Admin {})
.unwrap()
}

fn query_nft_contracts(&mut self) -> Vec<(String, Addr)> {
self.app
.wrap()
Expand Down Expand Up @@ -2337,6 +2346,7 @@ fn test_pause() {
incoming_proxy: None,
outgoing_proxy: None,
cw721_base_code_id: None,
cw721_admin: None,
})
.unwrap(),
}
Expand Down Expand Up @@ -2378,9 +2388,10 @@ fn test_migration() {
assert_eq!(cw721_code_id, test.source_cw721_id);

// migrate changes
let admin = test.app.api().addr_make(ICS721_ADMIN_AND_PAUSER);
test.app
.execute(
test.app.api().addr_make(ICS721_ADMIN_AND_PAUSER),
admin.clone(),
WasmMsg::Migrate {
contract_addr: test.ics721.to_string(),
new_code_id: test.ics721_id,
Expand All @@ -2389,6 +2400,7 @@ fn test_migration() {
incoming_proxy: None,
outgoing_proxy: None,
cw721_base_code_id: Some(12345678),
cw721_admin: Some(admin.to_string()),
})
.unwrap(),
}
Expand All @@ -2402,6 +2414,7 @@ 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),);

// migrate without changing code id
test.app
Expand All @@ -2415,6 +2428,7 @@ fn test_migration() {
incoming_proxy: None,
outgoing_proxy: None,
cw721_base_code_id: None,
cw721_admin: Some("".to_string()),
})
.unwrap(),
}
Expand All @@ -2428,4 +2442,5 @@ 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,);
}
2 changes: 1 addition & 1 deletion justfile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
set dotenv-load

platform := if arch() =~ "aarch64" {"linux/arm64"} else {"linux/amd64"}
image := if arch() =~ "aarch64" {"cosmwasm/workspace-optimizer-arm64:0.14.0"} else {"cosmwasm/workspace-optimizer:0.14.0"}
image := if arch() =~ "aarch64" {"cosmwasm/workspace-optimizer-arm64:0.15.0"} else {"cosmwasm/workspace-optimizer:0.15.0"}

alias log := optimize-watch

Expand Down
71 changes: 46 additions & 25 deletions packages/ics721/schema/ics721.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
"cw721_base_code_id"
],
"properties": {
"cw721_admin": {
"description": "The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": [
"string",
"null"
]
},
"cw721_base_code_id": {
"description": "Code ID of cw721-ics contract. A new cw721-ics will be instantiated for each new IBCd NFT classID.\n\nNOTE: this _must_ correspond to the cw721-base contract. Using a regular cw721 may cause the ICS 721 interface implemented by this contract to stop working, and IBCd away NFTs to be unreturnable as cw721 does not have a mint method in the spec.",
"type": "integer",
Expand Down Expand Up @@ -167,31 +174,6 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"receive_proxy_nft"
],
"properties": {
"receive_proxy_nft": {
"type": "object",
"required": [
"eyeball",
"msg"
],
"properties": {
"eyeball": {
"type": "string"
},
"msg": {
"$ref": "#/definitions/Cw721ReceiveMsg"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
Expand Down Expand Up @@ -921,6 +903,20 @@
},
"additionalProperties": false
},
{
"description": "Gets the admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": "object",
"required": [
"cw721_admin"
],
"properties": {
"cw721_admin": {
"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 @@ -1129,6 +1125,31 @@
}
}
},
"cw721_admin": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nullable_Nullable_Addr",
"anyOf": [
{
"anyOf": [
{
"$ref": "#/definitions/Addr"
},
{
"type": "null"
}
]
},
{
"type": "null"
}
],
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
}
}
},
"cw721_code_id": {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "uint64",
Expand Down
25 changes: 0 additions & 25 deletions packages/ics721/schema/raw/execute.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,31 +41,6 @@
}
},
"additionalProperties": false
},
{
"type": "object",
"required": [
"receive_proxy_nft"
],
"properties": {
"receive_proxy_nft": {
"type": "object",
"required": [
"eyeball",
"msg"
],
"properties": {
"eyeball": {
"type": "string"
},
"msg": {
"$ref": "#/definitions/Cw721ReceiveMsg"
}
},
"additionalProperties": false
}
},
"additionalProperties": false
}
],
"definitions": {
Expand Down
7 changes: 7 additions & 0 deletions packages/ics721/schema/raw/instantiate.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@
"cw721_base_code_id"
],
"properties": {
"cw721_admin": {
"description": "The admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": [
"string",
"null"
]
},
"cw721_base_code_id": {
"description": "Code ID of cw721-ics contract. A new cw721-ics will be instantiated for each new IBCd NFT classID.\n\nNOTE: this _must_ correspond to the cw721-base contract. Using a regular cw721 may cause the ICS 721 interface implemented by this contract to stop working, and IBCd away NFTs to be unreturnable as cw721 does not have a mint method in the spec.",
"type": "integer",
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 @@ -189,6 +189,20 @@
},
"additionalProperties": false
},
{
"description": "Gets the admin address for instantiating new cw721 contracts. In case of None, contract is immutable.",
"type": "object",
"required": [
"cw721_admin"
],
"properties": {
"cw721_admin": {
"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
25 changes: 25 additions & 0 deletions packages/ics721/schema/raw/response_to_cw721_admin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Nullable_Nullable_Addr",
"anyOf": [
{
"anyOf": [
{
"$ref": "#/definitions/Addr"
},
{
"type": "null"
}
]
},
{
"type": "null"
}
],
"definitions": {
"Addr": {
"description": "A human readable address.\n\nIn Cosmos, this is typically bech32 encoded. But for multi-chain smart contracts no assumptions should be made other than being UTF-8 encoded and of reasonable length.\n\nThis type represents a validated address. It can be created in the following ways 1. Use `Addr::unchecked(input)` 2. Use `let checked: Addr = deps.api.addr_validate(input)?` 3. Use `let checked: Addr = deps.api.addr_humanize(canonical_addr)?` 4. Deserialize from JSON. This must only be done from JSON that was validated before such as a contract's state. `Addr` must not be used in messages sent by the user because this would result in unvalidated instances.\n\nThis type is immutable. If you really need to mutate it (Really? Are you sure?), create a mutable copy using `let mut mutable = Addr::to_string()` and operate on that `String` instance.",
"type": "string"
}
}
}
48 changes: 43 additions & 5 deletions packages/ics721/src/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ use crate::{
},
msg::{CallbackMsg, ExecuteMsg, InstantiateMsg, MigrateMsg},
state::{
CollectionData, UniversalAllNftInfoResponse, CLASS_ID_TO_CLASS, CLASS_ID_TO_NFT_CONTRACT,
CW721_CODE_ID, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID, OUTGOING_CLASS_TOKEN_TO_CHANNEL,
OUTGOING_PROXY, PO, TOKEN_METADATA,
CollectionData, UniversalAllNftInfoResponse, ADMIN_USED_FOR_CW721, CLASS_ID_TO_CLASS,
CLASS_ID_TO_NFT_CONTRACT, CW721_CODE_ID, INCOMING_PROXY, NFT_CONTRACT_TO_CLASS_ID,
OUTGOING_CLASS_TOKEN_TO_CHANNEL, OUTGOING_PROXY, PO, TOKEN_METADATA,
},
token_types::{VoucherCreation, VoucherRedemption},
ContractError,
Expand Down Expand Up @@ -62,10 +62,23 @@ where
));
}

ADMIN_USED_FOR_CW721.save(
deps.storage,
&msg.cw721_admin
.as_ref()
.map(|h| deps.api.addr_validate(h))
.transpose()?,
)?;

Ok(Response::default()
.add_submessages(proxies_instantiate)
.add_attribute("method", "instantiate")
.add_attribute("cw721_code_id", msg.cw721_base_code_id.to_string()))
.add_attribute("cw721_code_id", msg.cw721_base_code_id.to_string())
.add_attribute(
"cw721_admin",
msg.cw721_admin
.map_or_else(|| "immutable".to_string(), |or| or),
))
}

fn execute(
Expand Down Expand Up @@ -323,9 +336,12 @@ where
CLASS_ID_TO_NFT_CONTRACT.save(deps.storage, class_id.clone(), &cw721_addr)?;
NFT_CONTRACT_TO_CLASS_ID.save(deps.storage, cw721_addr, &class_id)?;

let admin = ADMIN_USED_FOR_CW721
.load(deps.storage)?
.map(|a| a.to_string());
let message = SubMsg::<T>::reply_on_success(
WasmMsg::Instantiate2 {
admin: None,
admin,
code_id: cw721_code_id,
msg: self.init_msg(deps.as_ref(), &env, &class)?,
funds: vec![],
Expand Down Expand Up @@ -471,6 +487,7 @@ where
incoming_proxy,
outgoing_proxy,
cw721_base_code_id,
cw721_admin,
} => {
// disables incoming proxy if none is provided!
INCOMING_PROXY.save(
Expand All @@ -492,6 +509,14 @@ where
if let Some(cw721_base_code_id) = cw721_base_code_id {
CW721_CODE_ID.save(deps.storage, &cw721_base_code_id)?;
}
if let Some(cw721_admin) = cw721_admin.clone() {
if cw721_admin.is_empty() {
ADMIN_USED_FOR_CW721.save(deps.storage, &None)?;
} else {
ADMIN_USED_FOR_CW721
.save(deps.storage, &Some(deps.api.addr_validate(&cw721_admin)?))?;
}
}
Ok(Response::default()
.add_attribute("method", "migrate")
.add_attribute("pauser", pauser.map_or_else(|| "none".to_string(), |or| or))
Expand All @@ -506,6 +531,19 @@ where
.add_attribute(
"cw721_base_code_id",
cw721_base_code_id.map_or_else(|| "none".to_string(), |or| or.to_string()),
)
.add_attribute(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain what this line is doing?

Copy link
Collaborator Author

@taitruong taitruong Jan 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here cw721_base_code_id is of type Option<u64>. In response it just say "none" is provided - instead of returning an empty string.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My question here is why do we have the plaintext "none" instead of an actual None?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Attribute must be a string, that's why we need to convert all these data.

"cw721_admin",
cw721_admin.map_or_else(
|| "none".to_string(),
|or| {
if or.is_empty() {
"immutable".to_string()
} else {
or
}
},
),
))
}
}
Expand Down
Loading
Loading