Solidity為什麼
為什麼 throw
和 revert()
創建不同的字節碼?
throw
並且revert()
都在編譯revert
操作(操作碼0xfd
)。根據文件:throw 關鍵字也可以用作revert() 的替代方法。
那麼為什麼下面的契約
contract test { function () { throw; //revert(); } }
revert()
如果我使用而不是上面的範例會產生不同的字節碼throw
?我正在使用帶有 Solidity 0.4.13+commit.0fb4cb1a.Emscripten.clang 的 Remix。這些是生成的操作碼:using throw: PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH1 0xE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST JUMPDEST PUSH1 0x47 DUP1 PUSH1 0x1C PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE JUMPDEST CALLVALUE ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x19 JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST JUMP JUMPDEST STOP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x4a PUSH32 0x5473469C00A2379987B5AF61DFF50F8FABE3B71589C4D2BBB53073BEB9D10029 using revert(): PUSH1 0x60 PUSH1 0x40 MSTORE CALLVALUE ISZERO PUSH1 0xE JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST JUMPDEST PUSH1 0x47 DUP1 PUSH1 0x1C PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x60 PUSH1 0x40 MSTORE JUMPDEST CALLVALUE ISZERO PUSH1 0xF JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST PUSH1 0x19 JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST JUMP JUMPDEST STOP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x5f 0xef 0xc4 0xac 0x4c STATICCALL DUP15 TIMESTAMP CODECOPY PUSH10 0x17070269221C62F6F5D4 0xba 0xe1 BALANCE BYTE 0xf7 EQ 0xca SWAP6 SWAP13 0xd0 0x27 0x24 STOP 0x29
我們看到最後的指令是不同的。而
throw
結束的版本0x627A7A723058 KECCAK256 0x4a PUSH32 0x5473469C00A2379987B5AF61DFF50F8FABE3B71589C4D2BBB53073BEB9D10029
revert()
結束的版本0x627A7A723058 KECCAK256 0x5f 0xef 0xc4 0xac 0x4c STATICCALL DUP15 TIMESTAMP CODECOPY PUSH10 0x17070269221C62F6F5D4 0xba 0xe1 BALANCE BYTE 0xf7 EQ 0xca SWAP6 SWAP13 0xd0 0x27 0x24 STOP 0x29
我會將 OpCode 的精確解釋留給其他人,並指出它們是不同的指令,因此可以預期不同的實現。
從 Metropolis 開始,
revert;
將返回未使用的 gas,而throw
將繼續消耗所有可用的 gas。就合約狀態變化而言,它們是相同的——一切都會回滾。希望能幫助到你。