metatx.adoc 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. :github-icon: pass:[<svg class="icon"><use href="#github-icon"/></svg>]
  2. :ERC2771Context: pass:normal[xref:metatx.adoc#ERC2771Context[`ERC2771Context`]]
  3. :ERC2771Forwarder: pass:normal[xref:metatx.adoc#ERC2771Forwarder[`ERC2771Forwarder`]]
  4. :xref-ERC2771Context-constructor-address-: xref:metatx.adoc#ERC2771Context-constructor-address-
  5. :xref-ERC2771Context-trustedForwarder--: xref:metatx.adoc#ERC2771Context-trustedForwarder--
  6. :xref-ERC2771Context-isTrustedForwarder-address-: xref:metatx.adoc#ERC2771Context-isTrustedForwarder-address-
  7. :xref-ERC2771Context-_msgSender--: xref:metatx.adoc#ERC2771Context-_msgSender--
  8. :xref-ERC2771Context-_msgData--: xref:metatx.adoc#ERC2771Context-_msgData--
  9. :xref-ERC2771Context-_contextSuffixLength--: xref:metatx.adoc#ERC2771Context-_contextSuffixLength--
  10. :ERC2771Context: pass:normal[xref:metatx.adoc#ERC2771Context[`ERC2771Context`]]
  11. :xref-ERC2771Forwarder-constructor-string-: xref:metatx.adoc#ERC2771Forwarder-constructor-string-
  12. :xref-ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-
  13. :xref-ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-
  14. :xref-ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-: xref:metatx.adoc#ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-
  15. :xref-ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-
  16. :xref-ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-: xref:metatx.adoc#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-
  17. :xref-ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-: xref:metatx.adoc#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-
  18. :xref-ERC2771Forwarder-_isTrustedByTarget-address-: xref:metatx.adoc#ERC2771Forwarder-_isTrustedByTarget-address-
  19. :xref-Nonces-nonces-address-: xref:utils.adoc#Nonces-nonces-address-
  20. :xref-Nonces-_useNonce-address-: xref:utils.adoc#Nonces-_useNonce-address-
  21. :xref-Nonces-_useCheckedNonce-address-uint256-: xref:utils.adoc#Nonces-_useCheckedNonce-address-uint256-
  22. :xref-EIP712-_domainSeparatorV4--: xref:utils/cryptography.adoc#EIP712-_domainSeparatorV4--
  23. :xref-EIP712-_hashTypedDataV4-bytes32-: xref:utils/cryptography.adoc#EIP712-_hashTypedDataV4-bytes32-
  24. :xref-EIP712-eip712Domain--: xref:utils/cryptography.adoc#EIP712-eip712Domain--
  25. :xref-EIP712-_EIP712Name--: xref:utils/cryptography.adoc#EIP712-_EIP712Name--
  26. :xref-EIP712-_EIP712Version--: xref:utils/cryptography.adoc#EIP712-_EIP712Version--
  27. :xref-ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-: xref:metatx.adoc#ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-
  28. :xref-IERC5267-EIP712DomainChanged--: xref:interfaces.adoc#IERC5267-EIP712DomainChanged--
  29. :xref-ERC2771Forwarder-ERC2771ForwarderInvalidSigner-address-address-: xref:metatx.adoc#ERC2771Forwarder-ERC2771ForwarderInvalidSigner-address-address-
  30. :xref-ERC2771Forwarder-ERC2771ForwarderMismatchedValue-uint256-uint256-: xref:metatx.adoc#ERC2771Forwarder-ERC2771ForwarderMismatchedValue-uint256-uint256-
  31. :xref-ERC2771Forwarder-ERC2771ForwarderExpiredRequest-uint48-: xref:metatx.adoc#ERC2771Forwarder-ERC2771ForwarderExpiredRequest-uint48-
  32. :xref-ERC2771Forwarder-ERC2771UntrustfulTarget-address-address-: xref:metatx.adoc#ERC2771Forwarder-ERC2771UntrustfulTarget-address-address-
  33. :xref-Nonces-InvalidAccountNonce-address-uint256-: xref:utils.adoc#Nonces-InvalidAccountNonce-address-uint256-
  34. :xref-ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32: xref:metatx.adoc#ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32
  35. :EIP712-constructor: pass:normal[xref:utils/cryptography.adoc#EIP712-constructor-string-string-[`EIP712.constructor`]]
  36. :ECDSA-tryRecover: pass:normal[xref:utils/cryptography.adoc#ECDSA-tryRecover-bytes32-uint8-bytes32-bytes32-[`ECDSA.tryRecover`]]
  37. :ERC2771Context-isTrustedForwarder: pass:normal[xref:metatx.adoc#ERC2771Context-isTrustedForwarder-address-[`ERC2771Context.isTrustedForwarder`]]
  38. = Meta Transactions
  39. [.readme-notice]
  40. NOTE: This document is better viewed at https://docs.openzeppelin.com/contracts/api/metatx
  41. This directory includes contracts for adding meta-transaction capabilities (i.e. abstracting the execution context from the transaction origin) following the https://eips.ethereum.org/EIPS/eip-2771[ERC-2771 specification].
  42. - {ERC2771Context}: Provides a mechanism to override the sender and calldata of the execution context (`msg.sender` and `msg.data`) with a custom value specified by a trusted forwarder.
  43. - {ERC2771Forwarder}: A production-ready forwarder that relays operation requests signed off-chain by an EOA.
  44. == Core
  45. :constructor: pass:normal[xref:#ERC2771Context-constructor-address-[`++constructor++`]]
  46. :trustedForwarder: pass:normal[xref:#ERC2771Context-trustedForwarder--[`++trustedForwarder++`]]
  47. :isTrustedForwarder: pass:normal[xref:#ERC2771Context-isTrustedForwarder-address-[`++isTrustedForwarder++`]]
  48. :_msgSender: pass:normal[xref:#ERC2771Context-_msgSender--[`++_msgSender++`]]
  49. :_msgData: pass:normal[xref:#ERC2771Context-_msgData--[`++_msgData++`]]
  50. :_contextSuffixLength: pass:normal[xref:#ERC2771Context-_contextSuffixLength--[`++_contextSuffixLength++`]]
  51. :constructor-address: pass:normal[xref:#ERC2771Context-constructor-address-[`++constructor++`]]
  52. :trustedForwarder-: pass:normal[xref:#ERC2771Context-trustedForwarder--[`++trustedForwarder++`]]
  53. :isTrustedForwarder-address: pass:normal[xref:#ERC2771Context-isTrustedForwarder-address-[`++isTrustedForwarder++`]]
  54. :_msgSender-: pass:normal[xref:#ERC2771Context-_msgSender--[`++_msgSender++`]]
  55. :_msgData-: pass:normal[xref:#ERC2771Context-_msgData--[`++_msgData++`]]
  56. :_contextSuffixLength-: pass:normal[xref:#ERC2771Context-_contextSuffixLength--[`++_contextSuffixLength++`]]
  57. [.contract]
  58. [[ERC2771Context]]
  59. === `++ERC2771Context++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.4.0/contracts/metatx/ERC2771Context.sol[{github-icon},role=heading-link]
  60. [.hljs-theme-light.nopadding]
  61. ```solidity
  62. import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
  63. ```
  64. Context variant with ERC-2771 support.
  65. WARNING: Avoid using this pattern in contracts that rely in a specific calldata length as they'll
  66. be affected by any forwarder whose `msg.data` is suffixed with the `from` address according to the ERC-2771
  67. specification adding the address size in bytes (20) to the calldata size. An example of an unexpected
  68. behavior could be an unintended fallback (or another function) invocation while trying to invoke the `receive`
  69. function only accessible if `msg.data.length == 0`.
  70. WARNING: The usage of `delegatecall` in this contract is dangerous and may result in context corruption.
  71. Any forwarded request to this contract triggering a `delegatecall` to itself will result in an invalid {_msgSender}
  72. recovery.
  73. [.contract-index]
  74. .Functions
  75. --
  76. * {xref-ERC2771Context-constructor-address-}[`++constructor(trustedForwarder_)++`]
  77. * {xref-ERC2771Context-trustedForwarder--}[`++trustedForwarder()++`]
  78. * {xref-ERC2771Context-isTrustedForwarder-address-}[`++isTrustedForwarder(forwarder)++`]
  79. * {xref-ERC2771Context-_msgSender--}[`++_msgSender()++`]
  80. * {xref-ERC2771Context-_msgData--}[`++_msgData()++`]
  81. * {xref-ERC2771Context-_contextSuffixLength--}[`++_contextSuffixLength()++`]
  82. --
  83. [.contract-item]
  84. [[ERC2771Context-constructor-address-]]
  85. ==== `[.contract-item-name]#++constructor++#++(address trustedForwarder_)++` [.item-kind]#internal#
  86. [.contract-item]
  87. [[ERC2771Context-trustedForwarder--]]
  88. ==== `[.contract-item-name]#++trustedForwarder++#++() → address++` [.item-kind]#public#
  89. Returns the address of the trusted forwarder.
  90. [.contract-item]
  91. [[ERC2771Context-isTrustedForwarder-address-]]
  92. ==== `[.contract-item-name]#++isTrustedForwarder++#++(address forwarder) → bool++` [.item-kind]#public#
  93. Indicates whether any particular address is the trusted forwarder.
  94. [.contract-item]
  95. [[ERC2771Context-_msgSender--]]
  96. ==== `[.contract-item-name]#++_msgSender++#++() → address++` [.item-kind]#internal#
  97. Override for `msg.sender`. Defaults to the original `msg.sender` whenever
  98. a call is not performed by the trusted forwarder or the calldata length is less than
  99. 20 bytes (an address length).
  100. [.contract-item]
  101. [[ERC2771Context-_msgData--]]
  102. ==== `[.contract-item-name]#++_msgData++#++() → bytes++` [.item-kind]#internal#
  103. Override for `msg.data`. Defaults to the original `msg.data` whenever
  104. a call is not performed by the trusted forwarder or the calldata length is less than
  105. 20 bytes (an address length).
  106. [.contract-item]
  107. [[ERC2771Context-_contextSuffixLength--]]
  108. ==== `[.contract-item-name]#++_contextSuffixLength++#++() → uint256++` [.item-kind]#internal#
  109. ERC-2771 specifies the context as being a single address (20 bytes).
  110. == Utils
  111. :ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-ForwardRequestData[`++ForwardRequestData++`]]
  112. :_FORWARD_REQUEST_TYPEHASH: pass:normal[xref:#ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32[`++_FORWARD_REQUEST_TYPEHASH++`]]
  113. :ExecutedForwardRequest: pass:normal[xref:#ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-[`++ExecutedForwardRequest++`]]
  114. :ERC2771ForwarderInvalidSigner: pass:normal[xref:#ERC2771Forwarder-ERC2771ForwarderInvalidSigner-address-address-[`++ERC2771ForwarderInvalidSigner++`]]
  115. :ERC2771ForwarderMismatchedValue: pass:normal[xref:#ERC2771Forwarder-ERC2771ForwarderMismatchedValue-uint256-uint256-[`++ERC2771ForwarderMismatchedValue++`]]
  116. :ERC2771ForwarderExpiredRequest: pass:normal[xref:#ERC2771Forwarder-ERC2771ForwarderExpiredRequest-uint48-[`++ERC2771ForwarderExpiredRequest++`]]
  117. :ERC2771UntrustfulTarget: pass:normal[xref:#ERC2771Forwarder-ERC2771UntrustfulTarget-address-address-[`++ERC2771UntrustfulTarget++`]]
  118. :constructor: pass:normal[xref:#ERC2771Forwarder-constructor-string-[`++constructor++`]]
  119. :verify: pass:normal[xref:#ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-[`++verify++`]]
  120. :execute: pass:normal[xref:#ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-[`++execute++`]]
  121. :executeBatch: pass:normal[xref:#ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-[`++executeBatch++`]]
  122. :_validate: pass:normal[xref:#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-[`++_validate++`]]
  123. :_recoverForwardRequestSigner: pass:normal[xref:#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-[`++_recoverForwardRequestSigner++`]]
  124. :_execute: pass:normal[xref:#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-[`++_execute++`]]
  125. :_isTrustedByTarget: pass:normal[xref:#ERC2771Forwarder-_isTrustedByTarget-address-[`++_isTrustedByTarget++`]]
  126. :constructor-string: pass:normal[xref:#ERC2771Forwarder-constructor-string-[`++constructor++`]]
  127. :verify-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-[`++verify++`]]
  128. :execute-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-[`++execute++`]]
  129. :executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable: pass:normal[xref:#ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-[`++executeBatch++`]]
  130. :_validate-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-[`++_validate++`]]
  131. :_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData: pass:normal[xref:#ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-[`++_recoverForwardRequestSigner++`]]
  132. :_execute-struct-ERC2771Forwarder-ForwardRequestData-bool: pass:normal[xref:#ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-[`++_execute++`]]
  133. :_isTrustedByTarget-address: pass:normal[xref:#ERC2771Forwarder-_isTrustedByTarget-address-[`++_isTrustedByTarget++`]]
  134. [.contract]
  135. [[ERC2771Forwarder]]
  136. === `++ERC2771Forwarder++` link:https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v5.4.0/contracts/metatx/ERC2771Forwarder.sol[{github-icon},role=heading-link]
  137. [.hljs-theme-light.nopadding]
  138. ```solidity
  139. import "@openzeppelin/contracts/metatx/ERC2771Forwarder.sol";
  140. ```
  141. A forwarder compatible with ERC-2771 contracts. See {ERC2771Context}.
  142. This forwarder operates on forward requests that include:
  143. * `from`: An address to operate on behalf of. It is required to be equal to the request signer.
  144. * `to`: The address that should be called.
  145. * `value`: The amount of native token to attach with the requested call.
  146. * `gas`: The amount of gas limit that will be forwarded with the requested call.
  147. * `nonce`: A unique transaction ordering identifier to avoid replayability and request invalidation.
  148. * `deadline`: A timestamp after which the request is not executable anymore.
  149. * `data`: Encoded `msg.data` to send with the requested call.
  150. Relayers are able to submit batches if they are processing a high volume of requests. With high
  151. throughput, relayers may run into limitations of the chain such as limits on the number of
  152. transactions in the mempool. In these cases the recommendation is to distribute the load among
  153. multiple accounts.
  154. NOTE: Batching requests includes an optional refund for unused `msg.value` that is achieved by
  155. performing a call with empty calldata. While this is within the bounds of ERC-2771 compliance,
  156. if the refund receiver happens to consider the forwarder a trusted forwarder, it MUST properly
  157. handle `msg.data.length == 0`. `ERC2771Context` in OpenZeppelin Contracts versions prior to 4.9.3
  158. do not handle this properly.
  159. ==== Security Considerations
  160. If a relayer submits a forward request, it should be willing to pay up to 100% of the gas amount
  161. specified in the request. This contract does not implement any kind of retribution for this gas,
  162. and it is assumed that there is an out of band incentive for relayers to pay for execution on
  163. behalf of signers. Often, the relayer is operated by a project that will consider it a user
  164. acquisition cost.
  165. By offering to pay for gas, relayers are at risk of having that gas used by an attacker toward
  166. some other purpose that is not aligned with the expected out of band incentives. If you operate a
  167. relayer, consider whitelisting target contracts and function selectors. When relaying ERC-721 or
  168. ERC-1155 transfers specifically, consider rejecting the use of the `data` field, since it can be
  169. used to execute arbitrary code.
  170. [.contract-index]
  171. .Functions
  172. --
  173. * {xref-ERC2771Forwarder-constructor-string-}[`++constructor(name)++`]
  174. * {xref-ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-}[`++verify(request)++`]
  175. * {xref-ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-}[`++execute(request)++`]
  176. * {xref-ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-}[`++executeBatch(requests, refundReceiver)++`]
  177. * {xref-ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-}[`++_validate(request)++`]
  178. * {xref-ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-}[`++_recoverForwardRequestSigner(request)++`]
  179. * {xref-ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-}[`++_execute(request, requireValidRequest)++`]
  180. * {xref-ERC2771Forwarder-_isTrustedByTarget-address-}[`++_isTrustedByTarget(target)++`]
  181. [.contract-subindex-inherited]
  182. .Nonces
  183. * {xref-Nonces-nonces-address-}[`++nonces(owner)++`]
  184. * {xref-Nonces-_useNonce-address-}[`++_useNonce(owner)++`]
  185. * {xref-Nonces-_useCheckedNonce-address-uint256-}[`++_useCheckedNonce(owner, nonce)++`]
  186. [.contract-subindex-inherited]
  187. .EIP712
  188. * {xref-EIP712-_domainSeparatorV4--}[`++_domainSeparatorV4()++`]
  189. * {xref-EIP712-_hashTypedDataV4-bytes32-}[`++_hashTypedDataV4(structHash)++`]
  190. * {xref-EIP712-eip712Domain--}[`++eip712Domain()++`]
  191. * {xref-EIP712-_EIP712Name--}[`++_EIP712Name()++`]
  192. * {xref-EIP712-_EIP712Version--}[`++_EIP712Version()++`]
  193. [.contract-subindex-inherited]
  194. .IERC5267
  195. --
  196. [.contract-index]
  197. .Events
  198. --
  199. * {xref-ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-}[`++ExecutedForwardRequest(signer, nonce, success)++`]
  200. [.contract-subindex-inherited]
  201. .Nonces
  202. [.contract-subindex-inherited]
  203. .EIP712
  204. [.contract-subindex-inherited]
  205. .IERC5267
  206. * {xref-IERC5267-EIP712DomainChanged--}[`++EIP712DomainChanged()++`]
  207. --
  208. [.contract-index]
  209. .Errors
  210. --
  211. * {xref-ERC2771Forwarder-ERC2771ForwarderInvalidSigner-address-address-}[`++ERC2771ForwarderInvalidSigner(signer, from)++`]
  212. * {xref-ERC2771Forwarder-ERC2771ForwarderMismatchedValue-uint256-uint256-}[`++ERC2771ForwarderMismatchedValue(requestedValue, msgValue)++`]
  213. * {xref-ERC2771Forwarder-ERC2771ForwarderExpiredRequest-uint48-}[`++ERC2771ForwarderExpiredRequest(deadline)++`]
  214. * {xref-ERC2771Forwarder-ERC2771UntrustfulTarget-address-address-}[`++ERC2771UntrustfulTarget(target, forwarder)++`]
  215. [.contract-subindex-inherited]
  216. .Nonces
  217. * {xref-Nonces-InvalidAccountNonce-address-uint256-}[`++InvalidAccountNonce(account, currentNonce)++`]
  218. [.contract-subindex-inherited]
  219. .EIP712
  220. [.contract-subindex-inherited]
  221. .IERC5267
  222. --
  223. [.contract-index]
  224. .Internal Variables
  225. --
  226. * {xref-ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32}[`++bytes32 constant _FORWARD_REQUEST_TYPEHASH++`]
  227. [.contract-subindex-inherited]
  228. .Nonces
  229. [.contract-subindex-inherited]
  230. .EIP712
  231. [.contract-subindex-inherited]
  232. .IERC5267
  233. --
  234. [.contract-item]
  235. [[ERC2771Forwarder-constructor-string-]]
  236. ==== `[.contract-item-name]#++constructor++#++(string name)++` [.item-kind]#public#
  237. See {EIP712-constructor}.
  238. [.contract-item]
  239. [[ERC2771Forwarder-verify-struct-ERC2771Forwarder-ForwardRequestData-]]
  240. ==== `[.contract-item-name]#++verify++#++(struct ERC2771Forwarder.ForwardRequestData request) → bool++` [.item-kind]#public#
  241. Returns `true` if a request is valid for a provided `signature` at the current block timestamp.
  242. A transaction is considered valid when the target trusts this forwarder, the request hasn't expired
  243. (deadline is not met), and the signer matches the `from` parameter of the signed request.
  244. NOTE: A request may return false here but it won't cause {executeBatch} to revert if a refund
  245. receiver is provided.
  246. [.contract-item]
  247. [[ERC2771Forwarder-execute-struct-ERC2771Forwarder-ForwardRequestData-]]
  248. ==== `[.contract-item-name]#++execute++#++(struct ERC2771Forwarder.ForwardRequestData request)++` [.item-kind]#public#
  249. Executes a `request` on behalf of `signature`'s signer using the ERC-2771 protocol. The gas
  250. provided to the requested call may not be exactly the amount requested, but the call will not run
  251. out of gas. Will revert if the request is invalid or the call reverts, in this case the nonce is not consumed.
  252. Requirements:
  253. - The request value should be equal to the provided `msg.value`.
  254. - The request should be valid according to {verify}.
  255. [.contract-item]
  256. [[ERC2771Forwarder-executeBatch-struct-ERC2771Forwarder-ForwardRequestData---address-payable-]]
  257. ==== `[.contract-item-name]#++executeBatch++#++(struct ERC2771Forwarder.ForwardRequestData[] requests, address payable refundReceiver)++` [.item-kind]#public#
  258. Batch version of {execute} with optional refunding and atomic execution.
  259. In case a batch contains at least one invalid request (see {verify}), the
  260. request will be skipped and the `refundReceiver` parameter will receive back the
  261. unused requested value at the end of the execution. This is done to prevent reverting
  262. the entire batch when a request is invalid or has already been submitted.
  263. If the `refundReceiver` is the `address(0)`, this function will revert when at least
  264. one of the requests was not valid instead of skipping it. This could be useful if
  265. a batch is required to get executed atomically (at least at the top-level). For example,
  266. refunding (and thus atomicity) can be opt-out if the relayer is using a service that avoids
  267. including reverted transactions.
  268. Requirements:
  269. - The sum of the requests' values should be equal to the provided `msg.value`.
  270. - All of the requests should be valid (see {verify}) when `refundReceiver` is the zero address.
  271. NOTE: Setting a zero `refundReceiver` guarantees an all-or-nothing requests execution only for
  272. the first-level forwarded calls. In case a forwarded request calls to a contract with another
  273. subcall, the second-level call may revert without the top-level call reverting.
  274. [.contract-item]
  275. [[ERC2771Forwarder-_validate-struct-ERC2771Forwarder-ForwardRequestData-]]
  276. ==== `[.contract-item-name]#++_validate++#++(struct ERC2771Forwarder.ForwardRequestData request) → bool isTrustedForwarder, bool active, bool signerMatch, address signer++` [.item-kind]#internal#
  277. Validates if the provided request can be executed at current block timestamp with
  278. the given `request.signature` on behalf of `request.signer`.
  279. [.contract-item]
  280. [[ERC2771Forwarder-_recoverForwardRequestSigner-struct-ERC2771Forwarder-ForwardRequestData-]]
  281. ==== `[.contract-item-name]#++_recoverForwardRequestSigner++#++(struct ERC2771Forwarder.ForwardRequestData request) → bool isValid, address signer++` [.item-kind]#internal#
  282. Returns a tuple with the recovered the signer of an EIP712 forward request message hash
  283. and a boolean indicating if the signature is valid.
  284. NOTE: The signature is considered valid if {ECDSA-tryRecover} indicates no recover error for it.
  285. [.contract-item]
  286. [[ERC2771Forwarder-_execute-struct-ERC2771Forwarder-ForwardRequestData-bool-]]
  287. ==== `[.contract-item-name]#++_execute++#++(struct ERC2771Forwarder.ForwardRequestData request, bool requireValidRequest) → bool success++` [.item-kind]#internal#
  288. Validates and executes a signed request returning the request call `success` value.
  289. Internal function without msg.value validation.
  290. Requirements:
  291. - The caller must have provided enough gas to forward with the call.
  292. - The request must be valid (see {verify}) if the `requireValidRequest` is true.
  293. Emits an {ExecutedForwardRequest} event.
  294. IMPORTANT: Using this function doesn't check that all the `msg.value` was sent, potentially
  295. leaving value stuck in the contract.
  296. [.contract-item]
  297. [[ERC2771Forwarder-_isTrustedByTarget-address-]]
  298. ==== `[.contract-item-name]#++_isTrustedByTarget++#++(address target) → bool++` [.item-kind]#internal#
  299. Returns whether the target trusts this forwarder.
  300. This function performs a static call to the target contract calling the
  301. {ERC2771Context-isTrustedForwarder} function.
  302. NOTE: Consider the execution of this forwarder is permissionless. Without this check, anyone may transfer assets
  303. that are owned by, or are approved to this forwarder.
  304. [.contract-item]
  305. [[ERC2771Forwarder-ExecutedForwardRequest-address-uint256-bool-]]
  306. ==== `[.contract-item-name]#++ExecutedForwardRequest++#++(address indexed signer, uint256 nonce, bool success)++` [.item-kind]#event#
  307. Emitted when a `ForwardRequest` is executed.
  308. NOTE: An unsuccessful forward request could be due to an invalid signature, an expired deadline,
  309. or simply a revert in the requested call. The contract guarantees that the relayer is not able to force
  310. the requested call to run out of gas.
  311. [.contract-item]
  312. [[ERC2771Forwarder-ERC2771ForwarderInvalidSigner-address-address-]]
  313. ==== `[.contract-item-name]#++ERC2771ForwarderInvalidSigner++#++(address signer, address from)++` [.item-kind]#error#
  314. The request `from` doesn't match with the recovered `signer`.
  315. [.contract-item]
  316. [[ERC2771Forwarder-ERC2771ForwarderMismatchedValue-uint256-uint256-]]
  317. ==== `[.contract-item-name]#++ERC2771ForwarderMismatchedValue++#++(uint256 requestedValue, uint256 msgValue)++` [.item-kind]#error#
  318. The `requestedValue` doesn't match with the available `msgValue`.
  319. [.contract-item]
  320. [[ERC2771Forwarder-ERC2771ForwarderExpiredRequest-uint48-]]
  321. ==== `[.contract-item-name]#++ERC2771ForwarderExpiredRequest++#++(uint48 deadline)++` [.item-kind]#error#
  322. The request `deadline` has expired.
  323. [.contract-item]
  324. [[ERC2771Forwarder-ERC2771UntrustfulTarget-address-address-]]
  325. ==== `[.contract-item-name]#++ERC2771UntrustfulTarget++#++(address target, address forwarder)++` [.item-kind]#error#
  326. The request target doesn't trust the `forwarder`.
  327. [.contract-item]
  328. [[ERC2771Forwarder-_FORWARD_REQUEST_TYPEHASH-bytes32]]
  329. ==== `bytes32 [.contract-item-name]#++_FORWARD_REQUEST_TYPEHASH++#` [.item-kind]#internal constant#