클레이튼 토큰(Klaytn Token), 핵심만 정리했습니다

sumong·2023년 1월 8일
0

블록체인

목록 보기
6/6
post-thumbnail

2021년 9월에 Klaytn Token에 대해 공부하면서 정리한 글입니다. 이 때문에, 현재는 아래의 내용과는 다른 부분이 있을 수 있습니다. 아래 문서는 Klaytn Token에 대한 참고 용도로만 사용하는 것을 권장하고, 더 정확한 건 공식 문서를 확인하시기 바랍니다.

참고 자료 : Klaytn Docs (Klaytn 자체 코인 - KLAY, Klaytn 호환 토큰)


KLAY

KLAY = Klaytn에서 전송 가능한 주요 내부 암호화폐

용도

  • 스마트 컨트랙트 작성 및 실행 시 수수료 지불 용도
  • KLAY를 전송할 때 트랜잭션 수수료 지불 용도

단위

  • peb은 가장 작은 화폐단위.
  • ston = Gpeb
  • KLAY = 10^18 peb
  • 기타 단위는 제목에 걸린 링크 참고.

KLAY 단위

단위peb 환산 가치
peb1 peb
kpeb10^3 peb
Mpeb10^6 peb
ston (Gpeb)10^9 peb
KLAY10^18 peb

KIP-7

KIP-7 = ERC-20 기반 Klaytn 대체 가능 토큰 표준이자, Klaytn 호환 토큰(KCT, Klaytn Compatible Token)의 일종. 특정 기술 스펙을 구현한 특별한 타입의 스마트 컨트랙트로, Klaytn에서 토큰을 발행하려면 이 스펙을 따라야 한다.

대체 가능한 토큰

대체 가능한 토큰 = 균등성과 가분(可分)성을 가진 토큰.
(각 토큰 단위는 동일한 가치를 가지므로 모든 가용 토큰은 서로 호환된다.)

인터페이스

아래 인터페이스를 기반으로, 새로운 기능과 논리를 추가하여 토큰을 커스터마이징하고, Klaytn 네트워크에 배포할 수 있다.

(KIP-17을 구현 시 KIP-13도 반드시 함께 구현해야 함)

// IKIP7
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);

function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
function safeTransfer(address recipient, uint256 amount, bytes data) external;
function safeTransfer(address recipient, uint256 amount) external;
function safeTransferFrom(address sender, address recipient, uint256 amount, bytes data) external;
function safeTransferFrom(address sender, address recipient, uint256 amount) external;

// IKIP7Metadata (optional)
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);

// IKIP7Mintable (optional)
function mint(address _to, uint256 _amount) external returns (bool);
function isMinter(address _account) external view returns (bool);
function addMinter(address _account) external;
function renounceMinter() external;

// IKIP7Burnable (optional)
function burn(uint256 _amount) external;
function burnFrom(address _account, uint256 _amount) external;

// IKIP7Pausable (optional)
event Paused(address _account);
event Unpaused(address _account);

function paused() external view returns (bool);
function pause() external;
function unpause() external;
function isPauser(address _account) external view returns (bool);
function addPauser(address _account) external;
function renouncePauser() external;
  • wallet interface를 구현해 지갑 애플리케이션도 개발 가능하다.
/// @title KIP-7 Fungible Token Standard, optional wallet interface
/// @dev Note: the KIP-13 identifier for this interface is 0x9d188c22.
interface IKIP7TokenReceiver {
    /// @notice Handle the receipt of KIP-7 token
    /// @dev The KIP-7 smart contract calls this function on the recipient
    ///  after a `safeTransfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param _operator The address which called `safeTransferFrom` function
    /// @param _from The address which previously owned the token
    /// @param _amount The token amount which is being transferred.
    /// @param _data Additional data with no specified format
    /// @return `bytes4(keccak256("onKIP7Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onKIP7Received(address _operator, address _from, uint256 _amount, bytes _data) external returns(bytes4);
}

