###############################
Meta-Transactions
###############################

Meta-Transactions are signed messages that instruct the 0x Protocol to run function(s) in the context of the signer. This signed mtx can then be shared off-chain, allowing anyone to execute on-chain. This is useful for integrators who would like to subsidize the Ethereum Gas Fee, or add custom smart contract logic to run atomically a fill. A signed meta-transaction can only be executed once.

A common use case for this is in Request For Quote (RFQ) systems. The Maker creates an order; the Taker signs a mtx permitting 0x Protocol to fill the order on their behalf; the mtx is returned to the Maker who submits it on-chain.

.. image:: ../_static/img/rfqm.png
    :alt: Meta-Transaction Example
    :align: center



Constructing
============

To construct a Meta-Transaction, abi-encode the following struct and sign it.

.. code-block:: solidity

    /// @dev Describes an exchange proxy meta transaction.
    struct MetaTransactionData {
        // Signer of meta-transaction. On whose behalf to execute the MTX.
        address payable signer;
        // Required sender, or NULL for anyone.
        address sender;
        // Minimum gas price.
        uint256 minGasPrice;
        // Maximum gas price.
        uint256 maxGasPrice;
        // MTX is invalid after this time.
        uint256 expirationTimeSeconds;
        // Nonce to make this MTX unique.
        uint256 salt;
        // Encoded call data to a function on the exchange proxy.
        bytes callData;
        // Amount of ETH to attach to the call.
        uint256 value;
        // ERC20 fee `signer` pays `sender`.
        IERC20TokenV06 feeToken;
        // ERC20 fee amount.
        uint256 feeAmount;
    }

The ``calldata`` field is specific to the function you wish to execute. At this time, the following functions are supported:

- `fillLimitOrder <../basics/functions.html#filllimitorder>`_
- `fillRfqOrder <../basics/functions.html#fillrfqorder>`_
- `transformERC20 <../advanced/erc20_transformations.html>`_

Signing
=======

Meta-Transactions use the same signing technique as 0x Orders; see the `How to Sign <../basics/orders.html#how-to-sign>`_ section of the Orders documentation. See `getMetaTransactionHash`_ for generating a unique hash for your mtx.

Functionality
=============

+----------------------------------------+------------------------------------------------------------------------------------------------+
| Function                               | Overview                                                                                       |
+----------------------------------------+------------------------------------------------------------------------------------------------+
| `executeMetaTransaction`_              | Executes a single meta-transaction                                                             |
+----------------------------------------+------------------------------------------------------------------------------------------------+
| `batchExecuteMetaTransactions`_        | Executes a batch of meta-transactions.                                                         |
+----------------------------------------+------------------------------------------------------------------------------------------------+
| `getMetaTransactionExecutedBlock`_     | Returns the block that a meta-transaction was executed at.                                     |
+----------------------------------------+------------------------------------------------------------------------------------------------+
| `getMetaTransactionHashExecutedBlock`_ | Same as ``getMetaTransactionExecutedBlock``, only this function takes a meta-transaction hash. |
+----------------------------------------+------------------------------------------------------------------------------------------------+
| `getMetaTransactionHash`_              | Returns the hash of a meta-transaction.                                                        |
+----------------------------------------+------------------------------------------------------------------------------------------------+



executeMetaTransaction
----------------------

A single Meta-Transaction is executed by calling ``executeMetaTransaction``. A batch of mtx's can be executed by calling ``batchExecuteMetaTransactions``.

.. code-block:: solidity

    /// @dev Execute a single meta-transaction.
    /// @param mtx The meta-transaction.
    /// @param signature The signature by `mtx.signer`.
    /// @return returnResult The ABI-encoded result of the underlying call.
    function executeMetaTransaction(
        MetaTransactionData calldata mtx,
        LibSignature.Signature calldata signature
    )
        external
        payable
        returns (bytes memory returnResult);

A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted on succes. The ``returnResult`` contains the raw return data for the executed function. For example, if the function returns a ``uint256`` then the ``returnResult`` could be abi-decoded into a ``uint256``.

This call will revert in the following scenarios:

