Contract 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac190

Contract Overview

Balance:
0 AVAX
Txn Hash Method
Block
From
To
Value [Txn Fee]
0x16ed81b4241c6451136b274f812af19aa8601427233b1a8ac5d647aadf1f8c84Transfer120531362022-07-29 10:50:56185 days 20 hrs ago0x819315af06c8bfdc98ee5e569a35f8c8f948fac9 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1901 AVAX0.0011988865 26.5
0x2466bbd6be7adc41d080408a9dc907746808848f40a8f0a509201e0e9af99ba1Transfer118562822022-07-22 18:58:37192 days 12 hrs ago0x819315af06c8bfdc98ee5e569a35f8c8f948fac9 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900.1 AVAX0.001240734425 27.425
0x1334755ae50c93a617ed153d16940762f3a6ac5b8e0d78a94b6ec7bc2eb61662Transfer111557232022-07-01 15:23:33213 days 15 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900.7 AVAX0.01609539057 355.77
0xcba2ed106b95e5efcfeecaf18b2aca10f3e78b8e2c2af4fa002585a667d88ab7Transfer111556932022-07-01 15:22:09213 days 15 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900.2 AVAX0.00135044385 29.85
0x93f20153ff5cec633e4cd3466250a8a9e077365644acdd923cb18de515bd1d7aSet Relay Hub110913372022-06-29 20:10:07215 days 11 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX0.000909525
0xa48298910283a7494647d91d729b83c9bb35a9e2d09f24db07c060aade09d69dSet Trusted Forw...110711672022-06-29 8:13:33215 days 22 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX0.001329825
0x9f4e9b2c65899baf39adb50be57ad92c555de023c430918ec4b312b71f2d2b48Set Relay Hub110711662022-06-29 8:13:28215 days 22 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX0.00133725
0xa3476670f5ae238c8754adeb3f3bbfa61888f5c46c09037857306dd25a064b890x60806040110711632022-06-29 8:13:21215 days 22 hrs ago0xd21934ed8eaf27a67f0a70042af50a1d6d195e81 IN  Create: TestPaymasterEverythingAccepted0 AVAX0.02925507525
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0x6122d1bd033055a3085b24c51e5b5a76059363953e32f21ae07b7304a6c4e5cc162865082022-11-27 18:54:2464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x6122d1bd033055a3085b24c51e5b5a76059363953e32f21ae07b7304a6c4e5cc162865082022-11-27 18:54:2464 days 12 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900xa3b0ed2ea235b964cd77d7ef1952d496288d30220 AVAX
0x6122d1bd033055a3085b24c51e5b5a76059363953e32f21ae07b7304a6c4e5cc162865082022-11-27 18:54:2464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x6122d1bd033055a3085b24c51e5b5a76059363953e32f21ae07b7304a6c4e5cc162865082022-11-27 18:54:2464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8ef7536d568d81e8119f0b318da6e35d0286d06ed6465efd1e5489eb40fd6a4f162860702022-11-27 18:36:5964 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8ef7536d568d81e8119f0b318da6e35d0286d06ed6465efd1e5489eb40fd6a4f162860702022-11-27 18:36:5964 days 12 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900xab8ae9e3754d85ff892ea37e9fb6d4a550d92a1e0 AVAX
0x8ef7536d568d81e8119f0b318da6e35d0286d06ed6465efd1e5489eb40fd6a4f162860702022-11-27 18:36:5964 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8ef7536d568d81e8119f0b318da6e35d0286d06ed6465efd1e5489eb40fd6a4f162860702022-11-27 18:36:5964 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8110e909d83567e15c830484c263f379ad82c96a01dd7794c881f408eb847a12162857892022-11-27 18:26:1464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8110e909d83567e15c830484c263f379ad82c96a01dd7794c881f408eb847a12162857892022-11-27 18:26:1464 days 12 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900x2f39a9f60d71f7e227dc2e511dbf3f99b5eea2230 AVAX
0x8110e909d83567e15c830484c263f379ad82c96a01dd7794c881f408eb847a12162857892022-11-27 18:26:1464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8110e909d83567e15c830484c263f379ad82c96a01dd7794c881f408eb847a12162857892022-11-27 18:26:1464 days 12 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8402630264c57aa9681552725ac8ae1cdad53a6f0c8478402ab0545ac432dd28162627452022-11-27 4:13:5765 days 2 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8402630264c57aa9681552725ac8ae1cdad53a6f0c8478402ab0545ac432dd28162627452022-11-27 4:13:5765 days 2 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900xec4411cc7941039ac74f218ccf28283abcfd0d4e0 AVAX
0x8402630264c57aa9681552725ac8ae1cdad53a6f0c8478402ab0545ac432dd28162627452022-11-27 4:13:5765 days 2 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x8402630264c57aa9681552725ac8ae1cdad53a6f0c8478402ab0545ac432dd28162627452022-11-27 4:13:5765 days 2 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x2241e537b45025820cb62110565524a1d6002c07c6afd7cffd5f148581ceeb4f162519962022-11-26 20:48:4665 days 10 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x2241e537b45025820cb62110565524a1d6002c07c6afd7cffd5f148581ceeb4f162519962022-11-26 20:48:4665 days 10 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900x3a1df71d11774f25b9d8a35df4af1918bff416810 AVAX
0x2241e537b45025820cb62110565524a1d6002c07c6afd7cffd5f148581ceeb4f162519962022-11-26 20:48:4665 days 10 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x2241e537b45025820cb62110565524a1d6002c07c6afd7cffd5f148581ceeb4f162519962022-11-26 20:48:4665 days 10 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0xa7c4d9d155ff485f5e7b011572498ea5074b5219d98683b75a6cc23d713edb13160440852022-11-21 9:43:0670 days 21 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0xa7c4d9d155ff485f5e7b011572498ea5074b5219d98683b75a6cc23d713edb13160440852022-11-21 9:43:0670 days 21 hrs ago 0x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900x3a1df71d11774f25b9d8a35df4af1918bff416810 AVAX
0xa7c4d9d155ff485f5e7b011572498ea5074b5219d98683b75a6cc23d713edb13160440852022-11-21 9:43:0670 days 21 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0xa7c4d9d155ff485f5e7b011572498ea5074b5219d98683b75a6cc23d713edb13160440852022-11-21 9:43:0670 days 21 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
0x865492ba367ad5ab4fc953663b15a49c1c4e50f1b04264718b2712be55840e06158396242022-11-16 3:58:4276 days 3 hrs ago 0x2d493cde51adc74d4494b3dc146759cf32957a230x1e4d8ebd5071d117bcf351e3d53e34620d3ac1900 AVAX
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TestPaymasterEverythingAccepted

Compiler Version
v0.8.7+commit.e28d00a7

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 18 : Ownable.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 2 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol)

pragma solidity ^0.8.0;

import "../utils/introspection/IERC165.sol";

File 3 of 18 : IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) external returns (bool);
}

File 4 of 18 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

File 5 of 18 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 6 of 18 : ERC165Checker.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165Checker.sol)

pragma solidity ^0.8.0;

import "./IERC165.sol";

/**
 * @dev Library used to query support of an interface declared via {IERC165}.
 *
 * Note that these functions return the actual result of the query: they do not
 * `revert` if an interface is not supported. It is up to the caller to decide
 * what to do in these cases.
 */
library ERC165Checker {
    // As per the EIP-165 spec, no interface should ever match 0xffffffff
    bytes4 private constant _INTERFACE_ID_INVALID = 0xffffffff;

    /**
     * @dev Returns true if `account` supports the {IERC165} interface,
     */
    function supportsERC165(address account) internal view returns (bool) {
        // Any contract that implements ERC165 must explicitly indicate support of
        // InterfaceId_ERC165 and explicitly indicate non-support of InterfaceId_Invalid
        return
            _supportsERC165Interface(account, type(IERC165).interfaceId) &&
            !_supportsERC165Interface(account, _INTERFACE_ID_INVALID);
    }

    /**
     * @dev Returns true if `account` supports the interface defined by
     * `interfaceId`. Support for {IERC165} itself is queried automatically.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsInterface(address account, bytes4 interfaceId) internal view returns (bool) {
        // query support of both ERC165 as per the spec and support of _interfaceId
        return supportsERC165(account) && _supportsERC165Interface(account, interfaceId);
    }

    /**
     * @dev Returns a boolean array where each value corresponds to the
     * interfaces passed in and whether they're supported or not. This allows
     * you to batch check interfaces for a contract where your expectation
     * is that some interfaces may not be supported.
     *
     * See {IERC165-supportsInterface}.
     *
     * _Available since v3.4._
     */
    function getSupportedInterfaces(address account, bytes4[] memory interfaceIds)
        internal
        view
        returns (bool[] memory)
    {
        // an array of booleans corresponding to interfaceIds and whether they're supported or not
        bool[] memory interfaceIdsSupported = new bool[](interfaceIds.length);

        // query support of ERC165 itself
        if (supportsERC165(account)) {
            // query support of each interface in interfaceIds
            for (uint256 i = 0; i < interfaceIds.length; i++) {
                interfaceIdsSupported[i] = _supportsERC165Interface(account, interfaceIds[i]);
            }
        }

        return interfaceIdsSupported;
    }

    /**
     * @dev Returns true if `account` supports all the interfaces defined in
     * `interfaceIds`. Support for {IERC165} itself is queried automatically.
     *
     * Batch-querying can lead to gas savings by skipping repeated checks for
     * {IERC165} support.
     *
     * See {IERC165-supportsInterface}.
     */
    function supportsAllInterfaces(address account, bytes4[] memory interfaceIds) internal view returns (bool) {
        // query support of ERC165 itself
        if (!supportsERC165(account)) {
            return false;
        }

        // query support of each interface in _interfaceIds
        for (uint256 i = 0; i < interfaceIds.length; i++) {
            if (!_supportsERC165Interface(account, interfaceIds[i])) {
                return false;
            }
        }

        // all interfaces supported
        return true;
    }

    /**
     * @notice Query if a contract implements an interface, does not check ERC165 support
     * @param account The address of the contract to query for support of an interface
     * @param interfaceId The interface identifier, as specified in ERC-165
     * @return true if the contract at account indicates support of the interface with
     * identifier interfaceId, false otherwise
     * @dev Assumes that account contains a contract that supports ERC165, otherwise
     * the behavior of this method is undefined. This precondition can be checked
     * with {supportsERC165}.
     * Interface identification is specified in ERC-165.
     */
    function _supportsERC165Interface(address account, bytes4 interfaceId) private view returns (bool) {
        bytes memory encodedParams = abi.encodeWithSelector(IERC165.supportsInterface.selector, interfaceId);
        (bool success, bytes memory result) = account.staticcall{gas: 30000}(encodedParams);
        if (result.length < 32) return false;
        return success && abi.decode(result, (bool));
    }
}

File 7 of 18 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 8 of 18 : BasePaymaster.sol
pragma solidity >=0.7.6;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol";

import "./utils/GsnTypes.sol";
import "./interfaces/IPaymaster.sol";
import "./interfaces/IRelayHub.sol";
import "./utils/GsnEip712Library.sol";
import "./forwarder/IForwarder.sol";

/**
 * @notice An abstract base class to be inherited by a concrete Paymaster.
 * A subclass must implement:
 *  - preRelayedCall
 *  - postRelayedCall
 */
