티스토리 뷰

반응형

OpenZepplin은 오픈소스 블록체인 프레임워크 및 라이브러리로, 이더리움 및 다른 블록체인 플랫폼에서 스마트 컨트랙트를 구축하는데 사용되고 있다. OpenZepplin은 강력한 보안 기능과 높은 수준의 코드 재사용성을 제공하는 것으로 유명하다. (OpenZepplin의 오픈소스들은 보안측면에서 검증받은 코드들이기에, DApp 개발에 신뢰하고 사용할 수 있다.)

 

OpenZepplin은 다양한 프로그래밍 언어로 기본적인 컨트랙트들을 제공하는데, 그 중 우리는 솔리디티 기반의 Ownable 컨트랙트에 대해서 알아볼 것이다.


Ownable 컨트랙트(소유 가능한 컨트랙트)란?

Ownable 컨트랙트는 컨트랙트의 소유자를 지정하고 그 소유자만이 특정 기능을 수행할 수 있도록 하는 기능을 제공한다.

즉, Ownable 컨트랙트의 기능은 특별한 권한을 가지는 소유자를 생성하거나 구별할 수 있는 것이다.

 

아래는 Ownable 컨트랙트의 솔리디티 코드이다.

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }
}

Ownable 컨트랙트 구조

Ownable 컨트랙트에는 두가지 중요한 요소가 있다.

● 컨트랙트 소유자 저장 : 컨트랙트의 상단에 owner 변수를 볼 수 있을 것이다. owner 변수는 컨트랙트의 소유자를 나타내는 것으로, 컨트랙트의 생성자 함수를 통해 설정된다. 생성자 함수는 컨트랙트를 최초로 배포할 때 딱 한번만 실행된다. 컨트랙트 내부에서 constructor로 작성되거나 function Ownable()로 작성된다. 생성자 함수에서는 msg.sender라는 특수한 변수를 사용하여, 컨트랙트를 배포한 계정을 소유자로 설정한다.
아래 코드에서 owner 변수는 address 타입으로 선언되어 있다. 생성자 함수에서 msg.sender를 onwer 변수에 대입함으로써, 컨트랙트를 배포한 계정이 owner 변수에 할당된다. 그 후, owner 변수에 저장되어 있는 계정을 통해 컨트랙트의 소유자를 식별하고, 소유자만이 특정 함수를 실행할 수 있도록 설정할 수 있다.

contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    // 이하 생략
}

 


● 소유자만이 특정 함수 호출
: 컨트랙트 내부에 modifier onlyOwner 함수를 볼 수 있을 것이다. 이 함수는 소유자만이 특정 함수를 호출할 수 있도록하는 보안 기능을 담당하는 함수이다. 
onlyOwner modifier는 다른 함수에 적용될 수 있으며, 해당 함수가 실행되기 전에 호출한 계정이 컨트랙트의 owner인지 확인한다. 만약 호출자가 owner가 아니면 함수 실행이 실패하고 에러가 발생한다. 이를 통해 소유자만이 컨트랙트의 중요한 기능을 호출할 수 있도록 보호할 수 있다.

예를 들어, Ownable 컨트랙트를 상속하여 새로운 컨트랙트를 만들면, onlyOwner modifier를 사용하여 컨트랙트의 소유자만이 호출할 수 있는 함수를 정의할 수 있다. 아래 코드에서 MyContract가 Ownable을 상속하며, setMyNumber 함수는 onlyOwner modifier가 적용되어 컨트랙트 소유자만이 호출할 수 있다. 이를 통해 소유자만이 myNumber 변수를 변경할 수 있도록 보호할 수 있다.

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/access/Ownable.sol";

contract MyContract is Ownable {
    uint256 public myNumber;

    function setMyNumber(uint256 number) public onlyOwner {
        myNumber = number;
    }
}


아래는 Ownable 컨트랙트에 구현된 onlyOwner modifier의 예시이다. 함수 호출자가 컨트랙트 소유자와 일치하지 않는 경우, require 함수는 예외를 발생시켜 함수 실행을 중단시키고 에러문구를 띄운다. (_; 이 부분은 원래 호출했던 함수로 돌아가라는 뜻이다.)

contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    modifier onlyOwner() {
        require(msg.sender == owner, "Only the owner of this contract can call this function");
        _;
    }

    // 이하 생략
}

Ownable 컨트랙트의 활용

Ownable 컨트랙트는 다른 스마트 컨트랙트에서 상속하여 사용할 수 있다. 상속된 컨트랙트에서는 onlyOwner modifier를 사용하여, 자신만이 호출할 수 있는 함수를 정의한다. 예를 들면, 아래처럼 상속을 통해 Ownable 컨트랙트를 사용한다. 상속은 contract 이름 뒤에 is 를 붙여 사용한다.

import "@openzeppelin/contracts/access/Ownable.sol";

contract MyContract is Ownable {
   function doSomething() public onlyOwner {
    	// ...
	}
}

 

Ownable 컨트랙트는 transferOwnership 함수를 제공하여, 소유자 변경 기능을 제공한다. 이 함수는 새로운 소유자의 주소를 인자로 받아, 소유자를 변경하는 기능을 수행한다.

function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0), "New owner address cannot be zero");
    emit OwnershipTransferred(owner, newOwner);
    owner = newOwner;
}

위 코드에서, transferOwnership 함수는 onlyOwner modifier를 사용하여 소유자만이 호출할 수 있도록 하여 보안 기능을 강화할 수 있다. 새로운 소유자의 주소가 0x0000....인 경우에 예외가 발생하여 호출한 함수의 실행이 중지될 것이다. 만약 소유자 변경이 성공적으로 완료되면, OwnershipTransferred 이벤트를 emit하여 변경 내용을 블록체인에 기록한다. 이렇게 Ownable 컨트랙트를 상속하면, 다른 스마트 컨트랙트에서도 소유자 관리와 관련된 기능을 구현할 수 있다.

반응형
댓글
공지사항