Building ERC1155 Smart Contract with OpenZeppelin 3

Rickhy Siswanto
4 min readJan 25, 2021

Why ERC-1155? ERC-1155 is the first and only Ethereum token standard that allows users to mint both fungible (identical) and non-fungible (unique) assets in a single smart contract, Its Multi Token Standard allows for each
token ID to represent a new configurable token type, which may have its own
meta-data, supply and other attributes

ERC-1155 Functions and Events :

1. Function > balanceOf(address account, uint256 id) → uint256

Get the balance of an account’s Tokens

2. Function > balanceOfBatch(address[] accounts, uint256[] ids) → uint256[]

Get the balance of multiple account/token pairs

3. Function > setApprovalForAll(address operator, bool approved)

Enable or disable approval for a third party (“operator”) to manage all of the caller’s tokens.

4. Function > isApprovedForAll(address account, address operator) → bool

Queries the approval status of an operator for a given owner.

5. Function > safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes data)

Transfers value amount of an id from the fromAddress to the toAddress specified (with safety call).

6. Function > safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes data)

Transfers value amounts of ids from the fromAddress to the toAddress specified (with safety call).

7. Events > TransferSingle(address operator, address from, address to, uint256 id, uint256 value)

TransferSingle MUST emit when tokens are transferred, including zero value transfers as well as minting or burning (see “Safe Transfer Rules” section of the standard).

8. Events > TransferBatch(address operator, address from, address to, uint256[] ids, uint256[] values)

Equivalent to multiple TransferSingle events, where operator, from and to are the same for all transfers.

9. Events > ApprovalForAll(address account, address operator, bool approved)

Emit when approval for a second party/operator address to manage all tokens for an owner address is enabled or disabled (absense of an event assumes disabled).

10. Events > URI(string value, uint256 id)

Emit when the URI is updated for a token ID.

Developing smart contracts

According to openzeppelin, Truffle can be installed globally but recommend installing locally in each project so that you can control the version on a project by project basis.

first, you can run command in your project directory:

$ mkdir rickhy-erc1155 && cd rickhy-erc1155
$ npx truffle init
Starting init...================> Copying project files to ....Init successful, sweet!$ npm install --save-dev @openzeppelin/contracts

Make sure you are inside your project’s directory when running npx ! Otherwise, it will download the full executable

Store Solidity source files in a contracts directory. This is equivalent to the src directory you may be familiar with from other languages. Each file should have the code for a single contract, and be named after it.

Here’s what a contract for tokenized items might look like:

pragma solidity 0.6.2;import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";contract Coba is ERC1155 {constructor(
uint256[] memory _id,
uint256[] memory _tokenSuply
) public ERC1155("https://lare-media.tech/api/{id}.json") {
for (uint i=0; i<_id.length; i++) {
_mint(msg.sender, _id[i], _tokenSuply[i], "");
}
}
}

and this migration files:

const Coba = artifacts.require("Coba.sol");
module.exports = async function (deployer) {
/* Passing constructor value */return deployer .then(() => deployer.deploy(Coba, [1, 2], [10**8, 20**8]))};

Writing test in javascript

All test files should be located in the ./test directory. Truffle will only run test files with the following file extensions: .js, .ts, .es, .es6, and .jsx, and .sol. All other files are ignored.

To run all tests, simply run: $ truffle test

const Coba = artifacts.require("Coba");contract("Coba", async accounts => {  it("should put 100000000 & 25600000000 in the first & second account", async () => {    let instance = await Coba.deployed();    let balance1 = await instance.balanceOf.call(accounts[0], 1);    let balance2 = await instance.balanceOf.call(accounts[0], 2);    assert.equal(balance1.valueOf(), 100000000);    assert.equal(balance2.valueOf(), 25600000000);  });});

This test will produce the following output:

If you want to see my final code, this article is available here:

Conclusion

The ultimate purpose of building a ERC-1155 smart contracts is usage for One Smart Contract, Many Token. Whether or not your Blockchain use case has requirement of fungible, non-fungible and semi-fungible items, it is always good to have the capability to offer any of these tokens in a single token standard

--

--