인터페이스 상세 : IKIP7

  • KIP-7 대체 가능 토큰 표준 인터페이스.
  • 실제 구현시에는 KIP-13 인터페이스(IKIP13)를 상속받아야 한다.
interface IKIP7 {
	/// value만큼의 token이 from에서 to로 이동한 후,
	///   token 생성(from==0), 또는 token 삭제(to==0)시 발생하는 이벤트.
  /// (value는 0이 될 수 있다.)
  event Transfer(address indexed from, address indexed to, uint256 value);

  /// @dev Emitted when the allowance of a `spender` for an `owner` is set by
  /// a call to {approve}. `value` is the new allowance.
  event Approval(address indexed owner, address indexed spender, uint256 value);

  /// @notice 존재하는 모든 토큰 양을 반환.
  function totalSupply() external view returns (uint256);

  /// @notice 특정 계정이 소유한 토큰 양을 반환.
  /// @param account: 특정 계정 주소, address type.
  /// @return 토큰의 양, uint256 type.
  function balanceOf(address account) external view returns (uint256);

  /// @notice 함수를 호출한 사람의 계정에서 'recipient'의 계정으로 'amount'만큼의 토큰을 보냄.
  /// @dev 함수를 호출한 사람의 계정 잔액에 충분한 토큰이 없을 경우 에러 발생.
  ///      마찬가지로, Contract가 pausable하거나 paused된 경우 에러 발생.
  ///      {Transfer} 이벤트를 발생시킴.
  /// @param recipient: 토큰을 받을 주소, address type.
  /// @param amount: 보낼 토큰 양, uint256 type.
  /// @return 성공 여부, bool type.
  function transfer(address recipient, uint256 amount) external returns (bool);

  /// @notice {transferFrom}을 통해 'owner' 대신 'spender'가 사용할 수 있는 남은 토큰 수를 반환.
	///         기본값은 0.
  /// @dev 마찬가지로, Contract가 pausable하거나 paused된 경우 에러 발생.
  /// 이 값은 {approve} 또는 {transferFrom}이(가) 호출되면 변경됨.
  /// @param owner: 'spender'가 계정에서 토큰을 인출하도록 허용한 계정, address type.
  /// @param spender: 토큰을 인출하도록 승인된 주소, address type.
  /// @return 'owner'가 승인한 'spender' 토큰 금액, uint256 type.
  function allowance(address owner, address spender) external view returns (uint256);

    /// @notice Sets `amount` as the allowance of `spender` over the caller's tokens.
    /// @dev Throws if the contract is pausable and paused.
    ///
    /// IMPORTANT: Beware that changing an allowance with this method brings the risk
    /// that someone may use both the old and the new allowance by unfortunate
    /// transaction ordering. One possible solution to mitigate this race
    /// condition is to first reduce the spender's allowance to 0 and set the
    /// desired value afterwards:
    /// https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
    ///
    /// Emits an {Approval} event.
    /// @param spender The address is approved to withdraw the tokens.
    /// @param amount The token amount will be approved.
    /// @return a boolean value indicating whether the operation succeeded.
    function approve(address spender, uint256 amount) external returns (bool);

    /// @notice Moves `amount` tokens from `sender` to `recipient` using the
    /// allowance mechanism. `amount` is then deducted from the caller's
    /// allowance.
    /// @dev Throw unless the `sender` account has deliberately authorized the sender of the message via some mechanism.
    /// Throw if `sender` or `recipient` is the zero address.
    /// Throws if the contract is pausable and paused.	
    ///
    /// Emits a {Transfer} event.
    /// Emits an `Approval` event indicating the updated allowance.
    /// @param sender The current owner of the tokens.
    /// @param recipient The owner will receive the tokens.
    /// @param amount The token amount will be transferred.
    /// @return A boolean value indicating whether the operation succeeded.
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
    
    /// @notice Moves `amount` tokens from the caller's account to `recipient`.
    /// @dev Throws if the message caller's balance does not have enough tokens to spend.
    /// Throws if the contract is pausable and paused.	
    /// Throws if `_to` is the zero address. 
    /// When transfer is complete, this function checks if `_to` is a smart 
    /// contract (code size > 0). If so, it calls
    ///  `onKIP7Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256("onKIP7Received(address,address,uint256,bytes)"))`.
    /// @param recipient The owner will receive the tokens.
    /// @param amount The token amount will be transferred.
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransfer(address recipient, uint256 amount, bytes data) external;
    
    
    /// @notice Moves `amount` tokens from the caller's account to `recipient`.
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to "".
    /// @param recipient The owner will receive the tokens.
    /// @param amount The token amount will be transferred.
    function safeTransfer(address recipient, uint256 amount) external;
    
    /// @notice Moves `amount` tokens from `sender` to `recipient` using the
    /// allowance mechanism. `amount` is then deducted from the caller's
    /// allowance.
    /// @dev Throw unless the `sender` account has deliberately authorized the sender of the message via some mechanism.
    /// Throw if `sender` or `recipient` is the zero address.
    /// Throws if the contract is pausable and paused.
    /// When transfer is complete, this function checks if `_to` is a smart 
    /// contract (code size > 0). If so, it calls
    ///  `onKIP7Received` on `_to` and throws if the return value is not
    ///  `bytes4(keccak256("onKIP7Received(address,address,uint256,bytes)"))`.
    /// Emits a {Transfer} event.
    /// Emits an `Approval` event indicating the updated allowance.
    /// @param sender The current owner of the tokens.
    /// @param recipient The owner will receive the tokens.
    /// @param amount The token amount will be transferred.
    /// @param data Additional data with no specified format, sent in call to `_to`
    function safeTransferFrom(address sender, address recipient, uint256 amount, bytes data) external;

    /// @notice Moves `amount` tokens from `sender` to `recipient` using the
    /// allowance mechanism. `amount` is then deducted from the caller's
    /// allowance.
    /// @dev This works identically to the other function with an extra data parameter,
    ///  except this function just sets data to "".
    /// @param sender The current owner of the tokens.
    /// @param recipient The owner will receive the tokens.
    /// @param amount The token amount will be transferred.
    function safeTransferFrom(address sender, address recipient, uint256 amount) external;
}

KIP-17

KIP-17 = ERC-721 기반 Klaytn 대체 불가능 토큰 표준이자, Klaytn 호환 토큰(KCT, Klaytn Compatible Token)의 일종. 특정 기술 스펙을 구현한 특별한 타입의 스마트 컨트랙트로, Klaytn에서 토큰을 발행하려면 이 스펙을 따라야 한다.

(이 때문에, Klaytn에선 ERC-721 기반의 NFT 또한 발급 가능하다. 단, 일부 호환되지 않는 부분이 존재할 수 있으므로, 특별한 이유가 없다면 KIP-17 기반으로 개발할 것을 권고하고 있다.)

대체 불가능한 토큰 표준(NFT)

NFT = 고유한 자산을 나타내는 특수한 토큰 유형.

  • 각각의 모든 토큰은 고유하고 나눠질 수 없음. 즉, 가용 토큰끼리 서로 호환되지 않음.
    이 때문에, NFT는 자산의 디지털화를 위한 새 지평을 열었다는 평가를 받음.
  • 각 토큰마다 그 가치가 다름.

인터페이스

아래 인터페이스를 기반으로, 새로운 기능과 논리를 추가하여 토큰을 커스터마이징하고, Klaytn 네트워크에 배포할 수 있다.

(KIP-7을 구현 시 KIP-13도 반드시 함께 구현해야 함.)

// IKIP17
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
event Approval(address indexed _owner, address indexed _approved, uint256 indexed _tokenId);
event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved);

