Разница между CALL, CALLCODE и DELEGATECALL

CALL и CALLCODE принимают одинаковое количество операндов (в стеке выполнения). Для того, чтобы флаг исключения помещался поверх стека: 0 означает исключение, 1 означает успешное выполнение. CALL легко понять, но я не мог переварить тонкую разницу между CALL & CALLCODE. В желтой статье указано, что для

  

CALLCODE: Это означает, что получатель   на самом деле та же учетная запись, что и сейчас, просто, что код   перезаписаны.

Что это означает, что код перезаписан ? Означает ли это, что я могу попросить контракт выполнить внешний код? Было бы полезно, если бы кто-нибудь мог предоставить мне пример, чтобы отличить эти два.

EDIT: в Homestead добавлен DELEGATECALL, в чем разница?

39 голосов | спросил Loi.Luu 6 Maypm16 2016, 19:21:20

1 ответ


49

DELEGATECALL в основном говорит, что я являюсь контрактом, и я разрешаю (делегировать) вы делать все, что захотите my хранилище . DELEGATECALL представляет собой угрозу безопасности для отправляющего контракта, которому нужно доверять тому, что принимающий контракт будет обрабатывать хранилище.

DELEGATECALL был новым кодом операции, который был исправлением ошибок для CALLCODE, который не сохранил msg.sender и msg.value. Если Алиса вызывает Боба, который делает DELEGATECALL для Charlie, msg.sender в DELEGATECALL - это Алиса (тогда как CALLCODE был использован msg.sender будет Боб).

Подробнее

Когда D выполняет CALL на E, код запускается в контексте E: используется хранилище E.

Когда D делает CALLCODE на E, код работает в контексте D. Предположим, что код E находится в D. Всякий раз, когда код записывается в хранилище, он записывает в хранилище учетной записи D вместо E.

contract D {
  uint public n;
  address public sender;

  function callSetN(address _e, uint _n) {
    _e.call(bytes4(sha3("setN(uint256)")), _n); // E's storage is set, D is not modified 
  }

  function callcodeSetN(address _e, uint _n) {
    _e.callcode(bytes4(sha3("setN(uint256)")), _n); // D's storage is set, E is not modified 
  }

  function delegatecallSetN(address _e, uint _n) {
    _e.delegatecall(bytes4(sha3("setN(uint256)")), _n); // D's storage is set, E is not modified 
  }
}

contract E {
  uint public n;
  address public sender;

  function setN(uint _n) {
    n = _n;
    sender = msg.sender;
    // msg.sender is D if invoked by D's callcodeSetN. None of E's storage is updated
    // msg.sender is C if invoked by C.foo(). None of E's storage is updated

    // the value of "this" is D, when invoked by either D's callcodeSetN or C.foo()
  }
}

contract C {
    function foo(D _d, E _e, uint _n) {
        _d.delegatecallSetN(_e, _n);
    }
}

Когда D делает CALLCODE на E, msg.sender внутри E является D , как указано в приведенном выше коде.

Когда учетная запись C вызывает D, а D DELEGATECALL на E, msg.sender внутри E есть C . То есть E имеет тот же msg.sender и msg.value как D.

Вы можете быстро протестировать выше в браузере Solidity .

ответил eth 6 Maypm16 2016, 22:45:39

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132