Solidity

了解 OpenZeppelin 的 Context 合約

  • June 27, 2021

我是剛接觸 Solidity 並試圖理解 OpenZeppelin 的Context契約。在撰寫本文時,文件說:

雖然這些通常可通過 msg.sender 和 msg.data 獲得,但不應以這種直接方式訪問它們,因為在處理元交易時,發送和支付執行費用的帳戶可能不是實際的發送者(就應用有關)。

只有中間的、類似庫的合約才需要此合約。

我有點理解msg.sender可能與元交易的實際發件人不同的高層次,但我不明白使用Context’s_msgSender()或對此有何_msgData()幫助。這兩個函式都只是簡單地返回msg.sender,它們看起來與直接訪問ormsg.data沒有什麼不同。msg.sender``msg.data

OpenZeppelin在其建構子和修飾符中的Ownable用途,但我不明白這與硬編碼有何不同。_msgSender()``onlyOwner()``msg.sender

呼叫_msgSender()不同於的具體範例msg.sender將非常有幫助!

這個問題已在 OZ 論壇上提出並回答:https ://forum.openzeppelin.com/t/help-understanding-contract-context/10579 。

和函式實際上在 OZ 智能合約ERC2771Context_msg.sender中被覆蓋,它實現了EIP-2771:原生元交易的安全協議_msg.data

_msg.sender在受信任的轉發器發送元交易的情況下,這裡允許接收者合約檢索原始發送者:

function _msgSender() internal view virtual override returns (address sender) {
   if (isTrustedForwarder(msg.sender)) {
       // The assembly code is more direct than the Solidity version using `abi.decode`.
       assembly {
           sender := shr(96, calldataload(sub(calldatasize(), 20)))
       }
   } else {
       return super._msgSender();
   }
}

來自 EIP-2771 :

Trusted Forwarder 負責呼叫 Recipient 合約,並且必須將 Transaction Signer 的地址(20 個字節的數據)附加到呼叫數據的末尾。

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