Contract 0x69015912aa33720b842dcd6ac059ed623f28d9f7 1

Contract Overview

Balance:
0 MATIC

Token:
Txn Hash
Method
Block
From
To
Value [Txn Fee]
0x4c767d849d497a0e8e0f8a511612bfddcbfa0ce632cd96fac3d97a148a60705aExecute EIP712336679102023-03-28 10:23:251 hr 8 mins ago0xdbf0bc79c7f6af4e9708cbc3eeb53478315f979a IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0002269620021.500000016
0x6f1c6e5effb96a7c0a84130a81b41f7dfcf02f92ccc204bb009ce0177c75c05aExecute EIP712336677042023-03-28 10:16:071 hr 15 mins ago0x1efcbae640386cd0071caa64f76e50ba7b7458bb IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0001485765011.500000015
0x408ad267e839d8c9f7e74b24146e610284cd4ff4545451f3786cbe5b53af0510Execute EIP712336649672023-03-28 8:39:012 hrs 52 mins ago0x97857d3f182428a92c7284e4df14c5ec4ee995db IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0008878759091.721917782
0x205bddccc7de179ba7e0c18567aafe52c766bdb161cd51a466931242f6659a78Execute EIP712336649342023-03-28 8:37:512 hrs 53 mins ago0x16aa5ec92aa4147d829d3d6a10726c2e6c720206 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0008878414711.721917782
0x704c8aff991af53b42ade3a7161b44c1246795491359f1169e3a39aec350b21bExecute EIP712336649182023-03-28 8:37:172 hrs 54 mins ago0xc65f107f3aee020aa55b8c8c2baf0affedc857c6 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0010055999841.721917782
0x72718176c69df1579d5e819b500d1c4b6287ef4a52dfe8fb38434b0029a37bf1Execute EIP712336648602023-03-28 8:35:132 hrs 56 mins ago0xedc074cfb71c919229a5651b58c7a7994386754b IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0015315184441.721917781
0xed86305ce9403aa3dee2177edd7344cb79ce31ab71f29ef750c2dfc699f40caeExecute Personal...336618242023-03-28 6:47:434 hrs 43 mins ago0x7e749a14758be0e8746be81c7618593946658c38 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000865417079 2.281682516
0xeed00bf71361e7f15076aa979a35b62b5039001e111ff6f1c9d375b483887246Execute Personal...336606562023-03-28 6:06:215 hrs 25 mins ago0xdbfd823e357f9f979de060b3717467fa8dd70ad1 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000334608743 2.281682531
0x45b9099fb991d9c9baeea7b814a13e2944790d3982c866824fc492c98f049bd4Execute Personal...336587842023-03-28 5:00:036 hrs 31 mins ago0x0cb456037ef2843c5503879bb8f9282673dc6005 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000886237505 2.500000016
0x6b13b24c27623fe99d328c1428cf5010031c575dac373f83373846014b62e38bExecute Personal...336587782023-03-28 4:59:496 hrs 31 mins ago0x7e749a14758be0e8746be81c7618593946658c38 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.002483390016 2.500000017
0x9402473a225d473e8a964ae5307bcb3288cc6939d55718088832befab8ec5195Execute Personal...336587732023-03-28 4:59:396 hrs 31 mins ago0xb1fb216d94a6409308aa919d1aafc7feb13a345b IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.002483360017 2.500000018
0x2b287d092225f013ec6c5c4f454b1fdb054c3ca4895f152d2d759131c41ac8a4Execute Personal...336560252023-03-28 3:22:198 hrs 9 mins ago0xc2cbad9f0cba3b871e8a160cc945d720e75252ff IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000961590004 2.655878443
0x356e8ef65df9f5b95983090024221f7e210cecb30dfff28bad47319ebdfa7f38Execute Personal...336560012023-03-28 3:21:298 hrs 10 mins ago0xbc62bd48934190bdc1da963425b1e38a62187b56 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.001006994902 2.655878443
0x097271cd7538c0606985abd47c028a38483c6a3986766fb2a33aa08de17bbe3dExecute Personal...336556972023-03-28 3:10:438 hrs 20 mins ago0x0cb456037ef2843c5503879bb8f9282673dc6005 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000426774782 2.910000014
0x4ccf9bf5c103c33f88d0442837c905341de430df96e6d7072d153b0a348416bfExecute Personal...336546582023-03-28 2:33:558 hrs 57 mins ago0x7b031f4da991b412734b46877486088a385c2912 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000174047422 2.082430068
0x14a7c659e8070a9930e8d00d264390d8c729caaf8a2a61b35d6cf6c7947652d7Execute Personal...336540992023-03-28 2:14:079 hrs 17 mins ago0x9bc6af5583b5278f3c50ed238e5c0fe8c126eb36 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000184935457 2.213232055
0x0ebbf93de0fac68619271170a93d7c1c4b3694da0ec8364d30dbb9ba4fa4aa69Execute Personal...336538452023-03-28 2:05:079 hrs 26 mins ago0x2ea96239e348e28c0a2edf22aaacc547c2ebce55 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000184979721 2.213232055
0xf38a0052c622e1cc70cb6884abc102ee463a92377015034d37afbc5e9062e218Execute Personal...336536042023-03-28 1:56:359 hrs 34 mins ago0xd908834b3e55e665086cf1916dc09a0ebc82d111 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000190700743 2.281682516
0x0660f4b0e3c8981116d0fd1a315e0c7a69298294bb5d95f463e11921317f2b17Execute Personal...336532662023-03-28 1:44:379 hrs 46 mins ago0x2cbc450e04a6379d37f1b85655d1fc09bda3e6da IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000232060701 2.777207742
0xce89633b9aadf33581381456a2d4de13a34592cc6171bd36c0cd06987daaf8c4Execute Personal...336529162023-03-28 1:32:139 hrs 59 mins ago0x146ddd79d5a764a23ad29dc5075dbb0c952f22c7 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000157011387 1.879048192
0x6b8146b0b27fc78c5a5cd7bf4305648260e4a6e63b5c48fa855ed3f0b4f3279cExecute Personal...336525442023-03-28 1:19:0310 hrs 12 mins ago0xacb2da78ef2f4f36247553ff01d77591aeb6ce0c IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000275577697 3.298001386
0x2c95c06693b90507194fc642c650108a4612d5e38d36a96cbb53113933a06c0bExecute Personal...336502332023-03-27 23:57:1111 hrs 34 mins ago0x7b031f4da991b412734b46877486088a385c2912 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000357466372 1.879048208
0x536a9bcc6738874032ae5ded601060111b17adea039559fc5ab1b2bc66671211Execute Personal...336502282023-03-27 23:57:0111 hrs 34 mins ago0xf0584bbeda83798a8680d145c1b5a805f9659df1 IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.000624708367 1.879048208
0xb1be6403dac4da323b7b0f00e030265c9d1243daad6b5abeef186266334c4102Execute EIP712336468242023-03-27 21:56:2713 hrs 35 mins ago0x16b59db66c4462045dd2f5ce5c717851dfe4538b IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0017098722363.590599563
0xe19ea46a2c70eadb4bc8eba817611e3d8c4e9f750216bc9a9a857564d3d324bdExecute EIP712336467642023-03-27 21:54:1913 hrs 37 mins ago0x8a664fa0cb783800ae3a2b7e844129beda1f7adf IN  0x69015912aa33720b842dcd6ac059ed623f28d9f70 MATIC0.0172263997394.32757352
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
BiconomyForwarderV2