abstract contract BasePaymaster is IPaymaster, Ownable, ERC165 {
    using ERC165Checker for address;

    IRelayHub internal relayHub;
    address private _trustedForwarder;

    /// @inheritdoc IPaymaster
    function getRelayHub() public override view returns (address) {
        return address(relayHub);
    }

    //overhead of forwarder verify+signature, plus hub overhead.
    uint256 constant public FORWARDER_HUB_OVERHEAD = 50000;

    //These parameters are documented in IPaymaster.GasAndDataLimits
    uint256 constant public PRE_RELAYED_CALL_GAS_LIMIT = 100000;
    uint256 constant public POST_RELAYED_CALL_GAS_LIMIT = 110000;
    uint256 constant public PAYMASTER_ACCEPTANCE_BUDGET = PRE_RELAYED_CALL_GAS_LIMIT + FORWARDER_HUB_OVERHEAD;
    uint256 constant public CALLDATA_SIZE_LIMIT = 10500;

    /// @inheritdoc IERC165
    function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC165) returns (bool) {
        return interfaceId == type(IPaymaster).interfaceId ||
            interfaceId == type(Ownable).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    /// @inheritdoc IPaymaster
    function getGasAndDataLimits()
    public
    override
    virtual
    view
    returns (
        IPaymaster.GasAndDataLimits memory limits
    ) {
        return IPaymaster.GasAndDataLimits(
            PAYMASTER_ACCEPTANCE_BUDGET,
            PRE_RELAYED_CALL_GAS_LIMIT,
            POST_RELAYED_CALL_GAS_LIMIT,
            CALLDATA_SIZE_LIMIT
        );
    }

    /**
     * @notice this method must be called from preRelayedCall to validate that the forwarder
     * is approved by the paymaster as well as by the recipient contract.
     */
    function _verifyForwarder(GsnTypes.RelayRequest calldata relayRequest)
    internal
    virtual
    view
    {
        require(getTrustedForwarder() == relayRequest.relayData.forwarder, "Forwarder is not trusted");
        GsnEip712Library.verifyForwarderTrusted(relayRequest);
    }

    function _verifyRelayHubOnly() internal virtual view {
        require(msg.sender == getRelayHub(), "can only be called by RelayHub");
    }

    function _verifyValue(GsnTypes.RelayRequest calldata relayRequest) internal virtual view{
        require(relayRequest.request.value == 0, "value transfer not supported");
    }

    function _verifyPaymasterData(GsnTypes.RelayRequest calldata relayRequest) internal virtual view {
        require(relayRequest.relayData.paymasterData.length == 0, "should have no paymasterData");
    }

    function _verifyApprovalData(bytes calldata approvalData) internal virtual view{
        require(approvalData.length == 0, "should have no approvalData");
    }

    /**
     * @notice The owner of the Paymaster can change the instance of the RelayHub this Paymaster works with.
     * :warning: **Warning** :warning: The deposit on the previous RelayHub must be withdrawn first.
     */
    function setRelayHub(IRelayHub hub) public onlyOwner {
        require(address(hub).supportsInterface(type(IRelayHub).interfaceId), "target is not a valid IRelayHub");
        relayHub = hub;
    }

    /**
     * @notice The owner of the Paymaster can change the instance of the Forwarder this Paymaster works with.
     * @notice the Recipients must trust this Forwarder as well in order for the configuration to remain functional.
     */
    function setTrustedForwarder(address forwarder) public virtual onlyOwner {
        require(forwarder.supportsInterface(type(IForwarder).interfaceId), "target is not a valid IForwarder");
        _trustedForwarder = forwarder;
    }

    function getTrustedForwarder() public virtual view override returns (address){
        return _trustedForwarder;
    }

    /**
     * @notice Any native Ether transferred into the paymaster is transferred as a deposit to the RelayHub.
     * This way, we don't need to understand the RelayHub API in order to replenish the paymaster.
     */
    receive() external virtual payable {
        require(address(relayHub) != address(0), "relay hub address not set");
        relayHub.depositFor{value:msg.value}(address(this));
    }

    /**
     * @notice Withdraw deposit from the RelayHub.
     * @param amount The amount to be subtracted from the sender.
     * @param target The target to which the amount will be transferred.
     */
    function withdrawRelayHubDepositTo(uint256 amount, address payable target) public onlyOwner {
        relayHub.withdraw(target, amount);
    }

    /// @inheritdoc IPaymaster
    function preRelayedCall(
        GsnTypes.RelayRequest calldata relayRequest,
        bytes calldata signature,
        bytes calldata approvalData,
        uint256 maxPossibleGas
    )
    external
    override
    returns (bytes memory, bool) {
        _verifyRelayHubOnly();
        _verifyForwarder(relayRequest);
        _verifyValue(relayRequest);
        _verifyPaymasterData(relayRequest);
        _verifyApprovalData(approvalData);
        return _preRelayedCall(relayRequest, signature, approvalData, maxPossibleGas);
    }

    /**
     * @notice internal logic the paymasters need to provide to select which transactions they are willing to pay for
     * @notice see the documentation for `IPaymaster::preRelayedCall` for details
     */
    function _preRelayedCall(
        GsnTypes.RelayRequest calldata,
        bytes calldata,
        bytes calldata,
        uint256
    )
    internal
    virtual
    returns (bytes memory, bool);

    /// @inheritdoc IPaymaster
    function postRelayedCall(
        bytes calldata context,
        bool success,
        uint256 gasUseWithoutPost,
        GsnTypes.RelayData calldata relayData
    )
    external
    override
    {
        _verifyRelayHubOnly();
        _postRelayedCall(context, success, gasUseWithoutPost, relayData);
    }

    /**
     * @notice internal logic the paymasters need to provide if they need to take some action after the transaction
     * @notice see the documentation for `IPaymaster::postRelayedCall` for details
     */
    function _postRelayedCall(
        bytes calldata,
        bool,
        uint256,
        GsnTypes.RelayData calldata
    )
    internal
    virtual;
}

File 9 of 18 : IForwarder.sol
pragma solidity >=0.7.6;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "@openzeppelin/contracts/interfaces/IERC165.sol";

/**
 * @title The Forwarder Interface
 * @notice The contracts implementing this interface take a role of authorization, authentication and replay protection
 * for contracts that choose to trust a `Forwarder`, instead of relying on a mechanism built into the Ethereum protocol.
 *
 * @notice if the `Forwarder` contract decides that an incoming `ForwardRequest` is valid, it must append 20 bytes that
 * represent the caller to the `data` field of the request and send this new data to the target address (the `to` field)
 *
 * :warning: **Warning** :warning: The Forwarder can have a full control over a `Recipient` contract.
 * Any vulnerability in a `Forwarder` implementation can make all of its `Recipient` contracts susceptible!
 * Recipient contracts should only trust forwarders that passed through security audit,
 * otherwise they are susceptible to identity theft.
 */
interface IForwarder is IERC165 {

    /**
     * @notice A representation of a request for a `Forwarder` to send `data` on behalf of a `from` to a target (`to`).
     */
    struct ForwardRequest {
        address from;
        address to;
        uint256 value;
        uint256 gas;
        uint256 nonce;
        bytes data;
        uint256 validUntilTime;
    }

    event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue);

    event RequestTypeRegistered(bytes32 indexed typeHash, string typeStr);

    /**
     * @param from The address of a sender.
     * @return The nonce for this address.
     */
    function getNonce(address from)
    external view
    returns(uint256);

    /**
     * @notice Verify the transaction is valid and can be executed.
     * Implementations must validate the signature and the nonce of the request are correct.
     * Does not revert and returns successfully if the input is valid.
     * Reverts if any validation has failed. For instance, if either signature or nonce are incorrect.
     * Reverts if `domainSeparator` or `requestTypeHash` are not registered as well.
     */
    function verify(
        ForwardRequest calldata forwardRequest,
        bytes32 domainSeparator,
        bytes32 requestTypeHash,
        bytes calldata suffixData,
        bytes calldata signature
    ) external view;

    /**
     * @notice Executes a transaction specified by the `ForwardRequest`.
     * The transaction is first verified and then executed.
     * The success flag and returned bytes array of the `CALL` are returned as-is.
     *
     * This method would revert only in case of a verification error.
     *
     * All the target errors are reported using the returned success flag and returned bytes array.
     *
     * @param forwardRequest All requested transaction parameters.
     * @param domainSeparator The domain used when signing this request.
     * @param requestTypeHash The request type used when signing this request.
     * @param suffixData The ABI-encoded extension data for the current `RequestType` used when signing this request.
     * @param signature The client signature to be validated.
     *
     * @return success The success flag of the underlying `CALL` to the target address.
     * @return ret The byte array returned by the underlying `CALL` to the target address.
     */
    function execute(
        ForwardRequest calldata forwardRequest,
        bytes32 domainSeparator,
        bytes32 requestTypeHash,
        bytes calldata suffixData,
        bytes calldata signature
    )
    external payable
    returns (bool success, bytes memory ret);

    /**
     * @notice Register a new Request typehash.
     *
     * @notice This is necessary for the Forwarder to be able to verify the signatures conforming to the ERC-712.
     *
     * @param typeName The name of the request type.
     * @param typeSuffix Any extra data after the generic params. Must contain add at least one param.
     * The generic ForwardRequest type is always registered by the constructor.
     */
    function registerRequestType(string calldata typeName, string calldata typeSuffix) external;

    /**
     * @notice Register a new domain separator.
     *
     * @notice This is necessary for the Forwarder to be able to verify the signatures conforming to the ERC-712.
     *
     * @notice The domain separator must have the following fields: `name`, `version`, `chainId`, `verifyingContract`.
     * The `chainId` is the current network's `chainId`, and the `verifyingContract` is this Forwarder's address.
     * This method accepts the domain name and version to create and register the domain separator value.
     * @param name The domain's display name.
     * @param version The domain/protocol version.
     */
    function registerDomainSeparator(string calldata name, string calldata version) external;
}

File 10 of 18 : IERC2771Recipient.sol
pragma solidity >=0.6.0;

// SPDX-License-Identifier: MIT

/**
 * @title The ERC-2771 Recipient Base Abstract Class - Declarations
 *
 * @notice A contract must implement this interface in order to support relayed transaction.
 *
 * @notice It is recommended that your contract inherits from the ERC2771Recipient contract.
 */
abstract contract IERC2771Recipient {

    /**
     * :warning: **Warning** :warning: The Forwarder can have a full control over your Recipient. Only trust verified Forwarder.
     * @param forwarder The address of the Forwarder contract that is being used.
     * @return isTrustedForwarder `true` if the Forwarder is trusted to forward relayed transactions by this Recipient.
     */
    function isTrustedForwarder(address forwarder) public virtual view returns(bool);

    /**
     * @notice Use this method the contract anywhere instead of msg.sender to support relayed transactions.
     * @return sender The real sender of this call.
     * For a call that came through the Forwarder the real sender is extracted from the last 20 bytes of the `msg.data`.
     * Otherwise simply returns `msg.sender`.
     */
    function _msgSender() internal virtual view returns (address);

    /**
     * @notice Use this method in the contract instead of `msg.data` when difference matters (hashing, signature, etc.)
     * @return data The real `msg.data` of this call.
     * For a call that came through the Forwarder, the real sender address was appended as the last 20 bytes
     * of the `msg.data` - so this method will strip those 20 bytes off.
     * Otherwise (if the call was made directly and not through the forwarder) simply returns `msg.data`.
     */
    function _msgData() internal virtual view returns (bytes calldata);
}

File 11 of 18 : IPaymaster.sol
pragma solidity >=0.7.6;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "@openzeppelin/contracts/interfaces/IERC165.sol";

import "../utils/GsnTypes.sol";

/**
 * @title The Paymaster Interface
 * @notice Contracts implementing this interface exist to make decision about paying the transaction fee to the relay.
 *
 * @notice There are two callbacks here that are executed by the RelayHub: `preRelayedCall` and `postRelayedCall`.
 *
 * @notice It is recommended that your implementation inherits from the abstract BasePaymaster contract.
*/
interface IPaymaster is IERC165 {
    /**
     * @notice The limits this Paymaster wants to be imposed by the RelayHub on user input. See `getGasAndDataLimits`.
     */
    struct GasAndDataLimits {
        uint256 acceptanceBudget;
        uint256 preRelayedCallGasLimit;
        uint256 postRelayedCallGasLimit;
        uint256 calldataSizeLimit;
    }

    /**
     * @notice Return the Gas Limits for Paymaster's functions and maximum msg.data length values for this Paymaster.
     * This function allows different paymasters to have different properties without changes to the RelayHub.
     * @return limits An instance of the `GasAndDataLimits` struct
     *
     * ##### `acceptanceBudget`
     * If the transactions consumes more than `acceptanceBudget` this Paymaster will be charged for gas no matter what.
     * Transaction that gets rejected after consuming more than `acceptanceBudget` gas is on this Paymaster's expense.
     *
     * Should be set to an amount gas this Paymaster expects to spend deciding whether to accept or reject a request.
     * This includes gas consumed by calculations in the `preRelayedCall`, `Forwarder` and the recipient contract.
     *
     * :warning: **Warning** :warning: As long this value is above `preRelayedCallGasLimit`
     * (see defaults in `BasePaymaster`), the Paymaster is guaranteed it will never pay for rejected transactions.
     * If this value is below `preRelayedCallGasLimit`, it might might make Paymaster open to a "griefing" attack.
     *
     * The relayers should prefer lower `acceptanceBudget`, as it improves their chances of being compensated.
     * From a Relay's point of view, this is the highest gas value a bad Paymaster may cost the relay,
     * since the paymaster will pay anything above that value regardless of whether the transaction succeeds or reverts.
     * Specifying value too high might make the call rejected by relayers (see `maxAcceptanceBudget` in server config).
     *
     * ##### `preRelayedCallGasLimit`
     * The max gas usage of preRelayedCall. Any revert of the `preRelayedCall` is a request rejection by the paymaster.
     * As long as `acceptanceBudget` is above `preRelayedCallGasLimit`, any such revert is not payed by the paymaster.
     *
     * ##### `postRelayedCallGasLimit`
     * The max gas usage of postRelayedCall. The Paymaster is not charged for the maximum, only for actually used gas.
     * Note that an OOG will revert the inner transaction, but the paymaster will be charged for it anyway.
     */
    function getGasAndDataLimits()
    external
    view
    returns (
        GasAndDataLimits memory limits
    );

