creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/standard/Contract.sol": {
        "content": "/**\n *Submitted for verification at Etherscan.io on 2023-10-13\n */\n\n// SPDX-License-Identifier: MIT\n\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.17;\n\n// This contract is only required for intermediate, Frengate contracts.\n\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(\n        address indexed previousOwner,\n        address indexed newOwner\n    );\n\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(\n            newOwner != address(0),\n            \"Ownable: new owner is the zero address\"\n        );\n        _transferOwnership(newOwner);\n    }\n\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    function balanceOf(address account) external view returns (uint256);\n\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    function allowance(\n        address owner,\n        address spender\n    ) external view returns (uint256);\n\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n\npragma solidity ^0.8.3;\n\ncontract Ecosystem is Ownable {\n    bool public paused;\n    IERC20 public token;\n    address public verifier;\n    mapping(bytes32 => bool) public tokens;\n\n    event EnhanceEcosystemToken(address sender, uint256 amount);\n    event DistributeEcosystemToken(\n        address sender,\n        uint256 amount,\n        bytes32 messageHash\n    );\n\n    constructor() {\n        verifier = msg.sender;\n    }\n\n    modifier whenNotPaused() {\n        require(!paused, \"paused\");\n        _;\n    }\n\n    function addEcosystemToken(uint256 _amount) external whenNotPaused {\n        token.transferFrom(msg.sender, address(this), _amount);\n        emit EnhanceEcosystemToken(msg.sender, _amount);\n    }\n\n    function distributeEcosystemToken(\n        uint256 _amount,\n        string memory _message,\n        uint256 _nonce,\n        bytes memory _signature\n    ) external whenNotPaused {\n        require(\n            verify(verifier, msg.sender, _amount, _message, _nonce, _signature),\n            \"invalid signature\"\n        );\n        bytes32 messageHash = getMessageHash(\n            msg.sender,\n            _amount,\n            _message,\n            _nonce\n        );\n        require(!tokens[messageHash], \"messageHash is submited\");\n\n        tokens[messageHash] = true;\n\n        emit DistributeEcosystemToken(msg.sender, _amount, messageHash);\n    }\n\n    function getMessageHash(\n        address _to,\n        uint256 _amount,\n        string memory _message,\n        uint256 _nonce\n    ) public pure returns (bytes32) {\n        return keccak256(abi.encodePacked(_to, _amount, _message, _nonce));\n    }\n\n    function getEthSignedMessageHash(\n        bytes32 _messageHash\n    ) public pure returns (bytes32) {\n        return\n            keccak256(\n                abi.encodePacked(\n                    \"\\x19Ethereum Signed Message:\\n32\",\n                    _messageHash\n                )\n            );\n    }\n\n    function verify(\n        address _signer,\n        address _to,\n        uint256 _amount,\n        string memory _message,\n        uint256 _nonce,\n        bytes memory signature\n    ) public pure returns (bool) {\n        bytes32 messageHash = getMessageHash(_to, _amount, _message, _nonce);\n        bytes32 ethSignedMessageHash = getEthSignedMessageHash(messageHash);\n\n        return recoverSigner(ethSignedMessageHash, signature) == _signer;\n    }\n\n    function recoverSigner(\n        bytes32 _ethSignedMessageHash,\n        bytes memory _signature\n    ) public pure returns (address) {\n        (bytes32 r, bytes32 s, uint8 v) = splitSignature(_signature);\n        return ecrecover(_ethSignedMessageHash, v, r, s);\n    }\n\n    function splitSignature(\n        bytes memory sig\n    ) public pure returns (bytes32 r, bytes32 s, uint8 v) {\n        require(sig.length == 65, \"invalid signature length\");\n\n        assembly {\n            r := mload(add(sig, 32))\n            s := mload(add(sig, 64))\n            v := byte(0, mload(add(sig, 96)))\n        }\n    }\n\n    function togglePause() external onlyOwner {\n        paused = !paused;\n    }\n\n    function setVerifier(address _verifier) external onlyOwner {\n        verifier = _verifier;\n    }\n\n    function setToken(address _token) external onlyOwner {\n        token = IERC20(_token);\n    }\n\n    function withdrawToken(address _token, uint256 _amount) external onlyOwner {\n        IERC20(_token).transfer(msg.sender, _amount);\n    }\n\n    function withdrawETH(uint256 _amount) external onlyOwner {\n        payable(msg.sender).transfer(_amount);\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "evmVersion": "shanghai",
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "metadata": {
        "useLiteralContent": true
      },
      "libraries": {}
    }
  }}