[그림] delegatecall callcode call의 차이
소개
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의 num
와 sender
가 갱신된다.
Call로 호출
위의 callSetNum
에 의한 호출.
구체적으로 호출은 함수명의 sha3 의 상위 4 바이트를 사용해 호출한다.
c2.call(bytes4(sha3("setNum(uint256)")), _num)
거동으로서는 직접 호출과 같다.
callcode로 호출
위의 callcodeSetNum
에 의한 호출.
이 호출 방법에서는, C2가 가리키는 Storage 영역은 C1의 것이 된다. msg.sender
는 직접 호출자 인 C1의 주소입니다.
이 함수가 실행되고 끝나면 C1의 num
와 storage
가 업데이트되고 C2의 num
와 storage
가 업데이트되지 않습니다.
현재는 비추천의 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를 가리킵니다.
도서관 등
Reference
이 문제에 관하여([그림] delegatecall callcode call의 차이), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/doskin/items/c4fd8952275c67deb594
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
위의 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의
num
와 sender
가 갱신된다.Call로 호출
위의
callSetNum
에 의한 호출.구체적으로 호출은 함수명의 sha3 의 상위 4 바이트를 사용해 호출한다.
c2.call(bytes4(sha3("setNum(uint256)")), _num)
거동으로서는 직접 호출과 같다.
callcode로 호출
위의
callcodeSetNum
에 의한 호출.이 호출 방법에서는, C2가 가리키는 Storage 영역은 C1의 것이 된다.
msg.sender
는 직접 호출자 인 C1의 주소입니다.이 함수가 실행되고 끝나면 C1의
num
와 storage
가 업데이트되고 C2의 num
와 storage
가 업데이트되지 않습니다.현재는 비추천의 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를 가리킵니다.
도서관 등
Reference
이 문제에 관하여([그림] delegatecall callcode call의 차이), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/doskin/items/c4fd8952275c67deb594
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
Reference
이 문제에 관하여([그림] delegatecall callcode call의 차이), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/doskin/items/c4fd8952275c67deb594텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)