了解 OpenZeppelin 的 Context 合約
我是剛接觸 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 個字節的數據)附加到呼叫數據的末尾。