Skip to content

이더리움의 안전한 관리를 위한 멀티시그 월렛

시작하는 말

일반적으로 암호화폐 지갑에는 크게 핫 월렛(HotWallet) 과 콜드 월렛(Cold Wallet) 이 있으며, 더 나아가 이더리움의 스마트 컨트랙트를 기반으로 한 멀티시그 월렛(Multi-Signature Wallet) 이 있다. 핫 월렛과 콜드 월렛은 인터넷에 연결되느냐 되지 않느냐의 차이로 구분을 하는데 그렇게 따지면 멀티시그 월렛은 핫 월렛으로 볼 수 있다. 컨트랙트를 기반으로 한 멀티시그 월렛이란 무엇이며 사용하려면 어떻게 해야 하는지 알아보려고 한다.

멀티시그 월렛이란?

멀티시그 월렛은 단일 서명을 통해 지갑에서 암호화폐를 출금하던 방식과 다르게 다중 서명을 통해 출금이 가능하도록 한 스마트 컨트랙트이다.

보통 개인이 사용하기보다는 거래소나 기업들처럼 공동의 자산을 보관하고 사용하는 곳에서 주로 사용된다.

이더리움은 트랜잭션 생성 시 하나의 서명만 할 수 있기 때문에 다중 서명(예를 들어 2 of 3)을 위해 스마트 컨트랙트를 이용한다.

이러한 방식의 멀티시그 월렛은 일반 월렛에 비해 보안이 더 우수하고 실수나 해킹으로 인한 사고를 방지할 수 있기를 기대하고 사용한다.

하지만 편의성이 부족하여 일반 월렛에 비해 사용하기가 쉽지 않고 해킹사고가 없었던 것도 아니다.

2017년 11월에 멀티시그 월렛(패리티)이 해킹되어 약 2억 8000만 달러가 묶여버리는 사고가 있었다.

또한 2019년 11월에는 업비트 핫 월렛에서 해커의 지갑으로 이더리움 34만 2천 개가 이동되는 사고가 있었다.

  • 컨트랙트를 이용한 멀티시그 월렛이라면 아래처럼 Contract로 표시되어야 한다.
위 사례들처럼 아무리 멀티시그 월렛이라고 해도 사고가 없는 것은 아니므로 사용하는데 각별한 주의가 필요할 것 같다.

멀티시그 월렛 종류

ConsenSys

  • 멀티시그 컨트랙트에 필요한 모든 공통 기능을 포함하였으나, 꾸준한 유지 관리가 되지 않았다.
  • Gnosis 멀티시그 월렛에서 계속 개발이 되고 있다.
  • https://github.com/ConsenSysMesh/MultiSigWallet

Gnosis

Argent

  • “Guardians” 기능으로 다른 Argent 사용자를 선택하여 모든 출금에 그 사용자의 승인이 필요하도록 한다.
  • https://www.argent.xyz/security/

BitGo

  • end user 가 off-chain에서 서명을 하고 이 데이터를 또 다른 signer가 서명하여 트랜잭션을 발생시켜서 2 of 3을 만족해야 출금이 되는 방식이다.
  • https://github.com/BitGo/eth-multisig-v2

나만의 멀티시그 월렛을 만들고 사용해 보자

본 아티클에서 말하는 멀티시그 월렛은 스마트 컨트랙트라고 했으니 생성하려면 컨트랙트를 배포해야 한다. 위에 소개한 멀티시그 월렛 목록 중 필자는 Gnosis 멀티시그 컨트랙트를 이용해 보려고 한다.

1. Gnosis 멀티시그 컨트랙트 다운로드

2. Remix에서 컴파일

  • 크롬 브라우저를 실행하고 Remix 사이트로 이동한다.

  • 다운로드한 MultiSigWallet.sol 파일을 Remix에서 컴파일 한다.

    • 단, compiler 버전을 아무거나 하면 에러가 표시되었고, 0.4.16+commit.d7661dd9를 사용해야 에러 없이 컴파일이 되었다.

     

