일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- k8s
- CSS
- 파이썬
- next.js
- 클라우드
- HTML
- VUE
- 알고리즘
- 블록체인
- 자바스크립트
- 타입스크립트
- BFS
- 리액트
- 웹
- 이더리움
- 프론트엔드
- JavaScript
- AWS
- 솔리디티
- kubernetes
- 쿠버네티스
- docker
- TypeScript
- 가상화
- 컴퓨터공학
- 백엔드
- 이슈
- 백준
- es6
- react
- Today
- Total
즐겁게, 코드
이더리움의 표준, ERC-20 인터페이스와 구현 본문
솔리디티를 활용해 다양한 방법으로 스마트 컨트랙트의 로직을 작성할 수 있음을 알고 계실 것입니다.
그런데 아마 처음 컨트랙트를 작성하게 되면 막막한 점이 한둘이 아닐 것입니다.
pragma solidity >= 0.7.0 < 0.8.0;
contract CMToken {
// 어... 뭐부터 써야 할까...
}
토큰의 필수 요소이 누락되는 것을 막고 토큰들이 이더리움 생태계에서 *호환될 수 있도록 하기 위해 이더리움에는 여러 표준 인터페이스가 존재하는데요, 오늘은 그 중 가장 기본적인 ERC-20 인터페이스를 직접 구현해보도록 하겠습니다.
(※ 예를 들어 ERC-20 기반으로 구현된 찬민토큰이 있다면, 같은 ERC-20 기반의 펀디엑스(NPXS)와도 호환될 수 있다는 의미입니다.)
1. ERC-20 인터페이스
ERC-20 인터페이스는 사용자간 토큰을 주고받기 위한 기본적인 스마트 컨트랙트의 기능을 제공하며, 구성은 다음과 같습니다.
함수
1. totalSupply() : 발행된 총 토큰의 개수를 리턴함.
function totalSupply() public view returns (uint256 : 총 토큰 개수)
2. balanceOf() : _owner가 가진 계좌 잔고를 리턴함.
function balanceOf(address _owner) public view returns (uint256 : 잔고)
3. transfer() : _to 주소로 _value 만큼의 이더를 전송함.
function transfer(address _to, uint256 _value) public returns (bool : 성공 - 실패여부)
(※ Transfer 이벤트를 호출해야 하며, 보유한 이더가 _value보다 작을 경우 throw로 에러를 명시해줘야 한다.)
4. transferFrom() : _from 주소에서 _to 주소로 _value 만큼의 이더를 전송함.
function transferFrom(address _from, address _to, uint256 _value) public returns (bool : 성공 - 실패여부)
(※ Transfer 이벤트를 호출해야 하며, 0 이더를 보내는 동작도 정상으로 처리해야 한다.)
5. approve() : _spender가 인출할 수 있는 한도를 지정함. (신용카드 한도같은 느낌)
function approve(address _spender, uint256 _value) public returns (bool : 성공 - 실패여부)
(※ Approval 이벤트를 호출해야 함.)
6. allowance() : _owner가 _spender에게 인출을 허락한 토큰의 개수
function allowance(address _owner, address _spender) public view returns (uint256 : 남은 인출 한도)
이벤트 (발생 시, 클라이언트에 정보를 전달하는 용도)
- event Transfer(address indexed _from, address indexed _to, uint256 _value)
- event Approval(address indexed _owner, address indexed _spender, uint256 _value)
2. ERC-20 인터페이스의 구현
ERC-20 기반 찬민토큰의 코드로, 리믹스 0.7.0 ~ 0.7.6 사이 버전에서 테스트해보실 수 있습니다.
(※ 다만 allowance 부분만은 제가 완전히 이해하지 못해 구현하지 않은 상태입니다.)
pragma solidity >= 0.7.0 < 0.8.0;
contract CMToken {
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
/* 총 토큰은 제작자의 생일만큼 발행됩니다. */
uint256 constant tokenTotal = 19970623;
mapping(address => uint256) public balance;
mapping(address => uint256) public approved;
constructor(uint256 initialSupply) {
balance[msg.sender] = initialSupply;
}
function totalSupply() public pure returns(uint256) {
return tokenTotal;
}
function balanceOf(address _owner) public view returns(uint256) {
return balance[_owner];
}
function transfer(address _to, uint256 _value) public returns (bool success) {
/*
1. 함수 호출을 최소화해 가스를 절약하고자 require(balanceOf[msg.sender] >= value)
대신 require(balance[msg.sender] >= value) 처럼 작성했습니다.
2. 0원도 전송할 수 있도록 허용했습니다.
*/
require(balance[msg.sender] >= _value);
require(approved[msg.sender] >= _value);
require(balance[_to] + _value >= balance[_to]);
balance[msg.sender] -= _value;
balance[_to] += _value;
/* 사용한도(approved) 차감 */
approve(msg.sender, approved[msg.sender] - _value);
return true;
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(balance[_from] >= _value);
require(approved[_from] >= _value);
require(balance[_to] + _value >= balance[_to]);
balance[_from] -= _value;
balance[_to] += _value;
approve(_from, approved[_from] - _value);
emit Transfer(_from, _to, _value);
return true;
}
function approve(address _spender, uint256 _value) public returns (bool success) {
require(balance[_spender] >= _value);
approved[_spender] = _value;
emit Approval(_spender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
/* allowance(address _owner, address _spender) 가 인터페이스에서 주어진 인자인데,
_owner와 _spender가 왜 분리되어 있는지 이해하지 못해 _owner의 승인 한도(approved) 만을 리턴하도록 하였습니다. */
return approved[_owner];
}
}
이더리움과 스마트 컨트랙트를 후원하는 openZeppelin 에서 공개한 StandardToken.sol 파일 역시 존재하니, 완전한 ERC-20을 구현한 코드가 필요하시다면 여길 참고해보시는게 좋을 듯 합니다! 😆
'💬 언어 > Solidity' 카테고리의 다른 글
솔리디티 - 08. 가스 (Gas), 가스 최적화 기법 (0) | 2021.04.19 |
---|---|
솔리디티 - 07. 컨트랙트의 소유권 (0) | 2021.04.19 |
솔리디티 - 06. 상속과 인터페이스 (0) | 2021.04.16 |
솔리디티 - 05. Storage와 Memory (0) | 2021.04.16 |
솔리디티 - 04. 매핑과 msg.sender (0) | 2021.04.16 |