ERC1155 스마트 컨트랙트(SmartContract)를 만들어보자 [6]

SmartContract

1. 시작하기 앞서

ERC1155 스마트 컨트랙트는 단순하게 말하면 이전 편에서 했었던 ERC20과 ERC721을 결합한 형태라 볼 수 있다.

EIP-165를 지원하고 ERC20이나 ERC721과는 다르게 한 번의 트랜잭션으로 여러 자산을 전송하거나 일괄 승인이 가능하다. 또한 ERC1155에서 자산을 mint할때 공급량을 1로 하면 NFT로 처리가 된다.

2. ERC1155 예시

// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;

import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
import "@openzeppelin/contracts/utils/Counters.sol";

contract TestERC1155 is ERC1155 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() ERC1155("https://game.example/api/item/1.json") {
        _mint(msg.sender, GOLD, 10**18, "");  // 재화
        _mint(msg.sender, THORS_HAMMER, 1, ""); // NFT 아이템
    }

    function createNFT(address player, string memory tokenURI)
    public
    returns (uint256)
    {
        uint256 newItemId = _tokenIds.current();
        _mint(player, newItemId);
        _setTokenURI(newItemId, tokenURI);

        _tokenIds.increment();
        return newItemId;
    }
}

예시로 짜보았다. 스마트 컨트랙트 초기 생성자에서 골드라는 재화와 토르의 망치라는 NFT를 생성하고 스마트 컨트랙트 발급자에게 부여한다. 그리고 NFT를 만들 수 있는 기능을 넣어두었다. URI는 ERC721과 같이 MetadataURI인데 해당 형태는 이전 포스팅 ERC721편을 보면 나와 있다.

이처럼 ERC20의 재화와 ERC721의 NFT를 발급할 수 있어 ERC1155를 ERC20과 ERC721을 결합한 형태라고들 한다. 하지만 더 중요한 것은 하나의 트랜잭션으로 일괄 전송과 일괄 승인이 가능한 것인데 ERC1155의 해당 함수를 보자.

// 일괄 전송
function safeBatchTransferFrom(
    address from,
    address to,
    uint256[] memory ids,
    uint256[] memory amounts,
    bytes memory data
) public virtual override { 
	...
}


// 일괄 잔액 확인
function balanceOfBatch(
    address[] memory accounts,
    uint256[] memory ids
) public view virtual override returns (uint256[] memory) {
	...
}


// 일괄 승인
function setApprovalForAll(address operator, bool approved) public virtual override {
	...
}

위의 safeBatchTransferFrom함수에서 ids와 amounts가 array형태인 것을 볼 수 있다.

예를 들어, ids = [3,6,9]이고 amounts = [100,200,300]이라면 3번에게 100토큰을 6번에게 200토큰을 주게 된다.

기존에는 한 트랙잭션에서 한 주소에게 밖에 보내지 못했다면 ERC1155에서는 한 번에 일괄적으로 보낼 수 있어 수수료 절감 효과가 있다고 볼 수 있다.

3. ERC1155토큰을 다른 컨트랙트로 보낼 시 주의할 점

다른 스마트 컨트랙트에서 ERC1155에서 보낸 토큰을 받으려면 해당 컨트랙트가 ERC1155Holder라는 컨트랙트를 상속해야한다.

import "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol";

contract MyContract is ERC1155Holder {
}

여기서 ERC1155Holder의 onERC1155Received와 onERC1155BatchReceived 함수를 구현하여 좀 더 복잡한 시나리오를 구현할 수 있다.

이 외 ERC1155의 사전 설정으로 ERC1155PresetMinterPauser를 상속하여 mint에 대한 엑세스 제어 및 일시 중지 기능에 대한 엑세스를 제어할 수 있다.

4. 다음편에서는

다음편에서는 기존 배포 방식과는 달리 Upgradeable Proxy로 배포를 진행해 보겠다.

Upgradeable Proxy는 기능 추가, 버그 등을 수정할 수 있도록하는 플러그인이다. 물론 제약 사항도 있으니 다음 편에 알아보자.

Comments

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다