지난 글에서는 Smart Contract 를 처음 접하는 분들의 이해를 돕기 위한 글을 올렸다. 이번에도 약간 그러한 연장선상에서 Smart Contract 의 응용 예시에 대해 글을 올려보도록 하겠다. 다음 글 정도 부터는 본격적인 개발 이야기로 들어가보도록 하고, 우선 Overview 형태로 Smart Contract 가 돌아서 무엇을 할 수 있는지에 대해 이야기 해보도록 한다.


▌Crowd Funding 의 예시

 Smart Contract 를 이해하기에 가장 좋은 첫 예시는 Crowd Funding 이라고 생각한다. 돈도 들어가고, modifier 를 예로 들기에도 좋고, 코드도 간결하니 사람들이 이해하기에도 쉽고, event 도 넣기 좋고, 좀더 확장하면 DAO 를 이해하기에도 좋고, Contract 간의 Interface 로 확장해 나아가기에도 참 좋은 예시이다.

 일단 Smart Contract 로 가칭 Quick Starter 라는 어디서 많이 들어본것 같은 느낌의 크라우드 펀딩 Contract 가 갖는 기능을 보자.

[Quick Starter]

  ▶ 누구나 캠페인을 만들 수 있다 (캠페인 = 신규 펀딩 유치)
  ▶ 누구나 Ether 를 보내 펀딩할 수 있다
  ▶ 캠페인의 모금액이 목표 모금액보다 크면 수혜자에게 펀드를 전달한다
  ▶ 펀드 전달과 동시에 캠페인은 종료된다
  ▶ [확장] 캠페인 종료와 함께 캠페인 투자자의 지분(토큰)을 기록한다
  ▶ [확장] 수혜자는 매 년 수익을 이더로 공유하면 지분에 따라 수익이 분배된다
  ▶ [확장] 지분 보유자는 Quick Starter 컨트랙트를 통해 지분 거래가 가능하다

대략 이러한 시나리오(계약내용이라고 하지 않으나 시나리오의 구현 내용이 즉 계약 내용이라고 보면 이해가 빠르겠다)를 갖는 Contract 를 조금 도식화 해 보면 아래와 같다.


Smart Contract 에 대해 잘 모르고 비트코인만 접했던 사람들은 두어번 의문을 가지게 된다.

   Contract 에 송금을 한다고?
   지분 부여, 수익 분배, 지분 매도/매수를 Contract 가 한다고?

Bitcoin 의 Transaction 중심의 응용 방법으로는 이해가 가지 않는 부분이며, 동시에 Smart Contract 가 존재하는 가장 큰 이유이기도 하다. 

 비트코인이 처음 나오고 블록체인 기술이 소개될 때 항상 따라다니는 유행어 같은게 있었다. "중개자 없는 P2P 거래" 라는 말이다. 그리고 기업들은 고민한다. "P2P 는 전통적으로 기업이 참여할 시장이 아니야, 거기에다가 중애자 없이라고? 그럼 더 할 이유가 없네!'. 뭐 그런 회사가 있다.. 아니 많이 있다. P2P 가상화폐 이체P2P Digital Asset 발행 및 거래, Transaction 내에 증명데이터(Proof of Existence) 저장 이라는 틀에 갇혀있고 안그래도 복잡한데, 그 이상으로는 이해하고 싶지 않은 노력을 하는 기업들이다. (아 쫌 안티했나..^^;;)

 그러나 위 처럼 Smart Contract 가 끼면서 Blockchain 의 기존 관념에 큰 변화가 생긴다. 바로 "중개자" 가 Blockchain 내에 생기게 되는 것이다. 좀더 정확히 말하자면 "응용 서비스 제공자/가상기업" 이 생기게 된다. 기업이나 개인은 사람들에게 충분한 가치를 제공할 수 있는 서비스라면 Smart Contract 로 그러한 가치를 제공하는 가상기업을 운영하고 수익을 낼 수 있다. 


