본문 바로가기
블록체인/솔리디티

ERC20토큰

by 혀닙 2022. 7. 21.

목차

  1. 인터페이스 개념
  2. IERC20.sol
  3. ERC20.sol
  4. IvyToken.sol

 

 

1. 인터페이스 개념

인터페이스는 추상 contract와 비슷하지만, 절대로 body 부분, 즉 {} 을 가진 함수를 포함할 수 없다.

다음은 인터페이스가 가지고 있는 추가적인 제한의 내용이다.

  • 다른 contract로부터 상속받을 수 없지만, 다른 interface로부터 상속받을 수 있다.
  • 모든 선언된 함수는 contract 안에서 public일지라도, interface에서는 external 선언이 되어야만 한다.
  • constructor 선언 불가
  • 상태 변수 선언불가
  • modifier 선언 불가.

위의 제한은 미래에 변경될 수도 있는 부분임을 참고 바란다.

 

인터페이스는 기본적으로 Contract ABI가 나타낼 수 있는 것들로 제한된다.

또한 ABI와 인터페이스 간의 변환은 어떠한 정보의 손실 없이 이루어져야만 한다.

 

 

어떤 Contract가 다른 Contract로부터 상속 받을 수 있는 것처럼 Contract는 interface로부터 상속받을 수 있다.

 

인터페이스에서 선언된 모든 함수들은 묵시적으로 virtual 이다.

따라서 어떤 함수가 인터페이스에 선언된 함수를 override 하더라도 "override" 키워드를 붙일 필요는 없다.

 

(만약, 인터페이스에 선언된 함수를 override하는 함수가 자동적으로 override되도록 하고 싶다면, 그 override 함수에 virtual이라고 붙이면 된다)

 

 

2. IERC20.sol

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

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);   
    //함수 호출자: 사용자(msg.sender)
    //함수의 역할: 사용자의 대리인에 대한 위임 내용, 즉 금액에 대한 부분을 uint 타입으로 반환
    
    function approve(address spender, uint amount) external returns (bool);     /
    //함수 호출자: 사용자
    //함수의 역할: 위임
    
    function transferFrom(address spender, address recipient, uint amount) external returns(bool);    
    //함수 호출자: 대리인(msg.sender)
    //함수의 역할: 위임장에 의해 위임받은 내용 대로 행위


    event Transfer(address indexed from, address indexed to, uint value);
    event Approval(address indexed owner, address indexed spender, uint value);
	//indexed는 서브스크립트 로그로 당겨올 때 파싱하지 않아도 from과 to를 기본적으로 달아줌


}

 

 

3. ERC20.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.15;
import "./IERC20.sol";

contract ERC20 is IERC20 {

    string public name;
    string public symbol;
    uint8 public decimals = 18;

    uint public totalSupply;
    mapping(address => uint) public balances;
    mapping(address=>mapping(address=>uint)) public override allowance;
    //allowance[address1][address3] 뎁쓰가 2인 객체...

    function balanceOf(address _account) view override external returns(uint){
        return balances[_account];
    }

    function transfer(address _recipient, uint _amount) external override returns (bool){
        balances[msg.sender]-= _amount;
        balances[_recipient]+= _amount;
        return true;
    }

	//함수의 호출자는 사용자, 첫번째 매개변수인 spender는 대리인
    function approve(address spender, uint amount) external override returns (bool){
        allowance[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
    }
    
    
    //함수의 호출자는 대리인, 첫번째 매개변수인 sender는 사용자, 두번째 매개변수인 recipient는 거래상대방 
    function transferFrom(address sender, address recipient, uint amount) external override returns (bool) {
        require(allowance[sender][msg.sender] > amount);
        allowance[sender][msg.sender] -= amount;
        balances[sender] -= amount;
        balances[recipient] += amount;
        emit Transfer(sender, recipient, amount);
        return true;
    }


    //민팅. 엔트리 포인트 함수. ERC20의 컨트랙트를 상속받아서 민트 함수만 실행시켜서 간단하게 토큰 생성가능하도록 캡슐화 시킴
    //최초 생성자쪽에 넣어서 한번만 실행하게 하거나 좀더 나아가서는 컨트랙트 발송 전 발행량을 늘리기 위해 실행 가능

    function mint(uint amount) internal {
        balances[msg.sender] += amount;
        totalSupply += amount;
        emit Transfer(address(0), msg.sender, amount);
    }

    //총발행량
    function burn(uint amount) external {
        // require(owner == msg.sender);    따로 만들어서 처리
        balances[msg.sender] -= amount;
        totalSupply -= amount;
        emit Transfer(msg.sender, address(0), amount);
    }
}

 

 

4. IvyToken.sol

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

import "./ERC20.sol";

contract IvyToken is ERC20{
    address public owner;
    uint256 public ethCanBuy = 100;

    constructor(string memory _name, string memory _symbol, uint _amount){
        owner = msg.sender;
        name = _name;
        symbol = _symbol;

        mint(_amount * (10 ** uint256(decimals)));
    }

    receive() external payable{
        uint amount = msg.value * ethCanBuy;   //사용자가 tx에 보낸 value를 알 수 있음(단위: wei)
        require(balances[owner] >= amount);
        balances[owner] -= amount;
        balances[msg.sender] += amount;

        emit Transfer (owner,msg.sender, amount);
    }

    //익명함수: data 값이 없지만 to가 CA. data가 없으면 어떤 함수를 발동 시킬 지 모름. 그떄 발동되는 함수가 익명함수
    //크게 fallback과 receive 두가지 유형이 있음

    //smart contract
    /**
    {
        from: 보내는 사람
        to: CA
        data: 0x1029030
        value: 1000000000
        v
        r
        s
    }
     */
}

댓글