Category Archives: Blockchain

스마트컨트랙 폰지사기

요 근래 많은 사용자 수가 유입되고 있는 333ETH의 코드를 분석해 보자. 많은 폰지 사기들이 있어 왔지만 이렇게 코드로 확실히 그 모습을 드러내는 경우는 많지 않고 대부분 투자자를 모으지 못하고 끝나는데 333ETH는 출시된지 20일정도된 지금 상당한 자금을 모으고 있다.

컨트랙트 주소는 0x311f71389e3de68f7b2097ad02c6ad7b2dde4c71이다. 이 주소로 0.01 ETH 이상을 보내면 투자는 완료된다. 배당은 이 주소로 0ETH를 전송하면 보내준다. 아래 코드에 나와 있다.

function() public payable {
  // investor get him dividends
  if (msg.value == 0) {
    getMyDividends();
    return;
  }

  // sender do invest
  address a = msg.data.toAddr();
  address[3] memory refs;
  if (a.notZero()) {
    refs[0] = a;
    doInvest(refs); 
  } else {
    doInvest(refs);
  }
}

우선 doInvest를 살펴보자.

function doInvest(address[3] refs) public payable notOnPause balanceChanged {
  require(msg.value >= minInvesment, "msg.value must be >= minInvesment");
  require(address(this).balance <= maxBalance, "the contract eth balance limit");

  uint value = msg.value;
  // ref system works only once for sender-referral
  if (!m_referrals[msg.sender]) {
    // level 1
    if (notZeroNotSender(refs[0]) && m_investors.contains(refs[0])) {
      uint reward = m_refPercent.mul(value);
      assert(m_investors.addRefBonus(refs[0], reward)); // referrer 1 bonus
      m_referrals[msg.sender] = true;
      value = m_dividendsPercent.add(value); // referral bonus
      emit LogNewReferral(msg.sender, now, value);
      // level 2
      if (notZeroNotSender(refs[1]) && m_investors.contains(refs[1]) && refs[0] != refs[1]) { 
        assert(m_investors.addRefBonus(refs[1], reward)); // referrer 2 bonus
        // level 3
        if (notZeroNotSender(refs[2]) && m_investors.contains(refs[2]) && refs[0] != refs[2] && refs[1] != refs[2]) { 
          assert(m_investors.addRefBonus(refs[2], reward)); // referrer 3 bonus
        }
      }
    }
  }

  // commission
  adminAddr.transfer(m_adminPercent.mul(msg.value));
  payerAddr.transfer(m_payerPercent.mul(msg.value));    
  
  // write to investors storage
  if (m_investors.contains(msg.sender)) {
    assert(m_investors.addValue(msg.sender, value));
  } else {
    assert(m_investors.insert(msg.sender, value));
    emit LogNewInvestor(msg.sender, now, value); 
  }
  
  if (m_paysys.mode == Paymode.Pull)
    assert(m_investors.setPaymentTime(msg.sender, now));

  emit LogNewInvesment(msg.sender, now, value);   
  investmentsNum++;
}

앞부분은 referrall에 관한 부분으로 중요하지 않다.(추천인에게 일정 배당을 주는 것) 489, 490 라인에서 관리자가 자기꺼 먼저 챙긴다. 즉 투자자는 24시간이 지난 다음부터 0ETH를 contract로 전송해야 일 3.33%를 받지만 관리자는 투자즉시 17%를 빼간다. Admin이 10%, payer가 7%를 떼간다.

아무튼 이런식으로 돈을 떼가면 금방 자금이 바닥나게 되어 있는데 자금이 바닥날 경우를 살펴보자.

