| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758 | // SPDX-License-Identifier: MITpragma solidity ^0.8.0;import "../utils/cryptography/ECDSA.sol";import "../utils/cryptography/draft-EIP712.sol";/** * @dev Simple minimal forwarder to be used together with an ERC2771 compatible contract. See {ERC2771Context}. */contract MinimalForwarder is EIP712 {    using ECDSA for bytes32;    struct ForwardRequest {        address from;        address to;        uint256 value;        uint256 gas;        uint256 nonce;        bytes data;    }    bytes32 private constant _TYPEHASH =        keccak256("ForwardRequest(address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data)");    mapping(address => uint256) private _nonces;    constructor() EIP712("MinimalForwarder", "0.0.1") {}    function getNonce(address from) public view returns (uint256) {        return _nonces[from];    }    function verify(ForwardRequest calldata req, bytes calldata signature) public view returns (bool) {        address signer = _hashTypedDataV4(            keccak256(abi.encode(_TYPEHASH, req.from, req.to, req.value, req.gas, req.nonce, keccak256(req.data)))        ).recover(signature);        return _nonces[req.from] == req.nonce && signer == req.from;    }    function execute(ForwardRequest calldata req, bytes calldata signature)        public        payable        returns (bool, bytes memory)    {        require(verify(req, signature), "MinimalForwarder: signature does not match request");        _nonces[req.from] = req.nonce + 1;        (bool success, bytes memory returndata) = req.to.call{gas: req.gas, value: req.value}(            abi.encodePacked(req.data, req.from)        );        // Validate that the relayer has sent enough gas for the call.        // See https://ronan.eth.link/blog/ethereum-gas-dangers/        assert(gasleft() > req.gas / 63);        return (success, returndata);    }}
 |