3. MultiSigWallet 배포

  • 컴파일이 끝났으면 컨트랙트를 체인에 배포 한다.

    • 좌측 메뉴 중 Deploy & Run Transactions를 선택한다.

    • Environment 를 “Injected Web3″로 변경한다.

    • 메타마스크를 연결한다.

      • Ropsten network 선택
    • Deploy 버튼 우측에 owner address로 쓸 주소 2개 이상과 필요한 confirm 수 2 이상을 입력 후 transact 버튼을 누른다.

      • 주의할 사항은 메타마스크 지갑 하나에서 계정을 여러 개 생성해서 그것들을 owner address로 설정하면 나중에 confirm transaction 을 날릴 때 한 개는 성공해도 같은 지갑 다른 주소로 두 번째 날릴 때부터는 실패가 뜨게 된다.
      • 그러므로 owner address는 각각 다른 지갑의 주소를 입력해 주도록 하자.
      // 예를 들어 아래와 같이 입력한다.
      _OWNERS: ["0xBc42F665C48A3C9Fe9263994D02b87d6983f0665","0x1D2A53AF862D3315Dc61F1A21AE42A5C02e91Ee6"]
      _REQUIRED: 2
      

       

  • 그러면 메타마스크에 확인 노티 팝업이 뜨는데 확인 버튼을 눌러 준다.
  • 그러면 우측 아래 콘솔에 Ropsten 이더스캔 페이지의 url 이 출력되고 잠시 기다리면 배포 완료 메시지가 뜬다.
  • Deploy & Run Transactions 메뉴의 하단에 보면 MULTISIGWALLET AT 0xF70… 확장 메뉴가 보인다.
    • 이를 확장해 보면 컨트랙트의 기능 목록이 보이고 트랜잭션을 날려볼 수 있는 UI가 보인다.

4. Ether 를 전송해 보자.

4-1. 이더 입금

  • 우측 하단 콘솔창에 출력된 링크로 들어가서 생성된 Contract 주소를 클릭해 보면 아래와 같이 현재 멀티시그 월렛의 상태를 볼수 있다.
    • 멀티시그 월렛 주소: 0xF70f1631B4Cf7d7aD54fE687B59bA970FAcD5B8d
  • 멀티시그가 잘 되는지 확인해 보려면 저 멀티시그 월렛에 이더를 넣어야 한다.

  • 메타마스크를 이용해 멀티시그 월렛 주소로 이더를 전송한다. (2 이더가 전송 완료되었다.)

     

4-2. 멀티시그 월렛에서 이더 전송

  • 좌측 Deployed Contracts 항목에 표시된 MultiSigWallet 기능 중 submitTransaction 부분을 확장하여 이더를 전송할 주소, value, data를 넣고 transact 버튼을 클릭한다.

    • data 항목에 아무것도 안넣으면 아래와 같은 메시지가 뜨고 transact가 실패하므로 0x라고 넣자.
    • 여기서는 0.1 Ether를 보내보겠다.
  • 이때 submitTransaction 하는 owner의 address에는 당연히 수수료가 있어야 한다.
  • 아래와 같이 submit transaction이 멀티시그 월렛에 등록되었다.
  • 하지만 아직 이더는 전송되지 않고 멀티시그 월렛에 2이더가 그대로 남아있다.

4-3. confirm transaction (Ether)

  • confirm transaction 을 하기 전에 submitTransaction의 confirm 수를 조회해 보자.

    • 아무도 confirm 하지 않았는데 주소가 들어있다.
    • 이는 submitTransaction 함수 안에 confirmTransaction까지 불러주는 코드가 있기 때문이다.

     

/// @dev Allows an owner to submit and confirm a transaction.
/// @param destination Transaction target address.
/// @param value Transaction ether value.
/// @param data Transaction data payload.
/// @return Returns transaction ID.
function submitTransaction(address destination, uint value, bytes data)
        public
        returns (uint transactionId)
{
    transactionId = addTransaction(destination, value, data);
    confirmTransaction(transactionId);
}
  • transactionId는 최초 submitTransaction 이면 0일 것이다.

  • 우측 하단의 콘솔 창에 submitTransaction 실행한 것을 확장해보면 transactionId를 확인할 수 있다.
  • 또 다른 owner 계정으로 메타마스크에 로그인하여 confirmTransaction 을 실행해 보자.
  • confirmTransaction 이 승인되면서 submitTransaction 이 실행된 로그가 보인다.
  • getConfirmations 0 해보면 주소 두 개가 보인다.
  • Ropsten scan으로 확인해 보면 트랜잭션들이 정상적으로 승인되고 1.9 Ether 가 남은 것을 볼 수 있다.
  • 왜 executeTransaction 을 실행하지 않았는데도 이더가 전송되었을까? 그건 confirmTransaction 함수에서 executeTransaction 을 실행하도록 되어있기 때문에 confirm 수가 맞춰지는 confirmTransaction 이 들어오게 되면 자연스럽게 executeTransaction 이 실행된다.
/// @dev Allows an owner to confirm a transaction.
/// @param transactionId Transaction ID.
function confirmTransaction(uint transactionId)
    public
    ownerExists(msg.sender)
    transactionExists(transactionId)
    notConfirmed(transactionId, msg.sender)
{
    confirmations[transactionId][msg.sender] = true;
    Confirmation(msg.sender, transactionId);
    executeTransaction(transactionId);
}

