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

[2.0.0] feat: LookupMap and LookupSet #217

Merged
merged 8 commits into from
Aug 24, 2020
Merged
Show file tree
Hide file tree
Changes from 7 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
17 changes: 16 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
# Changelog

## `1.0.1`
## `2.0.0`

### Contract changes

* Updated `status-message-collections` to use `LookupMap`
* **BREAKING** Updated `fungible-token` implementation to use `LookupMap`. It changes storage layout.

### API changes

* Introduce `LookupMap` and `LookupSet` that are faster implementations of `UnorderedMap` and `UnorderedSet`, but without support for iterators.
Most read/lookup/write are done in 1 storage access instead of 2 or 3 for `Unordered*` implementations.
* **BREAKING** `Default` is removed from `near_sdk::collections` to avoid implicit state conflicts.
Collections should be initialized by explicitly specifying prefix using `new` method.
* **BREAKING** `TreeMap` implementation was updated to use `LookupMap`.
Previous `TreeMap` implementation was renamed to `LegacyTreeMap` and was deprecated.
It should only be used if the contract was already deployed and state has to be compatible with the previous implementation.

### Other changes

Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

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

18 changes: 9 additions & 9 deletions examples/cross-contract-high-level/Cargo.lock

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

Binary file not shown.
18 changes: 9 additions & 9 deletions examples/cross-contract-low-level/Cargo.lock

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

Binary file not shown.
8 changes: 4 additions & 4 deletions examples/fungible-token/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 examples/fungible-token/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "fungible-token"
version = "0.2.0"
version = "0.3.0"
authors = ["Near Inc <hello@nearprotocol.com>"]
edition = "2018"

Expand Down
9 changes: 9 additions & 0 deletions examples/fungible-token/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,12 @@ To test run:
```bash
cargo test --package fungible-token -- --nocapture
```

## Changelog

### `0.3.0`

#### Breaking storage change

- Switching `UnorderedMap` to `LookupMap`. It makes it cheaper and faster due to decreased storage access.

Binary file modified examples/fungible-token/res/fungible_token.wasm
Binary file not shown.
36 changes: 15 additions & 21 deletions examples/fungible-token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
* keys on its account.
*/
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::UnorderedMap;
use near_sdk::collections::LookupMap;
use near_sdk::json_types::U128;
use near_sdk::{env, near_bindgen, AccountId, Balance, Promise, StorageUsage};

Expand All @@ -34,22 +34,28 @@ pub struct Account {
/// Escrow Account ID hash to the allowance amount.
/// Allowance is the amount of tokens the Escrow Account ID can spent on behalf of the account
/// owner.
pub allowances: UnorderedMap<Vec<u8>, Balance>,
pub allowances: LookupMap<Vec<u8>, Balance>,
/// The number of allowances
pub num_allowances: u32,
}

impl Account {
/// Initializes a new Account with 0 balance and no allowances for a given `account_hash`.
pub fn new(account_hash: Vec<u8>) -> Self {
Self { balance: 0, allowances: UnorderedMap::new(account_hash) }
Self { balance: 0, allowances: LookupMap::new(account_hash), num_allowances: 0 }
}

/// Sets allowance for account `escrow_account_id` to `allowance`.
pub fn set_allowance(&mut self, escrow_account_id: &AccountId, allowance: Balance) {
let escrow_hash = env::sha256(escrow_account_id.as_bytes());
if allowance > 0 {
self.allowances.insert(&escrow_hash, &allowance);
if self.allowances.insert(&escrow_hash, &allowance).is_none() {
self.num_allowances += 1;
}
} else {
self.allowances.remove(&escrow_hash);
if self.allowances.remove(&escrow_hash).is_some() {
self.num_allowances -= 1;
}
}
}

Expand All @@ -64,7 +70,7 @@ impl Account {
#[derive(BorshDeserialize, BorshSerialize)]
pub struct FungibleToken {
/// sha256(AccountID) -> Account details.
pub accounts: UnorderedMap<Vec<u8>, Account>,
pub accounts: LookupMap<Vec<u8>, Account>,

/// Total supply of the all token.
pub total_supply: Balance,
Expand All @@ -83,7 +89,7 @@ impl FungibleToken {
pub fn new(owner_id: AccountId, total_supply: U128) -> Self {
let total_supply = total_supply.into();
assert!(!env::state_exists(), "Already initialized");
let mut ft = Self { accounts: UnorderedMap::new(b"a".to_vec()), total_supply };
let mut ft = Self { accounts: LookupMap::new(b"a".to_vec()), total_supply };
let mut account = ft.get_account(&owner_id);
account.balance = total_supply;
ft.set_account(&owner_id, &account);
Expand Down Expand Up @@ -238,7 +244,7 @@ impl FungibleToken {
/// Helper method to set the account details for `owner_id` to the state.
fn set_account(&mut self, owner_id: &AccountId, account: &Account) {
let account_hash = env::sha256(owner_id.as_bytes());
if account.balance > 0 || !account.allowances.is_empty() {
if account.balance > 0 || account.num_allowances > 0 {
self.accounts.insert(&account_hash, &account);
} else {
self.accounts.remove(&account_hash);
Expand Down Expand Up @@ -318,18 +324,6 @@ mod tests {
assert_eq!(contract.get_balance(bob()).0, total_supply);
}

#[test]
#[should_panic]
fn test_new_twice_fails() {
let context = get_context(carol());
testing_env!(context);
let total_supply = 1_000_000_000_000_000u128;
{
let _contract = FungibleToken::new(bob(), total_supply.into());
}
FungibleToken::new(bob(), total_supply.into());
}

#[test]
fn test_transfer() {
let mut context = get_context(carol());
Expand Down Expand Up @@ -418,7 +412,7 @@ mod tests {

#[test]
#[should_panic(
expected = "The required attached deposit is 33100000000000000000000, but the given attached deposit is is 0"
expected = "The required attached deposit is 12400000000000000000000, but the given attached deposit is is 0"
)]
fn test_self_allowance_fail_no_deposit() {
let mut context = get_context(carol());
Expand Down
18 changes: 9 additions & 9 deletions examples/gas-fee-tester/Cargo.lock

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

Binary file modified examples/gas-fee-tester/res/gas_fee_tester.wasm
Binary file not shown.
Loading