ERC (Ehereum Request for Comments)
ERC는 이더리움 기반 블록체인 네트워크에서 사용되는 표준 프로토콜을 말합니다
ERC20 - 토큰
ERC721 - NFT
ERC1155 - NFT (ERC20 + ERC721)
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의 역할
이번에는 가나쉬 > 테스트넷 순으로 배포작업을 진행해보려 합니다
npx ganache-cli
npx truffle init
[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'
[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(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
}
}