[그림] delegatecall callcode call의 차이

3892 단어 이더리움solidity

소개



Solidity에는 contract이 다른 contract를 호출하는 메커니즘이 있지만 몇 가지 함수가 있기 때문에 어떤 것을 사용하면 좋은지 약간 혼란스러웠습니다. Remix에서 움직이면서 거동을 확인했으므로 각각의 특징을 정리해 보았습니다.

실제로 움직여 거동을 시도하고 싶은 분은 이 gist를 remix에 붙여 움직임을 보는 것을 추천합니다.
htps : // 기 st. 기주 b. m/c ri s shosh/68593429fd2f84f8f55d4f7b74f0323

함수와 특징



위의 gist 계약을 예로 들어 각 함수의 동작을 설명합니다.
pragma solidity ^0.4.15;

contract C1 {
  uint public num;
  address public sender;

  // 直接呼び出し
  function c2setNum(address _c2, uint _num) public{
      C2 c2 = C2(_c2);
      c2.setNum(_num);
  }

  // call 呼び出し
  function callSetNum(address c2, uint _num) public {
    if(!c2.call(bytes4(sha3("setNum(uint256)")), _num)) revert(); // C2's num is set 
  }

  // callcode 呼び出し
  function callcodeSetNum(address c2, uint _num) public {
    if(!c2.callcode(bytes4(sha3("setNum(uint256)")), _num)) revert(); // C1's num is set
  }

  // delegatecall 呼び出し
  function delegatecallSetNum(address c2, uint _num) public {
    if(!c2.delegatecall(bytes4(sha3("setNum(uint256)")), _num)) revert(); // C1's num is set 
  }
}

contract C2 {
  uint public num;
  address public sender;

  function setNum(uint _num) public {
    num = _num;
    sender = msg.sender;
    // msg.sender is C1 if invoked by C1.callcodeSetNum
    // msg.sender is C3 if invoked by C3.foo()

  }
}

함수의 직접 호출



위의 c2setNum 에 의한 호출.



가장 전통적인 호출 방법으로 C2 측의 msg.sender에는 C1의 주소가 들어간다.
C2가 참조하는 storage 영역은 C2의 것이므로, C2의 numsender가 갱신된다.

Call로 호출



위의 callSetNum 에 의한 호출.
구체적으로 호출은 함수명의 sha3 의 상위 4 바이트를 사용해 호출한다.
c2.call(bytes4(sha3("setNum(uint256)")), _num)



거동으로서는 직접 호출과 같다.

callcode로 호출



위의 callcodeSetNum 에 의한 호출.



이 호출 방법에서는, C2가 가리키는 Storage 영역은 C1의 것이 된다. msg.sender는 직접 호출자 인 C1의 주소입니다.
이 함수가 실행되고 끝나면 C1의 numstorage가 업데이트되고 C2의 numstorage가 업데이트되지 않습니다.
현재는 비추천의 method이므로 기본적으로는 사용하지 않는 것이 좋다.

delegatecall에 의한 호출



위의 delegatecallSetNum 에 의한 호출.



이 호출 방법에서는, C2가 가리키는 Storage 영역은 C1의 것이 된다. msg.sender는 원래 호출자 인 EOA의 주소입니다.
EOA 에서 보면 마치 C1 컨트랙트가 모든 처리를 실시해 결과를 격납하고 있는 것처럼 보이므로, 라이브러리 등을 이용할 때에는 이 호출 방법을 사용하면 좋다.

요약



각각의 함수는의 특징을 정리해 다음과 같이 됩니다.


함수를 호출하는 방법
msg.sender
storage
용도


직접 호출
직접 호출자
불려 간 contract 의 storage 를 가리킨다
Crowdsale contract가 token contract의 함수를 호출하는 등

call
직접 호출자
불려 간 contract 의 storage 를 가리킨다
Crowdsale contract가 token contract의 함수를 호출하는 등

callcode
직접 호출자
직접 호출자 contract의 storage를 가리킵니다.
비추천

delegatecall
EOA
직접 호출자 contract의 storage를 가리킵니다.
도서관 등

좋은 웹페이지 즐겨찾기