Etherscan

為什麼 Etherscan 的 opcode view 和 opcode disassembler 顯示 USDT 合約的 opcode 不同?

  • January 8, 2022

我們有 USDT 智能合約,位於0xdac17f958d2ee523a2206206994597c13d831ec7. 我正在嘗試反編譯智能合約(至少將其視為操作碼)。我看到的是它以 60606040526000 (etherscan 上的 ABI)開頭

[0] PUSH1 0x60 -> 6060
[2] PUSH1 0x40 -> 6040
[4] MSTORE -> 52
[5] PUSH1 0x00 -> 6000

所以說 opcode tool,但如果你Switch to opcode view合約頁面上 ,你會看到以下操作碼:

PUSH1 0x60
PUSH1 0x40
MSTORE
PUSH1 0x04
CALLDATASIZE
LT
PUSH2 0x0196
JUMPI
PUSH1 0x00
CALLDATALOAD

哪些不是

# from opcode tool

[1] PUSH1 0x60
[3] PUSH1 0x40
[4] MSTORE
[6] PUSH1 0x00
[7] DUP1
[9] PUSH1 0x14
[12] PUSH2 0x0100
[13] EXP
[14] DUP2
[15] SLOAD
[16] DUP2

問題是為什麼這些不同?什麼是正確的?我猜第二個變體是正確的,因為docs,但是 etherscan 會出錯嗎?順便說一句,如果你知道任何關於編譯的智能合約結構的文件,很高興分享,這樣我和每個人都能更好地理解它。

您的“操作碼工具”連結指向一個完全不同的地址 ( 0x9e1b57fc92eba6434251a8458811c32690f32c45)。如果您檢查原始地址的操作碼,您會發現它們是相同的:

PUSH1 0x60
PUSH1 0x40
MSTORE
PUSH1 0x04
CALLDATASIZE
LT
PUSH2 0x0196
JUMPI
PUSH1 0x00
CALLDATALOAD
PUSH29 0x0100000000000000000000000000000000000000000000000000000000
SWAP1
DIV
...
[1] PUSH1 0x60
[3] PUSH1 0x40
[4] MSTORE
[6] PUSH1 0x04
[7] CALLDATASIZE
[8] LT
[11] PUSH2 0x0196
[12] JUMPI
[14] PUSH1 0x00
[15] CALLDATALOAD
[45] PUSH29 0x0100000000000000000000000000000000000000000000000000000000
[46] SWAP1
[47] DIV 
...

順便說一句,如果你知道任何關於編譯的智能合約結構的文件,很高興分享,這樣我和每個人都能更好地理解它。

查看來自 OpenZeppelin 的多部分文章系列:解構 Solidity 合約 — 第 I 部分:簡介

請注意,這只是描述了 Solidity 編譯器生成的字節碼。目前 EVM 不強制執行任何結構,因此不同的編譯器可以以不同的方式執行。EVM 所做的只是在位置 0 處開始執行二進制 blob,然後去任何跳轉的地方。二進製文件的某些部分可能永遠不會被執行——例如,您可以將隨機垃圾附加到任何有效的字節碼中,並且它將保持有效(並且該部分不會被執行,因為不能跳轉到它)。solc 使用這個事實來創建程式碼/數據部分(子程序集/子對象)並在最後添加元數據雜湊。例如,要部署的執行時程式碼是一個子程序集。如果你的合約部署了其他合約new,這些合約中的每一個的字節碼也有一個單獨的子程序集。

這種自由形式的結構有其缺點,並且將來會發生變化。請參閱EIP-3540:EVM 對象格式 (EOF) v1,這是一個新標準,將使其更加嚴格。

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