■ 번외  Smart Contract 현황

 현재 Ethereum 에는 93,711 개의 Smart Contract 가 Deploy 되어있으며, 이러한 Smart Contract Account 에는 총 16,921,390.231 이더가 담겨있다. 한화로 따지면 약 2,115억원 (1 ether 12,500 원 기준) 규모이다. DAO Smart Contract 또한 이 Contract 들 중 하나이며, 이번에 문제가 된 TheDarkDAO 가 이중 21.5% (454억)를 갖고있다. 조만간 무용지물 되겠지만 큰 규모의 악행 이었다. (아 왜 갑자기 이야기가 DAO 로 가나...^^;;)


 위 http://etherscan.io 사이트에서 Contract Account Address 를 클릭하면 Contract 의 Internal Transaction (Contract 간 호출) 과 Contract 의 Byte Code 를 볼 수 있다. 만약, 소스가 공개된 Smart Contract 의 Source Code 까지 보고싶다면, http://etherchain.org 에서 해당 기능을 제공하고있다.

 오늘 카페(http://cafe.naver.com/decentral) 어느분께서 Byte Code 를 Solidity 로 Disassemble 하여 Reverse 가능하냐고 하셨는데, 아직 그런툴은 없다고 답변드렸다. 물론 OPCode 로는 가능하지만 Solidity 로 변환해주는 툴은 아직 없다.

 만약 어느정도 퀄리티가 된다 싶은 공개 Smart Contract 기반의 Dapp 들을 보고 싶다면, http://dapps.ethercasts.com/ 에서 하나씩 눌러보는것들도 재미지다.


 깔끔하게 https://docs.google.com/spreadsheets/d/1VdRMFENPzjL2V-vZhcc_aa5-ysf243t5vXlxC2b054g/edit?usp=sharing 를 통해 엑셀로 정리된 버전을 볼 수도 있다.



▌Smart Contract Code 구조

 이제부터는 Code 로 가보자. 저 위의 Quick Starter 컨셉의 매우 핵심 기능만을 하는 Crowd Funding Contract 를 보자. 지분 개념이나 거래개념은 없으며

  ▶ 누구나 캠페인을 만들 수 있다 (캠페인 = 신규 펀딩 유치)
  ▶ 누구나 Ether 를 보내 펀딩할 수 있다
  ▶ 캠페인의 모금액이 목표 모금액보다 크면 수혜자에게 펀드를 전달한다
  ▶ 펀드 전달과 동시에 캠페인은 종료된다
 
위 기능만을 하는 Contract Code 를 보자. 지금은 그 구조만을 눈여겨 본다. 이 다음 글 부터는 본격적인 Smart Contract 개발환경 설명을 시작으로 개발에 대한 상세한 방법을 써볼 예정이니 일단 참고 보도록 하자. 이후로도 계속 사용할 언어는 Solidity 이다. 작년에는 Serpent 도 섰었지만 이제는 Solidity 가 대세이므로 앞으로도 계속 Solidity 중심으로만 설명한다.

contract CrowdFunding {
  struct Funder {
    address addr;
    uint amount;
  }
  struct Campaign {
    address beneficiary;
    uint fundingGoal;
    uint numFunders;
    uint amount;
    mapping (uint => Funder) funders;
  }
  uint numCampaigns;
  mapping (uint => Campaign) campaigns;
  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){
    campaignID = numCampaigns++
    campaigns[campaignID] = Campaign(beneficiary, goal, 00);
  }
  function contribute(uint campaignID) {
    Campaign c = campaigns[campaignID];
    c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
    c.amount += msg.value;
  }
  function checkGoalReached(uint campaignID) returns (bool reached) {
    Campaign c = campaigns[campaignID];
    if (c.amount < c.fundingGoal)
      return false;
    c.beneficiary.send(c.amount);
    c.amount = 0;
    return true;
  }
}

코드 분석을 위한 글은 아니므로, 코드에 대한 설명을 간단히만 해본다.

