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.
The ./upgrade_tracker
contract is an optional feature for easier
upgrades. It allows multiple contracts to use upgradable APIs
without having to have "admin" support in each contract.
Install cargo-contract
.
cargo install cargo-contract --force
Build the contract:
cargo +nightly contract build --release
Contract file needed for upload ./target/ink/polymesh_ink.contract
.
Cargo.toml:
```toml
[package]
name = "example_contract"
version = "1.0.0"
authors = ["
[dependencies] inkprimitives = { version = "3.0", default-features = false } inkprelude = { version = "3.0", default-features = false } inkmetadata = { version = "3.0", default-features = false, features = ["derive"], optional = true } inkenv = { version = "3.0", default-features = false } inkstorage = { version = "3.0", default-features = false } inklang = { version = "3.0", default-features = false } inklangcodegen = { version = "3.0", default-features = false }
scale = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive"] } scale-info = { version = "2", default-features = false, features = ["derive"], optional = true }
polymesh-ink = { version = "0.5.3", path = "../../", default-features = false, features = ["as-library", "tracker", "always-delegate"] }
[lib] name = "example_contract" path = "lib.rs" crate-type = ["cdylib"]
[features] default = ["std"] std = [ "inkprimitives/std", "inkmetadata/std", "inkenv/std", "inkstorage/std", "ink_lang/std", "scale/std", "scale-info/std", "polymesh-ink/std", ] ink-as-dependency = [] ```
lib.rs:
``rust
//! Example contract for upgradable
polymesh-ink` API.
extern crate alloc;
use ink_lang as ink;
use polymesh_ink::*;
pub mod example_contract { use crate::*; use alloc::vec::Vec;
/// Exchange contract using the Polymesh Ink! API.
#[ink(storage)]
pub struct ExampleContract {
/// Upgradable Polymesh Ink API.
api: PolymeshInk,
}
/// The contract error types.
#[derive(Debug, scale::Encode, scale::Decode)]
#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
pub enum Error {
/// PolymeshInk errors.
PolymeshInk(PolymeshError),
/// Upgrade error.
UpgradeError(UpgradeError)
}
impl From<PolymeshError> for Error {
fn from(err: PolymeshError) -> Self {
Self::PolymeshInk(err)
}
}
impl From<UpgradeError> for Error {
fn from(err: UpgradeError) -> Self {
Self::UpgradeError(err)
}
}
/// The contract result type.
pub type Result<T> = core::result::Result<T, Error>;
impl ExampleContract {
/// Instantiate this contract with an address of the `logic` contract.
///
/// Sets the privileged account to the caller. Only this account may
/// later changed the `forward_to` address.
#[ink(constructor)]
pub fn new(tracker: UpgradeTrackerRef) -> Self {
Self {
api: PolymeshInk::new_tracker(tracker),
}
}
/// Update the `polymesh-ink` API using the tracker.
///
/// Anyone can pay the gas fees to do the update using the tracker.
#[ink(message)]
pub fn update_polymesh_ink(&mut self) -> Result<()> {
self.api.check_for_upgrade()?;
Ok(())
}
// Simple example of using the Polymesh Ink! API.
#[ink(message)]
pub fn create_asset(&mut self, name: Vec<u8>, ticker: Ticker, amount: Balance) -> Result<()> {
self.api
.asset_create_and_issue(AssetName(name), ticker, AssetType::EquityCommon, true, Some(amount))?;
Ok(())
}
}
} ```
./upgrade_tracker/
../target/ink/polymesh_ink.contract
../examples/
. Use the code hash from step #2 and the tracker contract address from step #1 if used.The update_polymesh_ink
or update_code_hash
calls can be used to update the code hash for the Polymesh Ink! API.