크립토 좀비 - 5

Lumi·2021년 11월 27일
0

크립토 좀비

목록 보기
5/7
post-thumbnail

🔥 개요

이번 챕터에서는 ERC-721 토큰 의 전반적인 코드와 SafeMath 라이브러리에 대해서 주로 학습을 하였다.

별로 코드 자체가 어렵지 않았기 때문에 간단하게 분석만 다루어 보겠다.

  • 블록체인을 정리하는 글에서도 한번 다루었었다.

🔥 ERC-721.sol

contract ERC721 {
  event Transfer(address indexed _from, address indexed _to, uint256 _tokenId);
  event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId);

  function balanceOf(address _owner) public view returns (uint256 _balance);
  function ownerOf(uint256 _tokenId) public view returns (address _owner);
  function transfer(address _to, uint256 _tokenId) public;
  function approve(address _to, uint256 _tokenId) public;
  function takeOwnership(uint256 _tokenId) public;
}

이 부분은 어떠한 함수가 있는지를 정리해 두는 곳이다.

  • 이후 오버라이딩하여 이 함수들을 사용하게 된다.
pragma solidity ^0.4.19;

import "./zombieattack.sol";
import "./erc721.sol";
import "./safemath.sol";

contract ZombieOwnership is ZombieAttack, ERC721 {

  using SafeMath for uint256;

  mapping (uint => address) zombieApprovals;

  function balanceOf(address _owner) public view returns (uint256 _balance) {
    return ownerZombieCount[_owner];
  }

  function ownerOf(uint256 _tokenId) public view returns (address _owner) {
    return zombieToOwner[_tokenId];
  }

  function _transfer(address _from, address _to, uint256 _tokenId) private {
    ownerZombieCount[_to] = ownerZombieCount[_to].add(1);
    ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].sub(1);
    zombieToOwner[_tokenId] = _to;
    Transfer(_from, _to, _tokenId);
  }

  function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
    _transfer(msg.sender, _to, _tokenId);
  }

  function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) {
    zombieApprovals[_tokenId] = _to;
    Approval(msg.sender, _to, _tokenId);
  }

  function takeOwnership(uint256 _tokenId) public {
    require(zombieApprovals[_tokenId] == msg.sender);
    address owner = ownerOf(_tokenId);
    _transfer(owner, msg.sender, _tokenId);
  }
}
  • 원래는 토큰을 주고 받는 로직이지만 이곳에서는 좀비를 주고받는 로직으로 수정을 하였고 설명은 토큰을 주고 받는 방식으로 설명을 해보겠다.

앞서 있던 ERC-721.sol 부분을 상속받음으로써 오버라이딩 가능하게 해준다.

  • SafeMath부분은 후에 다루어 보겠다.

ERC-721에는 토큰을 전송할 떄 2개의 다른 방식이 있다.

  • transfer, approve

transfer함수 같은 경우에는 돈을 전송할 송신자가 직접 호출하여 수신자에게 돈을 송금하는 방법이다.

반대로 approve는 수신자가 송신자가 맡겨놓은 돈을 가져가는 방식이다.

_transfer함수는 그저 로직이 중복되는 것을 막기위해 선언한 함수이다.

transfer 함수 같은 경우에는 단순하게 돈을 보내고자 하는 송신자가 값을 입력하고 호출하면 된다.

approve함수는 일단 송신자가 허가를 받은 사용자에 한에서 승인을 해주어야만 전송이 가능한 함수이다.

  • 그러기 떄문에 일단 approve함수를 실행시켜 zombieApprovals에 값을 저장한다.

그후 수신자가 takeOwnership 송신자가 맡겨놓은 돈을 가져가면 된다.

중요한점

ERC-721토큰에 대해서 기본적인 함수 조건들만 지키면 된다.
- 이전에 적은 인터페이스부분에 있는 함수들만 구현하면 된다.

이러한 함수들만 구현이 된 이후에는 입맛에 따라 함수를 추가해도 된다.
- 클레이튼 같은 경우에는 4가지의 함수를 추가 하였다.

즉 ERC-721은 일종의 예시코드일 뿐이지 굳이 이 방식을 따라가지 않아도 된다.

🔥 SafeMath

library SafeMath {

  function mul(uint256 a, uint256 b) internal pure returns (uint256) {
    if (a == 0) {
      return 0;
    }
    uint256 c = a * b;
    assert(c / a == b);
    return c;
  }

  function div(uint256 a, uint256 b) internal pure returns (uint256) {
    // assert(b > 0); // Solidity automatically throws when dividing by 0
    uint256 c = a / b;
    // assert(a == b * c + a % b); // There is no case in which this doesn't hold
    return c;
  }

  function sub(uint256 a, uint256 b) internal pure returns (uint256) {
    assert(b <= a);
    return a - b;
  }

  function add(uint256 a, uint256 b) internal pure returns (uint256) {
    uint256 c = a + b;
    assert(c >= a);
    return c;
  }
}

오버 플로우, 언더 플로우 같은 오류를 방지하기 위해 사용하는 라이브러리 이다.

라이브러리를 사용할 경우에는
using SafeMath for uint256; 이런식으로 사용해야 하며

uint의 형에 따라서 사용방법이 달린다.

  • using SafeMath32 for uint32, using SafeMath16 for uint16

이 라이브러리를 사용하는 것은 별로 어렵지 않기 떄문에 간단한 예시만 보고 넘어가도록 하겠다.

기존에는 ownerZombieCount[msg.sender]++;

이렇게 사용하던 로직을

ownerZombieCount[msg.sender] = ownerZombieCount[msg.sender].add(1);

과 같이 수정하여 사용 가능하다.
profile
[기술 블로그가 아닌 하루하루 기록용 블로그]

0개의 댓글