본문 바로가기
Blockchain

[Blockchain] ERC-20 투표로 관리자 owner 설정 하는 방법

by 개발자 염상진 2022. 7. 18.

ERC-20 토큰은 이더리움 블록체인 네트워크에서 대체 가능한 토큰을 발행하는 기술 표준입니다. 이더(ETH)와 교환가능하며, 이더리움 블록체인 위에서 발행된 토큰들과 SWAP이 가능한 토큰을 발행하기 위해서는 ERC-20 표준을 지켜서 토큰을 발행해야 합니다.

 

 

 

 

토큰을 발행하는 ERC-20에는 관리자 계정이 존재합니다. 관리자는 자신의 권한을 다른 사용자에게 넘길 수 있고, 계정의 Lock 을 잠그거나 해제할 수도 있습니다. 1명의 관리자에 의해 관리자 권한이 관리될 수 있지만 좀 더 민주적인 방법인 투표를 통해 관리자 권한을 관리할 수 있습니다.

 

 

① 총 3명의 사용자가 관리자 후보로 등록됩니다. 이 때 관리자 후보로 등록하는 권한은 현재 관리자만이 할 수 있습니다.

② 총 3명의 관리자가 투표하고 가장 많은 투표를 받은 후보자가 관리자로 선임됩니다.

③ 투표는 1번만 가능하며, 자기 자신에게 투표는 금지됩니다. 투표수가 동일하거나 0명의 후보자가 나오는 경우 기존 관리자가 연임합니다.

 

관리자 추가 구현

 

ⓐ 추상 계약인 OwnerHelper 생성자 함수를 수정합니다. 상태 변수로 _owners(address 형 동적 배열), voteCount(mapping), voteResult(mapping)를 선언합니다. 

address public _owner;
address[3] private _owners;
mapping(address=>uint8) private voteCount;
mapping(address=>uint8) private voteResult;

 

ⓑ 생성자 함수에는 기존 관리자를 0번 후보자로 등록합니다. 0번 후보자의 voteCount와 voteResult를 초기화합니다.

constructor() {
  _owner = msg.sender;
  _owners[0] = msg.sender;
  voteCount[msg.sender] = 0;
  voteResult[msg.sender] = 0;
}

 

 

 

 

ⓒ 후보자를 추가하는 함수를 선언합니다. 인자로는 후보자 번호와 후보자 계정 주소를 받습니다. 현재 관리자만 사용할 수 있는 함수이며, 후보자 번호는 0~2번 사이값을 가지게 됩니다. voteCount, voteResult는 0으로 초기화됩니다.

function addOwner(uint8 _ownerNumber, address _newOwner) onlyOwner public returns(bool){
    require(_ownerNumber > 0 && _ownerNumber < 3);
    _owners[_ownerNumber] = _newOwner;
    voteCount[_newOwner] = 0;
    voteResult [_newOwner] = 0;
    return true;
}

 

ⓓ 등록한 후보자를 대상으로 투표를 진행합니다. voteForOwner 내부에서는 내부함수 _voteForOwner()함수를 실행합니다. 투표를 받은 후보자는 등록된 후보여야 하며, 계정당 1번의 투표만 가능합니다. 또한 자기 자신에게 투표는 금지됩니다. 

투표가 종료되면 해당 후보자가 얻은 투표수(voteResult)는 1씩 증가하며, 유권자의 투표가능 횟수는 1이 올라가면서추가로 투표가 불가능해집니다.

function voteForOwner(address _voteForAddress) public virtual returns(bool){
    _voteForOwner(msg.sender, _voteForAddress);
    return true;
}

function _voteForOwner(address sender, address voteForAddress) internal virtual returns(bool){
    require(_owners[0] == sender || _owners[1] == sender || _owners[2] == sender);
    require(voteCount[sender] == 0);
    require(sender != voteForAddress);
    voteResult[voteForAddress] += 1;
    voteCount[sender] += 1;
    return true;
}

 

ⓔ 투표 결과를 확인하는 함수 result() 를 선언합니다. 스토리지를 건드리지 않고, 단순히 조회만 하므로 view 속성을 사용합니다.

function result() public view returns(uint8) {
    return voteResult[msg.sender];
}

 

ⓕ 투표 결과를 바탕으로 실제 관리자 권한을 위임하는 transferOwnershipByVote() 함수를 선언합니다. 후보자 중 가장 많은 득표를 한 후보자가 maxCandidates가 되며, 관리자 권한을 받은 후 OwnershipTransferred 이벤트가 실행됩니다. 

function transferOwnershipByVote() onlyOwner public returns(bool){
        uint8 max = 0;
        address maxCandidates;
        
        for(uint8 i=0; i<_owners.length; i++){
          if(voteResult[_owners[i]] > max){
            max = voteResult[_owners[i]];
            maxCandidates = _owners[i];
          }
        }
        require(maxCandidates != _owner);
        require(maxCandidates != address(0x0));
        address preOwner = _owner;
        _owner = maxCandidates;
        emit OwnershipTransferred(preOwner, maxCandidates);
        return true;
    }

 

 

작동 영상

 

재사용 가능 Lock 구현

 

관리자는 전송 계정과 수신 계정에 대해 Lock 상태를 관리할 수 있습니다. 최초 Lock 걸려 있고, Lock 을 제거해야만 토큰 전송이 가능한 구조입니다.

 

 

 

 

Lock을 재사용 하기 위해서는 Lock을 추가하는 함수를 구현해야 합니다. 기본 로직은 RemoveLock과 동일합니다. require문을 활용해서 현재 해당 계정 Lock이 걸려 있지 않으면 다시 Lock을 걸어줍니다.

function addTokenLock() onlyOwner public{
  require(_tokenLock == false);
  _tokenLock = true;
}

function addPersonalTokenLock(address _who) onlyOwner public{
  require(_personalTokenLock[_who] == false);
  _personalTokenLock[_who] = true;
}

 

 

 

 

Reference

 

 

 

 

[Blockchain] Truffle(트러플) 프레임워크 사용법(개발 배포 테스트)

Truffle framework는 솔리디티로 스마트 컨트랙트 개발시 배포/테스트 환경을 제공합니다. node.js 위에서 작동하며 NPM으로 설치합니다. Truffle을 사용하기 위해서는 NodeJS Version 5.0이상이 필요하며, JSON

about-tech.tistory.com

 

 

[Blockchain] 가나슈(Ganache) 로컬 테스트 환경 구축하기(설치방법 사용법 메타마스크 연동)

가나슈(Ganache)는 가상 이더리움 네트워크를 구축하여 스마트 컨트랙트를 테스트할 수 있는 툴입니다. Ganache를 통해 생성된 가상 환경을 TestRPC라고 부릅니다. 일반적으로 스마트 컨트랙트를 개발

about-tech.tistory.com

 

 

[Blockchain] 이더리움 토큰 발행 ERC-20 이란?

이더리움 블록체인 메인넷에서 토큰을 발행하고, 관리할 수 있습니다. 내가 만든 토큰으로 디앱을 구동하고, 특정 행동을 유인하는 수단으로 사용할 수 있습니다. ERC(Ethereum Request for Comment)는 이

about-tech.tistory.com

 

 

 

댓글