하드코딩으로 나만의 토큰 생성, 트랜잭션 발생 시 이더와 토큰의 이동

2021. 10. 19. 20:27Blockchain/Remix IDE

코드 작성

 

  1. MinimumViableToken.sol 파일 생성 후 코드 작성
    pragma solidity ^0.8.0;
    
    interface ERC20 {
        event Transfer(address _from, address _to, uint256 _value);
        event Approval(address _from, address _to, uint256 _value); // 한도설정
        /**
         * 총 토큰
         **/
        function totalSupply() external view returns(uint256);
        /**
         * 해당 오너가 보유한 토큰
         * */
        function balanceOf(address _owner) external view returns(uint256);
        /**
         * 실행 시 오류 확인에 편리
         * */
        function transfer(address _to, uint256 _value) external returns(bool); // 다이렉트
        function transferFrom(address _from, address _to, uint256 _value) external returns(bool); // 거쳤다 가기
        
        function approve(address _spender, uint256 _value) external returns(bool);
        function allowance(address _owner, address _spender) external view returns(uint256);
    }
    
    // default 기능 구현
    contract StandardToken is ERC20 { // 상속 == js : extended
        // 상속 받았으면 들어있는 함수를 강제로 다 사용해야함, 안하면 컴파일 시 에러 발생
        mapping(address => uint256) balances;
        mapping(address => mapping(address => uint256)) allowed; // 이중배열과 비슷
        // allowed[_from][_to] = 50eth;
        
        function totalSupply() override external view returns(uint256) {}
        
        function balanceOf(address _owner) override external view returns(uint256) {
            return balances[_owner];
        }
        
        function transfer(address _to, uint256 _value) override external returns(bool) {
            // owner -> to, owner 10 eth, _value 11 eth
            if (balances[msg.sender] >= _value && _value > 0) {
                balances[msg.sender] -= _value;
                balances[_to] += _value;
                emit Transfer(msg.sender, _to, _value);
                return true;
            } else {
                return false;
            }
        }
        
        function transferFrom(address _from, address _to, uint256 _value) override external returns(bool) {
            if (balances[_from] >= _value && _value > 0) {
                balances[_from] -= _value;
                balances[_to] += _value;
                allowed[_from][_to] -= _value;
                emit Transfer(_from, _to, _value);
                return true;
            } else {
                return false;
            }
        }
        
        function approve(address _spender, uint256 _value) override external returns(bool) {
            allowed[msg.sender][_spender] = _value;
            emit Approval(msg.sender, _spender, _value);
            return true;
        }
        
        function allowance(address _owner, address _spender) override external view returns(uint256) {
            return allowed[_owner][_spender];
        }
    }
    
    contract IngToken is StandardToken {
        string public name;                 // token name
        uint8 public decimals;              // 소수점 18 (wei)
        string public symbol;               // 단위, 이더리움의 ETH
        string public version;              // 1.0.0
        uint256 public uintsOneEthCanBuy;
        uint256 public totalEthInWei;
        address public fundWallet; // 6e0651d6ad2c6305ea6113340dc902561619eb510cd26abf38f1e35718dcca41
        
        constructor() payable public {
            name = "IngToken";
            decimals = 18;
            symbol = "ING";
            uintsOneEthCanBuy = 100;
            fundWallet = msg.sender; // 6e0651d6ad2c6305ea6113340dc902561619eb510cd26abf38f1e35718dcca41
            balances[msg.sender] = 1000000000000000000000;
        }
        
        // 2가지 익명 함수
        // fallback : 솔리디티 내장 함수
        fallback() external payable {
            totalEthInWei = totalEthInWei + msg.value;
            uint256 amount = msg.value * uintsOneEthCanBuy;
            require(balances[fundWallet] >= amount);
            
            balances[fundWallet] -= amount;
            balances[msg.sender] += amount;
            
            emit Transfer(fundWallet, msg.sender, amount);
            
            payable(fundWallet).transfer(msg.value); // 이더를 받았을 때 내 이더를 다른사람에게 주고 내 지갑에 이더를 넣는 작업
        }
        
        // approveAndCall
        function approveAndCall(address _spender, uint256 _value, bytes memory _extraData) public returns(bool){
            allowed[msg.sender][_spender] = _value;
            emit Approval(msg.sender, _spender, _value);
            
            // "receiveApproval(address, uint256, address, bytes)"
            // msg.sender
            // _value
            // address(this)
            // _extraData
            
            // abi.encodeWithSignature(,,,,) << 인자값 5개
            // 1 function       : "receiveApproval(address, uint256, address, bytes)"
            // 2 msg.sender     : 호출 시킨 사람의 주소
            // 3 _value         : 이더 수량
            // 4 address        : 받는 사람 address(this)
            // 5 byte           : _extraData
            // call이라는 함수가 실행 => object (bool, bytes)
            
            (bool success, bytes memory data) = _spender.call(
                abi.encodeWithSignature("receiveApproval(address, uint256, address, bytes)",
                    msg.sender,
                    _value,
                    address(this),
                    _extraData
                )
            );
            require(success, "call failed");
            return true;
        }
    }
  2. Auto Compile로 솔리디티 컴파일
  3. 솔리디티 배포, 아래 설정 후 Deploy 클릭
    ENVIRONMENT : InjectedWeb3
    CONTRACT : contracts/[토큰명].sol
  4. 정상적으로 완료 됐을 경우 아래 화면처럼 출력
    빨간 버튼 클릭 // 0x2867b070c3b81fEc48CCD51b25d8B00f92803cBF
    복사한 텍스트와 가나슈 [TRANSACTION] 탭에 CREATED CONTRACT ADDRESS 값과 일치하는지 확인
  5. 가나슈 0번과 1번 인덱스의 PRIVATE KEY를 메타마스크 가져오기로 각각 연결
    Show Keys 클릭 -> ACCOUNT INFORMATION 화면
    계정 가져오기 클릭
    가나슈에서 복사한 PRIVATE KEY 입력
    계정 2개 확인
  6. 가져온 계정에서 Import Token 하기
    Import tokens 클릭
    토큰 계약 주소 : 가나슈에서 CREATED CONTRACT ADDRESS 복사하여 입력, 나머지는 하드코딩 된 내용으로 자동 입력 됨
    첫 번째 계정에서 1000 ING 확인
  7. 계정에서 계정으로 이더를 보내 토큰의 변화 확인
    빨간 네모 클릭
    보내기 클릭
    내 계정 간 전송 클릭 후 보낼 계정 선택
    100~200 ING 입력 후 다음 클릭 후 확인 선택하여 이더와 토큰의 개수 변화 확인
    첫 번째 계정 : 101.9664 ETH -> 101.9653 ETH, 1000 ING -> 800 ING
    두 번째 계정 (전)
    두 번째 계정 (후) : 97.9991 ETH -> 97.9983 ETH, 0 ING -> 200 ING

그 외 확인 사항

빨간 네모 클릭
주황색(함수), 파란색(상태변수)
각 버튼 클릭하면 터미널에도 내용이 출력되며, 버튼 밑 텍스트로 상태 변수 확인 가능