    /**
     * @notice :warning: **Warning** :warning: using incorrect Forwarder may cause the Paymaster to agreeing to pay for invalid transactions.
     * @return trustedForwarder The address of the `Forwarder` that is trusted by this Paymaster to execute the requests.
     */
    function getTrustedForwarder() external view returns (address trustedForwarder);

    /**
     * @return relayHub The address of the `RelayHub` that is trusted by this Paymaster to execute the requests.
     */
    function getRelayHub() external view returns (address relayHub);

    /**
     * @notice Called by the Relay in view mode and later by the `RelayHub` on-chain to validate that
     * the Paymaster agrees to pay for this call.
     *
     * The request is considered to be rejected by the Paymaster in one of the following conditions:
     *  - `preRelayedCall()` method reverts
     *  - the `Forwarder` reverts because of nonce or signature error
     *  - the `Paymaster` returned `rejectOnRecipientRevert: true` and the recipient contract reverted
     *    (and all that did not consume more than `acceptanceBudget` gas).
     *
     * In any of the above cases, all Paymaster calls and the recipient call are reverted.
     * In any other case the Paymaster will pay for the gas cost of the transaction.
     * Note that even if `postRelayedCall` is reverted the Paymaster will be charged.
     *

     * @param relayRequest - the full relay request structure
     * @param signature - user's EIP712-compatible signature of the `relayRequest`.
     * Note that in most cases the paymaster shouldn't try use it at all. It is always checked
     * by the forwarder immediately after preRelayedCall returns.
     * @param approvalData - extra dapp-specific data (e.g. signature from trusted party)
     * @param maxPossibleGas - based on values returned from `getGasAndDataLimits`
     * the RelayHub will calculate the maximum possible amount of gas the user may be charged for.
     * In order to convert this value to wei, the Paymaster has to call "relayHub.calculateCharge()"
     *
     * @return context
     * A byte array to be passed to postRelayedCall.
     * Can contain any data needed by this Paymaster in any form or be empty if no extra data is needed.
     * @return rejectOnRecipientRevert
     * The flag that allows a Paymaster to "delegate" the rejection to the recipient code.
     * It also means the Paymaster trust the recipient to reject fast: both preRelayedCall,
     * forwarder check and recipient checks must fit into the GasLimits.acceptanceBudget,
     * otherwise the TX is paid by the Paymaster.
     * `true` if the Paymaster wants to reject the TX if the recipient reverts.
     * `false` if the Paymaster wants rejects by the recipient to be completed on chain and paid by the Paymaster.
     */
    function preRelayedCall(
        GsnTypes.RelayRequest calldata relayRequest,
        bytes calldata signature,
        bytes calldata approvalData,
        uint256 maxPossibleGas
    )
    external
    returns (bytes memory context, bool rejectOnRecipientRevert);

    /**
     * @notice This method is called after the actual relayed function call.
     * It may be used to record the transaction (e.g. charge the caller by some contract logic) for this call.
     *
     * Revert in this functions causes a revert of the client's relayed call (and preRelayedCall(), but the Paymaster
     * is still committed to pay the relay for the entire transaction.
     *
     * @param context The call context, as returned by the preRelayedCall
     * @param success `true` if the relayed call succeeded, false if it reverted
     * @param gasUseWithoutPost The actual amount of gas used by the entire transaction, EXCEPT
     *        the gas used by the postRelayedCall itself.
     * @param relayData The relay params of the request. can be used by relayHub.calculateCharge()
     *
     */
    function postRelayedCall(
        bytes calldata context,
        bool success,
        uint256 gasUseWithoutPost,
        GsnTypes.RelayData calldata relayData
    ) external;

    /**
     * @return version The SemVer string of this Paymaster's version.
     */
    function versionPaymaster() external view returns (string memory);
}

File 12 of 18 : IRelayHub.sol
pragma solidity >=0.7.6;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "@openzeppelin/contracts/interfaces/IERC165.sol";

import "../utils/GsnTypes.sol";
import "./IStakeManager.sol";

/**
 * @title The RelayHub interface
 * @notice The implementation of this interface provides all the information the GSN client needs to
 * create a valid `RelayRequest` and also serves as an entry point for such requests.
 *
 * @notice The RelayHub also handles all the related financial records and hold the balances of participants.
 * The Paymasters keep their Ether deposited in the `RelayHub` in order to pay for the `RelayRequest`s that thay choose
 * to pay for, and Relay Servers keep their earned Ether in the `RelayHub` until they choose to `withdraw()`
 *
 * @notice The RelayHub on each supported network only needs a single instance and there is usually no need for dApp
 * developers or Relay Server operators to redeploy, reimplement, modify or override the `RelayHub`.
 */
interface IRelayHub is IERC165 {
    /**
     * @notice A struct that contains all the parameters of the `RelayHub` that can be modified after the deployment.
     */
    struct RelayHubConfig {
        // maximum number of worker accounts allowed per manager
        uint256 maxWorkerCount;
        // Gas set aside for all relayCall() instructions to prevent unexpected out-of-gas exceptions
        uint256 gasReserve;
        // Gas overhead to calculate gasUseWithoutPost
        uint256 postOverhead;
        // Gas cost of all relayCall() instructions after actual 'calculateCharge()'
        // Assume that relay has non-zero balance (costs 15'000 more otherwise).
        uint256 gasOverhead;
        // Minimum unstake delay seconds of a relay manager's stake on the StakeManager
        uint256 minimumUnstakeDelay;
        // Developers address
        address devAddress;
        // 0 < fee < 100, as percentage of total charge from paymaster to relayer
        uint8 devFee;
        // baseRelayFee The base fee the Relay Server charges for a single transaction in Ether, in wei.
        uint80 baseRelayFee;
        // pctRelayFee The percent of the total charge to add as a Relay Server fee to the total charge.
        uint16 pctRelayFee;
    }

    /// @notice Emitted when a configuration of the `RelayHub` is changed
    event RelayHubConfigured(RelayHubConfig config);

    /// @notice Emitted when relays are added by a relayManager
    event RelayWorkersAdded(
        address indexed relayManager,
        address[] newRelayWorkers,
        uint256 workersCount
    );

    /// @notice Emitted when an account withdraws funds from the `RelayHub`.
    event Withdrawn(
        address indexed account,
        address indexed dest,
        uint256 amount
    );

    /// @notice Emitted when `depositFor` is called, including the amount and account that was funded.
    event Deposited(
        address indexed paymaster,
        address indexed from,
        uint256 amount
    );

    /// @notice Emitted for each token configured for staking in setMinimumStakes
    event StakingTokenDataChanged(
        address token,
        uint256 minimumStake
    );

    /**
     * @notice Emitted when an attempt to relay a call fails and the `Paymaster` does not accept the transaction.
     * The actual relayed call was not executed, and the recipient not charged.
     * @param reason contains a revert reason returned from preRelayedCall or forwarder.
     */
    event TransactionRejectedByPaymaster(
        address indexed relayManager,
        address indexed paymaster,
        bytes32 indexed relayRequestID,
        address from,
        address to,
        address relayWorker,
        bytes4 selector,
        uint256 innerGasUsed,
        bytes reason
    );

    /**
     * @notice Emitted when a transaction is relayed. Note that the actual internal function call might be reverted.
     * The reason for a revert will be indicated in the `status` field of a corresponding `RelayCallStatus` value.
     * @notice `charge` is the Ether value deducted from the `Paymaster` balance.
     * The amount added to the `relayManager` balance will be lower if there is an activated `devFee` in the `config`.
     */
    event TransactionRelayed(
        address indexed relayManager,
        address indexed relayWorker,
        bytes32 indexed relayRequestID,
        address from,
        address to,
        address paymaster,
        bytes4 selector,
        RelayCallStatus status,
        uint256 charge
    );

    /// @notice This event is emitted in case the internal function returns a value or reverts with a revert string.
    event TransactionResult(
        RelayCallStatus status,
        bytes returnValue
    );

    /// @notice This event is emitted in case this `RelayHub` is deprecated and will stop serving transactions soon.
    event HubDeprecated(uint256 deprecationTime);

    /**
     * @notice This event is emitted in case a `relayManager` has been deemed "abandoned" for being
     * unresponsive for a prolonged period of time.
     * @notice This event means the entire balance of the relay has been transferred to the `devAddress`.
     */
    event AbandonedRelayManagerBalanceEscheated(
        address indexed relayManager,
        uint256 balance
    );

    /**
     * Error codes that describe all possible failure reasons reported in the `TransactionRelayed` event `status` field.
     *  @param OK The transaction was successfully relayed and execution successful - never included in the event.
     *  @param RelayedCallFailed The transaction was relayed, but the relayed call failed.
     *  @param RejectedByPreRelayed The transaction was not relayed due to preRelatedCall reverting.
     *  @param RejectedByForwarder The transaction was not relayed due to forwarder check (signature,nonce).
     *  @param PostRelayedFailed The transaction was relayed and reverted due to postRelatedCall reverting.
     *  @param PaymasterBalanceChanged The transaction was relayed and reverted due to the paymaster balance change.
     */
    enum RelayCallStatus {
        OK,
        RelayedCallFailed,
        RejectedByPreRelayed,
        RejectedByForwarder,
        RejectedByRecipientRevert,
        PostRelayedFailed,
        PaymasterBalanceChanged
    }

    /**
     * @notice Add new worker addresses controlled by the sender who must be a staked Relay Manager address.
     * Emits a `RelayWorkersAdded` event.
     * This function can be called multiple times, emitting new events.
     */
    function addRelayWorkers(address[] calldata newRelayWorkers) external;

    /**
     * @notice The `RelayRegistrar` callback to notify the `RelayHub` that this `relayManager` has updated registration.
     */
    function onRelayServerRegistered(address relayManager) external;

    // Balance management

    /**
     * @notice Deposits ether for a `Paymaster`, so that it can and pay for relayed transactions.
     * :warning: **Warning** :warning: Unused balance can only be withdrawn by the holder itself, by calling `withdraw`.
     * Emits a `Deposited` event.
     */
    function depositFor(address target) external payable;

    /**
     * @notice Withdraws from an account's balance, sending it back to the caller.
     * Relay Managers call this to retrieve their revenue, and `Paymasters` can also use it to reduce their funding.
     * Emits a `Withdrawn` event.
     */
    function withdraw(address payable dest, uint256 amount) external;

    /**
     * @notice Withdraws from an account's balance, sending funds to multiple provided addresses.
     * Relay Managers call this to retrieve their revenue, and `Paymasters` can also use it to reduce their funding.
     * Emits a `Withdrawn` event for each destination.
     */
    function withdrawMultiple(address payable[] memory dest, uint256[] memory amount) external;

    // Relaying

    /**
     * @notice Relays a transaction. For this to succeed, multiple conditions must be met:
     *  - `Paymaster`'s `preRelayCall` method must succeed and not revert.
     *  - the `msg.sender` must be a registered Relay Worker that the user signed to use.
     *  - the transaction's gas fees must be equal or larger than the ones that were signed by the sender.
     *  - the transaction must have enough gas to run all internal transactions if they use all gas available to them.
     *  - the `Paymaster` must have enough balance to pay the Relay Worker if all gas is spent.
     *
     * @notice If all conditions are met, the call will be relayed and the `Paymaster` charged.
     *
     * @param maxAcceptanceBudget The maximum valid value for `paymaster.getGasLimits().acceptanceBudget` to return.
     * @param relayRequest All details of the requested relayed call.
     * @param signature The client's EIP-712 signature over the `relayRequest` struct.
     * @param approvalData The dapp-specific data forwarded to the `Paymaster`'s `preRelayedCall` method.
     * This value is **not** verified by the `RelayHub` in any way.
     * As an example, it can be used to pass some kind of a third-party signature to the `Paymaster` for verification.
     *
     * Emits a `TransactionRelayed` event regardless of whether the transaction succeeded or failed.
     */
    function relayCall(
        uint256 maxAcceptanceBudget,
        GsnTypes.RelayRequest calldata relayRequest,
        bytes calldata signature,
        bytes calldata approvalData
    )
    external
    returns (
        bool paymasterAccepted,
        uint256 charge,
        IRelayHub.RelayCallStatus status,
        bytes memory returnValue
    );