5. ERC20 토큰을 전송해 보자.

5-1. ERC 20 토큰 배포

  • 미리 ERC 20 JUSTIN 토큰을 배포해 두었다.
    • JUSTIN 토큰 주소: 0x30F5b49C8Eb7DE72C7B370805071FB4Aa49B457d
  • 미리 필자가 만들어 뒀던 ERC20 JUSTIN 토큰을 멀티시그 월렛으로 100개를 전송해보면 아래와 같이 보이게 된다.

5-2. 멀티시그 월렛에 있는 토큰을 다른 주소로 전송해 보자.

  • destination 은 JUSTIN token의 주소를 입력한다.
  • value는 0 을 넣고,
  • data에는 abi encoding 된 byte code를 넣어야 한다.
    • 온라인 abi encoding 사이트가 있어서 사용했다.
    • 위 사이트에서 아래쪽 “enter your parameters manually” 부분에 아래와 같이 입력하면 encoding 을 해준다.
      • Address에는 실제 토큰을 받을 주소를 입력한다.
  • 바이트 코드를 복사하고 앞에 “0x”를 붙여 submitTransaction의 data 항목에 넣고 transact 한다.

5-3. confirm transaction (ERC 20)

  • 토큰 전송 submitTransaction에 대해 마찬가지로 다른 owner의 confirm 이 필요하다.
  • 이번 transactionId는 1이다.  
  • 또 다른 owner로 confirmTransaction 을 해준다.
  • 0.05 JUSTIN 토큰이 전송된것을 확인할 수 있다.

5-4. 전송된 토큰 확인

  • 메타마스크로 들어가 보면 토큰이 전송되지 않은 상태이다.

    • 토큰을 직접 추가해 줘야 보인다.
  • 토큰 추가 버튼을 통해 토큰 주소를 입력하면 등록이 되고 전송된 0.05 JUSTIN 토큰이 보인다.

    • JUSTIN 토큰 주소: 0x30F5b49C8Eb7DE72C7B370805071FB4Aa49B457d

     

6. 이더와 토큰을 동시에 보낼 수 있을까?

  • 궁금해서 해봤는데 안 되는 것 같다.
  • value 와 data 둘 다 입력하고 transact 하면 메타마스크 팝업이 뜨는데 value 가 0으로 되어있고 수정도 할 수 없다.
  • 확인 누른 후 트랜잭션을 열어보면 value 는 0이고 data만 들어있는 걸 확인할 수 있다.
  • 이더와 토큰을 동시에 전송하는 건 안되는 걸 알 수 있었다.

마치는 말

이렇게 특별히 코드 수정 없이도 나만의 이더리움 멀티시그 월렛이 간단하게 완성된 것을 확인할 수 있었다.

해킹 뉴스를 심심치 않게 볼 수 있는 요즘, 사용에 약간의 불편함이 있겠지만 중요한 자산인 경우 멀티시그 월렛을 사용하여 조금 더 안전하게 보관, 관리하면 좋을것 같다.

<참고>

Share your blockchain-related digital insights with your friends

Facebook
Twitter
LinkedIn

Get more insights

NFTfi는 무엇일까?(ERC 4907)

Danksharding is an improved version of Ethereum’s sharding technology, which is one of the techniques that greatly increase transaction capacity and reduce gas fees in Ethreum 2.0 upgrade. To help you understand what Danksharding is, let’s first take a look at Ethereum's scalability strategy, which aims to increase network performance and ensure scalability.

댕크샤딩은 무엇일까? – #2 샤딩 vs. 댕크샤딩

Danksharding is an improved version of Ethereum’s sharding technology, which is one of the techniques that greatly increase transaction capacity and reduce gas fees in Ethreum 2.0 upgrade. To help you understand what Danksharding is, let’s first take a look at Ethereum's scalability strategy, which aims to increase network performance and ensure scalability.

이더리움 확장성 솔루션, 댕크샤딩 (Danksharding)은 무엇일까? #1

댕크샤딩(Danksharding)은 이더리움 네트워크의 샤딩 기술을 개선한 것으로, 이더리움 2.0 업그레이드에서 채택된 기술 중 하나입니다. 댕크샤딩은 이더리움의 트랜잭션 처리량을 크게 향상시키고, 수수료를 낮추는 데 중점을 두고 있습니다.

NFT 마케팅 전략: 고객 참여와 브랜드 가치 높이기

가상화폐 시장은 한 풀 죽었다는 여론과 달리, 시장을 선도하는 글로벌 기업들은 2021년을 기점으로 웹3(디지털 자산) 사업 진출에 속도를 내고 있습니다. 이 글에서는 스타벅스와 같은 글로벌 기업들이 디지털 자산을 어떻게 활용했는지