contract CrowdFunding {

Contract 를 선언한다. Contract 의 이름은 CrowdFunding 으로 하였다. Library 나 상속, 참조 없이 하나의 Contract 만으로 개발한 코드이므로 1개의 Contract 만 보인다.

 struct Funder {

Funding 을 한 EOA(Externally Owned Account / 사람소유계정)의 정보를 담을 구조체이다. 간단하게 Address 와 투자한 Ether (Wei) 의 양을 저장하고 있다.
Solidity 에서는 이 struct, mapping, dynamic array 를 매우 자주 사용한다. 여러 Account 를 대상으로 하거나 내부적인 데이터를 여럿 갖고있어야 하는 경우가 대부분이므로 이는 매우 중요하다.

  uint numCampaigns;

State 변수를 uint 타입으로 하나 선언한다. uint 는 uint256 과 동일하다. 32바이트 변수이다. 

  mapping (uint => Campaign) campaigns;

앞으로도 매우 자주 보게 될 mapping 변수이다. (괄호) 안의 uint => Campaign 은, Key 를 uint 타입으로 하고, Value 를 Campaign 구조체로 갖는 Mapping 을 만든다는 이야기 이며, 이러한 Map 을 campaigns 라는 이름의 State 변수로 선언한 예이다. Key 는 위의 numCampaigns 의 증가값을 ID 로 사용할 예정이다.

  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){

새로운 Campaign 을 만드는 함수이다. address 타입과 uint 타입으로 파라미터를 받으며, uint 타입을 리턴한다. 수혜자의 EOA Address 와 목표금액을 넣는 함수이다. 그리고 신규 campaign ID 를 리턴하도록 되어있다. 그런데, 이 return 값은 Smart Contract 로 Transaction 을 발생시켜서는 받을 수 없다. 리턴값을 받으려면 CALL 을 해야 한다. 그래서 이 함수는 CALL 로 실행해서 새로운 campaignID 를 받아보는 용도로도 쓰일 수 있으며 실제 Transaction 을 발생해서 신규 캠페인을 등록하는 용도로도 사용할 수 있다. 이 부분에 대해서는 차츰 이해가 가게 될 것이다.

  function contribute(uint campaignID) {

투자자는 이 contribute 함수로 Message Transaction 을 발생시키면서 동시에 투자할 ether 를 Transaction 의 value 로 담아서 보내면 된다. 그러면 해당 campaignID 의 캠페인에 투자를 하게되고, campaigns Map 의 Campaign 내의 funders Map 에 신규 Funder 를 추가하도록 되어있다.

  function checkGoalReached(uint campaignID) returns (bool reached) {

특정 캠페인의 모금액이 목표금액에 도달하였는지를 점검하고, 도달하였다면 실제로 자금을 이체하도록 하는 함수이다. 이 함수 내용을 보면 Smart Contract 의 특징이 하나 보인다. 바로 "Smart Contract 는 스스로 실행될 수 없다" 는 특징이다. 그래서 특정 EOA 나 Contract 가 이 함수에 Message Transaction 을 보냈을 때에만 목표 도달 시 실제 이체를 실행하게 된다. 그러므로 CALL 을 통해 수시로 체크를 하다가 실제 목표 금액에 도달하였을 때 수혜자 혹은 누군가가(수혜자가 해야겠지요?) Message Transaction 을 보내면서 이 함수를 실행시키는것이 비용적으로 타당한 동작 방식이다. 

 짧은 설명이었고, 더 깊고 많은 설명은 점차 기술 설명으로 들어가면서 해 나아가겠다.


▌1/2 끝에

 오늘도 시간이 빨리간다. 사실 오늘 아예 허접하지만 UI 붙이고 돌아가는 흐름과 캡춰 까지 올리려고 하였으나 반만 쓴다.. 졸려서~ ^^;; 

 이제부터는 조금씩 잘라서 여러번 올려야겠다. 코드가 들어가니 괜히 페이지가 길어질 듯 하다.

 다음 글에는 동작 흐름, 실행 결과, 개발로 들어가기 전의 결론에 대해 말해볼 예정이다.


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,