    /**
     * @notice In case the Relay Worker has been found to be in violation of some rules by the `Penalizer` contract,
     * the `Penalizer` will call this method to execute a penalization.
     * The `RelayHub` will look up the Relay Manager of the given Relay Worker and will forward the call to
     * the `StakeManager` contract. The `RelayHub` does not perform the actual penalization either.
     * @param relayWorker The address of the Relay Worker that committed a penalizable offense.
     * @param beneficiary The address that called the `Penalizer` and will receive a reward for it.
     */
    function penalize(address relayWorker, address payable beneficiary) external;

    /**
     * @notice Sets or changes the configuration of this `RelayHub`.
     * @param _config The new configuration.
     */
    function setConfiguration(RelayHubConfig memory _config) external;

    /**
     * @notice Sets or changes the minimum amount of a given `token` that needs to be staked so that the Relay Manager
     * is considered to be 'staked' by this `RelayHub`. Zero value means this token is not allowed for staking.
     * @param token An array of addresses of ERC-20 compatible tokens.
     * @param minimumStake An array of minimal amounts necessary for a corresponding token, in wei.
     */
    function setMinimumStakes(IERC20[] memory token, uint256[] memory minimumStake) external;

    /**
     * @notice Deprecate hub by reverting all incoming `relayCall()` calls starting from a given timestamp
     * @param _deprecationTime The timestamp in seconds after which the `RelayHub` stops serving transactions.
     */
    function deprecateHub(uint256 _deprecationTime) external;

    /**
     * @notice
     * @param relayManager
     */
    function escheatAbandonedRelayBalance(address relayManager) external;

    /**
     * @notice The fee is expressed as a base fee in wei plus percentage of the actual charge.
     * For example, a value '40' stands for a 40% fee, so the recipient will be charged for 1.4 times the spent amount.
     * @param gasUsed An amount of gas used by the transaction.
     * @param relayData The details of a transaction signed by the sender.
     * @return The calculated charge, in wei.
     */
    function calculateCharge(uint256 gasUsed, GsnTypes.RelayData calldata relayData) external view returns (uint256);

    /**
     * @notice The fee is expressed as a  percentage of the actual charge.
     * For example, a value '40' stands for a 40% fee, so the Relay Manager will only get 60% of the `charge`.
     * @param charge The amount of Ether in wei the Paymaster will be charged for this transaction.
     * @return The calculated devFee, in wei.
     */
    function calculateDevCharge(uint256 charge) external view returns (uint256);
    /* getters */

    /// @return config The configuration of the `RelayHub`.
    function getConfiguration() external view returns (RelayHubConfig memory config);

    /**
     * @param token An address of an ERC-20 compatible tokens.
     * @return The minimum amount of a given `token` that needs to be staked so that the Relay Manager
     * is considered to be 'staked' by this `RelayHub`. Zero value means this token is not allowed for staking.
     */
    function getMinimumStakePerToken(IERC20 token) external view returns (uint256);

    /**
     * @param worker An address of the Relay Worker.
     * @return The address of its Relay Manager.
     */
    function getWorkerManager(address worker) external view returns (address);

    /**
     * @param manager An address of the Relay Manager.
     * @return The count of Relay Workers associated with this Relay Manager.
     */
    function getWorkerCount(address manager) external view returns (uint256);

    /// @return An account's balance. It can be either a deposit of a `Paymaster`, or a revenue of a Relay Manager.
    function balanceOf(address target) external view returns (uint256);

    /// @return The `StakeManager` address for this `RelayHub`.
    function getStakeManager() external view returns (IStakeManager);

    /// @return The `Penalizer` address for this `RelayHub`.
    function getPenalizer() external view returns (address);

    /// @return The `RelayRegistrar` address for this `RelayHub`.
    function getRelayRegistrar() external view returns (address);

    /// @return The `BatchGateway` address for this `RelayHub`.
    function getBatchGateway() external view returns (address);

    /**
     * @notice Uses `StakeManager` to decide if the Relay Manager can be considered staked or not.
     * Returns if the stake's token, amount and delay satisfy all requirements, reverts otherwise.
     */
    function verifyRelayManagerStaked(address relayManager) external view;

    /**
     * @notice Uses `StakeManager` to check if the Relay Manager can be considered abandoned or not.
     * Returns true if the stake's abandonment time is in the past including the escheatment delay, false otherwise.
     */
    function isRelayEscheatable(address relayManager) external view returns (bool);

    /// @return `true` if the `RelayHub` is deprecated, `false` it it is not deprecated and can serve transactions.
    function isDeprecated() external view returns (bool);

    /// @return The timestamp from which the hub no longer allows relaying calls.
    function getDeprecationTime() external view returns (uint256);

    /// @return The block number in which the contract has been deployed.
    function getCreationBlock() external view returns (uint256);

    /// @return a SemVer-compliant version of the `RelayHub` contract.
    function versionHub() external view returns (string memory);

    /// @return A total measurable amount of gas left to current execution. Same as 'gasleft()' for pure EVMs.
    function aggregateGasleft() external view returns (uint256);
}

File 13 of 18 : IStakeManager.sol
pragma solidity >=0.7.6;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/utils/introspection/ERC165.sol";

/**
 * @title The StakeManager Interface
 * @notice In order to prevent an attacker from registering a large number of unresponsive relays, the GSN requires
 * the Relay Server to maintain a permanently locked stake in the system before being able to register.
 *
 * @notice Also, in some cases the behavior of a Relay Server may be found to be illegal by a `Penalizer` contract.
 * In such case, the stake will never be returned to the Relay Server operator and will be slashed.
 *
 * @notice An implementation of this interface is tasked with keeping Relay Servers' stakes, made in any ERC-20 token.
 * Note that the `RelayHub` chooses which ERC-20 tokens to support and how much stake is needed.
 */
interface IStakeManager is IERC165 {

    /// @notice Emitted when a `stake` or `unstakeDelay` are initialized or increased.
    event StakeAdded(
        address indexed relayManager,
        address indexed owner,
        IERC20 token,
        uint256 stake,
        uint256 unstakeDelay
    );

    /// @notice Emitted once a stake is scheduled for withdrawal.
    event StakeUnlocked(
        address indexed relayManager,
        address indexed owner,
        uint256 withdrawTime
    );

    /// @notice Emitted when owner withdraws `relayManager` funds.
    event StakeWithdrawn(
        address indexed relayManager,
        address indexed owner,
        IERC20 token,
        uint256 amount
    );

    /// @notice Emitted when an authorized `RelayHub` penalizes a `relayManager`.
    event StakePenalized(
        address indexed relayManager,
        address indexed beneficiary,
        IERC20 token,
        uint256 reward
    );

    /// @notice Emitted when a `relayManager` adds a new `RelayHub` to a list of authorized.
    event HubAuthorized(
        address indexed relayManager,
        address indexed relayHub
    );

    /// @notice Emitted when a `relayManager` removes a `RelayHub` from a list of authorized.
    event HubUnauthorized(
        address indexed relayManager,
        address indexed relayHub,
        uint256 removalTime
    );

    /// @notice Emitted when a `relayManager` sets its `owner`. This is necessary to prevent stake hijacking.
    event OwnerSet(
        address indexed relayManager,
        address indexed owner
    );

    /// @notice Emitted when a `burnAddress` is changed.
    event BurnAddressSet(
        address indexed burnAddress
    );

    /// @notice Emitted when a `devAddress` is changed.
    event DevAddressSet(
        address indexed devAddress
    );

    /// @notice Emitted if Relay Server is inactive for an `abandonmentDelay` and contract owner initiates its removal.
    event RelayServerAbandoned(
        address indexed relayManager,
        uint256 abandonedTime
    );

    /// @notice Emitted to indicate an action performed by a relay server to prevent it from being marked as abandoned.
    event RelayServerKeepalive(
        address indexed relayManager,
        uint256 keepaliveTime
    );

    /// @notice Emitted when the stake of an abandoned relayer has been confiscated and transferred to the `devAddress`.
    event AbandonedRelayManagerStakeEscheated(
        address indexed relayManager,
        address indexed owner,
        IERC20 token,
        uint256 amount
    );

    /**
     * @param stake - amount of ether staked for this relay
     * @param unstakeDelay - number of seconds to elapse before the owner can retrieve the stake after calling 'unlock'
     * @param withdrawTime - timestamp in seconds when 'withdraw' will be callable, or zero if the unlock has not been called
     * @param owner - address that receives revenue and manages relayManager's stake
     */
    struct StakeInfo {
        uint256 stake;
        uint256 unstakeDelay;
        uint256 withdrawTime;
        uint256 abandonedTime;
        uint256 keepaliveTime;
        IERC20 token;
        address owner;
    }

    struct RelayHubInfo {
        uint256 removalTime;
    }

    /**
     * @param devAddress - the address that will receive the 'abandoned' stake
     * @param abandonmentDelay - the amount of time after which the relay can be marked as 'abandoned'
     * @param escheatmentDelay - the amount of time after which the abandoned relay's stake and balance may be withdrawn to the `devAddress`
     */
    struct AbandonedRelayServerConfig {
        address devAddress;
        uint256 abandonmentDelay;
        uint256 escheatmentDelay;
    }

    /**
     * @notice Set the owner of a Relay Manager. Called only by the RelayManager itself.
     * Note that owners cannot transfer ownership - if the entry already exists, reverts.
     * @param owner - owner of the relay (as configured off-chain)
     */
    function setRelayManagerOwner(address owner) external;

    /**
     * @notice Put a stake for a relayManager and set its unstake delay.
     * Only the owner can call this function. If the entry does not exist, reverts.
     * The owner must give allowance of the ERC-20 token to the StakeManager before calling this method.
     * It is the RelayHub who has a configurable list of minimum stakes per token. StakeManager accepts all tokens.
     * @param token The address of an ERC-20 token that is used by the relayManager as a stake
     * @param relayManager The address that represents a stake entry and controls relay registrations on relay hubs
     * @param unstakeDelay The number of seconds to elapse before an owner can retrieve the stake after calling `unlock`
     * @param amount The amount of tokens to be taken from the relayOwner and locked in the StakeManager as a stake
     */
    function stakeForRelayManager(IERC20 token, address relayManager, uint256 unstakeDelay, uint256 amount) external;

    /**
     * @notice Schedule the unlocking of the stake. The `unstakeDelay` must pass before owner can call `withdrawStake`.
     * @param relayManager The address of a Relay Manager whose stake is to be unlocked.
     */
    function unlockStake(address relayManager) external;
    /**
     * @notice Withdraw the unlocked stake.
     * @param relayManager The address of a Relay Manager whose stake is to be withdrawn.
     */
    function withdrawStake(address relayManager) external;

    /**
     * @notice Add the `RelayHub` to a list of authorized by this Relay Manager.
     * This allows the RelayHub to penalize this Relay Manager. The `RelayHub` cannot trust a Relay it cannot penalize.
     * @param relayManager The address of a Relay Manager whose stake is to be authorized for the new `RelayHub`.
     * @param relayHub The address of a `RelayHub` to be authorized.
     */
    function authorizeHubByOwner(address relayManager, address relayHub) external;

    /**
     * @notice Same as `authorizeHubByOwner` but can be called by the RelayManager itself.
     */
    function authorizeHubByManager(address relayHub) external;

    /**
     * @notice Remove the `RelayHub` from a list of authorized by this Relay Manager.
     * @param relayManager The address of a Relay Manager.
     * @param relayHub The address of a `RelayHub` to be unauthorized.
     */
    function unauthorizeHubByOwner(address relayManager, address relayHub) external;

    /**
     * @notice Same as `unauthorizeHubByOwner` but can be called by the RelayManager itself.
     */
    function unauthorizeHubByManager(address relayHub) external;

    /**
     * Slash the stake of the relay relayManager. In order to prevent stake kidnapping, burns part of stake on the way.
     * @param relayManager The address of a Relay Manager to be penalized.
     * @param beneficiary The address that receives part of the penalty amount.
     * @param amount A total amount of penalty to be withdrawn from stake.
     */
    function penalizeRelayManager(address relayManager, address beneficiary, uint256 amount) external;

    /**
     * @notice Allows the contract owner to set the given `relayManager` as abandoned after a configurable delay.
     * Its entire stake and balance will be taken from a relay if it does not respond to being marked as abandoned.
     */
    function markRelayAbandoned(address relayManager) external;