function getMyDividends() public notOnPause atPaymode(Paymode.Pull) balanceChanged {
  // check investor info
  InvestorsStorage.investor memory investor = getMemInvestor(msg.sender);
  require(investor.keyIndex > 0, "sender is not investor"); 
  if (investor.paymentTime < m_paysys.latestTime) {
    assert(m_investors.setPaymentTime(msg.sender, m_paysys.latestTime));
    investor.paymentTime = m_paysys.latestTime;
  }

  // calculate days after latest payment
  uint256 daysAfter = now.sub(investor.paymentTime).div(24 hours);
  require(daysAfter > 0, "the latest payment was earlier than 24 hours");
  assert(m_investors.setPaymentTime(msg.sender, now));

  // check enough eth 
  uint value = m_dividendsPercent.mul(investor.value) * daysAfter;
  if (address(this).balance < value + investor.refBonus) {
    nextWave();
    return;
  }

  // send dividends and ref bonus
  if (investor.refBonus > 0) {
    assert(m_investors.setRefBonus(msg.sender, 0));
    sendDividendsWithRefBonus(msg.sender, value, investor.refBonus);
  } else {
    sendDividends(msg.sender, value);
  }
}

450라인에 나와있다. 더이상 줄돈이 없게 되면 nextWave를 부른다.

function nextWave() private {
  m_investors = new InvestorsStorage();
  changePaymode(Paymode.Push);
  m_paysys.latestKeyIndex = m_investors.iterStart();
  investmentsNum = 0;
  waveStartup = now;
  m_nextWave = false;
  emit LogNextWave(now);
}

이 코드는 컨트랙트 마지막에 있다. 단순하다. 그냥 모든것을 리셋하고 다시 시작한다. 그동안 투자한 사람들은? 그동안 배당받은게 전부이고 다 날린거다.

이 컨트랙트는 나름 의미가 있다. 어느정도 성공하고 있기 때문에 폰지사기가 어떻게 끝나는지 분명한 수치로 아마도 영구히 블록체인에 기록되어 후세에 좋은 연구자료와 귀감이 될 것이다. 현재는 하루 1,000이더 정도 들어오고 500 정도 나가고 있다.

 

복제와 가상화폐

화폐가 복제가 된다면 화폐가 될 수 없다. 가상화폐는 그러한 면에서 성공적인 출발을 했다고 할 수 있다. 그렇다고 해서 블록체인 기술을 이용하면 소프트웨어나 이미지, 동영상등을 불법 복제하는 것을 막을 수 있다고 주장하는 무리가 있다. 블록체인 기술에서 사용한 화폐에 대한 개념은 장부를 다수가 보유하고 어떤것이 진짜인지 확인 하는 알고리즘을 탑재한 것이다. 디지털로된 이미지인 화상, 소프트웨어, 동영상등을 블록체인 기술로 복제를 방지 할 수 있다는 것은 기본적인 이해가 부족한 것이다.

블록체인 기술을 이용하여 원본 동영상과 짝퉁을 구별은 할 수 있을 것이다. 그렇지만 실제 시청하는데 짝퉁이나 원본이나 별 지장이 없다면 누가 굳이 원본을 찾겠는가? 원본 확인 기술을 만들 수 있지만 시청하는 사람들이 원본이든 카피본이든 별 관계 없다면 무슨 상관이겠는가?

짝퉁 소프트웨어가 동작하지 못하도록 하는 방법은 이미 개발이 되었고 그것을 해킹하는 것은 시간 낭비다. 새로운 버전이 나오고 짝퉁은 업데이트를 받지 못한다. 업데이트를 하면 동작을 멈추니 업데이트 하기가 두렵다. 그래서 이제 소프트웨어는 짝퉁이 유통되기 어렵다.

동영상, 사진? 이건 좀 곤란하다. 그 자체가 프로그램이 아니라 데이터일 뿐이기 때문에 복제를 막기 어렵다. 그렇지만 이미 넷플릭스 같은 회사가 성공하고 있는 것은 복제가 그리 효과적인 동영상을 보는 방법이 아니라는 것을 의미한다.

소프트웨어 복제가 쉽던 시절 많은 회사들이 복제 때문에 회사가 망했다고 이야기 했다. 과연 진실일까? 사람들이 복제를 할만한 소프트웨어를 만든 사람들이 그런 이야기를 했을까? 별로 보지 못했다. 복제 때문에 망한다기 보다 아무도 복제를 안해서 망했다고 하는것이 더 정확 했을지도 모른다.

