체인의정석

ERC 20 주요 업데이트 사항(0.6 버젼) override, virtual, _beforeTokenTransfer의 역할 본문

개발

ERC 20 주요 업데이트 사항(0.6 버젼) override, virtual, _beforeTokenTransfer의 역할

체인의정석 2020. 10. 7. 17:35
728x90
반응형

 

github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol

 

OpenZeppelin/openzeppelin-contracts

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

github.com

오랜만에 펼쳐본 ERC20 소스, override, virtual이라는 새로운 문법도 보이고 무엇보다 ERC20에서 텅 비어있는 알 수 없는 _beforeTokenTransfer를 발견하였다. 버젼이 이렇게 빨리 바뀌니 주기적으로 들어가서 업데이트를 해주어야 한다.

 

Virtual & Override

solidity.readthedocs.io/en/v0.6.0/060-breaking-changes.html?highlight=virtual%20override#how-to-update-your-code

 

Solidity v0.6.0 Breaking Changes — Solidity 0.6.0 documentation

This section lists changes that are unrelated to the language itself, but that have an effect on the interfaces of the compiler. These may change the way how you use the compiler on the command line, how you use its programmable interface or how you analyz

solidity.readthedocs.io

functions can now only be overridden when they are either marked with the virtual keyword or defined in an interface. Functions without implementation outside an interface have to be marked virtual. When overriding a function or modifier, the new keyword override must be used. When overriding a function or modifier defined in multiple parallel bases, all bases must be listed in parentheses after the keyword like so: override(Base1, Base2).

 

이럴땐 공식문서를 봐줘야 한다. Virtual이라는 키워드는 0.6버젼부터 새로 생긴 키워드인데 virtual이라고 표시가 되어 있거나 interface안에 정의된 경우에만 오버라이딩이 된다고 한다. 그리고 vitrual표시가 되어 오버라이딩이 가능한 함수를 쓸때도 (오버라이딩이 일어나거나 모디파이어등을 쓸 때) Override를 써줘야 한다고 나와있다. 그리고 여러개의 함수나 모디파이어를 한번에 오버라이딩 시키는 경우에는 override(Base1, Base2)이런 식으로 표시해야 한다고 한다.

 

상속을 받고나서 함수를 수정해서 사용할때 주로 오버라이딩이 발생하므로 이를 고려하여서 virtual을 항상 넣어주고 이를 받아와서 쓸때는 override를 써줘야 하는것 같다. ERC20 코드를 봐도 이러한 virtual과 override가 여기저기 있는 것을 확인할 수 있었다.

 function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
        _transfer(_msgSender(), recipient, amount);
        return true;
    }

그럼 여기서 override가 어디서 온것인지 찾아보았다. 바로 IERC20이다.

 

IERC20

그럼 IERC20에 대해서도 알고 넘어가야 한다.

ethereum.stackexchange.com/questions/60940/what-is-ierc20

 

What is IERC20?

I understand the ERC20 standards which includes the functions like totalSupply() balanceOf() allowance() transfer() approve() transferFrom() When I check the openzeppelin, I could see "contr...

ethereum.stackexchange.com

오픈제플린의 깃허브를 보면 IERC20이 있다. IERC20은 ERC20에 대한 인터페이스다. 이러한 인터페이스에는 ABI에 명시되는 정보들이 들어가게 된다. IERC20을 사용해서 오버라이딩을 해서 컨트렉트를 만들면 ABI가 더 정확하게 만들어지는 영향도 있을것 같다. 인터페이스의 모든 요소들은 virtual을 기본적으로 가지고 있다. IERC20을 가져와서 오버라이딩을 하려는 함수는 virtual이 명시되어 있다면 인터페이스를 가져와서 오버라이딩을 할 수 있다. 따라서 IERC20을 가져와서 오버라이딩을 하는방식으로 작성되는 ERC20의 코드에는 모두 override가 붙어 있는것이라고 할 수 있다.

 

 

 

msgSender()

  function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

Context라는 것은 이더리움 가스 스테이션이라는 컨트렉트를 위해서 만들게 된것 같다. 그냥 msg.sender로 두게 되면 가스스테이션 네트워크에서 sender를 제대로 파악하지 못할 수 있다고 한다. GSN도 이제 ERC20 표준에 염두에 두고 있는것을 보니 한번 학습을 해야 할 것 같다.

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */

아무튼 _msgSender() 는 msg.sender를 리턴해주는 역할을 한다. 그래서 msg.sender를 사용하는 모든 ERC20함수는 msg.sender 대신에 _msgSender()를 사용하고 있다.

 

처음봤을땐 더 햇갈렸지만 이렇게 해두면 코드를 파악할 때 더 체계적으로 볼 수 있을것 같다. 스마트컨트렉트는 수정이 안되므로 이렇게 보안을 강화하고 문법에 규제를 더하는 식으로 수정이 되어가는것 같다. 나중에 되면 같은 내용을 쓰더라도 맞출 문법이 더 복잡해지지 않을까싶다.

beforeTokenTransfer

Transfer, mint, burn등등 모든곳에 들어있지만 텅 비어있는 이 함수는 뭘까?

 

forum.openzeppelin.com/t/how-to-use-beforetokentransfer-when-extending-erc721presetminterpauserautoid-contract/3505/2

 

How to use _beforeTokenTransfer when extending ERC721PresetMinterPauserAutoId contract?

Hi @cjd9s, Welcome to the community 👋 Hooks allow you lots of flexibility in modifying the behaviour of a token by allowing you to execute functionality, in the case of the _beforeTokenTransfer hook, you can execute functionality before the token is tra

forum.openzeppelin.com

해당 포럼의 글을 보고 답을 찾을 수 있었다. ERC20 기준으로 _beforeTokenTransfer을 달아둘 테니 실행전에 체크할 사항들을 여기에 넣어서 체크해두거나 제한을 두고 싶은 사항들을 설정하라는 것이였다. 만약 보안 이슈가 있는 상황이라면 이 곳에다가 특정 함수를 걸어두거나 할 수 있을것 같다.

728x90
반응형
Comments