    /**
     * @notice If more than `abandonmentDelay` has passed since the last Keepalive transaction, and relay manager
     * has been marked as abandoned, and after that more that `escheatmentDelay` have passed, entire stake and
     * balance will be taken from this relay.
     */
    function escheatAbandonedRelayStake(address relayManager) external;

    /**
     * @notice Sets a new `keepaliveTime` for the given `relayManager`, preventing it from being marked as abandoned.
     * Can be called by an authorized `RelayHub` or by the `relayOwner` address.
     */
    function updateRelayKeepaliveTime(address relayManager) external;

    /**
     * @notice Check if the Relay Manager can be considered abandoned or not.
     * Returns true if the stake's abandonment time is in the past including the escheatment delay, false otherwise.
     */
    function isRelayEscheatable(address relayManager) external view returns(bool);

    /**
     * @notice Get the stake details information for the given Relay Manager.
     * @param relayManager The address of a Relay Manager.
     * @return stakeInfo The `StakeInfo` structure.
     * @return isSenderAuthorizedHub `true` if the `msg.sender` for this call was a `RelayHub` that is authorized now.
     * `false` if the `msg.sender` for this call is not authorized.
     */
    function getStakeInfo(address relayManager) external view returns (StakeInfo memory stakeInfo, bool isSenderAuthorizedHub);

    /**
     * @return The maximum unstake delay this `StakeManger` allows. This is to prevent locking money forever by mistake.
     */
    function getMaxUnstakeDelay() external view returns (uint256);

    /**
     * @notice Change the address that will receive the 'burned' part of the penalized stake.
     * This is done to prevent malicious Relay Server from penalizing itself and breaking even.
     */
    function setBurnAddress(address _burnAddress) external;

    /**
     * @return The address that will receive the 'burned' part of the penalized stake.
     */
    function getBurnAddress() external view returns (address);

    /**
     * @notice Change the address that will receive the 'abandoned' stake.
     * This is done to prevent Relay Servers that lost their keys from losing access to funds.
     */
    function setDevAddress(address _burnAddress) external;

    /**
     * @return The structure that contains all configuration values for the 'abandoned' stake.
     */
    function getAbandonedRelayServerConfig() external view returns (AbandonedRelayServerConfig memory);

    /**
     * @return the block number in which the contract has been deployed.
     */
    function getCreationBlock() external view returns (uint256);

    /**
     * @return a SemVer-compliant version of the `StakeManager` contract.
     */
    function versionSM() external view returns (string memory);
}

File 14 of 18 : TestPaymasterEverythingAccepted.sol
pragma solidity ^0.8.0;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "../forwarder/IForwarder.sol";
import "../BasePaymaster.sol";

contract TestPaymasterEverythingAccepted is BasePaymaster {

    function versionPaymaster() external view override virtual returns (string memory){
        return "3.0.0-beta.0+opengsn.test-pea.ipaymaster";
    }

    event SampleRecipientPreCall();
    event SampleRecipientPostCall(bool success, uint256 actualCharge);

    // solhint-disable-next-line no-empty-blocks
    function _verifyValue(GsnTypes.RelayRequest calldata) internal override view{}

    function _preRelayedCall(
        GsnTypes.RelayRequest calldata relayRequest,
        bytes calldata signature,
        bytes calldata approvalData,
        uint256 maxPossibleGas
    )
    internal
    override
    virtual
    returns (bytes memory, bool) {
        (relayRequest, signature);
        (approvalData, maxPossibleGas);
        emit SampleRecipientPreCall();
        return ("no revert here",false);
    }

    function _postRelayedCall(
        bytes calldata context,
        bool success,
        uint256 gasUseWithoutPost,
        GsnTypes.RelayData calldata relayData
    )
    internal
    override
    virtual
    {
        (context, gasUseWithoutPost, relayData);
        emit SampleRecipientPostCall(success, gasUseWithoutPost);
    }

    function deposit() public payable {
        require(address(relayHub) != address(0), "relay hub address not set");
        relayHub.depositFor{value:msg.value}(address(this));
    }

    function withdrawAll(address payable destination) public {
        uint256 amount = relayHub.balanceOf(address(this));
        withdrawRelayHubDepositTo(amount, destination);
    }
}

File 15 of 18 : GsnEip712Library.sol
pragma solidity ^0.8.0;
pragma abicoder v2;

// SPDX-License-Identifier: GPL-3.0-only

import "../utils/GsnTypes.sol";
import "../interfaces/IERC2771Recipient.sol";
import "../forwarder/IForwarder.sol";

import "./GsnUtils.sol";

/**
 * @title The ERC-712 Library for GSN
 * @notice Bridge Library to convert a GSN RelayRequest into a valid `ForwardRequest` for a `Forwarder`.
 */
library GsnEip712Library {
    // maximum length of return value/revert reason for 'execute' method. Will truncate result if exceeded.
    uint256 private constant MAX_RETURN_SIZE = 1024;

    //copied from Forwarder (can't reference string constants even from another library)
    string public constant GENERIC_PARAMS = "address from,address to,uint256 value,uint256 gas,uint256 nonce,bytes data,uint256 validUntilTime";

    bytes public constant RELAYDATA_TYPE = "RelayData(uint256 maxFeePerGas,uint256 maxPriorityFeePerGas,uint256 transactionCalldataGasUsed,address relayWorker,address paymaster,address forwarder,bytes paymasterData,uint256 clientId)";

    string public constant RELAY_REQUEST_NAME = "RelayRequest";
    string public constant RELAY_REQUEST_SUFFIX = string(abi.encodePacked("RelayData relayData)", RELAYDATA_TYPE));

    bytes public constant RELAY_REQUEST_TYPE = abi.encodePacked(
        RELAY_REQUEST_NAME,"(",GENERIC_PARAMS,",", RELAY_REQUEST_SUFFIX);

    bytes32 public constant RELAYDATA_TYPEHASH = keccak256(RELAYDATA_TYPE);
    bytes32 public constant RELAY_REQUEST_TYPEHASH = keccak256(RELAY_REQUEST_TYPE);

    struct EIP712Domain {
        string name;
        string version;
        uint256 chainId;
        address verifyingContract;
    }

    bytes32 public constant EIP712DOMAIN_TYPEHASH = keccak256(
        "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
    );

    function splitRequest(
        GsnTypes.RelayRequest calldata req
    )
    internal
    pure
    returns (
        bytes memory suffixData
    ) {
        suffixData = abi.encode(
            hashRelayData(req.relayData));
    }

    //verify that the recipient trusts the given forwarder
    // MUST be called by paymaster
    function verifyForwarderTrusted(GsnTypes.RelayRequest calldata relayRequest) internal view {
        (bool success, bytes memory ret) = relayRequest.request.to.staticcall(
            abi.encodeWithSelector(
                IERC2771Recipient.isTrustedForwarder.selector, relayRequest.relayData.forwarder
            )
        );
        require(success, "isTrustedForwarder: reverted");
        require(ret.length == 32, "isTrustedForwarder: bad response");
        require(abi.decode(ret, (bool)), "invalid forwarder for recipient");
    }

    function verifySignature(GsnTypes.RelayRequest calldata relayRequest, bytes calldata signature) internal view {
        (bytes memory suffixData) = splitRequest(relayRequest);
        bytes32 _domainSeparator = domainSeparator(relayRequest.relayData.forwarder);
        IForwarder forwarder = IForwarder(payable(relayRequest.relayData.forwarder));
        forwarder.verify(relayRequest.request, _domainSeparator, RELAY_REQUEST_TYPEHASH, suffixData, signature);
    }

    function verify(GsnTypes.RelayRequest calldata relayRequest, bytes calldata signature) internal view {
        verifyForwarderTrusted(relayRequest);
        verifySignature(relayRequest, signature);
    }

    function execute(GsnTypes.RelayRequest calldata relayRequest, bytes calldata signature) internal returns (bool forwarderSuccess, bool callSuccess, bytes memory ret) {
        (bytes memory suffixData) = splitRequest(relayRequest);
        bytes32 _domainSeparator = domainSeparator(relayRequest.relayData.forwarder);
        /* solhint-disable-next-line avoid-low-level-calls */
        (forwarderSuccess, ret) = relayRequest.relayData.forwarder.call(
            abi.encodeWithSelector(IForwarder.execute.selector,
            relayRequest.request, _domainSeparator, RELAY_REQUEST_TYPEHASH, suffixData, signature
        ));
        if ( forwarderSuccess ) {

          //decode return value of execute:
          (callSuccess, ret) = abi.decode(ret, (bool, bytes));
        }
        truncateInPlace(ret);
    }

    //truncate the given parameter (in-place) if its length is above the given maximum length
    // do nothing otherwise.
    //NOTE: solidity warns unless the method is marked "pure", but it DOES modify its parameter.
    function truncateInPlace(bytes memory data) internal pure {
        MinLibBytes.truncateInPlace(data, MAX_RETURN_SIZE);
    }

    function domainSeparator(address forwarder) internal view returns (bytes32) {
        return hashDomain(EIP712Domain({
            name : "GSN Relayed Transaction",
            version : "3",
            chainId : getChainID(),
            verifyingContract : forwarder
            }));
    }

    function getChainID() internal view returns (uint256 id) {
        /* solhint-disable no-inline-assembly */
        assembly {
            id := chainid()
        }
    }

    function hashDomain(EIP712Domain memory req) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                EIP712DOMAIN_TYPEHASH,
                keccak256(bytes(req.name)),
                keccak256(bytes(req.version)),
                req.chainId,
                req.verifyingContract));
    }

    function hashRelayData(GsnTypes.RelayData calldata req) internal pure returns (bytes32) {
        return keccak256(abi.encode(
                RELAYDATA_TYPEHASH,
                req.maxFeePerGas,
                req.maxPriorityFeePerGas,
                req.transactionCalldataGasUsed,
                req.relayWorker,
                req.paymaster,
                req.forwarder,
                keccak256(req.paymasterData),
                req.clientId
            ));
    }
}

File 16 of 18 : GsnTypes.sol
pragma solidity ^0.8.0;

// SPDX-License-Identifier: GPL-3.0-only

import "../forwarder/IForwarder.sol";

interface GsnTypes {
    /// @notice maxFeePerGas, maxPriorityFeePerGas, pctRelayFee and baseRelayFee must be validated inside of the paymaster's preRelayedCall in order not to overpay
    struct RelayData {
        uint256 maxFeePerGas;
        uint256 maxPriorityFeePerGas;
        uint256 transactionCalldataGasUsed;
        address relayWorker;
        address paymaster;
        address forwarder;
        bytes paymasterData;
        uint256 clientId;
    }

    //note: must start with the ForwardRequest to be an extension of the generic forwarder
    struct RelayRequest {
        IForwarder.ForwardRequest request;
        RelayData relayData;
    }
}

File 17 of 18 : GsnUtils.sol
pragma solidity ^0.8.0;

/* solhint-disable no-inline-assembly */
// SPDX-License-Identifier: GPL-3.0-only

import "../utils/MinLibBytes.sol";
import "./GsnTypes.sol";

/**
 * @title The GSN Solidity Utils Library
 * @notice Some library functions used throughout the GSN Solidity codebase.
 */
library GsnUtils {

    bytes32 constant private RELAY_REQUEST_ID_MASK = 0x00000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;

    /**
     * @notice Calculate an identifier for the meta-transaction in a format similar to a transaction hash.
     * Note that uniqueness relies on signature and may not be enforced if meta-transactions are verified
     * with a different algorithm, e.g. when batching.
     * @param relayRequest The `RelayRequest` for which an ID is being calculated.
     * @param signature The signature for the `RelayRequest`. It is not validated here and may even remain empty.
     */
    function getRelayRequestID(GsnTypes.RelayRequest calldata relayRequest, bytes calldata signature)
    internal
    pure
    returns (bytes32) {
        return keccak256(abi.encode(relayRequest.request.from, relayRequest.request.nonce, signature)) & RELAY_REQUEST_ID_MASK;
    }

    /**
     * @notice Extract the method identifier signature from the encoded function call.
     */
    function getMethodSig(bytes memory msgData) internal pure returns (bytes4) {
        return MinLibBytes.readBytes4(msgData, 0);
    }

    /**
     * @notice Extract a parameter from encoded-function block.
     * see: https://solidity.readthedocs.io/en/develop/abi-spec.html#formal-specification-of-the-encoding
     * The return value should be casted to the right type (`uintXXX`/`bytesXXX`/`address`/`bool`/`enum`).
     * @param msgData Byte array containing a uint256 value.
     * @param index Index in byte array of uint256 value.
     * @return result uint256 value from byte array.
     */
    function getParam(bytes memory msgData, uint256 index) internal pure returns (uint256 result) {
        return MinLibBytes.readUint256(msgData, 4 + index * 32);
    }

    /// @notice Re-throw revert with the same revert data.
    function revertWithData(bytes memory data) internal pure {
        assembly {
            revert(add(data,32), mload(data))
        }
    }

}

