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

NFT standard refund account storage based on actual size #300

Merged
merged 3 commits into from
Nov 15, 2022
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
4 changes: 2 additions & 2 deletions examples/__tests__/standard-nft/test_approval.ava.js
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ test("Simple approve", async (t) => {
msg: null,
},
{
attachedDeposit: "450000000000000000000",
attachedDeposit: "550000000000000000000",
}
);
t.assert(res.result.status.SuccessValue);
Expand All @@ -165,7 +165,7 @@ test("Approve call", async (t) => {
account_id: approvalReceiver.accountId,
msg: "return-now",
},
{ attachedDeposit: "450000000000000000000", gas: "300 Tgas" }
{ attachedDeposit: "550000000000000000000", gas: "300 Tgas" }
);
t.is(res, "cool");

Expand Down
22 changes: 14 additions & 8 deletions near-contract-standards/lib/non_fungible_token/impl.js

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

6 changes: 1 addition & 5 deletions near-contract-standards/lib/non_fungible_token/utils.d.ts

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

12 changes: 1 addition & 11 deletions near-contract-standards/lib/non_fungible_token/utils.js

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

38 changes: 28 additions & 10 deletions near-contract-standards/src/non_fungible_token/impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,13 @@ import {
} from "near-sdk-js";
import { TokenMetadata } from "./metadata";
import {
refund_approved_account_ids,
refund_storage_deposit,
refund_deposit,
refund_deposit_to_account,
assert_at_least_one_yocto,
IntoStorageKey,
Option,
bytes_for_approved_account_id,
assert_one_yocto,
refund_approved_account_ids_iter,
} from "./utils";
import { NftMint, NftTransfer } from "./events";
import { NonFungibleTokenResolver } from "./core/resolver";
Expand Down Expand Up @@ -199,15 +197,18 @@ export class NonFungibleToken
const next_approval_id_by_id = expect_approval(this.next_approval_id_by_id);
const approved_account_ids = approvals_by_id.get(token_id) ?? {};
const approval_id = next_approval_id_by_id.get(token_id) ?? 1n;
const old_approval_id = approved_account_ids[account_id];
const old_approved_account_ids_size =
serialize(approved_account_ids).length;
approved_account_ids[account_id] = approval_id;
const new_approved_account_ids_size =
serialize(approved_account_ids).length;

approvals_by_id.set(token_id, approved_account_ids);

next_approval_id_by_id.set(token_id, approval_id + 1n);

const storage_used =
old_approval_id === null ? bytes_for_approved_account_id(account_id) : 0;
new_approved_account_ids_size - old_approved_account_ids_size;
refund_deposit(BigInt(storage_used));

if (msg) {
Expand Down Expand Up @@ -242,15 +243,23 @@ export class NonFungibleToken
);

const approved_account_ids = approvals_by_id.get(token_id);
const old_approved_account_ids_size =
serialize(approved_account_ids).length;
let new_approved_account_ids_size;

if (approved_account_ids[account_id]) {
delete approved_account_ids[account_id];
refund_approved_account_ids_iter(predecessorAccountId, [account_id]);

if (Object.keys(approved_account_ids).length === 0) {
approvals_by_id.remove(token_id);
new_approved_account_ids_size = serialize(approved_account_ids).length;
} else {
approvals_by_id.set(token_id, approved_account_ids);
new_approved_account_ids_size = 0;
}
refund_storage_deposit(
predecessorAccountId,
new_approved_account_ids_size - old_approved_account_ids_size
);
}
}

Expand All @@ -270,7 +279,10 @@ export class NonFungibleToken

const approved_account_ids = approvals_by_id.get(token_id);
if (approved_account_ids) {
refund_approved_account_ids(predecessorAccountId, approved_account_ids);
refund_storage_deposit(
predecessorAccountId,
serialize(approved_account_ids).length
);

approvals_by_id.remove(token_id);
}
Expand Down Expand Up @@ -708,7 +720,10 @@ export class NonFungibleToken
}
} else {
if (approved_account_ids) {
refund_approved_account_ids(previous_owner_id, approved_account_ids);
refund_storage_deposit(
previous_owner_id,
serialize(approved_account_ids).length
);
}
return true;
}
Expand All @@ -718,7 +733,10 @@ export class NonFungibleToken
if (this.approvals_by_id) {
const receiver_approvals = this.approvals_by_id.get(token_id);
if (receiver_approvals) {
refund_approved_account_ids(receiver_id, receiver_approvals);
refund_storage_deposit(
receiver_id,
serialize(receiver_approvals).length
);
}
if (approved_account_ids) {
this.approvals_by_id.set(token_id, approved_account_ids);
Expand Down
22 changes: 2 additions & 20 deletions near-contract-standards/src/non_fungible_token/utils.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,9 @@
import { near, assert, Bytes, AccountId } from "near-sdk-js";

export function bytes_for_approved_account_id(account_id: AccountId): number {
// The extra 4 bytes are coming from Borsh serialization to store the length of the string.
return account_id.length + 4 + 8;
}

export function refund_approved_account_ids_iter(
export function refund_storage_deposit(
account_id: AccountId,
approved_account_ids: AccountId[]
storage_released: number
): void {
const storage_released = approved_account_ids
.map(bytes_for_approved_account_id)
.reduce((a, b) => a + b);
const promise_id = near.promiseBatchCreate(account_id);
near.promiseBatchActionTransfer(
promise_id,
Expand All @@ -20,16 +12,6 @@ export function refund_approved_account_ids_iter(
near.promiseReturn(promise_id);
}

export function refund_approved_account_ids(
account_id: AccountId,
approved_account_ids: { [approvals: AccountId]: bigint }
) {
refund_approved_account_ids_iter(
account_id,
Array.from(Object.keys(approved_account_ids))
);
}

export function refund_deposit_to_account(
storage_used: bigint,
account_id: AccountId
Expand Down