Skip to content

Commit

Permalink
Use Mapping in ERC-1155 Example (#1057)
Browse files Browse the repository at this point in the history
* Switch out `BTreeMap` with `Mapping`

* Use new `Mapping::clear_entry` API

* Document panic behaviour in `perform_transfer`

* Use `initialize_contract` in constructor

* Pass tuples by reference when inserting into map

* RustFmt

* Pass tuple by reference when querying storage

* Add note about proper initialization

* Fix typo

Co-authored-by: Michael Müller <michi@parity.io>

Co-authored-by: Michael Müller <michi@parity.io>
  • Loading branch information
HCastano and Michael Müller authored Dec 9, 2021
1 parent ce37cad commit 9b154e8
Showing 1 changed file with 36 additions and 22 deletions.
58 changes: 36 additions & 22 deletions examples/erc1155/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -187,10 +187,13 @@ pub trait Erc1155TokenReceiver {
mod erc1155 {
use super::*;

use ink_prelude::collections::BTreeMap;
use ink_storage::traits::{
PackedLayout,
SpreadLayout,
use ink_storage::{
lazy::Mapping,
traits::{
PackedLayout,
SpreadAllocate,
SpreadLayout,
},
};

/// Indicate that a token transfer has occured.
Expand Down Expand Up @@ -236,6 +239,7 @@ mod erc1155 {
PartialOrd,
Eq,
PartialEq,
Default,
PackedLayout,
SpreadLayout,
scale::Encode,
Expand All @@ -249,12 +253,12 @@ mod erc1155 {

/// An ERC-1155 contract.
#[ink(storage)]
#[derive(Default)]
#[derive(Default, SpreadAllocate)]
pub struct Contract {
/// Tracks the balances of accounts across the different tokens that they might be holding.
balances: BTreeMap<(AccountId, TokenId), Balance>,
balances: Mapping<(AccountId, TokenId), Balance>,
/// Which accounts (called operators) have been approved to spend funds on behalf of an owner.
approvals: BTreeMap<Approval, ()>,
approvals: Mapping<Approval, ()>,
/// A unique identifier for the tokens which have been minted (and are therefore supported)
/// by this contract.
token_id_nonce: TokenId,
Expand All @@ -264,7 +268,11 @@ mod erc1155 {
/// Initialize a default instance of this ERC-1155 implementation.
#[ink(constructor)]
pub fn new() -> Self {
Default::default()
// This call is required in order to correctly initialize the
// `Mapping`s of our contract.
//
// Not that `token_id_nonce` will be initialized to its `Default` value.
ink_lang::codegen::initialize_contract(|_| {})
}

/// Create the initial supply for a token.
Expand All @@ -281,7 +289,7 @@ mod erc1155 {

// Given that TokenId is a `u128` the likelihood of this overflowing is pretty slim.
self.token_id_nonce += 1;
self.balances.insert((caller, self.token_id_nonce), value);
self.balances.insert(&(caller, self.token_id_nonce), &value);

// Emit transfer event but with mint semantics
self.env().emit_event(TransferSingle {
Expand All @@ -308,7 +316,7 @@ mod erc1155 {
ensure!(token_id <= self.token_id_nonce, Error::UnexistentToken);

let caller = self.env().caller();
self.balances.insert((caller, token_id), value);
self.balances.insert(&(caller, token_id), &value);

// Emit transfer event but with mint semantics
self.env().emit_event(TransferSingle {
Expand All @@ -326,21 +334,27 @@ mod erc1155 {
//
// Should not be used directly since it's missing certain checks which are important to the
// ERC-1155 standard (it is expected that the caller has already performed these).
//
// # Panics
//
// If `from` does not hold any `token_id` tokens.
fn perform_transfer(
&mut self,
from: AccountId,
to: AccountId,
token_id: TokenId,
value: Balance,
) {
self.balances
.entry((from, token_id))
.and_modify(|b| *b -= value);
let mut sender_balance = self
.balances
.get(&(from, token_id))
.expect("Caller should have ensured that `from` holds `token_id`.");
sender_balance -= value;
self.balances.insert(&(from, token_id), &sender_balance);

self.balances
.entry((to, token_id))
.and_modify(|b| *b += value)
.or_insert(value);
let mut recipient_balance = self.balances.get(&(to, token_id)).unwrap_or(0);
recipient_balance += value;
self.balances.insert(&(to, token_id), &recipient_balance);

let caller = self.env().caller();
self.env().emit_event(TransferSingle {
Expand Down Expand Up @@ -507,7 +521,7 @@ mod erc1155 {

#[ink(message)]
fn balance_of(&self, owner: AccountId, token_id: TokenId) -> Balance {
*self.balances.get(&(owner, token_id)).unwrap_or(&0)
self.balances.get(&(owner, token_id)).unwrap_or(0)
}

#[ink(message)]
Expand Down Expand Up @@ -541,7 +555,7 @@ mod erc1155 {
};

if approved {
self.approvals.insert(approval, ());
self.approvals.insert(&approval, &());
} else {
self.approvals.remove(&approval);
}
Expand Down Expand Up @@ -653,9 +667,9 @@ mod erc1155 {

fn init_contract() -> Contract {
let mut erc = Contract::new();
erc.balances.insert((alice(), 1), 10);
erc.balances.insert((alice(), 2), 20);
erc.balances.insert((bob(), 1), 10);
erc.balances.insert((alice(), 1), &10);
erc.balances.insert((alice(), 2), &20);
erc.balances.insert((bob(), 1), &10);

erc
}
Expand Down

0 comments on commit 9b154e8

Please sign in to comment.