ERC-20 - 발행&소각

프동프동·2023년 1월 9일
0

Blockchain

목록 보기
6/12
post-thumbnail

토큰 발행하기

변수

  • 토큰 발행은 컨트랙트를 발행한 owner만 실행할 수 있도록 하기 위함
contract ERC20{
  mapping(address => uint256) private _balances;
	// ...
  // ...
  address public owner;
}

생성자

  • 컨트랙트 생성 시에 컨트랙트 생성자를 owner로 만들기 위함
constructor(string memory _name_, string memory _symbol_, uint8 _decimals_){
		// ...
    owner = msg.sender;
  }

함수

mint() : owner로 설정된 사람이 amount만큼 토큰을 추가로 발행한다.

function mint(address to, uint amount)public onlyOwner{
    _balances[to] += amount;
    _totalSupply += amount;
}
  • 발행 함수는 권한을 가진 사람만 해당 함수를 호출 할 수 있도록 만들어야하기 때문에 modifier를 사용한다.
  • 컨트랙트 소유자의 토큰의 수를 늘려준다.
  • 총 발행량도 함께 늘려준다.

modifier onlyOwner() : owner로 설정된 사람만 사용할 수 있도록 하기 위함

modifier onlyOwner(){
    require(msg.sender == owner, "Only Owner");
    _;
}

mint 기능을 추가한 전체 코드

  • mint 함수를 적용한 전체 코드
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract ERC20{
      mapping(address => uint256) private _balances;
      mapping(address =>mapping(address=>uint256)) private _allowances;
      uint256 private _totalSupply;
      string private _name;
      string private _symbol;
      uint8 private _decimals; 
      address public owner;
    
      event Transfer( address indexed from,  address indexed to, uint amount);
      event Approval( address indexed  from, address indexed to, uint amount);
      modifier onlyOwner(){
        require(msg.sender == owner, "Only Owner");
        _;
      }
      modifier checkBalance(uint amount){
        require(_balances[msg.sender]> amount, "Not sufficient balance");
        _;
      }
      constructor(string memory _name_, string memory _symbol_, uint8 _decimals_){
        _name = _name_;
        _symbol = _symbol_;
        _decimals = _decimals_;
        _totalSupply = 10000000 * 10 **(18);
        owner = msg.sender;
      }
      function name() public view returns (string memory){
        return _name;
      }
      function symbol() public view returns (string memory){
        return _symbol;
      }
      function decimals() public view returns (uint8){
        return _decimals;
      }
    
      function totalSupply() public view returns (uint256){
        return _totalSupply;
      }
      
      function balanceOf(address account) public view returns (uint256){
        return _balances[account];
      }
    
      function transfer(address to, uint256 amount) public checkBalance(amount) returns (bool){
        _balances[msg.sender] -= amount;
        _balances[to] += amount; 
        emit Transfer(msg.sender, to, amount);
        return true;
      }
      
      function allowance(address _owner_, address spender)public view returns (uint256){
        return _allowances[_owner_][spender];
      }
      function mint(address to, uint amount)public onlyOwner{
        _balances[to] += amount;
        _totalSupply += amount;
      }
      
      function approve(address spender, uint256 amount) public checkBalance(amount) returns (bool){
        _allowances[msg.sender][spender] = amount;
        emit Approval(msg.sender, spender, amount);
        return true;
      }
    
      function transferFrom(address from, address to, uint256 amount) public returns (bool){
        require(_balances[from]> amount, "Not sufficient balance");
        require(_allowances[from][to]>amount,"Not allowed amount");
        require(to == msg.sender, "Not allowed user");
        _balances[from] -= amount;
        _balances[to] += amount;
        emit Transfer(from, to, amount);
        return true;
      }
    }

실행

  1. 컨트랙트를 WEMIX Testnet에 배포한다.(트랜잭션 발생)

    • 배포한 Account
    0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
  2. owner의 주소를 확인한다.

    [output]
    address : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
  3. owner의 주소를 통해 mint(owner, amount) 함수 호출(트랜잭션 발생)

    • 1000개 발행
    [intput]
    to : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    amount : 1000000000000000000000
  4. totalSupply() 함수를 이용해 총 발행량 확인

    [output]
    amount: 10001000000000000000000000
  5. transfer 함수를 이용해 다른 주소로 토큰 전송(트랜잭션 발생)

    • 100개의 토큰 전송
      [input]
      to : 0x4EBbD4881a45B836bAc17EA52F1BcEF72b787B0e
      
      [output]
      amount : 100000000000000000000
  6. balanceOf 함수를 이용해 전달받은 토큰 확인

    [input]
    account : 0x4EBbD4881a45B836bAc17EA52F1BcEF72b787B0e
    
    [output]
    amount : 1000000000000000000000
  7. balanceOf 함수를 이용해 보내고 남은 잔액 확인

    [input]
    account : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    
    [output]
    amount : 900000000000000000000

