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

Update to sdk3.0.0 node 2.3.0 nonfungible token contracts #37

Merged
merged 18 commits into from May 7, 2019
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
32 changes: 32 additions & 0 deletions libraries/NonFungibleToken/contracts/math.aes
@@ -0,0 +1,32 @@
namespace SafeMath =
alekseytsekov marked this conversation as resolved.
Show resolved Hide resolved

public function add(a : int, b : int) : int =
let c = a + b
require((b >= 0 && c >= a) || (b < 0 && c < a), "Invalid sum operation.")

c

public function sub(a : int, b : int) : int =
let c = a - b
require((b >= 0 && c =< a) || (b < 0 && c > a), "Invalid subtract operation.")

c

public function mul(a : int, b : int) : int =
if (a == 0)
0
else
let c = a * b
require(c / a == b, "Invalid multiplication operation.")

c

public function div(a : int, b : int) : int =
require(b > 0, "Cannot divide to 0.")
let c = a / b

c

private function require(expression : bool, error : string) =
if(!expression)
abort(error)
112 changes: 0 additions & 112 deletions libraries/NonFungibleToken/contracts/non-fungible-burnable-token.aes

This file was deleted.

210 changes: 90 additions & 120 deletions libraries/NonFungibleToken/contracts/non-fungible-full-token.aes
@@ -1,145 +1,115 @@
include "math.aes"

contract NonFungibleFull =
type token_id = int
record state = {
name : string,
symbol : string,
owner : address,
ownedTokensCount : map(address, int),
tokenOwner : map(token_id, address),
tokenApprovals : map(token_id, address),
operatorApprovals : map(address, map(address, bool)),
tokenURIs : map(token_id, string)}

public stateful function init(name : string, symbol : string) = {
name: string,
symbol: string,
owner: address,
m_owned_tokens_count: map(address, int),
alekseytsekov marked this conversation as resolved.
Show resolved Hide resolved
m_token_owner: map(token_id, address),
m_token_approvals: map(token_id, address),
m_operator_approvals: map(address, map(address, bool)),
m_token_uris: map(token_id, string)}

public stateful function init(name: string, symbol: string) = {
name = name,
symbol = symbol,
owner = Call.caller,
ownedTokensCount = {},
tokenOwner = {},
tokenApprovals = {},
operatorApprovals = {},
tokenURIs = {}}