- The address in the ``mtx.sender`` field does not match ``msg.sender``.
- The mtx has expired.
- The Ethereum transaction's gas price (``tx.gasprice``) is outside of the range ``[mtx.minGasPrice..mtx.maxGasPrice]``
- The ETH sent with the mtx is less than ``mtx.value``
- The allowance/balance of ``signer`` is insufficient to pay ``feeAmount`` of ``feeToken`` to the ``sender`` (if specified)
- The signature is invalid.
- The mtx was already executed
- The underlying function is not supported by meta-transactions (see list above).
- The underlying function call reverts.

batchExecuteMetaTransactions
----------------------------

.. code-block:: solidity

    /// @dev Execute multiple meta-transactions.
    /// @param mtxs The meta-transactions.
    /// @param signatures The signature by each respective `mtx.signer`.
    /// @return returnResults The ABI-encoded results of the underlying calls.
    function batchExecuteMetaTransactions(
        MetaTransactionData[] calldata mtxs,
        LibSignature.Signature[] calldata signatures
    )
        external
        payable
        returns (bytes[] memory returnResults);

A `MetaTransactionExecuted <../basics/events.html#metatransactionexecuted>`_ event is emitted for each mtx on succes. The ``returnResult`` contains the raw return data for the executed function This call will revert if the one of the ``mtxs`` reverts. Any exceess Ether will be refunded to the ``msg.sender``.


getMetaTransactionExecutedBlock
-------------------------------

The ``block.number`` is stored on-chain when a mtx is executed. This value can be retrieved using the following function.

.. code-block:: solidity

    /// @dev Get the block at which a meta-transaction has been executed.
    /// @param mtx The meta-transaction.
    /// @return blockNumber The block height when the meta-transactioin was executed.
    function getMetaTransactionExecutedBlock(MetaTransactionData calldata mtx)
        external
        view
        returns (uint256 blockNumber);

getMetaTransactionHashExecutedBlock
-----------------------------------

This is a more gas-efficient implementation of ``getMetaTransactionExecutedBlock``.

.. code-block:: solidity

    /// @dev Get the block at which a meta-transaction hash has been executed.
    /// @param mtxHash The meta-transaction hash.
    /// @return blockNumber The block height when the meta-transactioin was executed.
    function getMetaTransactionHashExecutedBlock(bytes32 mtxHash)
        external
        view
        returns (uint256 blockNumber);


getMetaTransactionHash
----------------------

The hash of the mtx is used to uniquely identify it inside the protocol. It is computed following the `EIP712 spec <https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md>`_ standard. In solidity, the hash is computed using:

.. code-block:: solidity

    /// @dev Get the EIP712 hash of a meta-transaction.
    /// @param mtx The meta-transaction.
    /// @return mtxHash The EIP712 hash of `mtx`.
    function getMetaTransactionHash(MetaTransactionData calldata mtx)
        external
        view
        returns (bytes32 mtxHash);

The simplest way to generate an order hash is by calling this function, ex:

.. code-block:: solidity

    bytes32 orderHash = IZeroEx(0xDef1C0ded9bec7F1a1670819833240f027b25EfF).getMetaTransactionHash(mtx);

The hash can be manually generated using the following code:

.. code-block:: solidity

    bytes32 orderHash = keccak256(abi.encodePacked(
        '\x19\x01',
        // The domain separator.
        keccak256(abi.encode(
            // The EIP712 domain separator type hash.
            keccak256(abi.encodePacked(
                'EIP712Domain(',
                'string name,',
                'string version,',
                'uint256 chainId,',
                'address verifyingContract)'
            )),
            // The EIP712 domain separator values.
            'ZeroEx',
            '1.0.0',
            1, // For mainnet
            0xDef1C0ded9bec7F1a1670819833240f027b25EfF, // Address of the Exchange Proxy
        )),
        // The struct hash.
        keccak256(abi.encode(
            // The EIP712 type hash.
            keccak256(abi.encodePacked(
                "MetaTransactionData("
                "address signer,"
                "address sender,"
                "uint256 minGasPrice,"
                "uint256 maxGasPrice,"
                "uint256 expirationTimeSeconds,"
                "uint256 salt,"
                "bytes callData,"
                "uint256 value,"
                "address feeToken,"
                "uint256 feeAmount"
            ")"
            )),
            // The struct values.
            mtx.signer,
            mtx.sender,
            mtx.minGasPrice,
            mtx.maxGasPrice,
            mtx.expirationTimeSeconds,
            mtx.salt,
            keccak256(mtx.callData),
            mtx.value,
            mtx.feeToken,
            mtx.feeAmount
        ))
    ));

