ERC (23/05/26)

nazzzo·2023년 5월 26일
0

ERC


ERC (Ehereum Request for Comments)

ERC는 이더리움 기반 블록체인 네트워크에서 사용되는 표준 프로토콜을 말합니다

ERC20 - 토큰
ERC721 - NFT
ERC1155 - NFT (ERC20 + ERC721)


ERC20

Token : 이더리움 메인넷을 따라서 스마트 컨트랙트로 발행된 화폐

토큰을 생성하는 것도 정해진 규칙을 따라야 하는데, 그 표준을 ERC라고 부릅니다

자산에 대한 변수명을 value로 할 것인지, amount로 할 것인지, balance로 할 것인지,
메서드명은 어떻게 할 것인지...
이러한 혼란을 막기 위해 통일성이 있는 표준이 필요하기 때문입니다
또한 실제로 가상화폐 거래소에서 거래되는 대부분의 화폐가 ERC20 토큰이기도 합니다


interface balance {
	address: string
    amount: number
}
interface Token {
	name: string
    balance: Balance[]
  	transfer(to, value) {}
}

const ZZToken = {
  name: "zzToken",
  balance : {
  	address: "0xabc...",
    amount: 50
  },
  {
  	address: "0xbcd...",
  	amount: 10
  }
}

zzToken.transfer("0xbcd...", 25)

↑ 간소화된 예시이긴 하지만, 이러한 인터페이스(ABI)를 제공하는것이 ERC의 역할



ERC20 토큰 생성하기


이번에는 가나쉬 > 테스트넷 순으로 배포작업을 진행해보려 합니다

npx ganache-cli
npx truffle init

  1. 컨트랙트 파일 작성

[SimpleStore.sol]

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;



contract SimpleStore {
    uint256 public value;
    address public owner; // 솔리디티에는 address라는 타입이 존재합니다

    constructor(uint256 _value){
        value = _value;
        owner = msg.sender;
    }
}

msg.sender는 트랜잭션을 발동시킨 사람의 주소를 가리킵니다
그래서 이 경우 owner 변수에는 해당 컨트랙트를 배포한 어카운트값이 담기게 됩니다
(가나쉬를 사용중이라면 기본값인 첫번째 어카운트가 할당됩니다)

그리고 상태변수만 만들어도 getter 메서드가 자동으로 만들어집니다
한 번 콘솔로 확인해보겠습니다

일단 배포부터 진행합니다

npx truffle migrate

*네트워크 옵션을 따로 지정하지 않으면 development(로컬) 네트워크로 배포됩니다


트러플 콘솔

// truffle console
let store;
SimpleStore.deployed().then(instance => store = instance)
store.methods

store.value()
// BN { negative: 0, words: [ 15, <1 empty item> ], length: 1, red: null }
store.owner()
// '0xbdB2e2090573cE871E64d96e7987255e65881E74'



  1. ERC20에 따라 토큰 컨트랙트 작성하기

[MyToken.sol]

contract MyToken {
    mapping(address => uint256) public balances; // balances[address] = uint256 ...매핑에 대한 추가 설명은 아래에
    string public name = 'MyToken';
    string public symbol = 'MTK'; // 통화기호
    uint8 public decimals = 18; // 1MTK = 10**18 ~ 이더리움이 사용중인 화폐 단위
    uint256 public totalSupply = 1000 * 10 ** decimals; // 총발행량 (1000개)

      constructor () {
        balances[msg.sender] = totalSupply; // owner 계좌에 총발행량 주입
    }
  
      function balanceOf(address _owner) public view returns(uint256) {
        return balances[_owner];
    } // 오너의 잔액 체크. 이 함수도 ERC20을 따릅니다
    function transter(address _to, uint256 _value) public returns(bool) {
        require(balances[msg.sender] >= _value); // throw처럼 조건검사(boolean) 후 함수를 종료시키는 함수
        return true;
    } // send 메서드 (송금)
}

이걸로 기본적인 토큰 컨트랙트 작성은 끝났습니다 (진짜...?)


이제 이 토큰 컨트랙트를 테스트넷에 배포할 차례입니다


우선 마이그레이션 파일 작성부터

[./migrations/02_delploy_myToken]

const MyToken = artifacts.require("Counter")

module.exports = (deployer) => {
    deployer.deploy(MyToken)
}

테스트넷으로 배포 실행

npx truffle migrate --network goerli

배포 결과

02_delpoy_myToken.js
====================

   Deploying 'MyToken'
   -------------------
   > transaction hash:    0xa33abdde2cb3ef5254032...
   > Blocks: 2            Seconds: 17
   > contract address:    0xb7b9Cd85a776979F76...
   > block number:        9065029
   > block timestamp:     1685071284
   > account:             0xFA2e0fBBE47B0dbe0B3c...
   > balance:             0.190967310734754099
   > gas used:            608680 (0x949a8)
   > gas price:           2.500000402 gwei
   > value sent:          0 ETH
   > total cost:          0.00152170024468936 ETH

   Pausing for 2 confirmations...

   -------------------------------
   > confirmation number: 1 (block: 9065030)
   > confirmation number: 2 (block: 9065031)
   > Saving artifacts
   -------------------------------------
   > Total cost:     0.00152170024468936 ETH

Summary
=======
> Total deployments:   2
> Final cost:          0.001969085313407696 ETH

지금까지 ERC20 표준을 잘 따랐다면, 생성된 CA값을 복사해서
메타마스크에서 바로 잔액을 확인하고 송금도 할 수 있습니다




거래소에서 토큰을 사지 말아야 할 이유...



번외) mapping()


솔리디티 mapping 함수에 대한 보충 설명입니다


mapping()

mapping(number => string) public a

a[0] = abc
a[1] = def

솔리디티는 위와 같은 방식으로 하나의 데이터를 key, value 구조의 쌍으로 그룹화할 수 있습니다
이는 하나의 상태변수에 여러 데이터를 담기 위해서(군집형) 사용합니다

자바스크립트 객체로 비유하면 한결 이해하기 쉽습니다

// mapping(number => string) public a
const a = ['abc', 'def']

0: abc
1: def

// mapping(string => string) public b
const b = {name: kim, id:"zzz"}

b.id : zzz

mapping함수는 솔리디티에만 존재하는 address 타입으로 매핑시키기도 하고,
또는 2차 배열 형태로 응용하는 등 여러 형태로 사용됩니다

mapping(address=> uint256) public c
mapping (address => mapping(uint256=> uint256)) public d

// d
{
  	"0xbdB2e2090573cE871E64d96e7987255e65881E74": {
    	0: 1234
    }
}

0개의 댓글