Solidity
msgSender() 這個程式碼在 OpenSea 儲存庫的範例 ERC721 中做了什麼?
abstract contract ContextMixin { function msgSender() internal view returns (address payable sender) { if (msg.sender == address(this)) { bytes memory array = msg.data; uint256 index = msg.data.length; assembly { // Load the 32 bytes word from memory with the address on the lower 20 bytes, and mask those. sender := and( mload(add(array, index)), 0xffffffffffffffffffffffffffffffffffffffff ) } } else { sender = payable(msg.sender); } return sender; } }
這是 OpenSea 特有的東西還是一般的東西?
我認為它應該用於元交易。您可以找到 OpenZeppelin 實現的類似範例,這些範例也旨在以這種方式使用。
為了支持原生元交易,OpenSea 繼承自
NativeMetaTransaction
執行另一個功能的合約(代錶帶有簽名的使用者),這將生成msg.sender
自己的地址 (address(this)
)。(如果你不明白為什麼 msg.sender 可以是合約地址本身,請閱讀這篇文章:msg.sender == address(this) 怎麼可能?)
在 OpenSea 的案例中,元事務由函式
executeMetaTransaction
here執行,該函式將使用者地址作為第一個參數。所以這個_msgSender()
函式基本上就是說,如果這是一個元交易,使用原始簽名者(使用者)的地址作為消息發送者,可以通過解析找到msg.data
。這就是他們如何支持一些無氣體交易的方式,您只需要簽署一個簽名,OpenSea 代理就會為您支付氣體,而契約將在您直接與其互動時工作,而無需在其中引入額外的角色契約。