블록체인은 신비의 기술이 아니다. 오히려 아주 무식하다. 하나만 보관하면 될 장부를 수십개, 수천개 보관하고 진위를 판별하는 무식한 기술이다. 저장공간의 낭비이고 네트워크 장비의 낭비일 수 있다. 기술 보다는 모두에게 장부를 공개한다는 철학이 중요하다. 그동안 장부는 숨기고 또 숨기는 것이 었다. 그래서 방어 하기 어려웠다. 그런데 다 공개하고 다만 조작하는 것을 막겠다는 것은 전혀 다른 접근이다.

블록체인은 그런면에서 특별하다. 프로그램이든 장부든 조작하는 것을 허용하지 않는다. 이러한 개념과 이미지, 동영상을 조작하지 못한다는 것은 다르다. 장부는 거기에 기록된 숫자 하나하나가 중요하고 이미지나 동영상은 그렇지 못하다. 몇비트 틀리다고 해서 그 동영상은 못보겠다고 하는 사람은 없다. 장부는 숫자 하나가 틀리면 안된다. 그것이 가장 중요하기 때문이다.

기존의 기술들도 충분히 훌륭하게 데이터를 보관하고 조작불가능하게 유지할 수 있다. 그런데 그렇게 사용하지 않았다. 어쩌면 종이로 기록된 문서보다 디지털 문서는 더 조작하기 간단하다. 그래서 많이들 조작했고, 대중들은 디지털 문서를 믿지 않게 되었다. 그동안의 디지털 문서는 독점적인 지배권을 가진 누군가에 의해서 유지 되었기 때문이다.

블록체인은 굳이 비효율 적인 방법으로 다수가 지배권을 행사하는 즉, 민주적인 방법의 자료 보관 방법을 제시한 것이다. 조작되었다고 의심할 필요가 없는 디지털 문서, 데이터, 계약이 가능하다는 것은 디지털 데이터에 대한 새로운 지평을 여는 것이다. 그렇지만 모든 데이터가 그러할 수는 없다. 적어도 지금은 그러하다.

 

 

토큰발행과 스마트 컨트랙트

현재 블록체인 최고의 킬러 어플리케이션은 ICO다. 특히 새로운 코인을 설계하지 않고 기존 이더리움 같은 블록체인을 이용하는 경우가 더욱 그러하다. 스마트 컨트랙을 통하여 토큰을 사는 사람에게 어떤 조건을 제시할지 미리 프로그램하고 확정 지을 수 있다.

예를들어 몇년 몇월까지 모인 ETH를 락업 하겠다고 했다면 그렇게 프로그램을 만들어야 한다. 환불이 가능하다면 환불에 관한 코드도 있어야 한다. 그렇게 편리하지는 않지만 MyEtherWallet같은 서비스가 있어서 일반인도 설명을 잘 보면 충분히 스마트컨트랙의 함수를 실행할 수 있다.

그런데 대부분의 ICO를 보면 이런 프로그램이 없이 진행된다. 프로그램이 있어도 코드가 공개되지 않아 계약서도 못보고 계약을 하는 꼴이다. 블록체인 생태계를 말하면서 프로그램으로 말하지 않고 블로그와 공지문으로 모든것을 대신한다.

블록체인위에 기록되는 코드는 강력하다. 작성자 조차도 프로그램이 실행되면 미리 정해진 코드 외에는 추가도 불가능하고 수정도 안된다. 오류가 발생해도 그냥 쳐다 보는것 외에 할 수 있는 일이 없다. 그러한 코드를 작성하는 것은 매우 어렵고 고통스러운 일이다. 그럼에도 불구하고 이러한 불변성(immutability) 때문에 블록체인이 새로운 기술로 인정 받는 것이 아닌가?

지금까지 모든 문서는 누가 만든 것이든 문제가 발생하면 항상 그 문서의 진위가 큰 논쟁이 된다. 조작 못하는 문서는 없다는 것이 이제까지 정설이 이었다면 블록체인 그 원칙을 바꿀 수 있는 새로운 기술이다. 제대로만 사용된다면 얼마나 많은 소모적인 분쟁을 줄 일 수 있겠는가?

불변성과 투명성을 담보하는 검증된 코드는 확실한 실행을 보장한다. 그러므로 당사자들간에 코드로된 계약의 명확성만 확인하면 실행은 보장된다. 이 보장성은 이제까지의 그 어떤 집행기관 보다도 강력할 수 있다.

