Skip to content

Commit

Permalink
Refactor smart contract structure (#174)
Browse files Browse the repository at this point in the history
* Refactor smart contract structure: rename FT to MRC20, NFT to MRC721, update imports, fix MRC721 name and symbol

* Refactor arithmetic operations in MRC1155 and MRC721 contracts for clarity

* Remove website deployer contract and associated test files

* Update references from ERC1155 to MRC1155 in contracts and tests
  • Loading branch information
Ben-Rey authored Dec 6, 2024
1 parent 5b2a21a commit 741f586
Show file tree
Hide file tree
Showing 53 changed files with 164 additions and 529 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,9 @@
import { Args, stringToBytes } from '@massalabs/as-types';
import { u256 } from 'as-bignum/assembly';
import * as token from './token';
import * as token from './MRC1155';
import * as mint from './mintable/mint';
import { Context } from '@massalabs/massa-as-sdk';
import { grantRole } from '../utils/accessControl';
export * from './burnable/burn';
export * from './mintable/mint';
export * from '../utils/accessControl';
export * from '../utils/ownership';

export function constructor(binaryArgs: StaticArray<u8>): void {
const args = new Args(binaryArgs);
Expand Down Expand Up @@ -35,6 +31,10 @@ export function constructor(binaryArgs: StaticArray<u8>): void {
);
}

export * from './burnable/burn';
export * from './mintable/mint';
export * from '../utils/accessControl';
export * from '../utils/ownership';
// export everything from the token module except the constructor
export {
uri,
Expand All @@ -44,4 +44,4 @@ export {
isApprovedForAll,
safeTransferFrom,
safeBatchTransferFrom,
} from './token';
} from './MRC1155';
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,15 @@ export const TRANSFER_BATCH_EVENT: string = 'TransferBatch';
export const URI_EVENT: string = 'URI';

export const INVALID_OPERATOR_ERROR: string = 'InvalidOperator';
export const ERC1155_BALANCE_OVERFLOW_ERROR: string = 'ERC1155BalanceOverflow';
export const ERC1155_INSUFFICIENT_BALANCE_ERROR: string =
'ERC1155InsufficientBalance';
export const ERC1155_INVALID_ARRAY_LENGTH_ERROR: string =
'ERC1155InvalidArrayLength';
export const ERC1155_INVALID_RECEIVER_ERROR: string = 'ERC1155InvalidReceiver';
export const ERC1155_INVALID_SENDER_ERROR: string = 'ERC1155InvalidSender';
export const ERC1155_MISSING_APPROVAL_FOR_ALL_ERROR: string =
'ERC1155MissingApprovalForAll';
export const MRC1155_BALANCE_OVERFLOW_ERROR: string = 'MRC1155BalanceOverflow';
export const MRC1155_INSUFFICIENT_BALANCE_ERROR: string =
'MRC1155InsufficientBalance';
export const MRC1155_INVALID_ARRAY_LENGTH_ERROR: string =
'MRC1155InvalidArrayLength';
export const MRC1155_INVALID_RECEIVER_ERROR: string = 'MRC1155InvalidReceiver';
export const MRC1155_INVALID_SENDER_ERROR: string = 'MRC1155InvalidSender';
export const MRC1155_MISSING_APPROVAL_FOR_ALL_ERROR: string =
'MRC1155MissingApprovalForAll';

/**
* Constructs a new Multi-NFT contract.
Expand Down Expand Up @@ -99,7 +99,7 @@ export function _balanceOfBatch(owners: string[], ids: u256[]): u256[] {
}

/**
* @param id - the id of the token - it is not used in this implementation but mandatory for the ERC1155 standard
* @param id - the id of the token - it is not used in this implementation but mandatory for the MRC1155 standard
* @returns the URI for the token
*/
export function _uri(_: u256): string {
Expand Down Expand Up @@ -165,7 +165,7 @@ export function _update(
ids: u256[],
values: u256[],
): void {
assert(ids.length == values.length, ERC1155_INVALID_ARRAY_LENGTH_ERROR);
assert(ids.length == values.length, MRC1155_INVALID_ARRAY_LENGTH_ERROR);

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

Expand All @@ -178,8 +178,9 @@ export function _update(
const fromBalance = Storage.has(fromBalanceKey)
? bytesToU256(Storage.get(fromBalanceKey))
: u256.Zero;
assert(fromBalance >= value, ERC1155_INSUFFICIENT_BALANCE_ERROR);
assert(fromBalance >= value, MRC1155_INSUFFICIENT_BALANCE_ERROR);

// @ts-ignore
Storage.set(fromBalanceKey, u256ToBytes(fromBalance - value));
}

Expand All @@ -188,9 +189,10 @@ export function _update(
const toBalance = Storage.has(toBalanceKey)
? bytesToU256(Storage.get(toBalanceKey))
: u256.Zero;
// @ts-ignore
const result = toBalance + value;
// check if toBalance + value overflow
assert(result >= toBalance, ERC1155_BALANCE_OVERFLOW_ERROR);
assert(result >= toBalance, MRC1155_BALANCE_OVERFLOW_ERROR);

Storage.set(toBalanceKey, u256ToBytes(result));
}
Expand Down Expand Up @@ -222,7 +224,7 @@ export function _update(
/**
* Update the balances of the sender and receiver
*
* It also calls the onERC1155Received or onERC1155BatchReceived function if the receiver is a contract
* It also calls the OnMRC1155Received or onMRC1155BatchReceived function if the receiver is a contract
*
* @param from - the address of the sender
* @param to - the address of the receiver
Expand All @@ -247,15 +249,15 @@ export function _updateWithAcceptanceCheck(
// use startsWith as a workaround for isAddressEoa which is not mocked in tests
if (
to.startsWith('AS') &&
functionExists(toAddress, 'onERC1155Received')
functionExists(toAddress, 'OnMRC1155Received')
) {
const output = call(
toAddress,
'onERC1155Received',
'OnMRC1155Received',
new Args().add(operator).add(from).add(id).add(value).add(data),
0,
);
// Check if the returned value is bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))
// Check if the returned value is bytes4(keccak256("OnMRC1155Received(address,address,uint256,uint256,bytes)"))
assert(
output.toString() ==
new Args().add('f23a6e61').serialize().toString(),
Expand All @@ -264,16 +266,16 @@ export function _updateWithAcceptanceCheck(
} else {
if (
to.startsWith('AS') &&
functionExists(toAddress, 'onERC1155BatchReceived')
functionExists(toAddress, 'onMRC1155BatchReceived')
) {
const output = call(
toAddress,
'onERC1155BatchReceived',
'onMRC1155BatchReceived',
new Args().add(operator).add(from).add(ids).add(values).add(data),
0,
);
// Check if the returned value is
// bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
// bytes4(keccak256("onMRC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))
assert(
output.toString() ==
new Args().add('bc197c81').serialize().toString(),
Expand All @@ -297,8 +299,8 @@ export function _safeTransferFrom(
value: u256,
data: StaticArray<u8>,
): void {
assert(to != '', ERC1155_INVALID_RECEIVER_ERROR);
assert(from != '', ERC1155_INVALID_SENDER_ERROR);
assert(to != '', MRC1155_INVALID_RECEIVER_ERROR);
assert(from != '', MRC1155_INVALID_SENDER_ERROR);

_updateWithAcceptanceCheck(from, to, [id], [value], data);
}
Expand All @@ -317,8 +319,8 @@ export function _safeBatchTransferFrom(
values: u256[],
data: StaticArray<u8>,
): void {
assert(to != '', ERC1155_INVALID_RECEIVER_ERROR);
assert(from != '', ERC1155_INVALID_SENDER_ERROR);
assert(to != '', MRC1155_INVALID_RECEIVER_ERROR);
assert(from != '', MRC1155_INVALID_SENDER_ERROR);

_updateWithAcceptanceCheck(from, to, ids, values, data);
}
Expand All @@ -335,7 +337,7 @@ export function _mint(
value: u256,
data: StaticArray<u8>,
): void {
assert(to != '', ERC1155_INVALID_RECEIVER_ERROR);
assert(to != '', MRC1155_INVALID_RECEIVER_ERROR);

_updateWithAcceptanceCheck('', to, [id], [value], data);
}
Expand All @@ -352,7 +354,7 @@ export function _mintBatch(
values: u256[],
data: StaticArray<u8>,
): void {
assert(to != '', ERC1155_INVALID_RECEIVER_ERROR);
assert(to != '', MRC1155_INVALID_RECEIVER_ERROR);

_updateWithAcceptanceCheck('', to, ids, values, data);
}
Expand All @@ -363,7 +365,7 @@ export function _mintBatch(
* @param value - the amount of tokens to burn
*/
export function _burn(from: string, id: u256, value: u256): void {
assert(from != '', ERC1155_INVALID_SENDER_ERROR);
assert(from != '', MRC1155_INVALID_SENDER_ERROR);

_updateWithAcceptanceCheck(from, '', [id], [value], []);
}
Expand All @@ -375,7 +377,7 @@ export function _burn(from: string, id: u256, value: u256): void {
* @param data - additional data to pass to the receiver
*/
export function _burnBatch(from: string, ids: u256[], values: u256[]): void {
assert(from != '', ERC1155_INVALID_SENDER_ERROR);
assert(from != '', MRC1155_INVALID_SENDER_ERROR);

_updateWithAcceptanceCheck(from, '', ids, values, []);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
*
* This file contains the implementation of the ERC1155 token standard.
* This file contains the implementation of the MRC1155 token standard.
*
* It can be extended with the following extensions:
* - mintable
Expand Down Expand Up @@ -28,9 +28,9 @@ import {
_isApprovedForAll,
_safeTransferFrom,
_safeBatchTransferFrom,
ERC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
ERC1155_INVALID_ARRAY_LENGTH_ERROR,
} from './token-internal';
MRC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
MRC1155_INVALID_ARRAY_LENGTH_ERROR,
} from './MRC1155-internal';

import { Context, isDeployingContract } from '@massalabs/massa-as-sdk';

Expand Down Expand Up @@ -104,7 +104,7 @@ export function balanceOfBatch(binaryArgs: StaticArray<u8>): StaticArray<u8> {
const ids = args
.nextFixedSizeArray<u256>()
.expect('ids argument is missing or invalid');
assert(owners.length == ids.length, ERC1155_INVALID_ARRAY_LENGTH_ERROR);
assert(owners.length == ids.length, MRC1155_INVALID_ARRAY_LENGTH_ERROR);

const balances = _balanceOfBatch(owners, ids);
return fixedSizeArrayToBytes<u256>(balances);
Expand Down Expand Up @@ -156,7 +156,7 @@ export function isApprovedForAll(binaryArgs: StaticArray<u8>): StaticArray<u8> {
/**
*
* Safe transfer of a specific amount of tokens to an address.
* The receiving address can implement the onERC1155Received interface to be called once a transfer happens.
* The receiving address can implement the OnMRC1155Received interface to be called once a transfer happens.
*
* Emits a TransferSingle event.
*
Expand All @@ -176,7 +176,7 @@ export function safeTransferFrom(binaryArgs: StaticArray<u8>): void {
const data = args.nextBytes().expect('data argument is missing or invalid');
assert(
from == sender || _isApprovedForAll(from, sender),
ERC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
MRC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
);

_safeTransferFrom(from, to, id, value, data);
Expand All @@ -185,7 +185,7 @@ export function safeTransferFrom(binaryArgs: StaticArray<u8>): void {
/**
*
* Safe transfer of a batch of tokens to an address.
* The receiving address can implement the onERC1155BatchReceived interface to be called once a transfer happens.
* The receiving address can implement the onMRC1155BatchReceived interface to be called once a transfer happens.
*
* Emits a TransferBatch event.
*
Expand All @@ -209,7 +209,7 @@ export function safeBatchTransferFrom(binaryArgs: StaticArray<u8>): void {
const data = args.nextBytes().expect('data argument is missing or invalid');
assert(
from == sender || _isApprovedForAll(from, sender),
ERC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
MRC1155_MISSING_APPROVAL_FOR_ALL_ERROR,
);

_safeBatchTransferFrom(from, to, ids, values, data);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createEvent, generateEvent } from '@massalabs/massa-as-sdk';

import { u256 } from 'as-bignum/assembly';

export function onERC1155BatchReceived(
export function onMRC1155BatchReceived(
binaryArgs: StaticArray<u8>,
): StaticArray<u8> {
const args = new Args(binaryArgs);
Expand All @@ -20,7 +20,7 @@ export function onERC1155BatchReceived(
const data = args.nextBytes().expect('data argument is missing or invalid');

generateEvent(
createEvent('ERC1155BatchReceived', [
createEvent('MRC1155BatchReceived', [
operator,
from,
ids.map<string>((id: u256) => id.toString()).join(';'),
Expand All @@ -31,7 +31,7 @@ export function onERC1155BatchReceived(
return new Args().add('bc197c81').serialize();
}

export function onERC1155Received(
export function OnMRC1155Received(
binaryArgs: StaticArray<u8>,
): StaticArray<u8> {
const args = new Args(binaryArgs);
Expand All @@ -44,7 +44,7 @@ export function onERC1155Received(
const data = args.nextBytes().expect('data argument is missing or invalid');

generateEvent(
createEvent('ERC1155Received', [
createEvent('MRC1155Received', [
operator,
from,
id.toString(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { createEvent, generateEvent } from '@massalabs/massa-as-sdk';

import { u256 } from 'as-bignum/assembly';

export function onERC1155BatchReceived(
export function onMRC1155BatchReceived(
binaryArgs: StaticArray<u8>,
): StaticArray<u8> {
const args = new Args(binaryArgs);
Expand All @@ -20,7 +20,7 @@ export function onERC1155BatchReceived(
const data = args.nextBytes().expect('data argument is missing or invalid');

generateEvent(
createEvent('ERC1155BatchReceived', [
createEvent('MRC1155BatchReceived', [
operator,
from,
ids.map<string>((id: u256) => id.toString()).join(';'),
Expand All @@ -31,7 +31,7 @@ export function onERC1155BatchReceived(
return new Args().add('wrong').serialize();
}

export function onERC1155Received(
export function OnMRC1155Received(
binaryArgs: StaticArray<u8>,
): StaticArray<u8> {
const args = new Args(binaryArgs);
Expand All @@ -44,7 +44,7 @@ export function onERC1155Received(
const data = args.nextBytes().expect('data argument is missing or invalid');

generateEvent(
createEvent('ERC1155Received', [
createEvent('MRC1155Received', [
operator,
from,
id.toString(),
Expand Down
2 changes: 1 addition & 1 deletion smart-contracts/assembly/contracts/MRC1155/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ On top of that it also includes multiples extensions to the standard to allow fo
- [mintable](./assembly/contracts/mintable.sol)
- [metadata](./assembly/contracts/metadata.sol)

It can be easily merged into massa-standards as this repository contains a set of smart contracts that are fully compatible with the ERC1155 standard with the only common depencies being ownership contract.
It can be easily merged into massa-standards as this repository contains a set of smart contracts that are fully compatible with the ERC1155 standard with the only common dependencies being ownership contract.

## Documentation

Expand Down
Loading

0 comments on commit 741f586

Please sign in to comment.