public function name() : string = state.name
public function symbol() : string = state.symbol
public function balanceOf(tokenOwner : address) : int = lookupByAddress(tokenOwner, state.ownedTokensCount, 0)
public function ownerOf(tokenId : token_id) : address = lookupById(tokenId, state.tokenOwner, #0)
public function getApproved(tokenId : token_id) : address = lookupById(tokenId, state.tokenApprovals, #0)

public function isApprovedForAll(_owner: address, operator : address) : bool =
let x : map(address, bool) = isOperatorApprovals(_owner)
switch(Map.lookup(operator, x))
None => false
Some(x) => x

public function getTokenURI(tokenId : token_id) : string = lookupById(tokenId, state.tokenURIs, "")

public stateful function setTokenURI(tokenId : token_id, uri : string) =
onlyTokenOwner(Call.caller, tokenId)
put(state{ tokenURIs[tokenId] = uri })

public stateful function mint(tokenId : token_id, to : address) =
onlyOwner(Call.caller)
require(!checkTokenExists(tokenId), "Token can't be overrided")
m_owned_tokens_count = {},
m_token_owner = {},
m_token_approvals = {},
m_operator_approvals = {},
m_token_uris = {}}

public function get_caller() : address =
Call.caller

public function name() : string =
state.name

public function symbol() : string =
state.symbol

public function balance_of(token_owner: address) : int =
Map.lookup_default(token_owner, state.m_owned_tokens_count, 0)

public function owner_of(token_id': token_id) : address =
Map.lookup_default(token_id', state.m_token_owner, #0)

public function get_approved(token_id': token_id) : address =
Map.lookup_default(token_id', state.m_token_approvals, #0)

public function is_approved_for_all(owner': address, operator: address) : bool =
let m_operator_approvals' : map(address, bool) = Map.lookup_default(owner', state.m_operator_approvals, {})
Map.lookup_default(operator, m_operator_approvals', false)

public function get_token_uri(token_id': token_id) : string =
Map.lookup_default(token_id', state.m_token_uris, "")

public stateful function set_token_uri(token_id': token_id, uri: string) =
only_token_owner(Call.caller, token_id')
put(state{ m_token_uris[token_id'] = uri })

public stateful function mint(token_id': token_id, to: address) =
only_owner(Call.caller)
require(Map.lookup_default(token_id', state.m_token_owner, #0) == #0, "Token can't be overrided")

put(state{
tokenOwner[tokenId] = to,
ownedTokensCount[to] = add(lookupByAddress(to, state.ownedTokensCount, 0), 1)})
m_token_owner[token_id'] = to,
m_owned_tokens_count[to] = SafeMath.add(Map.lookup_default(to, state.m_owned_tokens_count, 0), 1)})

public stateful function burn(tokenId : token_id) =
onlyTokenOwner(Call.caller, tokenId)
removeTokenFrom(Call.caller, tokenId)
removeTokenMetadata(tokenId)
public stateful function burn(token_id': token_id) =
only_token_owner(Call.caller, token_id')
remove_token_from(Call.caller, token_id')
remove_token_metadata(token_id')

public stateful function approve(tokenId : int, to : address) =
let _owner : address = ownerOf(tokenId)
public stateful function approve(token_id': int, to: address) =
let owner': address = owner_of(token_id')

require(to != Call.caller, "Receiver can't be same as sender")
require(Call.caller == _owner || isApprovedForAll(_owner, Call.caller), "Not owner or not approved")
require(Call.caller == owner' || is_approved_for_all(owner', Call.caller), "Not owner or not approved")

put(state{tokenApprovals[tokenId] = to})

public function get() : address =
Call.caller
put(state{m_token_approvals[token_id'] = to})

public stateful function transferFrom(from : address, to : address, tokenId : token_id) =
require(isApprovedOrOwner(Call.caller, tokenId), "Not owner or not approved")
public stateful function transfer_from(from: address, to: address, token_id': token_id) =
require(is_approved_or_owner(Call.caller, token_id'), "Not owner or not approved")

clearApproval(from, tokenId)
removeTokenFrom(from, tokenId)
addTokenTo(to, tokenId)

public stateful function setApprovalForAll(to : address, approved : bool) =
ensureAllowed(Call.caller)
put(state{operatorApprovals[Call.caller][to] = approved})

private function isOperatorApprovals(_owner: address) : map(address, bool) =
switch(Map.lookup(_owner, state.operatorApprovals))
None => {}
Some(x) => x

private function checkTokenExists(tokenId : token_id) : bool =
switch(Map.lookup(tokenId, state.tokenOwner))
None => false
Some(x) => true

private function ensureAllowed(key : address) =
switch(Map.lookup(key, state.operatorApprovals))
None => put(state{operatorApprovals[key] = {}})
Some(_) => ()

private stateful function addTokenTo(to : address, tokenId : token_id) =
put(state{
tokenOwner[tokenId] = to,
ownedTokensCount[to] = add(lookupByAddress(to, state.ownedTokensCount, 0), 1)})

private stateful function removeTokenFrom(from : address, tokenId : token_id) =
onlyTokenOwner(from, tokenId)
put(state{
tokenOwner[tokenId] = #0,
ownedTokensCount[from] = sub(lookupByAddress(from, state.ownedTokensCount, 0), 1)})
clear_approval(from, token_id')
remove_token_from(from, token_id')
add_token_to(to, token_id')

private stateful function clearApproval(owner : address, tokenId : token_id) =
onlyTokenOwner(owner, tokenId)
Map.delete(tokenId, state.tokenApprovals)
public stateful function set_approval_for_all(to: address, approved: bool) =
put(state{m_operator_approvals[Call.caller = {}][to] = approved})

private stateful function removeTokenMetadata(tokenId : token_id) =
Map.delete(tokenId, state.tokenURIs)

private function lookupByAddress(k : address, m, v) =
switch(Map.lookup(k, m))
None => v
Some(x) => x
private stateful function add_token_to(to: address, token_id': token_id) =
put(state{
m_token_owner[token_id'] = to,
m_owned_tokens_count[to] = SafeMath.add(Map.lookup_default(to, state.m_owned_tokens_count, 0), 1)})

private function lookupById(k : int, m, v) =
switch(Map.lookup(k, m))
None => v
Some(x) => x
private stateful function remove_token_from(from: address, token_id': token_id) =
only_token_owner(from, token_id')
put(state{
m_token_owner[token_id'] = #0,
m_owned_tokens_count[from] = SafeMath.sub(Map.lookup_default(from, state.m_owned_tokens_count, 0), 1)})

private function add(_a : int, _b : int) : int =
let c : int = _a + _b
require(c >= _a, "Error")
c
private stateful function clear_approval(owner: address, token_id': token_id) =
only_token_owner(owner, token_id')
put(state{m_token_approvals = Map.delete(token_id', state.m_token_approvals)})

private function sub(_a : int, _b : int) : int =
require(_b =< _a, "Error")
_a - _b
private stateful function remove_token_metadata(token_id': token_id) =
put(state{m_token_uris = Map.delete(token_id', state.m_token_uris)})

private function require(b : bool, err : string) =
if(!b)
abort(err)
private function require(expression: bool, error: string) =
if(!expression)
abort(error)

private function onlyOwner(owner : address) =
private function only_owner(owner: address) =
require(owner == state.owner, "Only owner can mint!")

private function onlyTokenOwner(owner : address, tokenId : token_id) =
require(owner == getTokenOwner(tokenId), "Only token owner can transfer!")

private function getTokenOwner(tokenId: token_id) : address =
switch(Map.lookup(tokenId, state.tokenOwner))
None => #0
Some(x) => x
private function only_token_owner(owner: address, token_id': token_id) =
require(owner == Map.lookup_default(token_id', state.m_token_owner, #0), "Only token owner can transfer!")

private function isApprovedOrOwner(spender : address, tokenId : token_id) : bool =
let owner : address = ownerOf(tokenId)
getApproved(tokenId) == spender || owner == spender || isApprovedForAll(owner, spender)
private function is_approved_or_owner(spender: address, token_id': token_id) : bool =
let owner : address = owner_of(token_id')
get_approved(token_id') == spender || owner == spender || is_approved_for_all(owner, spender)