Skip to content

Commit

Permalink
feat!: mutually exclude transfer & transfer_from
Browse files Browse the repository at this point in the history
A recommendation for an improvement to the NEP-4 spec at
near/NEPs#4

The change:

    -// * The caller of the function (`predecessor`) should have access to the token.
    +// * The caller of the function (`predecessor`) should own the token.
     export function transfer(new_owner_id: string, token_id: TokenId): void

BREAKING CHANGE: this intentionally deviates from the current spec
  • Loading branch information
TenzingSh committed May 20, 2020
1 parent 349d16b commit b05c6e7
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 9 deletions.
21 changes: 16 additions & 5 deletions contracts/assemblyscript/nep4/__tests__/main.unit.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { VM, Context } from 'near-sdk-as'

const alice = 'alice'
const bob = 'bob'
const carol = 'carol'

describe('grant_access', () => {
it('grants access to the given account_id for all the tokens that account has', () => {
Expand Down Expand Up @@ -58,15 +59,16 @@ describe('revoke_access', () => {
describe('transfer_from', () => {
it('transfers the given `token_id` from the given `owner_id` to `new_owner_id`', () => {
const aliceToken = nonSpec.mint_to(alice)
Context.setPredecessor_account_id(alice)

expect(get_token_owner(aliceToken)).toBe(alice)
expect(get_token_owner(aliceToken)).not.toBe(bob)
Context.setPredecessor_account_id(alice)
grant_access(bob)

transfer_from(alice, bob, aliceToken)
Context.setPredecessor_account_id(bob)
transfer_from(alice, carol, aliceToken)

expect(get_token_owner(aliceToken)).toBe(bob)
expect(get_token_owner(aliceToken)).toBe(carol)
expect(get_token_owner(aliceToken)).not.toBe(alice)
expect(get_token_owner(aliceToken)).not.toBe(bob)
})

it('requires the caller of the function to have access to the token.', () => {
Expand All @@ -77,6 +79,15 @@ describe('transfer_from', () => {
transfer_from(alice, bob, aliceToken);
}).toThrow(nonSpec.ERROR_CALLER_ID_DOES_NOT_MATCH_EXPECTATION)
})

it('requires the caller of the function to not have ownership of the token', () => {
expect(() => {
const aliceToken = nonSpec.mint_to(alice)
Context.setPredecessor_account_id(alice)

transfer_from(alice, bob, aliceToken);
}).toThrow(nonSpec.ERROR_CALLER_ID_DOES_NOT_MATCH_EXPECTATION)
})
})

describe('transfer', () => {
Expand Down
11 changes: 7 additions & 4 deletions contracts/assemblyscript/nep4/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,18 @@ export function revoke_access(escrow_account_id: string): void {
// * The caller of the function (`predecessor`) should have access to the token.
export function transfer_from(owner_id: string, new_owner_id: string, token_id: TokenId): void {
const predecessor = context.predecessor
assert(owner_id == predecessor, ERROR_CALLER_ID_DOES_NOT_MATCH_EXPECTATION)

// delegate to transfer function since this seems redundant
transfer(new_owner_id, token_id)
// fetch token escrow & verify access
const escrowAccounts = escrowAccess.getSome(owner_id)
assert(escrowAccounts.includes(predecessor), ERROR_CALLER_ID_DOES_NOT_MATCH_EXPECTATION)

// assign new owner to token
tokenToOwner.set(token_id, new_owner_id)
}

// Transfer the given `token_id` to the given `new_owner_id`. Account `new_owner_id` becomes the new owner.
// Requirements:
// * The caller of the function (`predecessor`) should have access to the token.
// * The caller of the function (`predecessor`) should own the token.
export function transfer(new_owner_id: string, token_id: TokenId): void {
const predecessor = context.predecessor

Expand Down

0 comments on commit b05c6e7

Please sign in to comment.