File 18 of 18 : MinLibBytes.sol
pragma solidity ^0.8.0;

// SPDX-License-Identifier: MIT
// minimal bytes manipulation required by GSN
// a minimal subset from 0x/LibBytes
/* solhint-disable no-inline-assembly */

library MinLibBytes {

    //truncate the given parameter (in-place) if its length is above the given maximum length
    // do nothing otherwise.
    //NOTE: solidity warns unless the method is marked "pure", but it DOES modify its parameter.
    function truncateInPlace(bytes memory data, uint256 maxlen) internal pure {
        if (data.length > maxlen) {
            assembly { mstore(data, maxlen) }
        }
    }

    /// @dev Reads an address from a position in a byte array.
    /// @param b Byte array containing an address.
    /// @param index Index in byte array of address.
    /// @return result address from byte array.
    function readAddress(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (address result)
    {
        require (b.length >= index + 20, "readAddress: data too short");

        // Add offset to index:
        // 1. Arrays are prefixed by 32-byte length parameter (add 32 to index)
        // 2. Account for size difference between address length and 32-byte storage word (subtract 12 from index)
        index += 20;

        // Read address from array memory
        assembly {
            // 1. Add index to address of bytes array
            // 2. Load 32-byte word from memory
            // 3. Apply 20-byte mask to obtain address
            result := and(mload(add(b, index)), 0xffffffffffffffffffffffffffffffffffffffff)
        }
        return result;
    }

    function readBytes32(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (bytes32 result)
    {
        require(b.length >= index + 32, "readBytes32: data too short" );

        // Read the bytes32 from array memory
        assembly {
            result := mload(add(b, add(index,32)))
        }
        return result;
    }

    /// @dev Reads a uint256 value from a position in a byte array.
    /// @param b Byte array containing a uint256 value.
    /// @param index Index in byte array of uint256 value.
    /// @return result uint256 value from byte array.
    function readUint256(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (uint256 result)
    {
        result = uint256(readBytes32(b, index));
        return result;
    }

    function readBytes4(
        bytes memory b,
        uint256 index
    )
        internal
        pure
        returns (bytes4 result)
    {
        require(b.length >= index + 4, "readBytes4: data too short");

        // Read the bytes4 from array memory
        assembly {
            result := mload(add(b, add(index,32)))
            // Solidity does not require us to clean the trailing bytes.
            // We do it anyway
            result := and(result, 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000)
        }
        return result;
    }
}

Settings
{
  "evmVersion": "london",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs",
    "useLiteralContent": true
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bool","name":"success","type":"bool"},{"indexed":false,"internalType":"uint256","name":"actualCharge","type":"uint256"}],"name":"SampleRecipientPostCall","type":"event"},{"anonymous":false,"inputs":[],"name":"SampleRecipientPreCall","type":"event"},{"inputs":[],"name":"CALLDATA_SIZE_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FORWARDER_HUB_OVERHEAD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PAYMASTER_ACCEPTANCE_BUDGET","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"POST_RELAYED_CALL_GAS_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PRE_RELAYED_CALL_GAS_LIMIT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getGasAndDataLimits","outputs":[{"components":[{"internalType":"uint256","name":"acceptanceBudget","type":"uint256"},{"internalType":"uint256","name":"preRelayedCallGasLimit","type":"uint256"},{"internalType":"uint256","name":"postRelayedCallGasLimit","type":"uint256"},{"internalType":"uint256","name":"calldataSizeLimit","type":"uint256"}],"internalType":"struct IPaymaster.GasAndDataLimits","name":"limits","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRelayHub","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTrustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"context","type":"bytes"},{"internalType":"bool","name":"success","type":"bool"},{"internalType":"uint256","name":"gasUseWithoutPost","type":"uint256"},{"components":[{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"transactionCalldataGasUsed","type":"uint256"},{"internalType":"address","name":"relayWorker","type":"address"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"address","name":"forwarder","type":"address"},{"internalType":"bytes","name":"paymasterData","type":"bytes"},{"internalType":"uint256","name":"clientId","type":"uint256"}],"internalType":"struct GsnTypes.RelayData","name":"relayData","type":"tuple"}],"name":"postRelayedCall","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"gas","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"validUntilTime","type":"uint256"}],"internalType":"struct IForwarder.ForwardRequest","name":"request","type":"tuple"},{"components":[{"internalType":"uint256","name":"maxFeePerGas","type":"uint256"},{"internalType":"uint256","name":"maxPriorityFeePerGas","type":"uint256"},{"internalType":"uint256","name":"transactionCalldataGasUsed","type":"uint256"},{"internalType":"address","name":"relayWorker","type":"address"},{"internalType":"address","name":"paymaster","type":"address"},{"internalType":"address","name":"forwarder","type":"address"},{"internalType":"bytes","name":"paymasterData","type":"bytes"},{"internalType":"uint256","name":"clientId","type":"uint256"}],"internalType":"struct GsnTypes.RelayData","name":"relayData","type":"tuple"}],"internalType":"struct GsnTypes.RelayRequest","name":"relayRequest","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"approvalData","type":"bytes"},{"internalType":"uint256","name":"maxPossibleGas","type":"uint256"}],"name":"preRelayedCall","outputs":[{"internalType":"bytes","name":"","type":"bytes"},{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IRelayHub","name":"hub","type":"address"}],"name":"setRelayHub","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"name":"setTrustedForwarder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"versionPaymaster","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"destination","type":"address"}],"name":"withdrawAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"target","type":"address"}],"name":"withdrawRelayHubDepositTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

608060405234801561001057600080fd5b5061001a3361001f565b61006f565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6113c18061007e6000396000f3fe6080604052600436106101225760003560e01c8063b039a88f116100a0578063da74222811610064578063da742228146103f5578063df463a6614610415578063f2fde38b1461042a578063f9c002f71461044a578063fa09e6301461046157600080fd5b8063b039a88f1461035a578063b90b41cf146103a2578063bbdaa3c9146103b8578063ce1b815f146103cf578063d0e30db0146103ed57600080fd5b806376fa01c3116100e757806376fa01c3146102a85780637bb05264146102c85780637bdf2ec7146102e85780638da5cb5b1461031a578063921276ea1461033857600080fd5b8062be5dd4146101e657806301ffc9a71461021d5780632d14c4b71461024d5780635c5e3db11461026f578063715018a61461029357600080fd5b366101e1576001546001600160a01b03166101805760405162461bcd60e51b81526020600482015260196024820152781c995b185e481a1d58881859191c995cdcc81b9bdd081cd95d603a1b60448201526064015b60405180910390fd5b60015460405163aa67c91960e01b81523060048201526001600160a01b039091169063aa67c9199034906024016000604051808303818588803b1580156101c657600080fd5b505af11580156101da573d6000803e3d6000fd5b5050505050005b600080fd5b3480156101f257600080fd5b506102066102013660046110d5565b610481565b60405161021492919061120b565b60405180910390f35b34801561022957600080fd5b5061023d61023836600461101b565b6104c6565b6040519015158152602001610214565b34801561025957600080fd5b5061026d610268366004611193565b610518565b005b34801561027b57600080fd5b5061028561290481565b604051908152602001610214565b34801561029f57600080fd5b5061026d6105ac565b3480156102b457600080fd5b5061026d6102c3366004611045565b6105e2565b3480156102d457600080fd5b5061026d6102e3366004610fe1565b6105fe565b3480156102f457600080fd5b506001546001600160a01b03165b6040516001600160a01b039091168152602001610214565b34801561032657600080fd5b506000546001600160a01b0316610302565b34801561034457600080fd5b5061034d6106b0565b604051610214919061122f565b34801561036657600080fd5b5061036f6106d0565b60405161021491908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b3480156103ae57600080fd5b5061028561c35081565b3480156103c457600080fd5b506102856201adb081565b3480156103db57600080fd5b506002546001600160a01b0316610302565b61026d610739565b34801561040157600080fd5b5061026d610410366004610fe1565b6107e7565b34801561042157600080fd5b50610285610899565b34801561043657600080fd5b5061026d610445366004610fe1565b6108ab565b34801561045657600080fd5b50610285620186a081565b34801561046d57600080fd5b5061026d61047c366004610fe1565b610946565b6060600061048d6109d2565b61049688610a2c565b61049f88610ac4565b6104a98585610b2e565b6104b7888888888888610b7c565b91509150965096945050505050565b60006001600160e01b031982166370d596f560e11b14806104f757506001600160e01b03198216630704183b60e11b145b8061051257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6000546001600160a01b031633146105425760405162461bcd60e51b815260040161017790611242565b60015460405163f3fef3a360e01b81526001600160a01b038381166004830152602482018590529091169063f3fef3a390604401600060405180830381600087803b15801561059057600080fd5b505af11580156105a4573d6000803e3d6000fd5b505050505050565b6000546001600160a01b031633146105d65760405162461bcd60e51b815260040161017790611242565b6105e06000610bde565b565b6105ea6109d2565b6105f78585858585610c2e565b5050505050565b6000546001600160a01b031633146106285760405162461bcd60e51b815260040161017790611242565b6106426001600160a01b0382166334f57c6760e01b610c70565b61068e5760405162461bcd60e51b815260206004820152601f60248201527f746172676574206973206e6f7420612076616c6964204952656c6179487562006044820152606401610177565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b606060405180606001604052806028815260200161136460289139905090565b6106fb6040518060800160405280600081526020016000815260200160008152602001600081525090565b604051806080016040528061c350620186a061071791906112ea565b8152602001620186a081526020016201adb08152602001612904815250905090565b6001546001600160a01b031661078d5760405162461bcd60e51b81526020600482015260196024820152781c995b185e481a1d58881859191c995cdcc81b9bdd081cd95d603a1b6044820152606401610177565b60015460405163aa67c91960e01b81523060048201526001600160a01b039091169063aa67c9199034906024016000604051808303818588803b1580156107d357600080fd5b505af11580156105f7573d6000803e3d6000fd5b6000546001600160a01b031633146108115760405162461bcd60e51b815260040161017790611242565b61082b6001600160a01b0382166309788f9960e21b610c70565b6108775760405162461bcd60e51b815260206004820181905260248201527f746172676574206973206e6f7420612076616c69642049466f727761726465726044820152606401610177565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b6108a861c350620186a06112ea565b81565b6000546001600160a01b031633146108d55760405162461bcd60e51b815260040161017790611242565b6001600160a01b03811661093a5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610177565b61094381610bde565b50565b6001546040516370a0823160e01b81523060048201526000916001600160a01b0316906370a082319060240160206040518083038186803b15801561098a57600080fd5b505afa15801561099e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109c2919061117a565b90506109ce8183610518565b5050565b6001546001600160a01b031633146105e05760405162461bcd60e51b815260206004820152601e60248201527f63616e206f6e6c792062652063616c6c65642062792052656c617948756200006044820152606401610177565b610a3960208201826112d4565b610a4a9060c081019060a001610fe1565b6001600160a01b0316610a656002546001600160a01b031690565b6001600160a01b031614610abb5760405162461bcd60e51b815260206004820152601860248201527f466f72776172646572206973206e6f74207472757374656400000000000000006044820152606401610177565b61094381610c93565b610ad160208201826112d4565b610adf9060c0810190611277565b1590506109435760405162461bcd60e51b815260206004820152601c60248201527f73686f756c642068617665206e6f207061796d617374657244617461000000006044820152606401610177565b80156109ce5760405162461bcd60e51b815260206004820152601b60248201527f73686f756c642068617665206e6f20617070726f76616c4461746100000000006044820152606401610177565b6040516060906000907fa8c41f12bf21d07540a32ccb08bbc931778b2943d4747381c9466041b89d7d7a908290a1505060408051808201909152600e81526d6e6f20726576657274206865726560901b60208201526000965096945050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b604080518415158152602081018490527f8c7dc6f54401600ae78b31aec3dec125cfa5b7bcbf4ff3cbc5bfd818ba082b49910160405180910390a15050505050565b6000610c7b83610e7c565b8015610c8c5750610c8c8383610eaf565b9392505050565b600080610ca083806112be565b610cb1906040810190602001610fe1565b6001600160a01b031663572b6c0560e01b610ccf60208601866112d4565b610ce09060c081019060a001610fe1565b6040516001600160a01b03909116602482015260440160408051601f198184030181529181526020820180516001600160e01b03166001600160e01b0319909416939093179092529051610d3491906111ef565b600060405180830381855afa9150503d8060008114610d6f576040519150601f19603f3d011682016040523d82523d6000602084013e610d74565b606091505b509150915081610dc65760405162461bcd60e51b815260206004820152601c60248201527f697354727573746564466f727761726465723a207265766572746564000000006044820152606401610177565b8051602014610e175760405162461bcd60e51b815260206004820181905260248201527f697354727573746564466f727761726465723a2062616420726573706f6e73656044820152606401610177565b80806020019051810190610e2b9190610ffe565b610e775760405162461bcd60e51b815260206004820152601f60248201527f696e76616c696420666f7277617264657220666f7220726563697069656e74006044820152606401610177565b505050565b6000610e8f826301ffc9a760e01b610eaf565b80156105125750610ea8826001600160e01b0319610eaf565b1592915050565b604080516001600160e01b0319831660248083019190915282518083039091018152604490910182526020810180516001600160e01b03166301ffc9a760e01b179052905160009190829081906001600160a01b0387169061753090610f169086906111ef565b6000604051808303818686fa925050503d8060008114610f52576040519150601f19603f3d011682016040523d82523d6000602084013e610f57565b606091505b5091509150602081511015610f725760009350505050610512565b818015610f8e575080806020019051810190610f8e9190610ffe565b9695505050505050565b60008083601f840112610faa57600080fd5b50813567ffffffffffffffff811115610fc257600080fd5b602083019150836020828501011115610fda57600080fd5b9250929050565b600060208284031215610ff357600080fd5b8135610c8c81611340565b60006020828403121561101057600080fd5b8151610c8c81611355565b60006020828403121561102d57600080fd5b81356001600160e01b031981168114610c8c57600080fd5b60008060008060006080868803121561105d57600080fd5b853567ffffffffffffffff8082111561107557600080fd5b61108189838a01610f98565b90975095506020880135915061109682611355565b90935060408701359250606087013590808211156110b357600080fd5b50860161010081890312156110c757600080fd5b809150509295509295909350565b600080600080600080608087890312156110ee57600080fd5b863567ffffffffffffffff8082111561110657600080fd5b908801906040828b03121561111a57600080fd5b9096506020880135908082111561113057600080fd5b61113c8a838b01610f98565b9097509550604089013591508082111561115557600080fd5b5061116289828a01610f98565b979a9699509497949695606090950135949350505050565b60006020828403121561118c57600080fd5b5051919050565b600080604083850312156111a657600080fd5b8235915060208301356111b881611340565b809150509250929050565b600081518084526111db816020860160208601611310565b601f01601f19169290920160200192915050565b60008251611201818460208701611310565b9190910192915050565b60408152600061121e60408301856111c3565b905082151560208301529392505050565b602081526000610c8c60208301846111c3565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b6000808335601e1984360301811261128e57600080fd5b83018035915067ffffffffffffffff8211156112a957600080fd5b602001915036819003821315610fda57600080fd5b6000823560de1983360301811261120157600080fd5b6000823560fe1983360301811261120157600080fd5b6000821982111561130b57634e487b7160e01b600052601160045260246000fd5b500190565b60005b8381101561132b578181015183820152602001611313565b8381111561133a576000848401525b50505050565b6001600160a01b038116811461094357600080fd5b801515811461094357600080fdfe332e302e302d626574612e302b6f70656e67736e2e746573742d7065612e697061796d6173746572a2646970667358221220352d95511a2741210207bd3d7609f1129f69a0cce7675d1933436327dbfa1dc864736f6c63430008070033

Deployed ByteCode Sourcemap

157:1593:13:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4642:8:7;;-1:-1:-1;;;;;4642:8:7;4626:69;;;;-1:-1:-1;;;4626:69:7;;8082:2:18;4626:69:7;;;8064:21:18;8121:2;8101:18;;;8094:30;-1:-1:-1;;;8140:18:18;;;8133:55;8205:18;;4626:69:7;;;;;;;;;4705:8;;:51;;-1:-1:-1;;;4705:51:7;;4750:4;4705:51;;;4853::18;-1:-1:-1;;;;;4705:8:7;;;;:19;;4731:9;;4826:18:18;;4705:51:7;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;157:1593:13;;;;;5154:533:7;;;;;;;;;;-1:-1:-1;5154:533:7;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;:::-;;;;;;;;1461:283;;;;;;;;;;-1:-1:-1;1461:283:7;;;;;:::i;:::-;;:::i;:::-;;;5375:14:18;;5368:22;5350:41;;5338:2;5323:18;1461:283:7;5210:187:18;4975:142:7;;;;;;;;;;-1:-1:-1;4975:142:7;;;;;:::i;:::-;;:::i;:::-;;1375:51;;;;;;;;;;;;1421:5;1375:51;;;;;11336:25:18;;;11324:2;11309:18;1375:51:7;11190:177:18;1668:101:0;;;;;;;;;;;;;:::i;6140:309:7:-;;;;;;;;;;-1:-1:-1;6140:309:7;;;;;:::i;:::-;;:::i;3551:197::-;;;;;;;;;;-1:-1:-1;3551:197:7;;;;;:::i;:::-;;:::i;829:103::-;;;;;;;;;;-1:-1:-1;916:8:7;;-1:-1:-1;;;;;916:8:7;829:103;;;-1:-1:-1;;;;;4871:32:18;;;4853:51;;4841:2;4826:18;829:103:7;4707:203:18;1036:85:0;;;;;;;;;;-1:-1:-1;1082:7:0;1108:6;-1:-1:-1;;;;;1108:6:0;1036:85;;222:148:13;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;1781:362:7:-;;;;;;;;;;;;;:::i;:::-;;;;;;10976:13:18;;10958:32;;11046:4;11034:17;;;11028:24;11006:20;;;10999:54;11109:4;11097:17;;;11091:24;11069:20;;;11062:54;11172:4;11160:17;;;11154:24;11132:20;;;11125:54;;;;10945:3;10930:19;;10745:440;1003:54:7;;;;;;;;;;;;1052:5;1003:54;;1198:60;;;;;;;;;;;;1252:6;1198:60;;4234:118;;;;;;;;;;-1:-1:-1;4328:17:7;;-1:-1:-1;;;;;4328:17:7;4234:118;;1381:181:13;;;:::i;3997:231:7:-;;;;;;;;;;-1:-1:-1;3997:231:7;;;;;:::i;:::-;;:::i;1264:105::-;;;;;;;;;;;;;:::i;1918:198:0:-;;;;;;;;;;-1:-1:-1;1918:198:0;;;;;:::i;:::-;;:::i;1133:59:7:-;;;;;;;;;;;;1186:6;1133:59;;1568:180:13;;;;;;;;;;-1:-1:-1;1568:180:13;;;;;:::i;:::-;;:::i;5154:533:7:-;5379:12;5393:4;5409:21;:19;:21::i;:::-;5440:30;5457:12;5440:16;:30::i;:::-;5516:34;5537:12;5516:20;:34::i;:::-;5560:33;5580:12;;5560:19;:33::i;:::-;5610:70;5626:12;5640:9;;5651:12;;5665:14;5610:15;:70::i;:::-;5603:77;;;;5154:533;;;;;;;;;:::o;1461:283::-;1563:4;-1:-1:-1;;;;;;1586:43:7;;-1:-1:-1;;;1586:43:7;;:99;;-1:-1:-1;;;;;;;1645:40:7;;-1:-1:-1;;;1645:40:7;1586:99;:151;;;-1:-1:-1;;;;;;;;;;937:40:4;;;1701:36:7;1579:158;1461:283;-1:-1:-1;;1461:283:7:o;4975:142::-;1082:7:0;1108:6;-1:-1:-1;;;;;1108:6:0;719:10:3;1248:23:0;1240:68;;;;-1:-1:-1;;;1240:68:0;;;;;;;:::i;:::-;5077:8:7::1;::::0;:33:::1;::::0;-1:-1:-1;;;5077:33:7;;-1:-1:-1;;;;;5123:32:18;;;5077:33:7::1;::::0;::::1;5105:51:18::0;5172:18;;;5165:34;;;5077:8:7;;::::1;::::0;:17:::1;::::0;5078:18:18;;5077:33:7::1;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;4975:142:::0;;:::o;1668:101:0:-;1082:7;1108:6;-1:-1:-1;;;;;1108:6:0;719:10:3;1248:23:0;1240:68;;;;-1:-1:-1;;;1240:68:0;;;;;;;:::i;:::-;1732:30:::1;1759:1;1732:18;:30::i;:::-;1668:101::o:0;6140:309:7:-;6347:21;:19;:21::i;:::-;6378:64;6395:7;;6404;6413:17;6432:9;6378:16;:64::i;:::-;6140:309;;;;;:::o;3551:197::-;1082:7:0;1108:6;-1:-1:-1;;;;;1108:6:0;719:10:3;1248:23:0;1240:68;;;;-1:-1:-1;;;1240:68:0;;;;;;;:::i;:::-;3622:59:7::1;-1:-1:-1::0;;;;;3622:30:7;::::1;-1:-1:-1::0;;;3622:30:7::1;:59::i;:::-;3614:103;;;::::0;-1:-1:-1;;;3614:103:7;;9872:2:18;3614:103:7::1;::::0;::::1;9854:21:18::0;9911:2;9891:18;;;9884:30;9950:33;9930:18;;;9923:61;10001:18;;3614:103:7::1;9670:355:18::0;3614:103:7::1;3727:8;:14:::0;;-1:-1:-1;;;;;;3727:14:7::1;-1:-1:-1::0;;;;;3727:14:7;;;::::1;::::0;;;::::1;::::0;;3551:197::o;222:148:13:-;290:13;314:49;;;;;;;;;;;;;;;;;;;222:148;:::o;1781:362:7:-;1879:41;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1879:41:7;1944:192;;;;;;;;1052:5;1186:6;1318:51;;;;:::i;:::-;1944:192;;;;1186:6;1944:192;;;;1252:6;1944:192;;;;1421:5;1944:192;;;1937:199;;1781:362;:::o;1381:181:13:-;1441:8;;-1:-1:-1;;;;;1441:8:13;1425:69;;;;-1:-1:-1;;;1425:69:13;;8082:2:18;1425:69:13;;;8064:21:18;8121:2;8101:18;;;8094:30;-1:-1:-1;;;8140:18:18;;;8133:55;8205:18;;1425:69:13;7880:349:18;1425:69:13;1504:8;;:51;;-1:-1:-1;;;1504:51:13;;1549:4;1504:51;;;4853::18;-1:-1:-1;;;;;1504:8:13;;;;:19;;1530:9;;4826:18:18;;1504:51:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3997:231:7;1082:7:0;1108:6;-1:-1:-1;;;;;1108:6:0;719:10:3;1248:23:0;1240:68;;;;-1:-1:-1;;;1240:68:0;;;;;;;:::i;:::-;4088:57:7::1;-1:-1:-1::0;;;;;4088:27:7;::::1;-1:-1:-1::0;;;4088:27:7::1;:57::i;:::-;4080:102;;;::::0;-1:-1:-1;;;4080:102:7;;8789:2:18;4080:102:7::1;::::0;::::1;8771:21:18::0;;;8808:18;;;8801:30;8867:34;8847:18;;;8840:62;8919:18;;4080:102:7::1;8587:356:18::0;4080:102:7::1;4192:17;:29:::0;;-1:-1:-1;;;;;;4192:29:7::1;-1:-1:-1::0;;;;;4192:29:7;;;::::1;::::0;;;::::1;::::0;;3997:231::o;1264:105::-;1318:51;1052:5;1186:6;1318:51;:::i;:::-;1264:105;:::o;1918:198:0:-;1082:7;1108:6;-1:-1:-1;;;;;1108:6:0;719:10:3;1248:23:0;1240:68;;;;-1:-1:-1;;;1240:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;2006:22:0;::::1;1998:73;;;::::0;-1:-1:-1;;;1998:73:0;;7318:2:18;1998:73:0::1;::::0;::::1;7300:21:18::0;7357:2;7337:18;;;7330:30;7396:34;7376:18;;;7369:62;-1:-1:-1;;;7447:18:18;;;7440:36;7493:19;;1998:73:0::1;7116:402:18::0;1998:73:0::1;2081:28;2100:8;2081:18;:28::i;:::-;1918:198:::0;:::o;1568:180:13:-;1652:8;;:33;;-1:-1:-1;;;1652:33:13;;1679:4;1652:33;;;4853:51:18;1635:14:13;;-1:-1:-1;;;;;1652:8:13;;:18;;4826::18;;1652:33:13;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1635:50;;1695:46;1721:6;1729:11;1695:25;:46::i;:::-;1625:123;1568:180;:::o;2621:140:7:-;916:8;;-1:-1:-1;;;;;916:8:7;2692:10;:27;2684:70;;;;-1:-1:-1;;;2684:70:7;;10232:2:18;2684:70:7;;;10214:21:18;10271:2;10251:18;;;10244:30;10310:32;10290:18;;;10283:60;10360:18;;2684:70:7;10030:354:18;2332:283:7;2484:22;;;;:12;:22;:::i;:::-;:32;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2459:57:7;:21;4328:17;;-1:-1:-1;;;;;4328:17:7;;4234:118;2459:21;-1:-1:-1;;;;;2459:57:7;;2451:94;;;;-1:-1:-1;;;2451:94:7;;8436:2:18;2451:94:7;;;8418:21:18;8475:2;8455:18;;;8448:30;8514:26;8494:18;;;8487:54;8558:18;;2451:94:7;8234:348:18;2451:94:7;2555:53;2595:12;2555:39;:53::i;2950:203::-;3065:22;;;;:12;:22;:::i;:::-;:36;;;;;;;:::i;:::-;:48;;-1:-1:-1;3057:89:7;;;;-1:-1:-1;;;3057:89:7;;6601:2:18;3057:89:7;;;6583:21:18;6640:2;6620:18;;;6613:30;6679;6659:18;;;6652:58;6727:18;;3057:89:7;6399:352:18;3159:160:7;3256:24;;3248:64;;;;-1:-1:-1;;;3248:64:7;;10591:2:18;3248:64:7;;;10573:21:18;10630:2;10610:18;;;10603:30;10669:29;10649:18;;;10642:57;10716:18;;3248:64:7;10389:351:18;617:420:13;965:24;;855:12;;869:4;;965:24;;869:4;;965:24;-1:-1:-1;;999:31:13;;;;;;;;;;;;-1:-1:-1;;;999:31:13;;;;1024:5;617:420;;;;;;;;;:::o;2270:187:0:-;2343:16;2362:6;;-1:-1:-1;;;;;2378:17:0;;;-1:-1:-1;;;;;;2378:17:0;;;;;;2410:40;;2362:6;;;;;;;2410:40;;2343:16;2410:40;2333:124;2270:187;:::o;1043:332:13:-;1317:51;;;5595:14:18;;5588:22;5570:41;;5642:2;5627:18;;5620:34;;;1317:51:13;;5543:18:18;1317:51:13;;;;;;;1043:332;;;;;:::o;1318:274:5:-;1405:4;1512:23;1527:7;1512:14;:23::i;:::-;:73;;;;;1539:46;1564:7;1573:11;1539:24;:46::i;:::-;1505:80;1318:274;-1:-1:-1;;;1318:274:5:o;2158:540:14:-;2260:12;;2294:20;:12;;:20;:::i;:::-;:23;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;2294:34:14;-1:-1:-1;;;2429:22:14;;;;:12;:22;:::i;:::-;:32;;;;;;;;;:::i;:::-;2342:133;;-1:-1:-1;;;;;4871:32:18;;;2342:133:14;;;4853:51:18;4826:18;;2342:133:14;;;-1:-1:-1;;2342:133:14;;;;;;;;;;;;;;-1:-1:-1;;;;;2342:133:14;-1:-1:-1;;;;;;2342:133:14;;;;;;;;;;2294:191;;;;2342:133;2294:191;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2259:226;;;;2503:7;2495:48;;;;-1:-1:-1;;;2495:48:14;;7725:2:18;2495:48:14;;;7707:21:18;7764:2;7744:18;;;7737:30;7803;7783:18;;;7776:58;7851:18;;2495:48:14;7523:352:18;2495:48:14;2561:3;:10;2575:2;2561:16;2553:61;;;;-1:-1:-1;;;2553:61:14;;9150:2:18;2553:61:14;;;9132:21:18;;;9169:18;;;9162:30;9228:34;9208:18;;;9201:62;9280:18;;2553:61:14;8948:356:18;2553:61:14;2643:3;2632:23;;;;;;;;;;;;:::i;:::-;2624:67;;;;-1:-1:-1;;;2624:67:14;;6958:2:18;2624:67:14;;;6940:21:18;6997:2;6977:18;;;6970:30;7036:33;7016:18;;;7009:61;7087:18;;2624:67:14;6756:355:18;2624:67:14;2249:449;;2158:540;:::o;689:411:5:-;753:4;960:60;985:7;-1:-1:-1;;;960:24:5;:60::i;:::-;:133;;;;-1:-1:-1;1037:56:5;1062:7;-1:-1:-1;;;;;;1037:24:5;:56::i;:::-;1036:57;941:152;689:411;-1:-1:-1;;689:411:5:o;4208:409::-;4346:71;;;-1:-1:-1;;;;;;5827:33:18;;4346:71:5;;;;5809:52:18;;;;4346:71:5;;;;;;;;;;5782:18:18;;;;4346:71:5;;;;;;;-1:-1:-1;;;;;4346:71:5;-1:-1:-1;;;4346:71:5;;;4465:45;;4301:4;;4346:71;4301:4;;;;-1:-1:-1;;;;;4465:18:5;;;4489:5;;4465:45;;4346:71;;4465:45;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4427:83;;;;4540:2;4524:6;:13;:18;4520:36;;;4551:5;4544:12;;;;;;;4520:36;4573:7;:37;;;;;4595:6;4584:26;;;;;;;;;;;;:::i;:::-;4566:44;4208:409;-1:-1:-1;;;;;;4208:409:5:o;14:347:18:-;65:8;75:6;129:3;122:4;114:6;110:17;106:27;96:55;;147:1;144;137:12;96:55;-1:-1:-1;170:20:18;;213:18;202:30;;199:50;;;245:1;242;235:12;199:50;282:4;274:6;270:17;258:29;;334:3;327:4;318:6;310;306:19;302:30;299:39;296:59;;;351:1;348;341:12;296:59;14:347;;;;;:::o;366:247::-;425:6;478:2;466:9;457:7;453:23;449:32;446:52;;;494:1;491;484:12;446:52;533:9;520:23;552:31;577:5;552:31;:::i;878:245::-;945:6;998:2;986:9;977:7;973:23;969:32;966:52;;;1014:1;1011;1004:12;966:52;1046:9;1040:16;1065:28;1087:5;1065:28;:::i;1128:286::-;1186:6;1239:2;1227:9;1218:7;1214:23;1210:32;1207:52;;;1255:1;1252;1245:12;1207:52;1281:23;;-1:-1:-1;;;;;;1333:32:18;;1323:43;;1313:71;;1380:1;1377;1370:12;1419:895;1542:6;1550;1558;1566;1574;1627:3;1615:9;1606:7;1602:23;1598:33;1595:53;;;1644:1;1641;1634:12;1595:53;1684:9;1671:23;1713:18;1754:2;1746:6;1743:14;1740:34;;;1770:1;1767;1760:12;1740:34;1809:58;1859:7;1850:6;1839:9;1835:22;1809:58;:::i;:::-;1886:8;;-1:-1:-1;1783:84:18;-1:-1:-1;1971:2:18;1956:18;;1943:32;;-1:-1:-1;1984:28:18;1943:32;1984:28;:::i;:::-;2031:5;;-1:-1:-1;2083:2:18;2068:18;;2055:32;;-1:-1:-1;2140:2:18;2125:18;;2112:32;;2156:16;;;2153:36;;;2185:1;2182;2175:12;2153:36;-1:-1:-1;2208:24:18;;2266:3;2248:16;;;2244:26;2241:46;;;2283:1;2280;2273:12;2241:46;2306:2;2296:12;;;1419:895;;;;;;;;:::o;2589:1055::-;2729:6;2737;2745;2753;2761;2769;2822:3;2810:9;2801:7;2797:23;2793:33;2790:53;;;2839:1;2836;2829:12;2790:53;2879:9;2866:23;2908:18;2949:2;2941:6;2938:14;2935:34;;;2965:1;2962;2955:12;2935:34;2988:22;;;;3044:2;3026:16;;;3022:25;3019:45;;;3060:1;3057;3050:12;3019:45;3083:2;;-1:-1:-1;3138:2:18;3123:18;;3110:32;;3154:16;;;3151:36;;;3183:1;3180;3173:12;3151:36;3222:60;3274:7;3263:8;3252:9;3248:24;3222:60;:::i;:::-;3301:8;;-1:-1:-1;3196:86:18;-1:-1:-1;3389:2:18;3374:18;;3361:32;;-1:-1:-1;3405:16:18;;;3402:36;;;3434:1;3431;3424:12;3402:36;;3473:60;3525:7;3514:8;3503:9;3499:24;3473:60;:::i;:::-;2589:1055;;;;-1:-1:-1;2589:1055:18;;;;;3634:2;3619:18;;;3606:32;;2589:1055;-1:-1:-1;;;;2589:1055:18:o;3649:184::-;3719:6;3772:2;3760:9;3751:7;3747:23;3743:32;3740:52;;;3788:1;3785;3778:12;3740:52;-1:-1:-1;3811:16:18;;3649:184;-1:-1:-1;3649:184:18:o;3838:323::-;3914:6;3922;3975:2;3963:9;3954:7;3950:23;3946:32;3943:52;;;3991:1;3988;3981:12;3943:52;4027:9;4014:23;4004:33;;4087:2;4076:9;4072:18;4059:32;4100:31;4125:5;4100:31;:::i;:::-;4150:5;4140:15;;;3838:323;;;;;:::o;4166:257::-;4207:3;4245:5;4239:12;4272:6;4267:3;4260:19;4288:63;4344:6;4337:4;4332:3;4328:14;4321:4;4314:5;4310:16;4288:63;:::i;:::-;4405:2;4384:15;-1:-1:-1;;4380:29:18;4371:39;;;;4412:4;4367:50;;4166:257;-1:-1:-1;;4166:257:18:o;4428:274::-;4557:3;4595:6;4589:13;4611:53;4657:6;4652:3;4645:4;4637:6;4633:17;4611:53;:::i;:::-;4680:16;;;;;4428:274;-1:-1:-1;;4428:274:18:o;5872:298::-;6041:2;6030:9;6023:21;6004:4;6061:44;6101:2;6090:9;6086:18;6078:6;6061:44;:::i;:::-;6053:52;;6155:6;6148:14;6141:22;6136:2;6125:9;6121:18;6114:50;5872:298;;;;;:::o;6175:219::-;6324:2;6313:9;6306:21;6287:4;6344:44;6384:2;6373:9;6369:18;6361:6;6344:44;:::i;9309:356::-;9511:2;9493:21;;;9530:18;;;9523:30;9589:34;9584:2;9569:18;;9562:62;9656:2;9641:18;;9309:356::o;11372:521::-;11449:4;11455:6;11515:11;11502:25;11609:2;11605:7;11594:8;11578:14;11574:29;11570:43;11550:18;11546:68;11536:96;;11628:1;11625;11618:12;11536:96;11655:33;;11707:20;;;-1:-1:-1;11750:18:18;11739:30;;11736:50;;;11782:1;11779;11772:12;11736:50;11815:4;11803:17;;-1:-1:-1;11846:14:18;11842:27;;;11832:38;;11829:58;;;11883:1;11880;11873:12;11898:331;11997:4;12055:11;12042:25;12149:3;12145:8;12134;12118:14;12114:29;12110:44;12090:18;12086:69;12076:97;;12169:1;12166;12159:12;12234:327;12329:4;12387:11;12374:25;12481:3;12477:8;12466;12450:14;12446:29;12442:44;12422:18;12418:69;12408:97;;12501:1;12498;12491:12;12566:225;12606:3;12637:1;12633:6;12630:1;12627:13;12624:136;;;12682:10;12677:3;12673:20;12670:1;12663:31;12717:4;12714:1;12707:15;12745:4;12742:1;12735:15;12624:136;-1:-1:-1;12776:9:18;;12566:225::o;12796:258::-;12868:1;12878:113;12892:6;12889:1;12886:13;12878:113;;;12968:11;;;12962:18;12949:11;;;12942:39;12914:2;12907:10;12878:113;;;13009:6;13006:1;13003:13;13000:48;;;13044:1;13035:6;13030:3;13026:16;13019:27;13000:48;;12796:258;;;:::o;13059:131::-;-1:-1:-1;;;;;13134:31:18;;13124:42;;13114:70;;13180:1;13177;13170:12;13195:118;13281:5;13274:13;13267:21;13260:5;13257:32;13247:60;;13303:1;13300;13293:12

Swarm Source

ipfs://352d95511a2741210207bd3d7609f1129f69a0cce7675d1933436327dbfa1dc8
Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading