Skip to content

Commit

Permalink
Transform u256 to u64 in NFT
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben-Rey committed Nov 3, 2023
1 parent b2e665c commit 609f299
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 114 deletions.
61 changes: 32 additions & 29 deletions smart-contracts/assembly/contracts/NFT/NFT-internals.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { stringToBytes, bytesToU256, u256ToBytes } from '@massalabs/as-types';
import { Storage, Context } from '@massalabs/massa-as-sdk';
import { u256 } from 'as-bignum/assembly';
import { stringToBytes, bytesToU64, u64ToBytes } from '@massalabs/as-types';
import { Storage, Context, validateAddress } from '@massalabs/massa-as-sdk';

import {
approvedForAllTokenKey,
approvedTokenKey,
Expand All @@ -14,31 +14,31 @@ import {
* Increment the NFT counter
*/
export function _increment(): void {
const currentID = bytesToU256(Storage.get(counterKey));
const newID = u256.add(currentID, u256.fromU32(1));
Storage.set(counterKey, u256ToBytes(newID));
const currentID = bytesToU64(Storage.get(counterKey));
const newID = currentID + 1;
Storage.set(counterKey, u64ToBytes(newID));
}

export function _updateBalanceOf(address: string, increment: boolean): void {
const balanceKey = stringToBytes('balanceOf_' + address);
const number = increment ? 1 : -1;

if (Storage.has(balanceKey)) {
const balance = bytesToU256(Storage.get(balanceKey));
const newBalance = u256.add(balance, u256.fromI32(number));
Storage.set(balanceKey, u256ToBytes(newBalance));
const balance = bytesToU64(Storage.get(balanceKey));
const newBalance = balance + number;
Storage.set(balanceKey, u64ToBytes(newBalance));
} else {
assert(number == 1, 'Balance cannot be negative');
Storage.set(balanceKey, u256ToBytes(new u256(1)));
Storage.set(balanceKey, u64ToBytes(1));
}
}

export function _getBalanceOf(address: string): u256 {
export function _getBalanceOf(address: string): u64 {
const balanceKey = stringToBytes('balanceOf_' + address);

if (!Storage.has(balanceKey)) return new u256(0);
if (!Storage.has(balanceKey)) return 0;

return bytesToU256(Storage.get(balanceKey));
return bytesToU64(Storage.get(balanceKey));
}

/**
Expand All @@ -52,10 +52,10 @@ export function _onlyOwner(): bool {
* @param tokenId - the tokenID
* @returns true if the caller is token's owner
*/
export function _isTokenOwner(address: string, tokenId: u256): bool {
export function _isTokenOwner(address: string, tokenId: u64): bool {
// as we need to compare two byteArrays, we need to compare the pointers
// we transform our byte array to their pointers and we compare them
const left = nft1_ownerOf(u256ToBytes(tokenId));
const left = nft1_ownerOf(u64ToBytes(tokenId));
return (
memory.compare(
changetype<usize>(left),
Expand All @@ -69,16 +69,16 @@ export function _isTokenOwner(address: string, tokenId: u256): bool {
* @param tokenId - the tokenID
* @returns true if the token is minted
*/
export function _onlyMinted(tokenId: u256): bool {
export function _onlyMinted(tokenId: u64): bool {
return Storage.has(ownerTokenKey + tokenId.toString());
}

/**
* Internal function returning the currentSupply
* @returns u256
* @returns u64
*/
export function _currentSupply(): u256 {
return bytesToU256(Storage.get(counterKey));
export function _currentSupply(): u64 {
return bytesToU64(Storage.get(counterKey));
}

// ==================================================== //
Expand All @@ -89,7 +89,7 @@ export function _transfer(
caller: string,
owner: string,
recipient: string,
tokenId: u256,
tokenId: u64,
): void {
assertIsMinted(tokenId);
assertIsOwner(owner, tokenId);
Expand All @@ -115,7 +115,7 @@ export function _transfer(
* @param tokenId - The token ID to approve
*/
export function _approve(
tokenId: u256,
tokenId: u64,
owner: string,
spenderAddress: string,
): void {
Expand All @@ -131,20 +131,19 @@ export function _approve(
* Removes the approval of the token
* @param tokenId - the tokenID
*/
function _removeApproval(id: u256): void {
const key = approvedTokenKey + id.toString();
function _removeApproval(tokenId: u64): void {
const key = approvedTokenKey + tokenId.toString();
Storage.set(key, '');
}

export function _getApproved(tokenId: u256): string {
export function _getApproved(tokenId: u64): string {
const key = approvedTokenKey + tokenId.toString();

if (!Storage.has(key)) return '';

return Storage.get(key);
}

export function _isApproved(address: string, tokenId: u256): bool {
export function _isApproved(address: string, tokenId: u64): bool {
if (address.length === 0) return false;
const approvedAddress = _getApproved(tokenId);
return approvedAddress === address;
Expand Down Expand Up @@ -176,18 +175,18 @@ export function _isApprovedForAll(owner: string, operator: string): bool {
// ==== General Assertions ==== //
// ==================================================== //

export function assertIsMinted(tokenId: u256): void {
export function assertIsMinted(tokenId: u64): void {
assert(_onlyMinted(tokenId), `Token ${tokenId.toString()} is not minted`);
}

export function assertIsOwner(address: string, tokenId: u256): void {
export function assertIsOwner(address: string, tokenId: u64): void {
assert(
_isTokenOwner(address, tokenId),
`${address} is not the owner of ${tokenId.toString()}`,
);
}

function assertIsApproved(owner: string, caller: string, tokenId: u256): void {
function assertIsApproved(owner: string, caller: string, tokenId: u64): void {
assert(
_isApproved(caller, tokenId) ||
_isApprovedForAll(owner, caller) ||
Expand All @@ -203,6 +202,10 @@ export function assertNotSelfTransfer(owner: string, recipient: string): void {
);
}

export function assertAddressIsValid(address: string): void {
assert(validateAddress(address), 'Address is not valid');
}

// ==================================================== //
// ==== EVENTS ==== //
// ==================================================== //
Expand Down
62 changes: 32 additions & 30 deletions smart-contracts/assembly/contracts/NFT/NFT.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ import {
import {
Args,
stringToBytes,
bytesToU256,
u256ToBytes,
bytesToU64,
u32ToBytes,
u64ToBytes,
} from '@massalabs/as-types';
import { u256 } from 'as-bignum/assembly';
import {
assertIsMinted,
_onlyOwner,
Expand All @@ -38,7 +37,7 @@ export const counterKey = stringToBytes('Counter');
export const ownerTokenKey = 'ownerOf_';
export const approvedTokenKey = 'approved_';
export const approvedForAllTokenKey = 'approvedForAll_';
export const initCounter = new u256(0);
export const initCounter = 0;

/**
* Initialize all the properties of the NFT (contract Owner, counter to 0...)
Expand All @@ -59,13 +58,13 @@ export const initCounter = new u256(0);
* new Args()
* .add(NFTName)
* .add(NFTSymbol)
* .add(u256(NFTtotalSupply))
* .add(NFTtotalSupply)
* .add(NFTBaseURI)
* .serialize(),
* );
* ```
*
* @param binaryArgs - arguments serialized with `Args` containing the name, the symbol, the totalSupply as u256,
* @param binaryArgs - arguments serialized with `Args` containing the name, the symbol, the totalSupply as u64,
* the baseURI
*/
export function constructor(binaryArgs: StaticArray<u8>): void {
Expand All @@ -79,18 +78,18 @@ export function constructor(binaryArgs: StaticArray<u8>): void {
.nextString()
.expect('symbol argument is missing or invalid');
const totalSupply = args
.nextU256()
.nextU64()
.expect('totalSupply argument is missing or invalid');
const baseURI = args
.nextString()
.expect('baseURI argument is missing or invalid');

Storage.set(nameKey, name);
Storage.set(symbolKey, symbol);
Storage.set(totalSupplyKey, u256ToBytes(totalSupply));
Storage.set(totalSupplyKey, u64ToBytes(totalSupply));
Storage.set(baseURIKey, baseURI);
Storage.set(ownerKey, Context.caller().toString());
Storage.set(counterKey, u256ToBytes(initCounter));
Storage.set(counterKey, u64ToBytes(initCounter));
}

/**
Expand Down Expand Up @@ -136,16 +135,18 @@ export function nft1_symbol(

/**
* Returns the token URI (external link written in NFT where pictures or others are stored)
* @param binaryArgs - u256 serialized tokenID with `Args`
* @param binaryArgs - u64 serialized tokenID with `Args`
*/
export function nft1_tokenURI(binaryArgs: StaticArray<u8>): StaticArray<u8> {
const args = new Args(binaryArgs);
const tokenId = args
.nextU256()
.nextU64()
.expect('token id argument is missing or invalid')
.toString();
if (Storage.has(tokenURIKey + tokenId)) {
return stringToBytes(Storage.get(tokenURIKey + tokenId));

const key = tokenURIKey + tokenId;
if (Storage.has(key)) {
return stringToBytes(Storage.get(key));
} else {
return stringToBytes(Storage.get(baseURIKey) + tokenId);
}
Expand All @@ -154,15 +155,17 @@ export function nft1_tokenURI(binaryArgs: StaticArray<u8>): StaticArray<u8> {
/**
* Set a token URI (external link written in NFT where pictures or others are stored).
* If not set the tokenURI will be the baseURI + tokenId
* @param binaryArgs - u256 serialized tokenID with `Args` + URI string
* @param binaryArgs - u64 serialized tokenID with `Args` + URI string
*/
export function nft1_setTokenURI(binaryArgs: StaticArray<u8>): void {
const args = new Args(binaryArgs);
const tokenId = args
.nextU256()
.nextU64()
.expect('token id argument is missing or invalid');

assertIsMinted(tokenId);
assertIsOwner(Context.caller().toString(), tokenId);

Storage.set(
tokenURIKey + tokenId.toString(),
args.nextString().expect('tokenURI argument is missing or invalid'),
Expand All @@ -182,7 +185,7 @@ export function nft1_baseURI(
/**
* Returns the max supply possible
* @param _ - unused see https://github.com/massalabs/massa-sc-std/issues/18
* @returns the u256 max supply
* @returns the u64 max supply
*/
export function nft1_totalSupply(
_: StaticArray<u8> = new StaticArray<u8>(0),
Expand All @@ -193,7 +196,7 @@ export function nft1_totalSupply(
/**
* Return the current supply.
* @param _ - unused see https://github.com/massalabs/massa-sc-std/issues/18
* @returns the u256 current counter
* @returns the u64 current counter
*/
export function nft1_currentSupply(
_: StaticArray<u8> = new StaticArray<u8>(0),
Expand All @@ -203,13 +206,13 @@ export function nft1_currentSupply(

/**
* Return the tokenId's owner
* @param _args - tokenId serialized with `Args` as u256
* @param _args - tokenId serialized with `Args` as u64
* @returns serialized Address as string
*/
export function nft1_ownerOf(_args: StaticArray<u8>): StaticArray<u8> {
const args = new Args(_args);
const tokenId = args
.nextU256()
.nextU64()
.expect('tokenId argument is missing or invalid');

assertIsMinted(tokenId);
Expand All @@ -222,7 +225,7 @@ export function nft1_ownerOf(_args: StaticArray<u8>): StaticArray<u8> {
/**
* Return the balance of the address
* @param _args - Address serialized with `Args`
* @returns the balance as u256
* @returns the balance as u64
* @throws if the address is invalid
*/
export function nft1_balanceOf(_args: StaticArray<u8>): StaticArray<u8> {
Expand All @@ -231,7 +234,7 @@ export function nft1_balanceOf(_args: StaticArray<u8>): StaticArray<u8> {
.nextString()
.expect('address argument is missing or invalid');

return u256ToBytes(_getBalanceOf(address));
return u64ToBytes(_getBalanceOf(address));
}

// ==================================================== //
Expand All @@ -245,7 +248,7 @@ export function nft1_balanceOf(_args: StaticArray<u8>): StaticArray<u8> {
*/
export function nft1_mint(_args: StaticArray<u8>): void {
assert(
bytesToU256(Storage.get(totalSupplyKey)) > _currentSupply(),
bytesToU64(Storage.get(totalSupplyKey)) > _currentSupply(),
'Max supply reached',
);

Expand All @@ -255,7 +258,6 @@ export function nft1_mint(_args: StaticArray<u8>): void {
.nextString()
.expect('mintAddress argument is missing or invalid');

// TODO: Check Address validity
_increment();

const tokenToMint = _currentSupply().toString();
Expand All @@ -266,7 +268,7 @@ export function nft1_mint(_args: StaticArray<u8>): void {

_updateBalanceOf(mintAddress, true);

generateEvent(createEvent('Mint', [tokenToMint, mintAddress]));
generateEvent(createEvent('Mint', [mintAddress]));
}

// ==================================================== //
Expand All @@ -279,7 +281,7 @@ export function nft1_mint(_args: StaticArray<u8>): void {
* @param binaryArgs - arguments serialized with `Args` containing the following data in this order :
* - the owner's account (address)
* - the recipient's account (address)
* - the tokenID (u256).
* - the tokenID (u64).
* @throws if the token is not minted or if the caller is not allowed to transfer the token
*/
export function nft1_transferFrom(binaryArgs: StaticArray<u8>): void {
Expand All @@ -292,7 +294,7 @@ export function nft1_transferFrom(binaryArgs: StaticArray<u8>): void {
.nextString()
.expect('toAddress argument is missing or invalid');
const tokenId = args
.nextU256()
.nextU64()
.expect('tokenId argument is missing or invalid');

_transfer(caller, owner, recipient, tokenId);
Expand All @@ -311,15 +313,15 @@ export function nft1_transferFrom(binaryArgs: StaticArray<u8>): void {
* @param binaryArgs - arguments serialized with `Args` containing the following data in this order:
* - the owner's - owner address
* - the spenderAddress - spender address
* - the tokenID (u256)
* - the tokenID (U64)
*/
export function nft1_approve(binaryArgs: StaticArray<u8>): void {
const args = new Args(binaryArgs);

const callerAddress = Context.caller().toString();

const tokenId = args
.nextU256()
.nextU64()
.expect('tokenId argument is missing or invalid');

const toAddress = new Address(
Expand All @@ -341,13 +343,13 @@ export function nft1_approve(binaryArgs: StaticArray<u8>): void {
* Return if the address is approved to transfer the tokenId
* @param binaryArgs - arguments serialized with `Args` containing the following data in this order :
* - the address (string)
* - the tokenID (u256)
* - the tokenID (U64)
* @returns true if the address is approved to transfer the tokenId, false otherwise
*/
export function nft1_getApproved(binaryArgs: StaticArray<u8>): StaticArray<u8> {
const args = new Args(binaryArgs);
const tokenId = args
.nextU256()
.nextU64()
.expect('tokenId argument is missing or invalid');

return stringToBytes(_getApproved(tokenId));
Expand Down
Loading

0 comments on commit 609f299

Please sign in to comment.