Solidity

合約互操作性的執行時範圍是什麼?

  • December 12, 2016

似乎每個契約都有一個範圍。Reddit 上對這種微妙之處進行了辯論:

https://www.reddit.com/r/ethereum/comments/5hiy29/solidity_throw_after_selfdestruct_why_does_the/

我可以使用模擬的 js 區塊鏈重現此聲明

contract Client{
   Server public s  = new Server();
   function doit(){
       s.homicide();
       throw;
   }
}
contract Server{ 
   bool public alive = true;
   function homicide(){
       Suicide();
       suicide(msg.sender);

   }
   event Suicide();
}

https://ethereum.github.io/browser-solidity/#version=soljson-v0.4.6+commit.2dabbdf0.js&optimize=undefined&gist=9a48bde651631bff7591817811610070

呼叫 doit() 後,屬性 Server#alive 返回錯誤。有趣的是,我無法在 Ropsten 上執行它,因為遠端呼叫自殺和投擲所需的氣體超過了塊限制。

對於契約的互操作性,恕我直言,每個契約的範圍界定是一個嚴重的缺陷。它的原因是什麼,更重要的是它在哪裡指定?

這看起來像是 Javascript EVM 中的一個錯誤。我可以確認上述程式碼的行為與您在 Javascript EVM 上描述的一樣。

然而,這種行為與黃皮書(第 6 節)所描述的相反。EVM 應該保持一個持續的“事務狀態”,只有在原始呼叫/方法/消息執行完成時才會“送出”。如果原始呼叫/方法/消息以某種方式被破壞(氣體耗盡,我認為 Solidity 編譯為無效跳轉目標的“拋出”等),那麼“事務狀態”不會被送出 - 它被有效地回滾。(我可能在實現的實際機制上弄錯了。即 EVM 可能實際上會在事務期間修改 EVM 狀態,然後撤銷所做的任何更改。但它相當於同一件事。)

正在進行的“交易狀態”包括在該交易期間自殺的契約列表。因此,投擲不應該這些契約自殺 - 它應該讓他們保持活力並保持交易前的狀態。

我在我的私有開發鏈(Solidity 0.4.4 和 Parity 1.4.6)上執行了以下程式碼,並且可以確認它的行為符合我的預期 - 正如黃皮書所述:

客戶端.sol

pragma solidity ^0.4.4;
import "server.sol";
contract Client{
   Server public server;
   function Client(address _server) {
       server = Server(_server);
   }
   function doit(){
       server.homicide();
       throw;
   }
}

伺服器.sol

pragma solidity ^0.4.4;
contract Server{ 
   bool public alive = true;
   function homicide(){
       alive = false;
       suicide(msg.sender);
   }
}

部署 Server 後,再部署 Client(指向部署的 Server),呼叫 Client#doit() 後,Server 仍然是有效的合約,Server#alive 仍然為 true。

引用自:https://ethereum.stackexchange.com/questions/10628