토큰 소각하기

방법 1. 사용자의 잔액을 Balance에서 없애버리기

방법 2. 사용자의 잔액을 쓸 수 없는 주소로 보내버리기

  • address(0)의 주소로 토큰을 보내버리는 것

사용자가 직접 소각하기

  • 사용자가 직접 자신의 토큰을 소각시킨다.
    • 해당 토큰의 생태계를 발전 시키기 위해 소각시키는 경우
    • transfer() 함수를 이용해 Zero Address로 보내버린다.
function burnByUser(uint amount) public {
    transfer(address(0),amount);
    _totalSupply -= amount;
}

관리자가 직접 소각하기

  • mint()와 반대로 사용자의 잔액에서 뺴주고 전체 발행량에서도 빼준다.
function burn(address to, uint amount) public onlyOwner{
    _balances[to] -= amount;
    _totalSupply -= amount;
 }

WEMIX3.0 Explorer (Testnet)

실행

  1. 컨트랙트 배포(트랜잭션 발생)

    0x2C79292506347d434C75168D0F9A91A4D6C07c3F
  2. owner()를 통해 owner 주소 확인

    [output]
    0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
  3. mint()를 통해 1000개의 토큰 발행(트랜잭션 발생)

    [input]
    to : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    amount : 1000000000000000000000
  4. balanceOf()를 통해 발행된 토큰 개수 확인하기

    [input] 
    account : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    
    [output]
    1000000000000000000000
  5. burn()를 통해 토큰 소각

    [input]
    to : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    amount : 500000000000000000000
  6. balanceOf()를 통해 확인하기

    [input]
    account : 0xDc45fE9fF7aF3522bB2B88a602670Ab4bE2C6f91
    
    [output]
    500000000000000000000

WEMIX3.0 Explorer (Testnet)

전체 코드

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

contract ERC20{
  mapping(address => uint256) private _balances;
  mapping(address =>mapping(address=>uint256)) private _allowances;
  uint256 private _totalSupply;
  string private _name;
  string private _symbol;
  uint8 private _decimals; 
  address public owner;

  event Transfer( address indexed from,  address indexed to, uint amount);
  event Approval( address indexed  from, address indexed to, uint amount);
  modifier onlyOwner(){
    require(msg.sender == owner, "Only Owner");
    _;
  }
  modifier checkBalance(uint amount){
    require(_balances[msg.sender]> amount, "Not sufficient balance");
    _;
  }
  constructor(string memory _name_, string memory _symbol_, uint8 _decimals_){
    _name = _name_;
    _symbol = _symbol_;
    _decimals = _decimals_;
    _totalSupply = 10000000 * 10 **(18);
    owner = msg.sender;
  }
  function name() public view returns (string memory){
    return _name;
  }
  function symbol() public view returns (string memory){
    return _symbol;
  }
  function decimals() public view returns (uint8){
    return _decimals;
  }

  function totalSupply() public view returns (uint256){
    return _totalSupply;
  }
  
  function balanceOf(address account) public view returns (uint256){
    return _balances[account];
  }

  function transfer(address to, uint256 amount) public checkBalance(amount) returns (bool){
    _balances[msg.sender] -= amount;
    _balances[to] += amount; 
    emit Transfer(msg.sender, to, amount);
    return true;
  }
  
  function allowance(address _owner_, address spender)public view returns (uint256){
    return _allowances[_owner_][spender];
  }
  function mint(address to, uint amount)public onlyOwner{
    _balances[to] += amount;
    _totalSupply += amount;
  }
  function burn(address to, uint amount) public onlyOwner{
    _balances[to] -= amount;
    _totalSupply -= amount;
  }
  function burnByUser(uint amount) public {
    transfer(address(0),amount);
    _totalSupply -= amount;
  }
  function approve(address spender, uint256 amount) public checkBalance(amount) returns (bool){
    _allowances[msg.sender][spender] = amount;
    emit Approval(msg.sender, spender, amount);
    return true;
  }

  function transferFrom(address from, address to, uint256 amount) public returns (bool){
    require(_balances[from]> amount, "Not sufficient balance");
    require(_allowances[from][to]>amount,"Not allowed amount");
    require(to == msg.sender, "Not allowed user");
    _balances[from] -= amount;
    _balances[to] += amount;
    emit Transfer(from, to, amount);
    return true;
  }
}
profile
좋은 개발자가 되고싶은

0개의 댓글