Compiler Version
v0.8.4+commit.c7e474f2

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 5 : BiconomyForwarderV2.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./ForwardRequestTypesV2.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 *
 * @title BiconomyForwarder
 *
 * @notice A trusted forwarder for Biconomy relayed meta transactions
 *
 * @dev - Inherits Forward Request structs from Forward Request Types
 * @dev - Verifies EIP712 signatures
 * @dev - Verifies traditional personalSign signatures
 * @dev - Implements 2D nonces... each Tx has a BatchId and a BatchNonce
 * @dev - Keeps track of highest BatchId used by a given address, to assist in encoding of transactions client-side
 * @dev - maintains a list of verified domain seperators
 *
 */

 contract BiconomyForwarderV2 is ForwardRequestTypesV2, Ownable {
    using ECDSA for bytes32;

    mapping(bytes32 => bool) public domains;

    uint256 chainId;

    string public constant EIP712_DOMAIN_TYPE = "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)";

    //@review
    bytes32 public constant REQUEST_TYPEHASH = keccak256(bytes("ForwardRequest(address from,address to,uint256 txGas,uint256 batchId,uint256 batchNonce,uint256 deadline,bytes data)"));

    //@review and rename
    bytes32 public constant FORWARD_REQUEST_TYPEHASH = keccak256(bytes("ERC20ForwardRequest(address from,address to,address token,uint256 txGas,uint256 tokenGasPrice,uint256 batchId,uint256 batchNonce,uint256 deadline,bytes data)"));

    //Sandbox use case
    bytes32 public constant CUSTOM_FORWARD_REQUEST_TYPEHASH = keccak256(bytes("CustomForwardRequest(string warning,string info,string action,ERC20ForwardRequest request)ERC20ForwardRequest(address from,address to,address token,uint256 txGas,uint256 tokenGasPrice,uint256 batchId,uint256 batchNonce,uint256 deadline,bytes data)"));

    mapping(address => mapping(uint256 => uint256)) nonces;

    constructor(
    ) public {
        uint256 id;
        assembly {
            id := chainid()
        }
        chainId = id;
    }

    /**
     * @dev registers domain seperators, maintaining that all domain seperators used for EIP712 forward requests use...
     * ... the address of this contract and the chainId of the chain this contract is deployed to
     * @param name : name of dApp/dApp fee proxy
     * @param version : version of dApp/dApp fee proxy
     */
    function registerDomainSeparator(string calldata name, string calldata version) external onlyOwner{
        uint256 id;
        /* solhint-disable-next-line no-inline-assembly */
        assembly {
            id := chainid()
        }

        bytes memory domainValue = abi.encode(
            keccak256(bytes(EIP712_DOMAIN_TYPE)),
            keccak256(bytes(name)),
            keccak256(bytes(version)),
            address(this),
            bytes32(id));

        bytes32 domainHash = keccak256(domainValue);

        domains[domainHash] = true;
        emit DomainRegistered(domainHash, domainValue);
    }

    event DomainRegistered(bytes32 indexed domainSeparator, bytes domainValue);

    event MetaTransactionExecuted(address indexed userAddress, address indexed relayerAddress, bytes indexed functionSignature);

    /**
     * @dev returns a value from the nonces 2d mapping
     * @param from : the user address
     * @param batchId : the key of the user's batch being queried
     * @return nonce : the number of transaction made within said batch
     */
    function getNonce(address from, uint256 batchId)
    public view
    returns (uint256) {
        return nonces[from][batchId];
    }

    //TODO
    //@review if new read method is needed for Custom
    /**
     * @dev an external function which exposes the internal _verifySigEIP712 method
     * @param req : request being verified
     * @param domainSeparator : the domain separator presented to the user when signing
     * @param sig : the signature generated by the user's wallet
     */
    function verifyEIP712(
        ERC20ForwardRequest calldata req,
        bytes32 domainSeparator,
        bytes calldata sig)
    external view {
        _verifySigEIP712(req, domainSeparator, sig);
    }

    /**
     * @dev verifies the call is valid by calling _verifySigEIP712
     * @dev executes the forwarded call if valid
     * @dev updates the nonce after
     * @param req : ERC20 forward request being executed
     * @param domainSeparator : the domain separator presented to the user when signing
     * @param sig : the signature generated by the user's wallet
     * @return success : false if call fails. true otherwise
     * @return ret : any return data from the call
     */
    function executeEIP712(
        ERC20ForwardRequest calldata req,
        bytes32 domainSeparator,
        bytes calldata sig
    )
    external 
    returns (bool success, bytes memory ret) {
        _verifySigEIP712(req,domainSeparator,sig);
        _updateNonce(req);
        /* solhint-disable-next-line avoid-low-level-calls */
         (success,ret) = req.to.call{gas : req.txGas}(abi.encodePacked(req.data, req.from));
         // Validate that the relayer has sent enough gas for the call.
        // See https://ronan.eth.link/blog/ethereum-gas-dangers/
        assert(gasleft() > req.txGas / 63);
        _verifyCallResult(success,ret,"Forwarded call to destination did not succeed");
        emit MetaTransactionExecuted(req.from, msg.sender, req.data);
    }

    /**
     * @dev verifies the call is valid by calling _verifySigEIP712Custom
     * @dev executes the forwarded call if valid
     * @dev updates the nonce after
     * @param req : Custom ERC20 forward request being executed
     * @param domainSeparator : the domain separator presented to the user when signing
     * @param sig : the signature generated by the user's wallet
     * @return success : false if call fails. true otherwise
     * @return ret : any return data from the call
     */
    function executeEIP712Custom(
        CustomForwardRequest calldata req,
        bytes32 domainSeparator,
        bytes calldata sig
    )
    external 
    returns (bool success, bytes memory ret) {
        _verifySigEIP712Custom(req,domainSeparator,sig);
        _updateNonceCustom(req);
        /* solhint-disable-next-line avoid-low-level-calls */
         (success,ret) = req.request.to.call{gas : req.request.txGas}(abi.encodePacked(req.request.data, req.request.from));
         // Validate that the relayer has sent enough gas for the call.
        // See https://ronan.eth.link/blog/ethereum-gas-dangers/
        assert(gasleft() > req.request.txGas / 63);
        _verifyCallResult(success,ret,"Forwarded call to destination did not succeed");
        emit MetaTransactionExecuted(req.request.from, msg.sender, req.request.data);
    }

    /**
     * @dev an external function which exposes the internal _verifySigPersonSign method
     * @param req : request being verified
     * @param sig : the signature generated by the user's wallet
     */
    function verifyPersonalSign(
        ERC20ForwardRequest calldata req,
        bytes calldata sig)
    external view {
        _verifySigPersonalSign(req, sig);
    }

    /**
     * @dev verifies the call is valid by calling _verifySigPersonalSign
     * @dev executes the forwarded call if valid
     * @dev updates the nonce after
     * @param req : ERC20 forward request being executed
     * @param sig : the signature generated by the user's wallet
     * @return success : false if call fails. true otherwise
     * @return ret : any return data from the call
     */
    function executePersonalSign(ERC20ForwardRequest calldata req,bytes calldata sig)
    external 
    returns(bool success, bytes memory ret){
        _verifySigPersonalSign(req, sig);
        _updateNonce(req);
        (success,ret) = req.to.call{gas : req.txGas}(abi.encodePacked(req.data, req.from));
        // Validate that the relayer has sent enough gas for the call.
        // See https://ronan.eth.link/blog/ethereum-gas-dangers/
        assert(gasleft() > req.txGas / 63);
        _verifyCallResult(success,ret,"Forwarded call to destination did not succeed");
        emit MetaTransactionExecuted(req.from, msg.sender, req.data);
    }

    /**
     * @dev Increments the nonce of given user/batch pair
     * @dev Updates the highestBatchId of the given user if the request's batchId > current highest
     * @dev only intended to be called post call execution
     * @param req : ERC20 forward request that was executed
     */
    function _updateNonce(ERC20ForwardRequest calldata req) internal {
        nonces[req.from][req.batchId]++;
    }
    
    /**
     * @dev Increments the nonce of given user/batch pair
     * @dev Updates the highestBatchId of the given user if the request's batchId > current highest
     * @dev only intended to be called post call execution
     * @param req : ERC20 custom forward request that was executed
     */
    function _updateNonceCustom(CustomForwardRequest calldata req) internal {
        nonces[req.request.from][req.request.batchId]++;
    }

    /**
     * @dev verifies the domain separator used has been registered via registerDomainSeparator()
     * @dev recreates the 32 byte hash signed by the user's wallet (as per EIP712 specifications)
     * @dev verifies the signature using Open Zeppelin's ECDSA library
     * @dev signature valid if call doesn't throw
     *
     * @param req : ERC20 forward request being executed
     * @param domainSeparator : the domain separator presented to the user when signing
     * @param sig : the signature generated by the user's wallet
     *
     */
    function _verifySigEIP712(
        ERC20ForwardRequest calldata req,
        bytes32 domainSeparator,
        bytes memory sig)
    internal
    view
    {   
        uint256 id;
        /* solhint-disable-next-line no-inline-assembly */
        assembly {
            id := chainid()
        }
        require(req.deadline == 0 || block.timestamp + 20 <= req.deadline, "request expired");
        require(domains[domainSeparator], "unregistered domain separator");
        require(chainId == id, "potential replay attack on the fork");
        bytes32 digest =
            keccak256(abi.encodePacked(
                "\x19\x01",
                domainSeparator,
                hashERC20ForwardRequest(req)
            ));
        require(digest.recover(sig) == req.from, "signature mismatch");
    }

    /**
     * @dev verifies the domain separator used has been registered via registerDomainSeparator()
     * @dev recreates the 32 byte hash signed by the user's wallet (as per EIP712 specifications)
     * @dev verifies the signature using Open Zeppelin's ECDSA library
     * @dev signature valid if call doesn't throw
     *
     * @param req : Custom ERC20 forward request being executed
     * @param domainSeparator : the domain separator presented to the user when signing
     * @param sig : the signature generated by the user's wallet
     *
     */
    function _verifySigEIP712Custom(
        CustomForwardRequest calldata req,
        bytes32 domainSeparator,
        bytes memory sig)
    internal
    view
    {   
        uint256 id;
        /* solhint-disable-next-line no-inline-assembly */
        assembly {
            id := chainid()
        }
        require(req.request.deadline == 0 || block.timestamp + 20 <= req.request.deadline, "request expired");
        require(domains[domainSeparator], "unregistered domain separator");
        require(chainId == id, "potential replay attack on the fork");
        bytes32 digest =
            keccak256(abi.encodePacked(
                "\x19\x01",
                domainSeparator,
                hashCustomForwardRequest(req)
            ));
        require(digest.recover(sig) == req.request.from, "signature mismatch");
    }


    function hashERC20ForwardRequest(ERC20ForwardRequest calldata request) internal view returns (bytes32) {
        return keccak256(abi.encode(
            FORWARD_REQUEST_TYPEHASH,
            request.from,
            request.to,
            request.token,
            request.txGas,
            request.tokenGasPrice,
            request.batchId,
            nonces[request.from][request.batchId],
            request.deadline,
            keccak256(request.data)
        ));
    }

    function hashCustomForwardRequest(CustomForwardRequest calldata req) internal view returns (bytes32) {
        return keccak256(abi.encode(
            CUSTOM_FORWARD_REQUEST_TYPEHASH,
            keccak256(bytes(req.warning)),
            keccak256(bytes(req.info)),
            keccak256(bytes(req.action)),
            hashERC20ForwardRequest(req.request) 
        ));
    }

    /**
     * @dev encodes a 32 byte data string (presumably a hash of encoded data) as per eth_sign
     *
     * @param hash : hash of encoded data that signed by user's wallet using eth_sign
     * @return input hash encoded to matched what is signed by the user's key when using eth_sign*/
    function prefixed(bytes32 hash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev recreates the 32 byte hash signed by the user's wallet
     * @dev verifies the signature using Open Zeppelin's ECDSA library
     * @dev signature valid if call doesn't throw
     *
     * @param req : ERC20 forward request being executed
     * @param sig : the signature generated by the user's wallet
     *
     */
    function _verifySigPersonalSign(
        ERC20ForwardRequest calldata req,
        bytes memory sig)
    internal
    view
    {
        require(req.deadline == 0 || block.timestamp + 20 <= req.deadline, "request expired");
        bytes32 digest = prefixed(keccak256(abi.encodePacked(
            req.from,
            req.to,
            req.token,
            req.txGas,
            req.tokenGasPrice,
            req.batchId,
            nonces[req.from][req.batchId],
            req.deadline,
            keccak256(req.data)
        )));
        require(digest.recover(sig) == req.from, "signature mismatch");
    }

    /**
     * @dev verifies the call result and bubbles up revert reason for failed calls
     *
     * @param success : outcome of forwarded call
     * @param returndata : returned data from the frowarded call
     * @param errorMessage : fallback error message to show 
     */
     function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure {
        if (!success) {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }

}

File 2 of 5 : ECDSA.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS,
        InvalidSignatureV
    }

    function _throwError(RecoverError error) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert("ECDSA: invalid signature");
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert("ECDSA: invalid signature length");
        } else if (error == RecoverError.InvalidSignatureS) {
            revert("ECDSA: invalid signature 's' value");
        } else if (error == RecoverError.InvalidSignatureV) {
            revert("ECDSA: invalid signature 'v' value");
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature` or error string. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     *
     * _Available since v4.3._
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {
        // Check the signature length
        // - case 65: r,s,v signature (standard)
        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else if (signature.length == 64) {
            bytes32 r;
            bytes32 vs;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            assembly {
                r := mload(add(signature, 0x20))
                vs := mload(add(signature, 0x40))
            }
            return tryRecover(hash, r, vs);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength);
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, signature);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address, RecoverError) {
        bytes32 s;
        uint8 v;
        assembly {
            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)
            v := add(shr(255, vs), 27)
        }
        return tryRecover(hash, v, r, s);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     *
     * _Available since v4.2._
     */
    function recover(
        bytes32 hash,
        bytes32 r,
        bytes32 vs
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, r, vs);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     *
     * _Available since v4.3._
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS);
        }
        if (v != 27 && v != 28) {
            return (address(0), RecoverError.InvalidSignatureV);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature);
        }

        return (signer, RecoverError.NoError);
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address) {
        (address recovered, RecoverError error) = tryRecover(hash, v, r, s);
        _throwError(error);
        return recovered;
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * produces hash corresponding to the one signed with the
     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]
     * JSON-RPC method as part of EIP-191.
     *
     * See {recover}.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }

    /**
     * @dev Returns an Ethereum Signed Typed Data, created from a
     * `domainSeparator` and a `structHash`. This produces hash corresponding
     * to the one signed with the
     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]
     * JSON-RPC method as part of EIP-712.
     *
     * See {recover}.
     */
    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
    }
}

File 3 of 5 : ForwardRequestTypesV2.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.4;


/* deadline can be removed : GSN reference https://github.com/opengsn/gsn/blob/master/contracts/forwarder/IForwarder.sol (Saves 250 more gas)*/
/**
* @title ForwardRequestTypes 
* @notice specifies structures required by Forwarders to verify structured signatures.
* @notice This contract defines a struct which both ERC20Forwarder and BiconomyForwarder inherit. ERC20ForwardRequest includes all the fields present in the GSN V2 ForwardRequest struct, 
* but adds the following :
* address token : address of the token to pay for gas fees. For gasless transactions token address will be 0 address
* uint256 tokenGasPrice : gas price in the context of fee token
* uint256 txGas : gas to be supplied for recipient method call
* uint256 batchNonce : used for 2D nonces
* uint256 deadline 
* @dev Fields are placed in type order, to minimise storage used when executing transactions.
*/
contract ForwardRequestTypesV2 {

/*allow the EVM to optimize for this, 
ensure that you try to order your storage variables and struct members such that they can be packed tightly*/

    struct ForwardRequest {
        address from; 
        address to; 
        uint256 txGas;
        uint256 batchId; 
        uint256 batchNonce; 
        uint256 deadline; 
        bytes data;
    }

    struct ERC20ForwardRequest {
        address from; 
        address to; 
        address token; 
        uint256 txGas;
        uint256 tokenGasPrice;
        uint256 batchId; 
        uint256 batchNonce; 
        uint256 deadline; 
        bytes data;
    }

    //@review
    //should be SandBox Forward Request?
    struct CustomForwardRequest {
        string warning; //optional
        string info;
        string action;
        ERC20ForwardRequest request;
    }

     //For DAI and EIP2612 type Permits
     struct PermitRequest {
        address holder; 
        address spender;  
        uint256 value;
        uint256 nonce;
        uint256 expiry;
        bool allowed; 
        uint8 v;
        bytes32 r; 
        bytes32 s; 
    }

}

File 4 of 5 : Ownable.sol
// SPDX-License-Identifier: MIT

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() {
        _setOwner(_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 {
        _setOwner(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");
        _setOwner(newOwner);
    }

    function _setOwner(address newOwner) private {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

File 5 of 5 : Context.sol
// SPDX-License-Identifier: MIT

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;
    }
}

Settings
{
  "evmVersion": "berlin",
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"domainValue","type":"bytes"}],"name":"DomainRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"userAddress","type":"address"},{"indexed":true,"internalType":"address","name":"relayerAddress","type":"address"},{"indexed":true,"internalType":"bytes","name":"functionSignature","type":"bytes"}],"name":"MetaTransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"inputs":[],"name":"CUSTOM_FORWARD_REQUEST_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EIP712_DOMAIN_TYPE","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"FORWARD_REQUEST_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"REQUEST_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"domains","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"txGas","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"uint256","name":"batchNonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ForwardRequestTypesV2.ERC20ForwardRequest","name":"req","type":"tuple"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"executeEIP712","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"string","name":"warning","type":"string"},{"internalType":"string","name":"info","type":"string"},{"internalType":"string","name":"action","type":"string"},{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"txGas","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"uint256","name":"batchNonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ForwardRequestTypesV2.ERC20ForwardRequest","name":"request","type":"tuple"}],"internalType":"struct ForwardRequestTypesV2.CustomForwardRequest","name":"req","type":"tuple"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"executeEIP712Custom","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"txGas","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"uint256","name":"batchNonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ForwardRequestTypesV2.ERC20ForwardRequest","name":"req","type":"tuple"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"executePersonalSign","outputs":[{"internalType":"bool","name":"success","type":"bool"},{"internalType":"bytes","name":"ret","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"batchId","type":"uint256"}],"name":"getNonce","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"version","type":"string"}],"name":"registerDomainSeparator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"txGas","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"uint256","name":"batchNonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ForwardRequestTypesV2.ERC20ForwardRequest","name":"req","type":"tuple"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"verifyEIP712","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"txGas","type":"uint256"},{"internalType":"uint256","name":"tokenGasPrice","type":"uint256"},{"internalType":"uint256","name":"batchId","type":"uint256"},{"internalType":"uint256","name":"batchNonce","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"internalType":"struct ForwardRequestTypesV2.ERC20ForwardRequest","name":"req","type":"tuple"},{"internalType":"bytes","name":"sig","type":"bytes"}],"name":"verifyPersonalSign","outputs":[],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b5061001a33610023565b46600255610073565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b611dbf806100826000396000f3fe608060405234801561001057600080fd5b50600436106100f55760003560e01c80639563096811610097578063c3f28abd11610066578063c3f28abd146101fc578063c722f17714610211578063e630543314610244578063f2fde38b1461024c57600080fd5b806395630968146101c65780639c7b4592146101ce5780639e39b73e146101e1578063a41a03f2146101e957600080fd5b8063715018a6116100d3578063715018a61461014c5780638171e6321461015457806389535803146101675780638da5cb5b146101ab57600080fd5b806341706c4e146100fa5780634abec93d146101245780636e4cb07514610137575b600080fd5b61010d6101083660046117f0565b61025f565b60405161011b929190611928565b60405180910390f35b61010d610132366004611795565b61041a565b61014a610145366004611844565b6105fa565b005b61014a61063f565b61010d610162366004611844565b61067e565b61019d6101753660046116eb565b6001600160a01b03919091166000908152600360209081526040808320938352929052205490565b60405190815260200161011b565b6000546040516001600160a01b03909116815260200161011b565b61019d610837565b61014a6101dc36600461172c565b61085a565b61019d61097b565b61014a6101f73660046117f0565b61099e565b6102046109e5565b60405161011b919061194b565b61023461021f366004611714565b60016020526000908152604090205460ff1681565b604051901515815260200161011b565b61019d610a01565b61014a61025a3660046116ca565b610a25565b600060606102a4868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ac092505050565b6102ad86610c30565b6102bd60408701602088016116ca565b6001600160a01b031660608701356102d96101008901896119ff565b6102e660208b018b6116ca565b6040516020016102f8939291906118e6565b60408051601f19818403018152908290526103129161190c565b60006040518083038160008787f1925050503d8060008114610350576040519150601f19603f3d011682016040523d82523d6000602084013e610355565b606091505b50909250905061036a603f6060880135611a88565b5a1161038657634e487b7160e01b600052600160045260246000fd5b6103a982826040518060600160405280602d8152602001611c66602d9139610c7f565b6103b76101008701876119ff565b6040516103c59291906118d6565b604051908190039020336103dc60208901896116ca565b6001600160a01b03167f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b60405160405180910390a494509492505050565b6000606061045f868686868080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610cae92505050565b61046886610de0565b6104756060870187611a5a565b6104869060408101906020016116ca565b6001600160a01b031661049c6060880188611a5a565b606001358780606001906104b09190611a5a565b6104bf906101008101906119ff565b6104cc60608b018b611a5a565b6104da9060208101906116ca565b6040516020016104ec939291906118e6565b60408051601f19818403018152908290526105069161190c565b60006040518083038160008787f1925050503d8060008114610544576040519150601f19603f3d011682016040523d82523d6000602084013e610549565b606091505b509092509050603f61055e6060880188611a5a565b6060013561056c9190611a88565b5a1161058857634e487b7160e01b600052600160045260246000fd5b6105ab82826040518060600160405280602d8152602001611c66602d9139610c7f565b6105b86060870187611a5a565b6105c7906101008101906119ff565b6040516105d59291906118d6565b604051908190039020336105ec6060890189611a5a565b6103dc9060208101906116ca565b61063a8383838080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610e4b92505050565b505050565b6000546001600160a01b031633146106725760405162461bcd60e51b815260040161066990611987565b60405180910390fd5b61067c6000611010565b565b600060606106c28585858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610e4b92505050565b6106cb85610c30565b6106db60408601602087016116ca565b6001600160a01b031660608601356106f76101008801886119ff565b61070460208a018a6116ca565b604051602001610716939291906118e6565b60408051601f19818403018152908290526107309161190c565b60006040518083038160008787f1925050503d806000811461076e576040519150601f19603f3d011682016040523d82523d6000602084013e610773565b606091505b509092509050610788603f6060870135611a88565b5a116107a457634e487b7160e01b600052600160045260246000fd5b6107c782826040518060600160405280602d8152602001611c66602d9139610c7f565b6107d56101008601866119ff565b6040516107e39291906118d6565b604051908190039020336107fa60208801886116ca565b6001600160a01b03167f5845892132946850460bff5a0083f71031bc5bf9aadcd40f1de79423eac9b10b60405160405180910390a4935093915050565b6040518060c00160405280609d8152602001611bc9609d91398051906020012081565b6000546001600160a01b031633146108845760405162461bcd60e51b815260040161066990611987565b600046905060006040518060800160405280604f8152602001611b06604f91398051906020012086866040516108bb9291906118d6565b604051809103902085856040516108d39291906118d6565b604080519182900382206020830194909452810191909152606081019190915230608082015260a0810183905260c00160408051601f198184030181528282528051602080830191909120600081815260019283905293909320805460ff1916909117905592509081907f4bc68689cbe89a4a6333a3ab0a70093874da3e5bfb71e93102027f3f073687d89061096a90859061194b565b60405180910390a250505050505050565b6040518060a0016040528060748152602001611b55607491398051906020012081565b6109df848484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610ac092505050565b50505050565b6040518060800160405280604f8152602001611b06604f913981565b60405180610120016040528060f78152602001611c9360f791398051906020012081565b6000546001600160a01b03163314610a4f5760405162461bcd60e51b815260040161066990611987565b6001600160a01b038116610ab45760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b6064820152608401610669565b610abd81611010565b50565b4660e08401351580610ae0575060e0840135610add426014611a70565b11155b610afc5760405162461bcd60e51b81526004016106699061195e565b60008381526001602052604090205460ff16610b5a5760405162461bcd60e51b815260206004820152601d60248201527f756e7265676973746572656420646f6d61696e20736570617261746f720000006044820152606401610669565b8060025414610b7b5760405162461bcd60e51b8152600401610669906119bc565b600083610b8786611060565b60405161190160f01b60208201526022810192909252604282015260620160408051601f1981840301815291905280516020918201209150610bcb908601866116ca565b6001600160a01b0316610bde828561119a565b6001600160a01b031614610c295760405162461bcd60e51b81526020600482015260126024820152710e6d2cedcc2e8eae4ca40dad2e6dac2e8c6d60731b6044820152606401610669565b5050505050565b60036000610c4160208401846116ca565b6001600160a01b031681526020808201929092526040908101600090812060a085013582529092528120805491610c7783611ad4565b919050555050565b8261063a57815115610c945781518083602001fd5b8060405162461bcd60e51b8152600401610669919061194b565b46610cbc6060850185611a5a565b60e001351580610ce65750610cd46060850185611a5a565b60e00135610ce3426014611a70565b11155b610d025760405162461bcd60e51b81526004016106699061195e565b60008381526001602052604090205460ff16610d605760405162461bcd60e51b815260206004820152601d60248201527f756e7265676973746572656420646f6d61696e20736570617261746f720000006044820152606401610669565b8060025414610d815760405162461bcd60e51b8152600401610669906119bc565b600083610d8d866111be565b60405161190160f01b60208201526022810192909252604282015260620160408051601f1981840301815291905280516020909101209050610dd26060860186611a5a565b610bcb9060208101906116ca565b60036000610df16060840184611a5a565b610dff9060208101906116ca565b6001600160a01b031681526020810191909152604001600090812090610e286060840184611a5a565b60a0013581526020019081526020016000206000815480929190610c7790611ad4565b60e08201351580610e6a575060e0820135610e67426014611a70565b11155b610e865760405162461bcd60e51b81526004016106699061195e565b6000610fa3610e9860208501856116ca565b610ea860408601602087016116ca565b610eb860608701604088016116ca565b6060870135608088013560a089013560036000610ed860208d018d6116ca565b6001600160a01b031681526020808201929092526040908101600090812060a08e0135825290925290205460e08b0135610f166101008d018d6119ff565b604051610f249291906118d6565b6040519081900381206bffffffffffffffffffffffff1960609a8b1b81166020840152988a1b891660348301529690981b9096166048880152605c870193909352607c860191909152609c85015260bc84015260dc83019190915260fc82015261011c016040516020818303038152906040528051906020012061128e565b9050610fb260208401846116ca565b6001600160a01b0316610fc5828461119a565b6001600160a01b03161461063a5760405162461bcd60e51b81526020600482015260126024820152710e6d2cedcc2e8eae4ca40dad2e6dac2e8c6d60731b6044820152606401610669565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b60006040518060c00160405280609d8152602001611bc9609d9139805160209182012090611090908401846116ca565b6110a060408501602086016116ca565b6110b060608601604087016116ca565b6060860135608087013560a0880135600360006110d060208c018c6116ca565b6001600160a01b031681526020808201929092526040908101600090812060a08d0135825290925290205460e08a013561110e6101008c018c6119ff565b60405161111c9291906118d6565b60408051918290038220602083019b909b526001600160a01b03998a1690820152968816606088015296909416608086015260a085019290925260c084015260e0830152610100820152610120810191909152610140810191909152610160015b604051602081830303815290604052805190602001209050919050565b60008060006111a985856112c9565b915091506111b681611339565b509392505050565b600060405180610120016040528060f78152602001611c9360f7913980516020909101206111ec8380611a44565b6040516111fa9291906118d6565b6040519081900390206112106020850185611a44565b60405161121e9291906118d6565b60405180910390208480604001906112369190611a44565b6040516112449291906118d6565b60405190819003902061126261125d6060880188611a5a565b611060565b6040805160208101969096528501939093526060840191909152608083015260a082015260c00161117d565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c0161117d565b6000808251604114156113005760208301516040840151606085015160001a6112f48782858561153a565b94509450505050611332565b82516040141561132a576020830151604084015161131f868383611627565b935093505050611332565b506000905060025b9250929050565b600081600481111561135b57634e487b7160e01b600052602160045260246000fd5b14156113645750565b600181600481111561138657634e487b7160e01b600052602160045260246000fd5b14156113d45760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610669565b60028160048111156113f657634e487b7160e01b600052602160045260246000fd5b14156114445760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610669565b600381600481111561146657634e487b7160e01b600052602160045260246000fd5b14156114bf5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610669565b60048160048111156114e157634e487b7160e01b600052602160045260246000fd5b1415610abd5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610669565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a0831115611571575060009050600361161e565b8460ff16601b1415801561158957508460ff16601c14155b1561159a575060009050600461161e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa1580156115ee573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166116175760006001925092505061161e565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b016116488782888561153a565b935093505050935093915050565b80356001600160a01b038116811461166d57600080fd5b919050565b60008083601f840112611683578182fd5b50813567ffffffffffffffff81111561169a578182fd5b60208301915083602082850101111561133257600080fd5b600061012082840312156116c4578081fd5b50919050565b6000602082840312156116db578081fd5b6116e482611656565b9392505050565b600080604083850312156116fd578081fd5b61170683611656565b946020939093013593505050565b600060208284031215611725578081fd5b5035919050565b60008060008060408587031215611741578182fd5b843567ffffffffffffffff80821115611758578384fd5b61176488838901611672565b9096509450602087013591508082111561177c578384fd5b5061178987828801611672565b95989497509550505050565b600080600080606085870312156117aa578384fd5b843567ffffffffffffffff808211156117c1578586fd5b90860190608082890312156117d4578586fd5b909450602086013593506040860135908082111561177c578384fd5b60008060008060608587031215611805578384fd5b843567ffffffffffffffff8082111561181c578586fd5b611828888389016116b2565b955060208701359450604087013591508082111561177c578384fd5b600080600060408486031215611858578283fd5b833567ffffffffffffffff8082111561186f578485fd5b61187b878388016116b2565b94506020860135915080821115611890578384fd5b5061189d86828701611672565b9497909650939450505050565b600081518084526118c2816020860160208601611aa8565b601f01601f19169290920160200192915050565b8183823760009101908152919050565b8284823760609190911b6bffffffffffffffffffffffff19169101908152601401919050565b6000825161191e818460208701611aa8565b9190910192915050565b821515815260406020820152600061194360408301846118aa565b949350505050565b6020815260006116e460208301846118aa565b6020808252600f908201526e1c995c5d595cdd08195e1c1a5c9959608a1b604082015260600190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b60208082526023908201527f706f74656e7469616c207265706c61792061747461636b206f6e2074686520666040820152626f726b60e81b606082015260800190565b6000808335601e19843603018112611a15578283fd5b83018035915067ffffffffffffffff821115611a2f578283fd5b60200191503681900382131561133257600080fd5b6000808335601e19843603018112611a15578182fd5b6000823561011e1983360301811261191e578182fd5b60008219821115611a8357611a83611aef565b500190565b600082611aa357634e487b7160e01b81526012600452602481fd5b500490565b60005b83811015611ac3578181015183820152602001611aab565b838111156109df5750506000910152565b6000600019821415611ae857611ae8611aef565b5060010190565b634e487b7160e01b600052601160045260246000fdfe454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c6164647265737320766572696679696e67436f6e74726163742c627974657333322073616c7429466f72776172645265717565737428616464726573732066726f6d2c6164647265737320746f2c75696e743235362074784761732c75696e7432353620626174636849642c75696e743235362062617463684e6f6e63652c75696e7432353620646561646c696e652c62797465732064617461294552433230466f72776172645265717565737428616464726573732066726f6d2c6164647265737320746f2c6164647265737320746f6b656e2c75696e743235362074784761732c75696e7432353620746f6b656e47617350726963652c75696e7432353620626174636849642c75696e743235362062617463684e6f6e63652c75696e7432353620646561646c696e652c6279746573206461746129466f727761726465642063616c6c20746f2064657374696e6174696f6e20646964206e6f742073756363656564437573746f6d466f72776172645265717565737428737472696e67207761726e696e672c737472696e6720696e666f2c737472696e6720616374696f6e2c4552433230466f7277617264526571756573742072657175657374294552433230466f72776172645265717565737428616464726573732066726f6d2c6164647265737320746f2c6164647265737320746f6b656e2c75696e743235362074784761732c75696e7432353620746f6b656e47617350726963652c75696e7432353620626174636849642c75696e743235362062617463684e6f6e63652c75696e7432353620646561646c696e652c6279746573206461746129a26469706673582212205fbc05e07af55f4c17f97fd5da997389fe94192a5be1e03a1620cd754a89d82a64736f6c63430008040033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading