본문 바로가기
Block Chain/Solidity

[Solidity] Event || emit | indexed | ethers | Solidity 0.8 ||

by 개발이 체질인 나그네 2022. 11. 21.
반응형

EVM의 Solidity는 데이터를 저장할 때, 두 가지 방법이 있습니다.

 

Data Storage Layout : uint256, array, mapping 등 전역 변수를 만들어 Storage에 저장하는 방법

Event : Event emit을 활용하여 트랜잭션 로그(Logs)에 담아 블록에 저장하는 방법

 

이번 게시글에서 예제 코드를 통해 Solidity Event 사용방법이더스캔 그리고 JacaScript를 통해 트랜잭션 로그(Logs)를 조회하는 방법에 대해 알아보겠습니다.

 


 

📜  Solidity Event 란?

Event는 Solidity의 문법 중 하나입니다. Event를 이용하여 블록에 데이터를 저장할 수 있고, EVM Logging 기능을 사용하여 저장된 트랜잭션에 저장된 데이터를 호출할 수 있습니다.

 

Event의 특징은 데이터 저장만 가능하며 삭제하거나 업데이트할 수 없습니다.

데이터 조회는 온 체인에서 할 수 없으며, 오프체인에서 JavaScript를 통해 블록의 트랜잭션을 조회하여 데이터를 확인할 수 있습니다.

하지만 Contract의 Data Storage에 저장하는 것보다 가스비가 훨씬 저렴합니다. 때문에 주로 블록체인에 영속성(persistence)을 가진 데이터 저장합니다. ex 코인 전송 기록

 

해당 데이터는 블록체인의 특수 데이터 구조인 트랜잭션 로그(Transaction Logs)에 인수가 저장됩니다. 로그는 Smart Contract 주소와 연결되며, 블록에 통합된 데이터 무리 속에서 해당 주소로 액세스 할 수 있으며, 블록에 없어지지 않는 이상 평생 유지됩니다.

 

📜  Solidity Event 란? 내용은 Solidity 공식 문서를 인용했습니다
> https://docs.soliditylang.org/en/v0.4.24/contracts.html#events

Events allow the convenient usage of the EVM logging facilities, which in turn can be used to “call” JavaScript callbacks in the user interface of a dapp, which listen for these events.

이벤트를 통해 EVM 로깅 기능을 편리하게 사용할 수 있으며, 이는 이러한 이벤트를 수신하는 dapp의 사용자 인터페이스에서 JavaScript 콜백을 "호출"하는 데 사용할 수 있습니다.

Events are inheritable members of contracts. When they are called, they cause the arguments to be stored in the transaction’s log - a special data structure in the blockchain. These logs are associated with the address of the contract and will be incorporated into the blockchain and stay there as long as a block is accessible (forever as of Frontier and Homestead, but this might change with Serenity). Log and event data is not accessible from within contracts (not even from the contract that created them).

이벤트는 계약의 상속 가능한 구성원입니다. 호출되면 블록체인의 특수 데이터 구조인 트랜잭션 로그에 인수가 저장됩니다. 이 로그는 계약의 주소와 연결되며 블록체인에 통합되고 블록에 액세스 할 수 있는 한 거기에 유지됩니다(Frontier 및 Homestead에서는 영구적이지만 Serenity에서는 변경될 수 있음). 로그 및 이벤트 데이터는 계약 내에서 액세스할 수 없습니다(이를 생성한 계약에서도 액세스할 수 없음).

 

📝  Solidity Event 사용방법 + 예제 코드

예제 코드로 ERC20의 function _transfer()를 사용하여 설명하겠습니다.

Reference by Openzeppelin ERC20.sol

더보기

https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v4.8.0/contracts/token/ERC20

 

GitHub - OpenZeppelin/openzeppelin-contracts: OpenZeppelin Contracts is a library for secure smart contract development.

OpenZeppelin Contracts is a library for secure smart contract development. - GitHub - OpenZeppelin/openzeppelin-contracts: OpenZeppelin Contracts is a library for secure smart contract development.

github.com

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.0;

contract ERC20 {
	...
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    
    function _transfer(
            address from,
            address to,
            uint256 amount
        ) internal virtual {
            require(from != address(0), "ERC20: transfer from the zero address");
            require(to != address(0), "ERC20: transfer to the zero address");

            _beforeTokenTransfer(from, to, amount);

            uint256 fromBalance = _balances[from];
            require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
            unchecked {
                _balances[from] = fromBalance - amount;
                // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
                // decrementing then incrementing.
                _balances[to] += amount;
            }

            emit Transfer(from, to, amount);

            _afterTokenTransfer(from, to, amount);
        }
        
   ...
}

1. Event 정의 🔖

 


// event 정의
event Transfer(address indexed from, address indexed to, uint256 value);
ㅤ

 

Event 이름 정의 :   event Transfer  

저장할 데이터의 Event 이름을 설정합니다.

 

데이터 정의 :   (address indexed from, address indexed to, uint256 value)  

저장할 데이터의 데이터 타입을 정의합니다. ERC20에서 from, to, value를 통해 전송자와 수령자 그리고 전송 금액을 기록합니다.

+ 배열( string및 포함 bytes)이 인덱스 인수로 사용되는 경우 배열의 Keccak-256 해시가 대신 주제로 저장됩니다.

 

데이터 인덱싱 :   indexed  

Event를 활용하여 저장되는 데이터는 생성된 블록에 저장됩니다. 평균 12 초마나 블록이 생성되며 데이터는 계속 축적됩니다. 이때 원하는 기준으로 데이터를 조회하는 Filtering(필터링) 기능을   indexed를 통해 이용할 수 있습니다. 최대 3개의 매개변수가 indexed 각각의 인수를 검색하게 하는 속성을 수신할 수 있습니다. 

만약 A라는 사람의 지갑 주소로 전송된 데이터만 골라서 보고 싶은 경우,   address indexed from에 A의 지갑 주소를 넣어 조회를 하면, 해당 데이터만 조회할 수 있습니다. 
이후 자바스크립트를 활용하여 Event 데이터를 조회하는 실습을 통해 자세히 알아보겠습니다.

 

2. Event 데이터 저장 방법(Emit) 🔖

 


function _transfer(address from, address to,uint256 amount) internal virtual {
	...
        
        // 전송 기록 Event에 저장
        emit Transfer(from, to, amount);
		
        ...
   }
   ㅤ

 

  emit Transfer(from, to, amount)을 보면 from, to, amount를 emit의 파라미터에 넣어 전송자, 수령자 그리고 전송 금액을 저장합니다. 파라미터에 입력되는 데이터는 Event의 데이터 정의에서 정의한 데이터 타입을 준수하며 입력해야 합니다.

 

 


 

🔎 이더스캔 트랜잭션 로그(Logs) 확인 하는 방법 :

이더리움의 Uniswap 토큰을 예시로 트랜잭션의 기록을 보면 트랜잭션 해쉬(Txn Hash)를 확인할 수 있습니다.

 

트랜잭션 해쉬를 누르면 해당 트랜잭션 레시피(Transaction Receipt)를 통해 Logs를 조회할 수 있습니다.

Logs 데이터에는 Event로 저장된 데이터를 확인 할 수 있습니다.

 

🔎  JacaScript 트랜잭션 로그(Logs) 확인하는 방법 :

> 작성 예정

 

 


지금까지 Solidity의 Event 문법과 활용 방법에 대해 알아봤습니다.

감사합니다.

 

반응형

댓글