OpenZeppelin이란?
OpenZeppelin은 이더리움 스마트 컨트랙트 개발에 사용되는 오픈 소스 라이브러리이다. 보안이 검증된 컨트랙트 및 구성 요소를 제공하여 개발자들이 안전하고 효율적인 스마트 컨트랙트를 구축할 수 있도록 돕는다. OpenZeppelin의 Context 컨트랙트는 이 라이브러리의 일부로 제공된다.
Context 컨트랙트란?
Context 컨트랙트는 현재 실행 컨텍스트에 대한 정보를 제공하는 추상 컨트랙트입니다. 트랜잭션의 발신자와 데이터를 다루는 데 사용되며 메타 트랜잭션과 같은 경우에도 올바른 정보를 처리할 수 있도록 돕는다.
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 v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @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 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.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
주석 부분의 설명을 보면 다음과 같다.
@dev 현재 실행 컨텍스트에 대한 정보를 제공합니다. 이에는 트랜잭션의 발신자와 데이터가 포함됩니다. 일반적으로 이러한 정보는 msg.sender와 msg.data를 통해 사용할 수 있지만, 메타 트랜잭션을 처리할 때 실행을 위한 비용을 지불하는 계정이 실제 발신자가 아닐 수 있기 때문에(애플리케이션 관점에서) 이러한 방식으로 직접 접근해서는 안됩니다. 이 컨트랙트는 중간, 라이브러리와 같은 컨트랙트에서만 필요합니다.
주요 기능
Context 컨트랙트는 다음 두 가지 주요 기능을 제공한다.
_msgSender()
이 함수는 현재 트랜잭션의 발신자를 반환한다. msg.sender를 직접 사용하는 대신 이 함수를 사용하여 발신자를 가져올 수 있다. 메타 트랜잭션과 같은 경우에도 발신자 정보를 올바르게 처리할 수 있도록 도와준다.
_msgData()
이 함수는 현재 트랜잭션의 데이터를 반환한다. msg.data를 직접 사용하는 대신 이 함수를 사용하여 데이터를 가져올 수 있다.
왜 Context를 사용해야 하는가?
Context 컨트랙트를 사용하면 스마트 컨트랙트의 보안과 간접성을 향상할 수 있다. 메타 트랜잭션을 다룰 때 애플리케이션 관점에서 실제 발신자와 다를 수 있기 때문에 직접적인 접근보다는 _msgSender()와 _msgData()와 같은 함수를 사용하는 것이 바람직하다. 이러한 함수를 사용하면 발신자와 데이터를 안전하게 처리하면서 동시에 메타 트랜잭션과 같은 특수한 상황을 고려할 수 있다. 또한, 이러한 기능은 코드의 재사용성과 유지 보수성을 향상한다. 일반적인 트랜잭션 정보를 처리하는 로직을 각각의 컨트랙트에 중복해서 작성하는 대신 Context 컨트랙트를 상속하여 필요한 기능을 손쉽게 가져올 수 있다.
보안 강화?
Context 컨트랙트를 사용하면 보안성이 강화되는 이유는 주로 메타 트랜잭션과 관련이 있다. 메타 트랜잭션은 트랜잭션 발신자와 실행을 지불하는 계정이 다를 수 있는 특수한 트랜잭션이다. 이런 경우, msg.sender를 직접 사용하면 실제 트랜잭션을 보낸 계정이 아닌, 실행을 위한 가스를 지불한 계정을 참조하게 된다. 이로 인해 발생할 수 있는 보안 문제나 오류를 방지하기 위해 Context 컨트랙트의 _msgSender() 함수를 사용하는 것이 좋다. _msgSender() 함수를 사용하면 메타 트랜잭션의 경우에도 실제 트랜잭션을 발생시킨 계정을 올바르게 참조할 수 있다. 따라서 악의적인 사용자가 가스를 지불하는 계정을 바꿔치기하여 스마트 컨트랙트의 로직을 훼손하는 것을 방지할 수 있다. 또한, 메타 트랜잭션과 관련된 다양한 구현 방식이 있기 때문에 _msgSender() 함수를 Override하여 원하는 방식에 맞게 구현할 수도 있다. 이런 유연성 덕분에 스마트 컨트랙트의 보안성이 강화되는 것이다.
결론
OpenZeppelin의 Context는 이더리움 스마트 컨트랙트 개발에서 발신자와 데이터 처리를 쉽고 안전하게 할 수 있는 도구를 제공한다. 이를 사용하면 메타 트랜잭션과 같은 상황에서도 올바르게 작동하는 스마트 컨트랙트를 구축할 수 있으며 코드의 재사용성과 유지 보수성도 높일 수 있다. 따라서 스마트 컨트랙트 개발자들은 OpenZeppelin 라이브러리와 Context 컨트랙트를 활용하여 더욱 견고한 애플리케이션을 구축하도록 권장한다.
'Develop > Solidity' 카테고리의 다른 글
[Solidity] OpenZeppelin ERC20.sol의 mint 함수 이해하기 (0) | 2023.05.08 |
---|---|
[Solidity] OpenZeppelin Ownable.sol로 스마트 컨트랙트의 소유권 관리하기 (0) | 2023.05.04 |
[Solidity] OpenZeppelin ERC20.sol의 approve와 allowance 함수 이해하기 (0) | 2023.05.03 |
[Solidity] ERC20 토큰 소각 기능 구현하기: 오픈제플린의 ERC20Burnable 컨트랙트 사용법 (0) | 2023.04.04 |
[Hardhat] Solidity 스마트 컨트랙트 배포를 위한 Hardhat + TypeScript 프로젝트 파일트리 (0) | 2023.02.21 |