Klaytn BaoBob Testnet에 Token Minting 해보기
Web 3.0/Klaytn

Klaytn BaoBob Testnet에 Token Minting 해보기

Token?

 

실습

/* practice.sol */

pragma solidity  >= 0.4.24 <=0.5.6;

contract Practice {
    uint256 private totalSupply = 10;
    // private 이라 Deploy 후 확인 불가
    string public name = "KlayLion";
    // 0: string: KlayLion
    address public owner;   // contract deployer
    mapping (uint256 => string) public tokenURIs;

    constructor () public {
        owner = msg.sender;
        // 0: address: 0x5329220B8b8e57D033D6F6C5B0d66249f72fdfb9
    }

    function getTotalSupply () public view returns (uint256){
    // view is only viewing function
        return totalSupply + 10000000;
        // 0: uints256: 10000010
    }

    function setTotalSupply(uint256 newSupply) public {
        require(owner == msg.sender, 'Not owner');
        // 만약 지갑 주소가 owner와 다르면 아래 코드가 실행되지 않고, gas fee가 무의미하게 소모됨
        totalSupply = newSupply;
        // if you input the 222 -> 0: uint256: 100000222
    }

    function setTokenUri(uint256 id, string memory uri) public {
        tokenURIs[id] = uri;
        // if setToeknUri(10, "HelloKlay") -> tokenURIs(10) -> 0: string: HelloKlay 출력
    }
}

 

/* practice2(unfinished).sol */

pragma solidity  >= 0.4.24 <=0.5.6;

contract Practice {
    string public name = "KlayLion";
    string public symbol = "KL";
    //  화폐단위 같은 개념

    mapping (uint256 => address) public tokenOwner;
    mapping (uint256 => string) public tokenURIs;

    // 소유한 토큰 리스트
    mapping (address => uint256[]) private _ownedTokens;

    // mint(tokenId, uri, owner)
    // transferFrom(from, to, tokenId) -> owner가 from에서 to로 바뀌는 것을 의미함

    function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public returns (bool) {
        // to에게 tokenId(일련번호)를 발행하겠다.
        // 적힐 글자는 tokenURI
        tokenOwner[tokenId] = to; 
        tokenURIs[tokenId] = tokenURI;

        /*
        to: 0x5329220B8b8e57D033D6F6C5B0d66249f72fdfb9
        tokenId: 0
        tokenURI: pretty

        -> tokenURIs : 0 call하면 -> 0: string: pretty 출력됨
        */
        
        // add token to the list
        _ownedTokens[to].push(tokenId);
        
        return true;
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        require(from == msg.sender, "from != msg.sender");
        // 보낸 사람이 from하고 같아야 하며
        require(from == tokenOwner[tokenId], "you r not the owner of the token");
        // 보낸 사람이 토큰 소유주여야 아래 코드에서 to로 토큰을 주게 됨
        tokenOwner[tokenId ] = to; 
    }


    function ownedTokens(address owner) public view returns (uint256[] memory){
        return _ownedTokens[owner]; 
    }

    function setTokenUri(uint256 id, string memory uri) public {
        tokenURIs[id] = uri;
        // if setToeknUri(10, "HelloKlay") -> tokenURIs(10) -> 0: string: HelloKlay 출력
    }
}

위와 같이 Klaytn Scope에서 트랜잭션을 자세히 살펴보면 정상적으로 mint된 것을 확인할 수 있다.

 

 여기까지는 코드가 미완성이라 토큰을 전송해도 지갑에서 토큰이 그대로 남아있게 되므로, 토큰을 삭제하는 함수를 아래와 같이 추가하면 된다.

 

완성코드

/* practice2.sol(finished) */

pragma solidity  >= 0.4.24 <=0.5.6;

contract Practice {
    string public name = "KlayLion";
    string public symbol = "KL";
    //  화폐단위 같은 개념

    mapping (uint256 => address) public tokenOwner;
    mapping (uint256 => string) public tokenURIs;

    // 소유한 토큰 리스트
    mapping (address => uint256[]) private _ownedTokens;

    // mint(tokenId, uri, owner)
    // transferFrom(from, to, tokenId) -> owner가 from에서 to로 바뀌는 것을 의미함

    function mintWithTokenURI(address to, uint256 tokenId, string memory tokenURI) public returns (bool) {
        // to에게 tokenId(일련번호)를 발행하겠다.
        // 적힐 글자는 tokenURI
        tokenOwner[tokenId] = to; 
        tokenURIs[tokenId] = tokenURI;

        /*
        to: 0x5329220B8b8e57D033D6F6C5B0d66249f72fdfb9
        tokenId: 0
        tokenURI: pretty

        -> tokenURIs : 0 call하면 -> 0: string: pretty 출력됨
        */
        
        // add token to the list
        _ownedTokens[to].push(tokenId);

        return true;
    }

    function safeTransferFrom(address from, address to, uint256 tokenId) public {
        // 보낸 사람이 from하고 같아야 하며
        require(from == msg.sender, "from != msg.sender");
        // 보낸 사람이 토큰 소유주여야 아래 코드에서 to로 토큰을 주게 됨
        require(from == tokenOwner[tokenId], "you r not the owner of the token");
        tokenOwner[tokenId ] = to; 

        _removeTokenFromList(from, tokenId);
        _ownedTokens[to].push(tokenId);

        tokenOwner[tokenId] = to;

    }

    function _removeTokenFromList(address from, uint256 tokenId) private{
        // 만약에 19벙 토큰을 삭제한다고 하면 아래와 같이 swap하여 배열을 조작함 
        // [10, 15, 19, 20]
        // [10, 15, 20, 19]
        // [10, 15, 20] 
        uint256 lastTokenIndex = _ownedTokens[from].length-1;

        for(uint256 i=0; i<_ownedTokens[from].length; i++){
            if (tokenId == _ownedTokens[from][i]) {
                // swap last token with deleting token 
                _ownedTokens[from][i] = _ownedTokens[from][lastTokenIndex];
                _ownedTokens[from][lastTokenIndex] = tokenId;
                break;
            }
        }
        
        _ownedTokens[from].length--;
    }


    function ownedTokens(address owner) public view returns (uint256[] memory){
        return _ownedTokens[owner]; 
    }

    function setTokenUri(uint256 id, string memory uri) public {
        tokenURIs[id] = uri;
        // if setToeknUri(10, "HelloKlay") -> tokenURIs(10) -> 0: string: HelloKlay 출력
    }
}