BlockChain
(BlockChain) Interface IERC20 / ERC20 Token 구현
JJeongHyun
2023. 3. 9. 19:35
반응형
Solidity의 interface
- 다른 컨트랙트와 상호작용이 가능
- You can interact with other contracts by declaring an interface
- 자식 컨트랙트를 위한 틀, 추상 함수로만 구성되어야 한다
- 추상 함수 : 함수이름, 매개변수, 출력만 선언해 두고 내용이 없는 함수를 뜻
- TS에서의 interface처럼 정의를 하지 않고 선언만 한다
- 특징
- 함수의 기능은 정의하지 않는다, 구현하지 못한다
- 다른 interface에서 상속이 가능하다
- 다른 interface으로부터 상속을 받을 수 없다
- 함수는 무조건 external 옵션을 설정해야 한다
- 생성자를 선언할 수 없다
- 상태변수를 선언할 수 없다
interface IERC20.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IERC20 {
function totalSupply() external view returns (uint);
function balanceOf(address account) external view returns (uint);
function transfer(address recipient, uint amount) external returns (bool);
function allowance(address owner, address spender) external returns (uint);
function approve(address spender, uint amount) external returns (bool);
function transferFrom(address sender, address recipient, uint amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint amount);
event Approval(address indexed owner, address indexed spender, uint amount);
}
- totalSupply() : 토큰(코인)의 총 수량, 토큰의 총 수량을 반환
- balanceOf(address account) : 지갑 계정의 잔액(토큰)
- transfer(address recipient, uint amount) : 토큰(코인) 보내기
- 수령인(recipient)에게 n(amount)개의 토큰을 보낸다
- 트랜잭션 발생
- allowance(address owner, address spender) : 권한을 위임받은 토큰을 관리하는 데이터 공간
- 현재 지갑 계정(owner)이 다른 누구(다른 지갑 계정 | CA)(spender)에게 얼마의 토큰에 대한 권한을 줬는지 반환
- approve(address spender, uint amount) : 권한을 위임하는 메서드
- allowance에서 확인할 수 있는 권한 위임을 실행하는 메서드. 누구(spender)에게 얼마(amount)만큼의 토큰에 대한 권한 위임
- spender가 인출할 수 있는 한도를 지정해준다(카드의 한도처럼)
- transferFrom(address sender, address recipient, uint amount) : 권한을 위임받은 토큰에 대해 거래(보내기)
- 위임받은 지갑 계정(spender)이 누구(recipient)에게 얼마(amount)만큼의 토큰을 보낸다
- sender주소에서 recipient주소로 amount만큼의 Ether를 전송
- event Transfer(address indexed from, address indexed to, uint amount) : 거래 시 기록하는 이벤트
- event Approval(address indexed from, address indexed to, uint amount) : 권한 위임 시 기록하는 이벤트
ERC20 Token 구현
- IERC20.sol를 상속받아 구현
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "./IERC20.sol";
contract ERC20 is IERC20 {
string public name;
string public symbol;
uint8 public decimals = 18;
uint public override totalSupply;
mapping(address => uint) public balances;
mapping(address => mapping(address => uint)) public override allowance;
function balanceOf(address account) external view override returns (uint) {
return balances[account];
}
function transfer(
address recipient,
uint amount
) external override returns (bool) {
balances[msg.sender] -= amount;
balances[recipient] += amount;
emit Transfer(msg.sender, recipient, amount);
return true;
}
function approve(
address spender,
uint amount
) external override returns (bool) {
allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transferFrom(
address sender,
address recipient,
uint amount
) external override returns (bool) {
require(allowance[sender][msg.sender] >= amount);
allowance[sender][msg.sender] -= amount;
balances[recipient] += amount;
balances[sender] -= amount;
emit Transfer(sender, recipient, amount);
return true;
}
function mint(uint amount) internal {
balances[msg.sender] += amount;
totalSupply += amount;
emit Transfer(address(0), msg.sender, amount);
}
function burn(uint amount) external {
balances[msg.sender] -= amount;
totalSupply -= amount;
emit Transfer(msg.sender, address(0), amount);
}
}
- import "./IERC20.sol"; : 미리 선언해 둔 interface IERC20 파일을 가져온다
- contract ERC20 is IERC20 : solidity에서 상속받을 때 is 옵션을 사용
※ interface에서 선언된 함수는 default 설정으로 virtual 옵션을 갖는다. 이러한 옵션을 가진 메서드를 상속할 경우 override 옵션을 추가해서 상속을 받아야 한다.
즉, 상속을 할 경우 상속을 받는 컨트랙트에서 override옵션을 사용하여 메서드를 다시 작성하여 덮어쓸 경우 상속하는 메서드는 virtual 옵션이어야 한다 - mapping(address => mapping(address => uint)) public override allowance; : { address : { address : uint } } 형식
- override 옵션으로 상속받는 메서드들
- function balanceOf(address account) : 계정 잔액 조회 함수
- function transfer(address recipient,uint amount) external override returns (bool) : 토큰 전송 함수
- function approve(address spender,uint amount) external override returns (bool) : 위임 권한을 주는 함수
- allowance[msg.sender][spender] = amount; : msg.sender 트랜잭션을 보낸 지갑의 계정의 토큰을 spender에게 amount 만큼 사용할 수 있도록 권한을 위임
- function transferFrom(address sender,address recipient,uint amount) external override returns (bool) : approve 메서드로 토큰에 대해 권한을 부여받은 지갑 계정(spender)이 위임받은 토큰을 다른 계정에 보낼 때 사용하는 메서드
- approve메서드의 msg.sender > transferFrom메서드의 sender
- approve메서드의 sender > transferFrom메서드의 msg.sender
- approve메서드의 msg.sender > transferFrom메서드의 sender
- function mint(uint amount) internal : 토큰 발행 메서드
- balances[msg.sender] += amount; : 트랜잭션을 보낸 지갑 계정에 원하는 만큼 토큰 추가
- totalSupply += amount; : 총 수량에 추가
- emit Transfer(address(0), msg.sender, amount); : mint함수는 토큰의 발행과 수량의 관련된 함수, 특정 계정에서 토큰이 빠져나가는 게 아니기에 Transfer 이벤트 메서드의 from값에 address(0)을 매개변수로 넘겨준다
※ address(0)은 주소에서의 null과 같다
- function burn(uint amount) external : 토큰 삭제 메서드, 토큰을 소각한다고 한다
- mint메서드와 반대로 더했던 거를 여기 burn메서드에서는 빼주고 from에 주소값이 address(0)인 것을 여기서는 to에 매개변수로 바꿔서 채워준다