수정 가능한 Smart Contract

vencott·2021년 5월 19일
1

1. 동기

기본적으로 이미 블록 체인에 배포 된 스마트 컨트랙트는 변경될 수 없다(immutable)

하지만 기존의 컨트랙트에서 버그가 발생하거나, 수정 사항이 발생하거나, 버전 컨트롤을 해야 할 경우가 있다

즉, 수정 및 확장이 가능한 컨트랙트로 설계가 되어야 한다

이를 위해 전혀 새로운 컨트랙트를 배포, 사용하는 대신 업데이트 기능과 비슷하게 동작하는 새로운 계약을 사용하는 것이 바람직하다

2. 개요

활성 스마트 컨트랙트의 주소를 보유하는 중간 스마트 컨트랙트(intermediary Smart Contract)를 생성한다

중간 스마트 컨트랙트의 핵심이 되는 함수는 delegatecall() 이다

delegatecall()은 현재 컨트렉트의 context 내 특정 주소의 컨트랙트의 코드를 호출하며 msg.sender와 msg.value가 그 값을 변경하지 않는 함수이다

이는 컨트랙트가 런타임에 다른 주소의 코드를 동적으로 로드할 수 있음을 뜻한다

저장소, 현 주소, balance는 여전히 delegatecall()을 호출하는 컨트랙트의 것을 참조하며 단지 타겟 컨트랙트의 코드만을 가져오는 기능을 수행한다

이는 solidity에서 "재사용성" 및 "라이브러리"의 특징을 구현하는 데 이용된다

모든 call과 transaction은 delegatecall()을 통해 활성 버전으로 리디렉션된다

궁극적으로 사용자는 동일한 계약 주소(중간 스마트 컨트랙트)를 사용하게 되지만 그 컨트랙트는 결국 다른 스마트 컨트랙트 코드를 실행하는 셈이다

3. 본문

여기서는 delegatecall() 함수를 통해 수정 가능한 컨트랙트를 작성하는 법을 알아본다

delegatecall()을 사용하는 방법은 다음과 같다

pragma solidity ^0.4.18;
contract A {
  uint public value;
  address public sender;

  function delegatecallSetN(address _b, uint _value) public {
    _b.delegatecall(bytes4(keccak256("setValue(uint256)")), _value); // A's storage is set, B is not modified 
  }
}

contract B {
  uint public value;
  address public sender;

  function setValue(uint _value) public {
    value = _value;
    sender = msg.sender;
  }
}

contract Main {
    function foo(A _a, B _b, uint _value) public {
        _a.delegatecallSetN(_b, _value);
    }
}

4. 주의할 점

이와 같이 함수 호출을 위임 중간 스마트 컨트랙트에 위임할 때는 중요한 보안 위험이 있으며 upgradable한 스마트 컨트랙트를 작성할 때에는 이 부분에 특히 주의를 기울여야 한다

5. 기타

가장 원시적인 방법으론 이전 스마트 컨트랙트에서 모든 정보를 추출하여 새 컨트랙트에 삽입한 후 사용자에게 표시 될 주소를 업데이트 하는 방법이 있다

출처 : Can a Smart Contract be upgraded/modified? Is CPU mining even worth the Ether? The Top questions answered here…

profile
Backend Developer

0개의 댓글