Skip to content

Commit

Permalink
Fix contract nft settlements (#1672)
Browse files Browse the repository at this point in the history
* Fix NFT & Offchain counts in settlement execute method.

* Add NFT owner check methods.

* Use verifiable build and add instructions to verify.
  • Loading branch information
Neopallium committed May 14, 2024
1 parent 54fbabb commit eb29808
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 13 deletions.
2 changes: 1 addition & 1 deletion contracts/upgradeable-polymesh-ink/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/upgradeable-polymesh-ink/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "polymesh-ink"
version = "3.2.0"
version = "3.3.0"
authors = ["PolymeshAssociation"]
edition = "2021"
license = "Apache-2.0"
Expand Down
19 changes: 19 additions & 0 deletions contracts/upgradeable-polymesh-ink/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@ An upgradable wrapper around the Polymesh Runtime API.
This allows contracts to use a stable API that can be updated
to support each major Polymesh release.

## Verifiable build

Install the docker image:
```
docker pull quay.io/subscan-explorer/wasm-compile-build:amd64-stable-1.70.0-v3.2.0
```

Build the contact inside the docker image:
```
docker run --rm -it -v .:/builds/contract -v ./target:/target/ quay.io/subscan-explorer/wasm-compile-build:amd64-stable-1.70.0-v3.2.0 cargo contract build --release
```

Check the contract hash from `./target/ink/polymesh_ink.json`
```
grep hash ./target/ink/polymesh_ink.json
```

Compare that hash to the current API hash on Testnet/Mainnet. Query `PolymeshContracts.currentApiHash`.

## Build the wrapped API contract.

Install [`cargo-contract`](https://github.com/paritytech/cargo-contract).
Expand Down
41 changes: 39 additions & 2 deletions contracts/upgradeable-polymesh-ink/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub enum PolymeshError {
selector: [u8; 4],
err: Option<InkEnvError>,
},
/// Not the NFT owner.
NotNftOwner,
}

/// Encodable `ink::env::Error`.
Expand Down Expand Up @@ -295,7 +297,13 @@ upgradable_api! {
/// Create and execute a settlement to transfer assets.
#[ink(message)]
pub fn settlement_execute(&self, venue: VenueId, legs: Vec<Leg>, portfolios: Vec<PortfolioId>) -> PolymeshResult<()> {
let leg_count = legs.len() as u32;
let (fungible, nfts, offchain) = legs.iter().fold((0, 0, 0), |(fungible, nfts, offchain), leg| {
match leg {
Leg::Fungible { .. } => (fungible + 1, nfts, offchain),
Leg::NonFungible { .. } => (fungible, nfts + 1, offchain),
Leg::OffChain { .. } => (fungible, nfts, offchain + 1),
}
});
let api = Api::new();
// Get the next instruction id.
let instruction_id = api
Expand All @@ -319,7 +327,7 @@ upgradable_api! {
// Create settlement.
api.call()
.settlement()
.execute_manual_instruction(instruction_id, None, leg_count, 0, 0, None)
.execute_manual_instruction(instruction_id, None, fungible, nfts, offchain, None)
.submit()?;
Ok(())
}
Expand Down Expand Up @@ -532,6 +540,35 @@ upgradable_api! {
ticker, asset_metadata_key
)?)
}

/// Get the portfolio owning an NFT.
#[ink(message)]
pub fn nft_owner(
&self,
ticker: Ticker,
nft: NFTId,
) -> PolymeshResult<Option<PortfolioId>> {
let api = Api::new();
Ok(api.query().nft().nft_owner(ticker, nft)?)
}

/// Check the owner of some NFTs.
#[ink(message)]
pub fn check_nfts_owner(
&self,
portfolio: PortfolioId,
ticker: Ticker,
nfts: Vec<NFTId>,
) -> PolymeshResult<()> {
let api = Api::new();
for nft in nfts {
let nft_owner = api.query().nft().nft_owner(ticker, nft)?;
if nft_owner != Some(portfolio) {
return Err(PolymeshError::NotNftOwner);
}
}
Ok(())
}
}

// Non-upgradable api.
Expand Down
2 changes: 1 addition & 1 deletion src/data/contracts/polymesh_ink_6.contract

Large diffs are not rendered by default.

