合約互操作性的執行時範圍是什麼?
似乎每個契約都有一個範圍。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(); }
呼叫 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。