이러한 블록체인 최고의 장점을 뽐낼 수 있는 ICO에서 이런 기술이 사용되지 않는 다는 것은 안타까운 일이다.

문제는 법정화폐로 바꾸는데 있다.

가상화폐는 그 생태계 안에서 움직일 때 안정적이다. 블록체인을 운영하고, 채굴자, 풀노드 운영자를 지원하며, 다앙한 DApp을 구동하게 해주는 에너지다. 그런데 이러한 본연의 기능이 법정화폐로 바꾸는 거래소의 활성화로 인해 법정화폐를 벌게 해주는 수단으로 인식되는 부분은 아쉬운 부분이다.

이것은 본질적으로 다양한 DApp이 부재하고 실질적으로 가상화폐를 소비하기 어려운 상황이다 보니 법정화폐로 바꾸어 소비해야 하는 실질적인 문제와 급격한 가격상승으로 인한 투기심리 확산으로 거래소 또는 환전소가 지나치게 많고 과열된 것이 사실이다.

가상화폐 세계에서 가장 강력한 어플리케이션인 ICO마저 토큰을 팔아서 들어온 가상화폐를 회사 운영에 사용하기 위해 법정화폐로 바꾸고 있는데 이 또한 간단히 생각할 문제는 아니다. ICO에 대한 모든 부정적 이미지는 가상화폐 투자를 받는다기 보다 가상화폐를 투자 받아 다시 법정화폐로 바꾸어 사용하는 행태에 있다. 이러한 행태에서는 사실상 가상화폐를 투자 받는 것이 아니라 법정화폐를 투자 받는 것이나 마찬가지라 할 것이다.

가상화폐 생태계는 많은 가능성이 있다. ICO를 통해서 가상화폐를 모으고 이를 기반으로 블록체인을 활성화 하는 앱이 개발되고 유용한 블록체인이 개발되어야 한다. ICO를 통해 모은 가상화폐를 이 가상화폐 생태계를 구축하는데 대부분 사용되어야 할 것이다. 회사 운영이나 개발비등은 성공한 ICO를 기반으로 기존 금융권에서도 조달이 가능할 것이다.

블록체인의 최대 강점이자 약점 – 수정불가

블록체인의 특성중에서 투명성 다음으로 많이 이야기 되는 것이 수정불가능이다. 한번 기록되면 수정이 안된다. 그래서 믿을 수 있는 것이다. 쌍방간에 몇날 몇시에 무엇을 하기로 하고 기록을 남기다 라고 써 놓으면 블록체인이 존재하는한 해당 기록은 인정될 수 있다. 그런데 작성해 놓고 나중에 보니 쌍방이 인정하는 오류가 있다해도 수정은 안된다. 계약을 다시 해야한다. 기존의 계약 시스템도 그러하다. 도장찍은 계약서를 고치기는 어렵고 새로 추가로 작성하는 것이 일반적이다.

그럼에도 불구하고 블록체인상의 프로그램이 수정불가능하다는 것은 참으로 두려운일이다. 프로그램은 복잡하다. 일반 계약서 처럼 여러번 검토하면 본질적인 내용은 거의 맞는것과는 차원이 다르다. 단순한 오타 하나가 시스템을 망가 뜨릴수 있다.

이더리움이 이더리움클래식으로 원래것을 버리면서 하드포크 할 수 밖에 없었던 이유도 DApp의 오류 때문이었고 많은 사람들이 오랫동안 정교하게 작업했음에도 치명적 결함이 있었고 플랫폼 자체를 수정하는 방법외에 오류로 인한 피해를 막을 방법이 없었다.

원천적으로 DApp의 소유자는 DApp을 파기할 수 있는 권위를 주면 최악의 사태는 피할수 있으나 그렇게 하면  컨트랙트 자체의 신뢰가 떨어진다.

프로그램의 무결성을 검증하는 것은 매우매우 어렵다. 그러므로 블록체인상의 프로그램은 매우 제한적으로 검증된 코드만을 쓸 수 밖에 없으므로 블록체인상에는 핵심적인 불가역적인 로직만을 배치하고 나머지 소소한 부분들은 블록체인 밖에서 일반 어플리케이션으로 처리하는 디자인이 필요하다.