210 changes: 202 additions & 8 deletions src/data/contracts/polymesh_ink_6.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"source": {
"hash": "0x4306285ed964afb6f08ab8c4e33d7d37a1383e847cd3299b35b80bab56cc89c6",
"hash": "0xab91551a532a13957ef35fcaf26b4a715929bb6791caf5ef85eac272c58ee24a",
"language": "ink! 4.3.0",
"compiler": "rustc 1.70.0",
"build_info": {
"build_mode": "Release",
"cargo_contract_version": "3.2.0",
"rust_toolchain": "stable-aarch64-apple-darwin",
"rust_toolchain": "stable-x86_64-unknown-linux-gnu",
"wasm_opt_settings": {
"keep_debug_symbols": false,
"optimization_passes": "Z"
Expand All @@ -15,7 +15,7 @@
},
"contract": {
"name": "polymesh-ink",
"version": "3.1.0",
"version": "3.3.0",
"authors": [
"PolymeshAssociation"
],
Expand Down Expand Up @@ -48,7 +48,7 @@
"displayName": [
"AccountId"
],
"type": 75
"type": 78
},
"balance": {
"displayName": [
Expand All @@ -66,13 +66,13 @@
"displayName": [
"ChainExtension"
],
"type": 77
"type": 80
},
"hash": {
"displayName": [
"Hash"
],
"type": 76
"type": 79
},
"maxEventTopics": 4,
"timestamp": {
Expand Down Expand Up @@ -791,6 +791,79 @@
"type": 71
},
"selector": "0xa8f59c06"
},
{
"args": [
{
"label": "ticker",
"type": {
"displayName": [],
"type": 25
}
},
{
"label": "nft",
"type": {
"displayName": [],
"type": 30
}
}
],
"default": false,
"docs": [
" Get the portfolio owning an NFT."
],
"label": "nft_owner",
"mutates": false,
"payable": true,
"returnType": {
"displayName": [
"ink",
"MessageResult"
],
"type": 75
},
"selector": "0x19f161f1"
},
{
"args": [
{
"label": "portfolio",
"type": {
"displayName": [],
"type": 16
}
},
{
"label": "ticker",
"type": {
"displayName": [],
"type": 25
}
},
{
"label": "nfts",
"type": {
"displayName": [],
"type": 29
}
}
],
"default": false,
"docs": [
" Check the owner of some NFTs."
],
"label": "check_nfts_owner",
"mutates": false,
"payable": true,
"returnType": {
"displayName": [
"ink",
"MessageResult"
],
"type": 5
},
"selector": "0x7f8caba0"
}
]
},
Expand Down Expand Up @@ -1016,6 +1089,10 @@
],
"index": 3,
"name": "InkDelegateCallError"
},
{
"index": 4,
"name": "NotNftOwner"
}
]
}
Expand Down Expand Up @@ -3122,6 +3199,123 @@
},
{
"id": 75,
"type": {
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 76
}
],
"index": 0,
"name": "Ok"
},
{
"fields": [
{
"type": 2
}
],
"index": 1,
"name": "Err"
}
]
}
},
"params": [
{
"name": "T",
"type": 76
},
{
"name": "E",
"type": 2
}
],
"path": [
"Result"
]
}
},
{
"id": 76,
"type": {
"def": {
"variant": {
"variants": [
{
"fields": [
{
"type": 77
}
],
"index": 0,
"name": "Ok"
},
{
"fields": [
{
"type": 7
}
],
"index": 1,
"name": "Err"
}
]
}
},
"params": [
{
"name": "T",
"type": 77
},
{
"name": "E",
"type": 7
}
],
"path": [
"Result"
]
}
},
{
"id": 77,
"type": {
"def": {
"variant": {
"variants": [
{
"index": 0,
"name": "None"
},
{
"fields": [
{
"type": 16
}
],
"index": 1,
"name": "Some"
}
]
}
},
"params": [
{
"name": "T",
"type": 16
}
],
"path": [
"Option"
]
}
},
{
"id": 78,
"type": {
"def": {
"composite": {
Expand All @@ -3141,7 +3335,7 @@
}
},
{
"id": 76,
"id": 79,
"type": {
"def": {
"composite": {
Expand All @@ -3161,7 +3355,7 @@
}
},
{
"id": 77,
"id": 80,
"type": {
"def": {
"variant": {}
Expand Down
Binary file modified src/data/contracts/polymesh_ink_6.wasm
Binary file not shown.

0 comments on commit eb29808

Please sign in to comment.