function balanceOf(address _owner) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes _data) external payable;
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
function transferFrom(address _from, address _to, uint256 _tokenId) external payable;
function approve(address _approved, uint256 _tokenId) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(address _owner, address _operator) external view returns (bool);

// IKIP17Metadata (optional)
function name() external view returns (string _name);
function symbol() external view returns (string _symbol);
function tokenURI(uint256 _tokenId) external view returns (string);

// IKIP17Enumerable (optional)
function totalSupply() external view returns (uint256);
function tokenByIndex(uint256 _index) external view returns (uint256);
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);

// IKIP17Mintable (optional)
function mint(address _to, uint256 _tokenId) public returns (bool);
function isMinter(address _account) public view returns (bool);
function addMinter(address _account) public;
function renounceMinter() public;

// IKIP17MetadataMintable (optional)
function mintWithTokenURI(address _to, uint256 _tokenId, string memory _tokenURI) public returns (bool);
function isMinter(address _account) public view returns (bool);
function addMinter(address _account) public;
function renounceMinter() public;

// IKIP17Burnable (optional)
function burn(uint256 _tokenId) public;

// IKIP17Pausable (optional)
event Paused(address _account);
event Unpaused(address _account);
function paused() public view returns (bool);
function pause() public;
function unpause() public;
function isPauser(address _account) public view returns (bool);
function addPauser(address _account) public;
function renouncePauser() public;
  • wallet interface를 구현해 지갑 애플리케이션도 개발 가능하다.
pragma solidity 0.4.24;

/// @title KIP-17 Non-Fungible Token Standard, optional wallet interface
/// @dev Note: the KIP-13 identifier for this interface is 0x6745782b.
interface IKIP17TokenReceiver {
    /// @notice Handle the receipt of an NFT
    /// @dev The KIP-17 smart contract calls this function on the recipient
    ///  after a `safeTransfer`. This function MAY throw to revert and reject the
    ///  transfer. Return of other than the magic value MUST result in the
    ///  transaction being reverted.
    ///  Note: the contract address is always the message sender.
    /// @param _operator The address which called `safeTransferFrom` function
    /// @param _from The address which previously owned the token
    /// @param _tokenId The NFT identifier which is being transferred
    /// @param _data Additional data with no specified format
    /// @return `bytes4(keccak256("onKIP17Received(address,address,uint256,bytes)"))`
    ///  unless throwing
    function onKIP17Received(address _operator, address _from, uint256 _tokenId, bytes _data) external returns(bytes4);
}

인터페이스 상세 : Enumeration Extension

  • OPTIONAL.
  • 모든 NFT의 mapping 정보를 들고 있는 부분.
pragma solidity 0.4.24;

interface IKIP17Enumerable {
  /// @notice 이 Contract에 의해 tracking된 NFT의 갯수를 센다.
  /// @return A count of valid NFTs tracked by this contract, where each one of
  ///  them has an assigned and queryable owner not equal to the zero address
  function totalSupply() external view returns (uint256);

  /// @notice Enumerate valid NFTs
  /// @dev Throws if `_index` >= `totalSupply()`.
  /// @param _index A counter less than `totalSupply()`
  /// @return The token identifier for the `_index`th NFT,
  ///  (sort order not specified)
  function tokenByIndex(uint256 _index) external view returns (uint256);

  /// @notice Enumerate NFTs assigned to an owner
  /// @dev Throws if `_index` >= `balanceOf(_owner)` or if
  ///  `_owner` is the zero address, representing invalid NFTs.
  /// @param _owner An address where we are interested in NFTs owned by them
  /// @param _index A counter less than `balanceOf(_owner)`
  /// @return The token identifier for the `_index`th NFT assigned to `_owner`,
  ///   (sort order not specified)
  function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
}
profile
Flutter 메인의 풀스택 개발자 / 한양대 컴퓨터소프트웨어학과, HUHS의 화석

0개의 댓글