일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- css기초
- JWT 만들어보기
- javascript기초
- FormData()
- 라우터 분리
- 라우트 매개변수
- OAuth 카카오
- nodejs파일업로드
- next 매개변수
- node.js path
- express router
- express session
- useContext
- mysql wsl
- JWT 하드코딩
- 라우터와 미들웨어
- 블록 만들기
- ws 라이브러리
- express실행
- useEffect clean up
- 아이디 중복체크기능
- cookie-parser 만들어보기
- JWT 로그인 기능 구현
- 라우터미들웨어 분리
- express.static
- 세션으로 로그인 구현
- 비동기파일업로드
- Uncaught Error: could not find react-redux context value; please ensure the component is wrapped in a <Provider>
- 시퀄라이즈 기본설정
- buffer.from
- Today
- Total
즐코
스마트 컨트랙트로 토큰 발행 및 전송해보기 본문
1. 코인과 토큰의 차이?!
쉽게 말하자면 메인넷의 유무이다!
- 코인 : 메인넷 즉, 독립적인 블록체인 생태계를 가지고 있는 암호화폐를 말한다.
- 토큰 : 독자적인 메인넷 없이 다른 블록체인 네트워크 위에서 발행되는 암호화폐를 말한다. 사실 화폐라기보단 파생상품 같은 느낌이다.
자세히 말하자면, 토큰을 만든다는 건 이더리움의 스마트 컨트랙트를 통해 토큰에 대한 내용을 작성하고 발행하는 것이다.
다만 정해놓은 규격에 맞춰서 스마트 컨트랙트를 작성해야하는데, 그 정해놓은 규격이 바로 ERC-20이다.
2. ERC-20
이더리움이 정한 표준 토큰 스펙, 이더리움 네트워크 상에서 발행되는 토큰의 표준, 규격이라고 보면 된다.
타입스크립트에서는 interface로 객체의 형태를 미리 정의, 규격화해서 이를 갖다 쓴다.
이와 마찬가지로 이더리움에도 미리 정해놓은 토큰 전용 interface가 존재한다고 보면 된다.
이 규격대로 솔리디티 코드를 작성하면 그 스마트 컨트랙트가 토큰이 되는 것이다.
// 타입스크립트로 토큰규격을 간단히 표현하자면 아래와 같다.
interface balance {
address: string;
amount: number;
}
interface token {
name: string;
symbol: string;
balances: balance[];
}
3. 솔리디티 문법으로 토큰용 스마트 컨트랙트 작성해보기
타입스크립트에서 interface 로 객체를 규격화했듯이 솔리디티에선 토큰용 스마트 컨트랙트 작성 시 특이한 타입을 사용해준다.
그게 바로 크립토좀비를 하면서 익힌 데이터 타입인 address, mapping, msg.sender 이다.
(관련 포스팅 : https://yjleekr.tistory.com/99 )
* 스마트 컨트랙트 작성 전에 인스턴스 생성에 관해서 짚고 넘어간다.
스마트 컨트랙트에 대한 인스턴스는 딱 한번만 생성되는데 인스턴스가 생성되는 시점은 컨트랙트를 배포할 때이다.
컨트랙트 배포 시점 = 스마트 컨트랙트가 블록에 담기고 이더리움 네트워크 (블록체인) 상에 추가될 때
스마트 컨트랙트 작성 시엔 당연히 constructor 생성자 함수에 인자값을 넣을 수 있다.
그렇다면 이 인자값을 전달해주는 시점은 언제일까? 위에서 언급한 인스턴스가 생성되는 시점 전이다. 즉 배포하기 전에 인자값을 전달해줘야한다. truffle을 이용해서 migration 파일을 작성할 때 필요한 인자값을 넣어줘야 한다!
// contracts/SimpleStore.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract SimpleStore{
uint256 public value;
address public owner;
constructor(uint256 _value){
value = _value;
owner = msg.sender;
// msg.sender : 배포 시엔 배포를 실행한 계정이 들어감
// 배포 이후엔 컨트랙트를 실행시킨 계정이 들어간다
}
function getAddress() public view returns (address){
return msg.sender;
}
}
SimpleStore 코드에서는 인스턴스 생성 시 (배포시) uint타입의 _value가 꼭 필요하다.
배포 파일에서 deploy의 2번째 인자값으로 _value를 전달해주면 된다.
// migration/2_deploy_SimpleStore.js
const SimpleStore = artifacts.require("SimpleStore");
module.exports = function(deployer){
deployer.deploy(SimpleStore, 10);
}
truffle migration 실행 후 트랜잭션을 조회해보면 input 내용은 아래와 같다.
솔리디티코드의 bytecode + 연속된 0 + 배포 코드에 넣은 인자값
연속된 0을 구분값으로 사용해서 인스턴스 생성 시 넣은 인자값을 나타내준 것이다.
본격적인 토큰 생성을 위해 토큰용 스마트 컨트랙트 작성을 해보자. 아주 기본적인 형태의 토큰이다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
contract yjToken {
mapping(address => uint256) public balances;
string public name = 'yjToken';
string public symbol = 'YTK';
uint8 public decimals = 18;
uint256 public totalSupply = 10000000000 * 10**decimals;
event Transfer(address _from, address _to, uint256 value);
// 메타마스크 상에서 보내는 계정에선 보낸 기록이 남는 반면, 받는 계정에선 받은 내역이 뜨지 않는다.
// 따라서 송금에 관한 이벤트 등록을 해준다.
constructor(){
balances[msg.sender] = totalSupply;
// 배포를 실행한 계정에다가 총 발행량을 지급해주기로 하자
}
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
// ERC-20에 의해 메타마스크가 인자값 _owner를 알아서 전달해준다고 한다. 연결된 계정을 전달해준다는 뜻
}
function transfer(address _to, uint256 _value) public returns (bool success){
require(balances[msg.sender] >= _value);
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
}
토큰을 위한 스마트 컨트랙트 발행시 정해놓은 규격인 ERC-20에 맞게 코드를 작성해야한다.
토큰에 들어가는 주요 속성들을 설명하자면 아래와 같다.
모두 public이 붙으므로 getter 함수가 자동으로 만들어져서 call() 을 통해 트랜잭션 발생없이 해당 값 조회가 가능하다.
mapping(address => uint256) public balances | { 계정/주소, 해당 계정의 잔액 } 의 배열 (ex. 비트코인에서의 utxo 같은 개념) |
string public name | 토큰의 이름 (ex. 비트코인, 이더리움 등...) |
string public symbol | 토큰의 단위 (ex. BTC, ETH 등...) |
uint8 public decimals | 토큰 십진수 |
uint256 public totalSupply | 토큰 총 발행량 |
balanceOf 함수
- 계정 잔액을 조회해주는 함수
- 인자값으로는 무조건 address 타입을 넣어줘야한다.
이는 해당 함수를 실행시킨 계정 외에도 다른 계정의 토큰 잔액을 조회할 수 있게 규격화 되있는거라고 보면 된다.
메타마스크는 연결된 계정들을 balanceOf() 함수의 인자값으로 자동으로 전달해줘서 각 계정의 토큰을 조회할 수 있게 도와준다.
transfer 함수
- 계정 간 토큰 전송을 도와주는 함수
- 트랜잭션을 발생시키기 때문에 인자값으론 무조건 address와 uint256 타입을 받는다.
메타마스크에서 해당 토큰 가져와서 다른 계정으로 전송까지 해보기!
1/ 현재 가나쉬 네트워크로 연결했으므로 가나쉬 네트워크가 제공해준 계정을 연결해준다.
2/ 계정 하단 쪽의 토큰 가져오기 버튼 클릭
3/ 아래 스크린샷이 뜨면 토큰 계약 주소에 토큰 컨트랙트 배포시 받은 CA 를 넣어준다.
=> 자동으로 컨트랙트 상의 토큰 기호(symbol), 토큰 십진수(decimals)가 들어간다! 이래서 규격을 따르는건가봄
=> 맞춤형 토큰 추가 클릭
4/ 토큰 가져오기 클릭
5/ 다른 계정을 추가로 연결하고 토큰 가져오기를 하면 이미 토큰을 배포한 계정이 총발행량을 다 가져갔기때문에 잔액이 0으로 찍힌다.
6/ 아래와 같이 배포한 계정에서 추가한 계정에게 토큰 전송이 가능하다.
'BlockChain' 카테고리의 다른 글
ETHER 전송을 위한 스마트 컨트랙트 작성 (payable) (0) | 2022.07.21 |
---|---|
스마트 컨트랙트로 초간단 투표 dApp 만들기 (0) | 2022.07.20 |
Crypto Zombie / lesson2 (0) | 2022.07.19 |
Crypto Zombie / lesson1 - Overview (0) | 2022.07.18 |
스마트 컨트랙트 이벤트 등록 / 백엔드에서 트랜잭션 생성 (0) | 2022.07.15 |