{
  "language": "Solidity",
  "sources": {
    "contracts/Controller.sol": {
      "content": "pragma solidity 0.8.7;\n\n/* solhint-disable indent */\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./interfaces/IController.sol\";\nimport \"./interfaces/IMemberToken.sol\";\nimport \"./interfaces/IControllerRegistry.sol\";\nimport \"./SafeTeller.sol\";\nimport \"./ens/IPodEnsRegistrar.sol\";\n\ncontract Controller is IController, SafeTeller, Ownable {\n    event CreatePod(uint256 podId, address safe, address admin, string ensName);\n    event UpdatePodAdmin(uint256 podId, address admin);\n\n    IMemberToken public immutable memberToken;\n    IControllerRegistry public immutable controllerRegistry;\n    IPodEnsRegistrar public podEnsRegistrar;\n\n    mapping(address => uint256) public safeToPodId;\n    mapping(uint256 => address) public podIdToSafe;\n    mapping(uint256 => address) public podAdmin;\n\n    uint8 internal constant CREATE_EVENT = 0x01;\n\n    /**\n     * @dev Will instantiate safe teller with gnosis master and proxy addresses\n     * @param _memberToken The address of the MemberToken contract\n     * @param _controllerRegistry The address of the ControllerRegistry contract\n     * @param _proxyFactoryAddress The proxy factory address\n     * @param _gnosisMasterAddress The gnosis master address\n     */\n    constructor(\n        address _memberToken,\n        address _controllerRegistry,\n        address _proxyFactoryAddress,\n        address _gnosisMasterAddress,\n        address _podEnsRegistrar\n    ) SafeTeller(_proxyFactoryAddress, _gnosisMasterAddress) {\n        require(_memberToken != address(0), \"Invalid address\");\n        require(_controllerRegistry != address(0), \"Invalid address\");\n        require(_proxyFactoryAddress != address(0), \"Invalid address\");\n        require(_gnosisMasterAddress != address(0), \"Invalid address\");\n        require(_podEnsRegistrar != address(0), \"Invalid address\");\n\n        memberToken = IMemberToken(_memberToken);\n        controllerRegistry = IControllerRegistry(_controllerRegistry);\n        podEnsRegistrar = IPodEnsRegistrar(_podEnsRegistrar);\n    }\n\n    function updatePodEnsRegistrar(address _podEnsRegistrar)\n        external\n        onlyOwner\n    {\n        require(_podEnsRegistrar != address(0), \"Invalid address\");\n        podEnsRegistrar = IPodEnsRegistrar(_podEnsRegistrar);\n    }\n\n    /**\n     * @param _members The addresses of the members of the pod\n     * @param threshold The number of members that are required to sign a transaction\n     * @param _admin The address of the pod admin\n     * @param _label label hash of pod name (i.e labelhash('mypod'))\n     * @param _ensString string of pod ens name (i.e.'mypod.pod.xyz')\n     */\n    function createPod(\n        address[] memory _members,\n        uint256 threshold,\n        address _admin,\n        bytes32 _label,\n        string memory _ensString\n    ) external {\n        address safe = createSafe(_members, threshold);\n\n        _createPod(_members, safe, _admin, _label, _ensString);\n    }\n\n    /**\n     * @dev Used to create a pod with an existing safe\n     * @dev Will automatically distribute membership NFTs to current safe members\n     * @param _admin The address of the pod admin\n     * @param _safe The address of existing safe\n     * @param _label label hash of pod name (i.e labelhash('mypod'))\n     * @param _ensString string of pod ens name (i.e.'mypod.pod.xyz')\n     */\n    function createPodWithSafe(\n        address _admin,\n        address _safe,\n        bytes32 _label,\n        string memory _ensString\n    ) external {\n        require(_safe != address(0), \"invalid safe address\");\n        require(safeToPodId[_safe] == 0, \"safe already in use\");\n        require(isSafeModuleEnabled(_safe), \"safe module must be enabled\");\n        require(\n            isSafeMember(_safe, msg.sender) || msg.sender == _safe,\n            \"caller must be safe or member\"\n        );\n\n        address[] memory members = getSafeMembers(_safe);\n\n        _createPod(members, _safe, _admin, _label, _ensString);\n    }\n\n    /**\n     * @param _members The addresses of the members of the pod\n     * @param _admin The address of the pod admin\n     * @param _safe The address of existing safe\n     * @param _label label hash of pod name (i.e labelhash('mypod'))\n     * @param _ensString string of pod ens name (i.e.'mypod.pod.xyz')\n     */\n    function _createPod(\n        address[] memory _members,\n        address _safe,\n        address _admin,\n        bytes32 _label,\n        string memory _ensString\n    ) private {\n        // add create event flag to token data\n        bytes memory data = new bytes(1);\n        data[0] = bytes1(uint8(CREATE_EVENT));\n\n        uint256 podId = memberToken.createPod(_members, data);\n\n        emit CreatePod(podId, _safe, _admin, _ensString);\n        emit UpdatePodAdmin(podId, _admin);\n\n        if (_admin != address(0)) podAdmin[podId] = _admin;\n        podIdToSafe[podId] = _safe;\n        safeToPodId[_safe] = podId;\n\n        // setup pod ENS\n        address reverseRegistrar = podEnsRegistrar.registerPod(\n            _label,\n            _safe,\n            msg.sender\n        );\n        setupSafeReverseResolver(_safe, reverseRegistrar, _ensString);\n    }\n\n    /**\n     * @param _podId The id number of the pod\n     * @param _newAdmin The address of the new pod admin\n     */\n    function updatePodAdmin(uint256 _podId, address _newAdmin) external {\n        address admin = podAdmin[_podId];\n        address safe = podIdToSafe[_podId];\n\n        require(safe != address(0), \"Pod doesn't exist\");\n\n        // if there is no admin it can only be added by safe\n        if (admin == address(0)) {\n            require(msg.sender == safe, \"Only safe can add new admin\");\n        } else {\n            require(msg.sender == admin, \"Only admin can update admin\");\n        }\n        podAdmin[_podId] = _newAdmin;\n\n        emit UpdatePodAdmin(_podId, _newAdmin);\n    }\n\n    /**\n     * @dev This will nullify all pod state on this controller\n     * @dev Update state on _newController\n     * @dev Update controller to _newController in Safe and MemberToken\n     * @param _podId The id number of the pod\n     * @param _newController The address of the new pod controller\n     * @param _prevModule The module that points to the orca module in the safe's ModuleManager linked list\n     */\n    function migratePodController(\n        uint256 _podId,\n        address _newController,\n        address _prevModule\n    ) external {\n        require(_newController != address(0), \"Invalid address\");\n        require(\n            controllerRegistry.isRegistered(_newController),\n            \"Controller not registered\"\n        );\n\n        address admin = podAdmin[_podId];\n        address safe = podIdToSafe[_podId];\n\n        require(\n            msg.sender == admin || msg.sender == safe,\n            \"User not authorized\"\n        );\n\n        Controller newController = Controller(_newController);\n\n        // nullify current pod state\n        podAdmin[_podId] = address(0);\n        podIdToSafe[_podId] = address(0);\n        safeToPodId[safe] = 0;\n        // update controller in MemberToken\n        memberToken.migrateMemberController(_podId, _newController);\n        // update safe module to _newController\n        migrateSafeTeller(safe, _newController, _prevModule);\n        // update pod state in _newController\n        newController.updatePodState(_podId, admin, safe);\n    }\n\n    /**\n     * @dev This is called by another version of controller to migrate a pod to this version\n     * @dev Will only accept calls from registered controllers\n     * @dev Can only be called once.\n     * @param _podId The id number of the pod\n     * @param _podAdmin The address of the pod admin\n     * @param _safeAddress The address of the safe\n     */\n    function updatePodState(\n        uint256 _podId,\n        address _podAdmin,\n        address _safeAddress\n    ) external {\n        require(_safeAddress != address(0), \"Invalid address\");\n        require(\n            controllerRegistry.isRegistered(msg.sender),\n            \"Controller not registered\"\n        );\n        require(\n            podAdmin[_podId] == address(0) &&\n                podIdToSafe[_podId] == address(0) &&\n                safeToPodId[_safeAddress] == 0,\n            \"Pod already exists\"\n        );\n        podAdmin[_podId] = _podAdmin;\n        podIdToSafe[_podId] = _safeAddress;\n        safeToPodId[_safeAddress] = _podId;\n\n        emit UpdatePodAdmin(_podId, _podAdmin);\n    }\n\n    /**\n     * @param operator The address that initiated the action\n     * @param from The address sending the membership token\n     * @param to The address recieveing the membership token\n     * @param ids An array of membership token ids to be transfered\n     * @param data Passes a flag for an initial creation event\n     */\n    function beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory,\n        bytes memory data\n    ) external override {\n        require(msg.sender == address(memberToken), \"Not Authorized\");\n\n        // if create event than side effects have been pre-handled\n        // only recognise data flags from this controller\n        if (operator == address(this) && uint8(data[0]) == CREATE_EVENT) return;\n\n        for (uint256 i = 0; i < ids.length; i += 1) {\n            uint256 podId = ids[i];\n            address safe = podIdToSafe[podId];\n            address admin = podAdmin[podId];\n\n            if (from == address(0)) {\n                // mint event\n\n                // there are no rules operator must be admin, safe or controller\n                require(\n                    operator == safe ||\n                        operator == admin ||\n                        operator == address(this),\n                    \"No Rules Set\"\n                );\n\n                onMint(to, safe);\n            } else if (to == address(0)) {\n                // burn event\n\n                // there are no rules  operator must be admin, safe or controller\n                require(\n                    operator == safe ||\n                        operator == admin ||\n                        operator == address(this),\n                    \"No Rules Set\"\n                );\n\n                onBurn(from, safe);\n            } else {\n                // transfer event\n                onTransfer(from, to, safe);\n            }\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/Ownable.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _setOwner(_msgSender());\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _setOwner(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
    },
    "contracts/interfaces/IController.sol": {
      "content": "pragma solidity 0.8.7;\n\ninterface IController{\n\n    /**\n     * @param operator The account address that initiated the action\n     * @param from The account address sending the membership token\n     * @param to The account address recieving the membership token\n     * @param ids An array of membership token ids to be transfered\n     * @param amounts The amount of each membership token type to transfer\n     * @param data Arbitrary data\n     */\n    function beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) external;\n\n}\n"
    },
    "contracts/interfaces/IMemberToken.sol": {
      "content": "pragma solidity 0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC1155/IERC1155.sol\";\n\ninterface IMemberToken is IERC1155 {\n    /**\n     * @dev Total amount of tokens in with a given id.\n     */\n    function totalSupply(uint256 id) external view returns (uint256);\n\n    /**\n     * @dev Indicates weither any token exist with a given id, or not.\n     */\n    function exists(uint256 id) external view returns (bool);\n\n    function getNextAvailablePodId() external view returns (uint256);\n\n    /**\n     * @param _podId The pod id number \n     * @param _newController The address of the new controller\n     */\n    function migrateMemberController(uint256 _podId, address _newController)\n        external;\n\n    /**\n     * @param _account The account address to transfer the membership token to\n     * @param _id The membership token id to mint\n     * @param data Arbitrary data\n     */\n    function mint(\n        address _account,\n        uint256 _id,\n        bytes memory data\n    ) external;\n\n    /**\n     * @param _accounts The account addresses to transfer the membership tokens to\n     * @param _id The membership token id to mint\n     * @param data Arbitrary data\n     */\n    function mintSingleBatch(\n        address[] memory _accounts,\n        uint256 _id,\n        bytes memory data\n    ) external;\n\n    function createPod(address[] memory _accounts, bytes memory data) external returns (uint256);\n}\n"
    },
    "contracts/interfaces/IControllerRegistry.sol": {
      "content": "pragma solidity 0.8.7;\n\n\ninterface IControllerRegistry{\n\n    /**\n     * @param _controller Address to check if registered as a controller\n     * @return Boolean representing if the address is a registered as a controller\n     */\n    function isRegistered(address _controller) external view returns (bool);\n\n}\n"
    },
    "contracts/SafeTeller.sol": {
      "content": "pragma solidity 0.8.7;\n\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"./interfaces/IGnosisSafe.sol\";\nimport \"./interfaces/IGnosisSafeProxyFactory.sol\";\n\ncontract SafeTeller {\n    using Address for address;\n\n    // mainnet: 0x76E2cFc1F5Fa8F6a5b3fC4c8F4788F0116861F9B;\n    address public immutable proxyFactoryAddress;\n\n    // mainnet: 0x34CfAC646f301356fAa8B21e94227e3583Fe3F5F;\n    address public immutable gnosisMasterAddress;\n\n    string public constant FUNCTION_SIG_SETUP =\n        \"setup(address[],uint256,address,bytes,address,address,uint256,address)\";\n    string public constant FUNCTION_SIG_EXEC =\n        \"execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)\";\n\n    string public constant FUNCTION_SIG_ENABLE = \"delegateSetup(address)\";\n\n    address internal constant SENTINEL = address(0x1);\n\n    /**\n     * @param _proxyFactoryAddress The proxy factory address\n     * @param _gnosisMasterAddress The gnosis master address\n     */\n    constructor(address _proxyFactoryAddress, address _gnosisMasterAddress) {\n        proxyFactoryAddress = _proxyFactoryAddress;\n        gnosisMasterAddress = _gnosisMasterAddress;\n    }\n\n    /**\n     * @param _safe The address of the safe\n     * @param _newSafeTeller The address of the new safe teller contract\n     */\n    function migrateSafeTeller(\n        address _safe,\n        address _newSafeTeller,\n        address _prevModule\n    ) internal {\n        // add new safeTeller\n        bytes memory enableData = abi.encodeWithSignature(\n            \"enableModule(address)\",\n            _newSafeTeller\n        );\n\n        bool enableSuccess = IGnosisSafe(_safe).execTransactionFromModule(\n            _safe,\n            0,\n            enableData,\n            IGnosisSafe.Operation.Call\n        );\n        require(enableSuccess, \"Migration failed on enable\");\n\n        // validate prevModule of current safe teller\n        (address[] memory moduleBuffer, ) = IGnosisSafe(_safe)\n            .getModulesPaginated(_prevModule, 1);\n        require(moduleBuffer[0] == address(this), \"incorrect prevModule\");\n\n        // disable current safeTeller\n        bytes memory disableData = abi.encodeWithSignature(\n            \"disableModule(address,address)\",\n            _prevModule,\n            address(this)\n        );\n\n        bool disableSuccess = IGnosisSafe(_safe).execTransactionFromModule(\n            _safe,\n            0,\n            disableData,\n            IGnosisSafe.Operation.Call\n        );\n        require(disableSuccess, \"Migration failed on disable\");\n    }\n\n    function getSafeMembers(address safe)\n        public\n        view\n        returns (address[] memory)\n    {\n        return IGnosisSafe(safe).getOwners();\n    }\n\n    function isSafeModuleEnabled(address safe) public view returns (bool) {\n        return IGnosisSafe(safe).isModuleEnabled(address(this));\n    }\n\n    function isSafeMember(address safe, address member)\n        public\n        view\n        returns (bool)\n    {\n        return IGnosisSafe(safe).isOwner(member);\n    }\n\n    /**\n     * @param _owners The  addresses to be owners of the safe\n     * @param _threshold The number of owners that are required to sign a transaciton\n     * @return safeAddress The address of the new safe\n     */\n    function createSafe(address[] memory _owners, uint256 _threshold)\n        internal\n        returns (address safeAddress)\n    {\n        bytes memory data = abi.encodeWithSignature(\n            FUNCTION_SIG_ENABLE,\n            address(this)\n        );\n\n        // encode the setup call that will be called on the new proxy safe\n        // from the proxy factory\n        bytes memory setupData = abi.encodeWithSignature(\n            FUNCTION_SIG_SETUP,\n            _owners,\n            _threshold,\n            this,\n            data,\n            address(0),\n            address(0),\n            uint256(0),\n            address(0)\n        );\n\n        try\n            IGnosisSafeProxyFactory(proxyFactoryAddress).createProxy(\n                gnosisMasterAddress,\n                setupData\n            )\n        returns (address newSafeAddress) {\n            return newSafeAddress;\n        } catch (bytes memory) {\n            revert(\"Create Proxy With Data Failed\");\n        }\n    }\n\n    /**\n     * @param to The account address to add as an owner\n     * @param safe The address of the safe\n     */\n    function onMint(address to, address safe) internal {\n        uint256 threshold = IGnosisSafe(safe).getThreshold();\n\n        bytes memory data = abi.encodeWithSignature(\n            \"addOwnerWithThreshold(address,uint256)\",\n            to,\n            threshold\n        );\n\n        bool success = IGnosisSafe(safe).execTransactionFromModule(\n            safe,\n            0,\n            data,\n            IGnosisSafe.Operation.Call\n        );\n\n        require(success, \"Module Transaction Failed\");\n    }\n\n    /**\n     * @param from The address to be removed as an owner\n     * @param safe The address of the safe\n     */\n    function onBurn(address from, address safe) internal {\n        uint256 threshold = IGnosisSafe(safe).getThreshold();\n        address[] memory owners = IGnosisSafe(safe).getOwners();\n\n        //look for the address pointing to address from\n        address prevFrom = address(0);\n        for (uint256 i = 0; i < owners.length; i++) {\n            if (owners[i] == from) {\n                if (i == 0) {\n                    prevFrom = SENTINEL;\n                } else {\n                    prevFrom = owners[i - 1];\n                }\n            }\n        }\n        if (owners.length - 1 < threshold) threshold -= 1;\n        bytes memory data = abi.encodeWithSignature(\n            \"removeOwner(address,address,uint256)\",\n            prevFrom,\n            from,\n            threshold\n        );\n\n        bool success = IGnosisSafe(safe).execTransactionFromModule(\n            safe,\n            0,\n            data,\n            IGnosisSafe.Operation.Call\n        );\n        require(success, \"Module Transaction Failed\");\n    }\n\n    /**\n     * @param from The address being removed as an owner\n     * @param to The address being added as an owner\n     * @param safe The address of the safe\n     */\n    function onTransfer(\n        address from,\n        address to,\n        address safe\n    ) internal {\n        address[] memory owners = IGnosisSafe(safe).getOwners();\n\n        //look for the address pointing to address from\n        address prevFrom;\n        for (uint256 i = 0; i < owners.length; i++) {\n            if (owners[i] == from) {\n                if (i == 0) {\n                    prevFrom = SENTINEL;\n                } else {\n                    prevFrom = owners[i - 1];\n                }\n            }\n        }\n\n        bytes memory data = abi.encodeWithSignature(\n            \"swapOwner(address,address,address)\",\n            prevFrom,\n            from,\n            to\n        );\n\n        bool success = IGnosisSafe(safe).execTransactionFromModule(\n            safe,\n            0,\n            data,\n            IGnosisSafe.Operation.Call\n        );\n        require(success, \"Module Transaction Failed\");\n    }\n\n    /**\n     * @dev This will execute a tx from the safe that will update the safe's ENS in the reverse resolver\n     * @param safe safe address\n     * @param reverseRegistrar The ENS default reverseRegistar\n     * @param _ensString string of pod ens name (i.e.'mypod.pod.xyz')\n     */\n    function setupSafeReverseResolver(\n        address safe,\n        address reverseRegistrar,\n        string memory _ensString\n    ) internal {\n        bytes memory data = abi.encodeWithSignature(\n            \"setName(string)\",\n            _ensString\n        );\n\n        bool success = IGnosisSafe(safe).execTransactionFromModule(\n            reverseRegistrar,\n            0,\n            data,\n            IGnosisSafe.Operation.Call\n        );\n        require(success, \"Module Transaction Failed\");\n    }\n\n    // TODO: move to library\n    // Used in a delegate call to enable module add on setup\n    function enableModule(address module) external {\n        require(module == address(0));\n    }\n\n    function delegateSetup(address _context) external {\n        this.enableModule(_context);\n    }\n}\n"
    },
    "contracts/ens/IPodEnsRegistrar.sol": {
      "content": "pragma solidity 0.8.7;\n\ninterface IPodEnsRegistrar { \n\n    function registerPod(bytes32 label, address podSafe, address podCreator) external returns (address);\n\n    function register(bytes32 label, address owner) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/Context.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like 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"
    },
    "@openzeppelin/contracts/token/ERC1155/IERC1155.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC1155 compliant contract, as defined in the\n * https://eips.ethereum.org/EIPS/eip-1155[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155 is IERC165 {\n    /**\n     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.\n     */\n    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);\n\n    /**\n     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all\n     * transfers.\n     */\n    event TransferBatch(\n        address indexed operator,\n        address indexed from,\n        address indexed to,\n        uint256[] ids,\n        uint256[] values\n    );\n\n    /**\n     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to\n     * `approved`.\n     */\n    event ApprovalForAll(address indexed account, address indexed operator, bool approved);\n\n    /**\n     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.\n     *\n     * If an {URI} event was emitted for `id`, the standard\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value\n     * returned by {IERC1155MetadataURI-uri}.\n     */\n    event URI(string value, uint256 indexed id);\n\n    /**\n     * @dev Returns the amount of tokens of token type `id` owned by `account`.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) external view returns (uint256);\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids)\n        external\n        view\n        returns (uint256[] memory);\n\n    /**\n     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,\n     *\n     * Emits an {ApprovalForAll} event.\n     *\n     * Requirements:\n     *\n     * - `operator` cannot be the caller.\n     */\n    function setApprovalForAll(address operator, bool approved) external;\n\n    /**\n     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.\n     *\n     * See {setApprovalForAll}.\n     */\n    function isApprovedForAll(address account, address operator) external view returns (bool);\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes calldata data\n    ) external;\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] calldata ids,\n        uint256[] calldata amounts,\n        bytes calldata data\n    ) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/IERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"
    },
    "@openzeppelin/contracts/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize, which returns 0 for contracts in\n        // construction, since the code is only stored at the end of the\n        // constructor execution.\n\n        uint256 size;\n        assembly {\n            size := extcodesize(account)\n        }\n        return size > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCall(target, data, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        require(isContract(target), \"Address: call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        require(isContract(target), \"Address: static call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(isContract(target), \"Address: delegate call to non-contract\");\n\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResult(success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            // Look for revert reason and bubble it up if present\n            if (returndata.length > 0) {\n                // The easiest way to bubble the revert reason is using memory via assembly\n\n                assembly {\n                    let returndata_size := mload(returndata)\n                    revert(add(32, returndata), returndata_size)\n                }\n            } else {\n                revert(errorMessage);\n            }\n        }\n    }\n}\n"
    },
    "contracts/interfaces/IGnosisSafe.sol": {
      "content": "pragma solidity 0.8.7;\n\ninterface IGnosisSafe {\n\n    enum Operation {Call, DelegateCall}\n\n    /// @dev Allows a Module to execute a Safe transaction without any further confirmations.\n    /// @param to Destination address of module transaction.\n    /// @param value Ether value of module transaction.\n    /// @param data Data payload of module transaction.\n    /// @param operation Operation type of module transaction.\n    function execTransactionFromModule(\n        address to,\n        uint256 value,\n        bytes calldata data,\n        Operation operation\n    ) external returns (bool success);\n\n    /// @dev Returns array of owners.\n    /// @return Array of Safe owners.\n    function getOwners() external view returns (address[] memory);\n\n    function isOwner(address owner) external view returns (bool);\n\n    function getThreshold() external returns (uint256);\n\n    /// @dev Returns array of modules.\n    /// @param start Start of the page.\n    /// @param pageSize Maximum number of modules that should be returned.\n    /// @return array Array of modules.\n    /// @return next Start of the next page.\n    function getModulesPaginated(address start, uint256 pageSize)\n        external \n        view\n        returns (address[] memory array, address next);\n\n    /// @dev Returns if an module is enabled\n    /// @return True if the module is enabled\n    function isModuleEnabled(address module) external view returns (bool);\n}\n"
    },
    "contracts/interfaces/IGnosisSafeProxyFactory.sol": {
      "content": "pragma solidity 0.8.7;\n\ninterface IGnosisSafeProxyFactory {\n    /// @dev Allows to create new proxy contact and execute a message call to the new proxy within one transaction.\n    /// @param singleton Address of singleton contract.\n    /// @param data Payload for message call sent to new proxy contract.\n    function createProxy(address singleton, bytes memory data)\n        external\n        returns (address);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC1155/ERC1155.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC1155.sol\";\nimport \"./IERC1155Receiver.sol\";\nimport \"./extensions/IERC1155MetadataURI.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of the basic standard multi-token.\n * See https://eips.ethereum.org/EIPS/eip-1155\n * Originally based on code by Enjin: https://github.com/enjin/erc-1155\n *\n * _Available since v3.1._\n */\ncontract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI {\n    using Address for address;\n\n    // Mapping from token ID to account balances\n    mapping(uint256 => mapping(address => uint256)) private _balances;\n\n    // Mapping from account to operator approvals\n    mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n    // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json\n    string private _uri;\n\n    /**\n     * @dev See {_setURI}.\n     */\n    constructor(string memory uri_) {\n        _setURI(uri_);\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n        return\n            interfaceId == type(IERC1155).interfaceId ||\n            interfaceId == type(IERC1155MetadataURI).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev See {IERC1155MetadataURI-uri}.\n     *\n     * This implementation returns the same URI for *all* token types. It relies\n     * on the token type ID substitution mechanism\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n     *\n     * Clients calling this function must replace the `\\{id\\}` substring with the\n     * actual token type ID.\n     */\n    function uri(uint256) public view virtual override returns (string memory) {\n        return _uri;\n    }\n\n    /**\n     * @dev See {IERC1155-balanceOf}.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function balanceOf(address account, uint256 id) public view virtual override returns (uint256) {\n        require(account != address(0), \"ERC1155: balance query for the zero address\");\n        return _balances[id][account];\n    }\n\n    /**\n     * @dev See {IERC1155-balanceOfBatch}.\n     *\n     * Requirements:\n     *\n     * - `accounts` and `ids` must have the same length.\n     */\n    function balanceOfBatch(address[] memory accounts, uint256[] memory ids)\n        public\n        view\n        virtual\n        override\n        returns (uint256[] memory)\n    {\n        require(accounts.length == ids.length, \"ERC1155: accounts and ids length mismatch\");\n\n        uint256[] memory batchBalances = new uint256[](accounts.length);\n\n        for (uint256 i = 0; i < accounts.length; ++i) {\n            batchBalances[i] = balanceOf(accounts[i], ids[i]);\n        }\n\n        return batchBalances;\n    }\n\n    /**\n     * @dev See {IERC1155-setApprovalForAll}.\n     */\n    function setApprovalForAll(address operator, bool approved) public virtual override {\n        require(_msgSender() != operator, \"ERC1155: setting approval status for self\");\n\n        _operatorApprovals[_msgSender()][operator] = approved;\n        emit ApprovalForAll(_msgSender(), operator, approved);\n    }\n\n    /**\n     * @dev See {IERC1155-isApprovedForAll}.\n     */\n    function isApprovedForAll(address account, address operator) public view virtual override returns (bool) {\n        return _operatorApprovals[account][operator];\n    }\n\n    /**\n     * @dev See {IERC1155-safeTransferFrom}.\n     */\n    function safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) public virtual override {\n        require(\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\n            \"ERC1155: caller is not owner nor approved\"\n        );\n        _safeTransferFrom(from, to, id, amount, data);\n    }\n\n    /**\n     * @dev See {IERC1155-safeBatchTransferFrom}.\n     */\n    function safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) public virtual override {\n        require(\n            from == _msgSender() || isApprovedForAll(from, _msgSender()),\n            \"ERC1155: transfer caller is not owner nor approved\"\n        );\n        _safeBatchTransferFrom(from, to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `to` cannot be the zero address.\n     * - `from` must have a balance of tokens of type `id` of at least `amount`.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function _safeTransferFrom(\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal virtual {\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, from, to, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n        uint256 fromBalance = _balances[id][from];\n        require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n        unchecked {\n            _balances[id][from] = fromBalance - amount;\n        }\n        _balances[id][to] += amount;\n\n        emit TransferSingle(operator, from, to, id, amount);\n\n        _doSafeTransferAcceptanceCheck(operator, from, to, id, amount, data);\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}.\n     *\n     * Emits a {TransferBatch} event.\n     *\n     * Requirements:\n     *\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function _safeBatchTransferFrom(\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n        require(to != address(0), \"ERC1155: transfer to the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, from, to, ids, amounts, data);\n\n        for (uint256 i = 0; i < ids.length; ++i) {\n            uint256 id = ids[i];\n            uint256 amount = amounts[i];\n\n            uint256 fromBalance = _balances[id][from];\n            require(fromBalance >= amount, \"ERC1155: insufficient balance for transfer\");\n            unchecked {\n                _balances[id][from] = fromBalance - amount;\n            }\n            _balances[id][to] += amount;\n        }\n\n        emit TransferBatch(operator, from, to, ids, amounts);\n\n        _doSafeBatchTransferAcceptanceCheck(operator, from, to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Sets a new URI for all token types, by relying on the token type ID\n     * substitution mechanism\n     * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP].\n     *\n     * By this mechanism, any occurrence of the `\\{id\\}` substring in either the\n     * URI or any of the amounts in the JSON file at said URI will be replaced by\n     * clients with the token type ID.\n     *\n     * For example, the `https://token-cdn-domain/\\{id\\}.json` URI would be\n     * interpreted by clients as\n     * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json`\n     * for token type ID 0x4cce0.\n     *\n     * See {uri}.\n     *\n     * Because these URIs cannot be meaningfully represented by the {URI} event,\n     * this function emits no events.\n     */\n    function _setURI(string memory newuri) internal virtual {\n        _uri = newuri;\n    }\n\n    /**\n     * @dev Creates `amount` tokens of token type `id`, and assigns them to `account`.\n     *\n     * Emits a {TransferSingle} event.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - If `account` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the\n     * acceptance magic value.\n     */\n    function _mint(\n        address account,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal virtual {\n        require(account != address(0), \"ERC1155: mint to the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, address(0), account, _asSingletonArray(id), _asSingletonArray(amount), data);\n\n        _balances[id][account] += amount;\n        emit TransferSingle(operator, address(0), account, id, amount);\n\n        _doSafeTransferAcceptanceCheck(operator, address(0), account, id, amount, data);\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the\n     * acceptance magic value.\n     */\n    function _mintBatch(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {\n        require(to != address(0), \"ERC1155: mint to the zero address\");\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, address(0), to, ids, amounts, data);\n\n        for (uint256 i = 0; i < ids.length; i++) {\n            _balances[ids[i]][to] += amounts[i];\n        }\n\n        emit TransferBatch(operator, address(0), to, ids, amounts);\n\n        _doSafeBatchTransferAcceptanceCheck(operator, address(0), to, ids, amounts, data);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens of token type `id` from `account`\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens of token type `id`.\n     */\n    function _burn(\n        address account,\n        uint256 id,\n        uint256 amount\n    ) internal virtual {\n        require(account != address(0), \"ERC1155: burn from the zero address\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, account, address(0), _asSingletonArray(id), _asSingletonArray(amount), \"\");\n\n        uint256 accountBalance = _balances[id][account];\n        require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n        unchecked {\n            _balances[id][account] = accountBalance - amount;\n        }\n\n        emit TransferSingle(operator, account, address(0), id, amount);\n    }\n\n    /**\n     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}.\n     *\n     * Requirements:\n     *\n     * - `ids` and `amounts` must have the same length.\n     */\n    function _burnBatch(\n        address account,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) internal virtual {\n        require(account != address(0), \"ERC1155: burn from the zero address\");\n        require(ids.length == amounts.length, \"ERC1155: ids and amounts length mismatch\");\n\n        address operator = _msgSender();\n\n        _beforeTokenTransfer(operator, account, address(0), ids, amounts, \"\");\n\n        for (uint256 i = 0; i < ids.length; i++) {\n            uint256 id = ids[i];\n            uint256 amount = amounts[i];\n\n            uint256 accountBalance = _balances[id][account];\n            require(accountBalance >= amount, \"ERC1155: burn amount exceeds balance\");\n            unchecked {\n                _balances[id][account] = accountBalance - amount;\n            }\n        }\n\n        emit TransferBatch(operator, account, address(0), ids, amounts);\n    }\n\n    /**\n     * @dev Hook that is called before any token transfer. This includes minting\n     * and burning, as well as batched variants.\n     *\n     * The same hook is called on both single and batched variants. For single\n     * transfers, the length of the `id` and `amount` arrays will be 1.\n     *\n     * Calling conditions (for each `id` and `amount` pair):\n     *\n     * - When `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * of token type `id` will be  transferred to `to`.\n     * - When `from` is zero, `amount` tokens of token type `id` will be minted\n     * for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens of token type `id`\n     * will be burned.\n     * - `from` and `to` are never both zero.\n     * - `ids` and `amounts` have the same, non-zero length.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual {}\n\n    function _doSafeTransferAcceptanceCheck(\n        address operator,\n        address from,\n        address to,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) private {\n        if (to.isContract()) {\n            try IERC1155Receiver(to).onERC1155Received(operator, from, id, amount, data) returns (bytes4 response) {\n                if (response != IERC1155Receiver.onERC1155Received.selector) {\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n                }\n            } catch Error(string memory reason) {\n                revert(reason);\n            } catch {\n                revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n            }\n        }\n    }\n\n    function _doSafeBatchTransferAcceptanceCheck(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) private {\n        if (to.isContract()) {\n            try IERC1155Receiver(to).onERC1155BatchReceived(operator, from, ids, amounts, data) returns (\n                bytes4 response\n            ) {\n                if (response != IERC1155Receiver.onERC1155BatchReceived.selector) {\n                    revert(\"ERC1155: ERC1155Receiver rejected tokens\");\n                }\n            } catch Error(string memory reason) {\n                revert(reason);\n            } catch {\n                revert(\"ERC1155: transfer to non ERC1155Receiver implementer\");\n            }\n        }\n    }\n\n    function _asSingletonArray(uint256 element) private pure returns (uint256[] memory) {\n        uint256[] memory array = new uint256[](1);\n        array[0] = element;\n\n        return array;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev _Available since v3.1._\n */\ninterface IERC1155Receiver is IERC165 {\n    /**\n        @dev Handles the receipt of a single ERC1155 token type. This function is\n        called at the end of a `safeTransferFrom` after the balance has been updated.\n        To accept the transfer, this must return\n        `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))`\n        (i.e. 0xf23a6e61, or its own function selector).\n        @param operator The address which initiated the transfer (i.e. msg.sender)\n        @param from The address which previously owned the token\n        @param id The ID of the token being transferred\n        @param value The amount of tokens being transferred\n        @param data Additional data with no specified format\n        @return `bytes4(keccak256(\"onERC1155Received(address,address,uint256,uint256,bytes)\"))` if transfer is allowed\n    */\n    function onERC1155Received(\n        address operator,\n        address from,\n        uint256 id,\n        uint256 value,\n        bytes calldata data\n    ) external returns (bytes4);\n\n    /**\n        @dev Handles the receipt of a multiple ERC1155 token types. This function\n        is called at the end of a `safeBatchTransferFrom` after the balances have\n        been updated. To accept the transfer(s), this must return\n        `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))`\n        (i.e. 0xbc197c81, or its own function selector).\n        @param operator The address which initiated the batch transfer (i.e. msg.sender)\n        @param from The address which previously owned the token\n        @param ids An array containing ids of each token being transferred (order and length must match values array)\n        @param values An array containing amounts of each token being transferred (order and length must match ids array)\n        @param data Additional data with no specified format\n        @return `bytes4(keccak256(\"onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)\"))` if transfer is allowed\n    */\n    function onERC1155BatchReceived(\n        address operator,\n        address from,\n        uint256[] calldata ids,\n        uint256[] calldata values,\n        bytes calldata data\n    ) external returns (bytes4);\n}\n"
    },
    "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC1155.sol\";\n\n/**\n * @dev Interface of the optional ERC1155MetadataExtension interface, as defined\n * in the https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[EIP].\n *\n * _Available since v3.1._\n */\ninterface IERC1155MetadataURI is IERC1155 {\n    /**\n     * @dev Returns the URI for token type `id`.\n     *\n     * If the `\\{id\\}` substring is present in the URI, it must be replaced by\n     * clients with the actual token type ID.\n     */\n    function uri(uint256 id) external view returns (string memory);\n}\n"
    },
    "@openzeppelin/contracts/utils/introspection/ERC165.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../ERC1155.sol\";\n\n/**\n * @dev Extension of ERC1155 that adds tracking of total supply per id.\n *\n * Useful for scenarios where Fungible and Non-fungible tokens have to be\n * clearly identified. Note: While a totalSupply of 1 might mean the\n * corresponding is an NFT, there is no guarantees that no other token with the\n * same id are not going to be minted.\n */\nabstract contract ERC1155Supply is ERC1155 {\n    mapping(uint256 => uint256) private _totalSupply;\n\n    /**\n     * @dev Total amount of tokens in with a given id.\n     */\n    function totalSupply(uint256 id) public view virtual returns (uint256) {\n        return _totalSupply[id];\n    }\n\n    /**\n     * @dev Indicates weither any token exist with a given id, or not.\n     */\n    function exists(uint256 id) public view virtual returns (bool) {\n        return ERC1155Supply.totalSupply(id) > 0;\n    }\n\n    /**\n     * @dev See {ERC1155-_mint}.\n     */\n    function _mint(\n        address account,\n        uint256 id,\n        uint256 amount,\n        bytes memory data\n    ) internal virtual override {\n        super._mint(account, id, amount, data);\n        _totalSupply[id] += amount;\n    }\n\n    /**\n     * @dev See {ERC1155-_mintBatch}.\n     */\n    function _mintBatch(\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal virtual override {\n        super._mintBatch(to, ids, amounts, data);\n        for (uint256 i = 0; i < ids.length; ++i) {\n            _totalSupply[ids[i]] += amounts[i];\n        }\n    }\n\n    /**\n     * @dev See {ERC1155-_burn}.\n     */\n    function _burn(\n        address account,\n        uint256 id,\n        uint256 amount\n    ) internal virtual override {\n        super._burn(account, id, amount);\n        _totalSupply[id] -= amount;\n    }\n\n    /**\n     * @dev See {ERC1155-_burnBatch}.\n     */\n    function _burnBatch(\n        address account,\n        uint256[] memory ids,\n        uint256[] memory amounts\n    ) internal virtual override {\n        super._burnBatch(account, ids, amounts);\n        for (uint256 i = 0; i < ids.length; ++i) {\n            _totalSupply[ids[i]] -= amounts[i];\n        }\n    }\n}\n"
    },
    "contracts/MemberToken.sol": {
      "content": "pragma solidity 0.8.7;\n\n/* solhint-disable indent */\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/utils/Address.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/ERC1155.sol\";\nimport \"@openzeppelin/contracts/token/ERC1155/extensions/ERC1155Supply.sol\";\nimport \"./interfaces/IControllerRegistry.sol\";\nimport \"./interfaces/IController.sol\";\n\ncontract MemberToken is ERC1155Supply, Ownable {\n    using Address for address;\n\n    IControllerRegistry public controllerRegistry;\n\n    mapping(uint256 => address) public memberController;\n\n    uint256 public nextAvailablePodId = 0;\n    string public _contractURI =\n        \"https://orcaprotocol-nft.vercel.app/assets/contract-metadata\";\n\n    event MigrateMemberController(uint256 podId, address newController);\n\n    /**\n     * @param _controllerRegistry The address of the ControllerRegistry contract\n     */\n    constructor(address _controllerRegistry, string memory uri) ERC1155(uri) {\n        require(_controllerRegistry != address(0), \"Invalid address\");\n        controllerRegistry = IControllerRegistry(_controllerRegistry);\n    }\n\n    // Provides metadata value for the opensea wallet. Must be set at construct time\n    // Source: https://www.reddit.com/r/ethdev/comments/q4j5bf/contracturi_not_reflected_in_opensea/\n    function contractURI() public view returns (string memory) {\n        return _contractURI;\n    }\n\n    // Note that OpenSea does not currently update contract metadata when this value is changed. - Nov 2021\n    function setContractURI(string memory newContractURI) public onlyOwner {\n        _contractURI = newContractURI;\n    }\n\n    /**\n     * @param _podId The pod id number\n     * @param _newController The address of the new controller\n     */\n    function migrateMemberController(uint256 _podId, address _newController)\n        external\n    {\n        require(_newController != address(0), \"Invalid address\");\n        require(\n            msg.sender == memberController[_podId],\n            \"Invalid migrate controller\"\n        );\n        require(\n            controllerRegistry.isRegistered(_newController),\n            \"Controller not registered\"\n        );\n\n        memberController[_podId] = _newController;\n        emit MigrateMemberController(_podId, _newController);\n    }\n\n    function getNextAvailablePodId() external view returns (uint256) {\n        return nextAvailablePodId;\n    }\n\n    function setUri(string memory uri) external onlyOwner {\n        _setURI(uri);\n    }\n\n    /**\n     * @param _account The account address to assign the membership token to\n     * @param _id The membership token id to mint\n     * @param data Passes a flag for initial creation event\n     */\n    function mint(\n        address _account,\n        uint256 _id,\n        bytes memory data\n    ) external {\n        _mint(_account, _id, 1, data);\n    }\n\n    /**\n     * @param _accounts The account addresses to assign the membership tokens to\n     * @param _id The membership token id to mint\n     * @param data Passes a flag for an initial creation event\n     */\n    function mintSingleBatch(\n        address[] memory _accounts,\n        uint256 _id,\n        bytes memory data\n    ) public {\n        for (uint256 index = 0; index < _accounts.length; index += 1) {\n            _mint(_accounts[index], _id, 1, data);\n        }\n    }\n\n    /**\n     * @param _accounts The account addresses to burn the membership tokens from\n     * @param _id The membership token id to burn\n     */\n    function burnSingleBatch(address[] memory _accounts, uint256 _id) public {\n        for (uint256 index = 0; index < _accounts.length; index += 1) {\n            _burn(_accounts[index], _id, 1);\n        }\n    }\n\n    function createPod(address[] memory _accounts, bytes memory data)\n        external\n        returns (uint256)\n    {\n        uint256 id = nextAvailablePodId;\n        nextAvailablePodId += 1;\n\n        require(\n            controllerRegistry.isRegistered(msg.sender),\n            \"Controller not registered\"\n        );\n\n        memberController[id] = msg.sender;\n\n        if (_accounts.length != 0) {\n            mintSingleBatch(_accounts, id, data);\n        }\n\n        return id;\n    }\n\n    /**\n     * @param _account The account address holding the membership token to destroy\n     * @param _id The id of the membership token to destroy\n     */\n    function burn(address _account, uint256 _id) external {\n        _burn(_account, _id, 1);\n    }\n\n    // this hook gets called before every token event including mint and burn\n    /**\n     * @param operator The account address that initiated the action\n     * @param from The account address recieveing the membership token\n     * @param to The account address sending the membership token\n     * @param ids An array of membership token ids to be transfered\n     * @param amounts The amount of each membership token type to transfer\n     * @param data Passes a flag for an initial creation event\n     */\n    function _beforeTokenTransfer(\n        address operator,\n        address from,\n        address to,\n        uint256[] memory ids,\n        uint256[] memory amounts,\n        bytes memory data\n    ) internal override {\n        // use first id to lookup controller\n        address controller = memberController[ids[0]];\n        require(controller != address(0), \"Pod doesn't exist\");\n\n        for (uint256 i = 0; i < ids.length; i += 1) {\n            // check if recipient is already member\n            if (to != address(0)) {\n                require(balanceOf(to, ids[i]) == 0, \"User is already member\");\n            }\n            // verify all ids use same controller\n            require(\n                memberController[ids[i]] == controller,\n                \"Ids have different controllers\"\n            );\n        }\n\n        // perform orca token transfer validations\n        IController(controller).beforeTokenTransfer(\n            operator,\n            from,\n            to,\n            ids,\n            amounts,\n            data\n        );\n    }\n}\n"
    },
    "contracts/ens/PodEnsRegistrar.sol": {
      "content": "pragma solidity 0.8.7;\n\nimport \"@ensdomains/ens-contracts/contracts/registry/ENS.sol\";\nimport \"@ensdomains/ens-contracts/contracts/resolvers/Resolver.sol\";\nimport \"../interfaces/IControllerRegistry.sol\";\nimport \"../interfaces/IInviteToken.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * A registrar that allocates subdomains to the first person to claim them.\n */\ncontract PodEnsRegistrar is Ownable {\n\n    enum State { \n        onlySafeWithShip, // Only safes with SHIP token\n        onlyShip, // Anyone with SHIP token\n        open, // Anyone can enroll\n        closed // Nobody can enroll, just in case\n    }\n\n    ENS ens;\n    Resolver resolver;\n    address reverseRegistrar;\n    IControllerRegistry controllerRegistry;\n    bytes32 rootNode;\n    IInviteToken inviteToken;\n    State public state = State.onlySafeWithShip; \n\n    /**\n     * Constructor.\n     * @param ensAddr The address of the ENS registry.\n     * @param node The node that this registrar administers.\n     */\n    constructor(ENS ensAddr, Resolver resolverAddr, address _reverseRegistrar, IControllerRegistry controllerRegistryAddr, bytes32 node, IInviteToken inviteTokenAddr) {\n        ens = ensAddr;\n        resolver = resolverAddr;\n        controllerRegistry = controllerRegistryAddr;\n        rootNode = node;\n        reverseRegistrar = _reverseRegistrar;\n        inviteToken = inviteTokenAddr;\n    }\n\n    function registerPod(bytes32 label, address podSafe, address podCreator) public returns(address) {\n        if (state == State.closed) {\n            revert(\"registrations are closed\");\n        }\n\n        if (state == State.onlySafeWithShip) {\n            // This implicitly prevents safes that were created in this transaction\n            // from registering, as they cannot have a SHIP token balance.\n            require(inviteToken.balanceOf(podSafe) > 0, \"safe must have SHIP token\");\n            inviteToken.burn(podSafe, 1);\n        }\n        if (state == State.onlyShip) {\n            // Prefer the safe's token over the user's\n            if (inviteToken.balanceOf(podSafe) > 0) {\n                inviteToken.burn(podSafe, 1);\n            } else if (inviteToken.balanceOf(podCreator) > 0) {\n                inviteToken.burn(podCreator, 1);\n            } else {\n                revert(\"sender or safe must have SHIP\");\n            }\n        }\n\n        bytes32 node = keccak256(abi.encodePacked(rootNode, label));\n\n        require(controllerRegistry.isRegistered(msg.sender), \"controller not registered\");\n\n        require(\n            ens.owner(node) == address(0),\n            \"label is already owned\"\n        );\n        \n        _register(label, address(this));\n\n        resolver.setAddr(node, podSafe);\n\n        return address(reverseRegistrar);\n    }\n\n\n    /**\n     * Register a name, or change the owner of an existing registration.\n     * @param label The hash of the label to register.\n     */\n    function register(bytes32 label, address owner) public onlyOwner {\n        _register(label, owner);\n    }\n\n    /**\n     * Register a name, or change the owner of an existing registration.\n     * @param label The hash of the label to register.\n     */\n    function _register(bytes32 label, address owner) internal {\n\n        ens.setSubnodeRecord(\n            rootNode,\n            label,\n            owner,\n            address(resolver),\n            0\n        );\n\n    }\n\n    function setText(bytes32 node, string calldata key, string calldata value) public onlyOwner {\n        resolver.setText(node, key, value);\n    }\n\n    function setAddr(bytes32 node, address newAddress) public onlyOwner {\n        resolver.setAddr(node, newAddress);\n    }\n\n    function setRestrictionState(uint256 _state) public onlyOwner {\n        state = State(_state);\n    }\n\n}\n"
    },
    "@ensdomains/ens-contracts/contracts/registry/ENS.sol": {
      "content": "pragma solidity >=0.8.4;\n\ninterface ENS {\n\n    // Logged when the owner of a node assigns a new owner to a subnode.\n    event NewOwner(bytes32 indexed node, bytes32 indexed label, address owner);\n\n    // Logged when the owner of a node transfers ownership to a new account.\n    event Transfer(bytes32 indexed node, address owner);\n\n    // Logged when the resolver for a node changes.\n    event NewResolver(bytes32 indexed node, address resolver);\n\n    // Logged when the TTL of a node changes\n    event NewTTL(bytes32 indexed node, uint64 ttl);\n\n    // Logged when an operator is added or removed.\n    event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n    function setRecord(bytes32 node, address owner, address resolver, uint64 ttl) external virtual;\n    function setSubnodeRecord(bytes32 node, bytes32 label, address owner, address resolver, uint64 ttl) external virtual;\n    function setSubnodeOwner(bytes32 node, bytes32 label, address owner) external virtual returns(bytes32);\n    function setResolver(bytes32 node, address resolver) external virtual;\n    function setOwner(bytes32 node, address owner) external virtual;\n    function setTTL(bytes32 node, uint64 ttl) external virtual;\n    function setApprovalForAll(address operator, bool approved) external virtual;\n    function owner(bytes32 node) external virtual view returns (address);\n    function resolver(bytes32 node) external virtual view returns (address);\n    function ttl(bytes32 node) external virtual view returns (uint64);\n    function recordExists(bytes32 node) external virtual view returns (bool);\n    function isApprovedForAll(address owner, address operator) external virtual view returns (bool);\n}\n"
    },
    "@ensdomains/ens-contracts/contracts/resolvers/Resolver.sol": {
      "content": "pragma solidity >=0.8.4;\npragma experimental ABIEncoderV2;\n\n/**\n * A generic resolver interface which includes all the functions including the ones deprecated\n */\ninterface Resolver{\n    event AddrChanged(bytes32 indexed node, address a);\n    event AddressChanged(bytes32 indexed node, uint coinType, bytes newAddress);\n    event NameChanged(bytes32 indexed node, string name);\n    event ABIChanged(bytes32 indexed node, uint256 indexed contentType);\n    event PubkeyChanged(bytes32 indexed node, bytes32 x, bytes32 y);\n    event TextChanged(bytes32 indexed node, string indexed indexedKey, string key);\n    event ContenthashChanged(bytes32 indexed node, bytes hash);\n    /* Deprecated events */\n    event ContentChanged(bytes32 indexed node, bytes32 hash);\n\n    function ABI(bytes32 node, uint256 contentTypes) external view returns (uint256, bytes memory);\n    function addr(bytes32 node) external view returns (address);\n    function addr(bytes32 node, uint coinType) external view returns(bytes memory);\n    function contenthash(bytes32 node) external view returns (bytes memory);\n    function dnsrr(bytes32 node) external view returns (bytes memory);\n    function name(bytes32 node) external view returns (string memory);\n    function pubkey(bytes32 node) external view returns (bytes32 x, bytes32 y);\n    function text(bytes32 node, string calldata key) external view returns (string memory);\n    function interfaceImplementer(bytes32 node, bytes4 interfaceID) external view returns (address);\n    function setABI(bytes32 node, uint256 contentType, bytes calldata data) external;\n    function setAddr(bytes32 node, address addr) external;\n    function setAddr(bytes32 node, uint coinType, bytes calldata a) external;\n    function setContenthash(bytes32 node, bytes calldata hash) external;\n    function setDnsrr(bytes32 node, bytes calldata data) external;\n    function setName(bytes32 node, string calldata _name) external;\n    function setPubkey(bytes32 node, bytes32 x, bytes32 y) external;\n    function setText(bytes32 node, string calldata key, string calldata value) external;\n    function setInterface(bytes32 node, bytes4 interfaceID, address implementer) external;\n    function supportsInterface(bytes4 interfaceID) external pure returns (bool);\n    function multicall(bytes[] calldata data) external returns(bytes[] memory results);\n\n    /* Deprecated functions */\n    function content(bytes32 node) external view returns (bytes32);\n    function multihash(bytes32 node) external view returns (bytes memory);\n    function setContent(bytes32 node, bytes32 hash) external;\n    function setMultihash(bytes32 node, bytes calldata hash) external;\n}\n"
    },
    "contracts/interfaces/IInviteToken.sol": {
      "content": "pragma solidity 0.8.7;\n\n/* solhint-disable indent */\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IInviteToken is IERC20 {\n    function batchMint(address[] calldata accounts, uint256 amount) external;\n\n    function mint(address account, uint256 amount) external;\n\n    function burn(address account, uint256 amount) external;\n\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/IERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
    },
    "contracts/ControllerRegistry.sol": {
      "content": "pragma solidity 0.8.7;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./interfaces/IControllerRegistry.sol\";\n\ncontract ControllerRegistry is IControllerRegistry, Ownable {\n    mapping(address => bool) public controllerRegistry;\n\n    event ControllerRegister(address newController);\n    event ControllerRemove(address newController);\n\n    /**\n     * @param _controller The address to register as a controller\n     */\n    function registerController(address _controller) external onlyOwner {\n        require(_controller != address(0), \"Invalid address\");\n        emit ControllerRegister(_controller);\n        controllerRegistry[_controller] = true;\n    }\n\n    /**\n     * @param _controller The address to remove as a controller\n     */\n    function removeController(address _controller) external onlyOwner {\n        require(_controller != address(0), \"Invalid address\");\n        emit ControllerRemove(_controller);\n        controllerRegistry[_controller] = false;\n    }\n\n    /**\n     * @param _controller The address to check if registered as a controller\n     * @return Boolean representing if the address is a registered as a controller\n     */\n    function isRegistered(address _controller)\n        external\n        view\n        override\n        returns (bool)\n    {\n        return controllerRegistry[_controller];\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/AccessControl.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n *     require(hasRole(MY_ROLE, msg.sender));\n *     ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n    struct RoleData {\n        mapping(address => bool) members;\n        bytes32 adminRole;\n    }\n\n    mapping(bytes32 => RoleData) private _roles;\n\n    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n    /**\n     * @dev Modifier that checks that an account has a specific role. Reverts\n     * with a standardized message including the required role.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     *\n     * _Available since v4.1._\n     */\n    modifier onlyRole(bytes32 role) {\n        _checkRole(role, _msgSender());\n        _;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n    }\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) public view override returns (bool) {\n        return _roles[role].members[account];\n    }\n\n    /**\n     * @dev Revert with a standard message if `account` is missing `role`.\n     *\n     * The format of the revert reason is given by the following regular expression:\n     *\n     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n     */\n    function _checkRole(bytes32 role, address account) internal view {\n        if (!hasRole(role, account)) {\n            revert(\n                string(\n                    abi.encodePacked(\n                        \"AccessControl: account \",\n                        Strings.toHexString(uint160(account), 20),\n                        \" is missing role \",\n                        Strings.toHexString(uint256(role), 32)\n                    )\n                )\n            );\n        }\n    }\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n        return _roles[role].adminRole;\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) public virtual override {\n        require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n        _revokeRole(role, account);\n    }\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event. Note that unlike {grantRole}, this function doesn't perform any\n     * checks on the calling account.\n     *\n     * [WARNING]\n     * ====\n     * This function should only be called from the constructor when setting\n     * up the initial roles for the system.\n     *\n     * Using this function in any other way is effectively circumventing the admin\n     * system imposed by {AccessControl}.\n     * ====\n     */\n    function _setupRole(bytes32 role, address account) internal virtual {\n        _grantRole(role, account);\n    }\n\n    /**\n     * @dev Sets `adminRole` as ``role``'s admin role.\n     *\n     * Emits a {RoleAdminChanged} event.\n     */\n    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n        bytes32 previousAdminRole = getRoleAdmin(role);\n        _roles[role].adminRole = adminRole;\n        emit RoleAdminChanged(role, previousAdminRole, adminRole);\n    }\n\n    function _grantRole(bytes32 role, address account) private {\n        if (!hasRole(role, account)) {\n            _roles[role].members[account] = true;\n            emit RoleGranted(role, account, _msgSender());\n        }\n    }\n\n    function _revokeRole(bytes32 role, address account) private {\n        if (hasRole(role, account)) {\n            _roles[role].members[account] = false;\n            emit RoleRevoked(role, account, _msgSender());\n        }\n    }\n}\n"
    },
    "@openzeppelin/contracts/access/IAccessControl.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n    /**\n     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n     *\n     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n     * {RoleAdminChanged} not being emitted signaling this.\n     *\n     * _Available since v3.1._\n     */\n    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n    /**\n     * @dev Emitted when `account` is granted `role`.\n     *\n     * `sender` is the account that originated the contract call, an admin role\n     * bearer except when using {AccessControl-_setupRole}.\n     */\n    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Emitted when `account` is revoked `role`.\n     *\n     * `sender` is the account that originated the contract call:\n     *   - if using `revokeRole`, it is the admin role bearer\n     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)\n     */\n    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n    /**\n     * @dev Returns `true` if `account` has been granted `role`.\n     */\n    function hasRole(bytes32 role, address account) external view returns (bool);\n\n    /**\n     * @dev Returns the admin role that controls `role`. See {grantRole} and\n     * {revokeRole}.\n     *\n     * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n     */\n    function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n    /**\n     * @dev Grants `role` to `account`.\n     *\n     * If `account` had not been already granted `role`, emits a {RoleGranted}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function grantRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from `account`.\n     *\n     * If `account` had been granted `role`, emits a {RoleRevoked} event.\n     *\n     * Requirements:\n     *\n     * - the caller must have ``role``'s admin role.\n     */\n    function revokeRole(bytes32 role, address account) external;\n\n    /**\n     * @dev Revokes `role` from the calling account.\n     *\n     * Roles are often managed via {grantRole} and {revokeRole}: this function's\n     * purpose is to provide a mechanism for accounts to lose their privileges\n     * if they are compromised (such as when a trusted device is misplaced).\n     *\n     * If the calling account had been granted `role`, emits a {RoleRevoked}\n     * event.\n     *\n     * Requirements:\n     *\n     * - the caller must be `account`.\n     */\n    function renounceRole(bytes32 role, address account) external;\n}\n"
    },
    "@openzeppelin/contracts/utils/Strings.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n    bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n     */\n    function toString(uint256 value) internal pure returns (string memory) {\n        // Inspired by OraclizeAPI's implementation - MIT licence\n        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n        if (value == 0) {\n            return \"0\";\n        }\n        uint256 temp = value;\n        uint256 digits;\n        while (temp != 0) {\n            digits++;\n            temp /= 10;\n        }\n        bytes memory buffer = new bytes(digits);\n        while (value != 0) {\n            digits -= 1;\n            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n            value /= 10;\n        }\n        return string(buffer);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n     */\n    function toHexString(uint256 value) internal pure returns (string memory) {\n        if (value == 0) {\n            return \"0x00\";\n        }\n        uint256 temp = value;\n        uint256 length = 0;\n        while (temp != 0) {\n            length++;\n            temp >>= 8;\n        }\n        return toHexString(value, length);\n    }\n\n    /**\n     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n     */\n    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n        bytes memory buffer = new bytes(2 * length + 2);\n        buffer[0] = \"0\";\n        buffer[1] = \"x\";\n        for (uint256 i = 2 * length + 1; i > 1; --i) {\n            buffer[i] = _HEX_SYMBOLS[value & 0xf];\n            value >>= 4;\n        }\n        require(value == 0, \"Strings: hex length insufficient\");\n        return string(buffer);\n    }\n}\n"
    },
    "contracts/InviteToken.sol": {
      "content": "pragma solidity 0.8.7;\n\n/* solhint-disable indent */\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport \"@openzeppelin/contracts/access/AccessControl.sol\";\n\ncontract InviteToken is ERC20, AccessControl {\n    bytes32 public constant MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n    bytes32 public constant BURNER_ROLE = keccak256(\"BURNER_ROLE\");\n\n    constructor() ERC20(\"Ship Token\", \"$SHIP\") {\n        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);\n        _setupRole(MINTER_ROLE, msg.sender);\n        _setupRole(BURNER_ROLE, msg.sender);\n    }\n\n    function decimals() public view override returns (uint8) {\n        return 0;\n    }\n\n    function batchMint(address[] calldata accounts, uint256 amount) public {\n        for (uint256 i = 0; i < accounts.length; i++) {\n            mint(accounts[i], amount);\n        }\n    }\n\n    function mint(address account, uint256 amount) public {\n        require(hasRole(MINTER_ROLE, msg.sender), \"Only minters can mint\");\n        _mint(account, amount);\n    }\n\n    function burn(address account, uint256 amount) public {\n        require(hasRole(BURNER_ROLE, msg.sender), \"Only burners can burn\");\n        _burn(account, amount);\n    }\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/ERC20.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n    mapping(address => uint256) private _balances;\n\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    uint256 private _totalSupply;\n\n    string private _name;\n    string private _symbol;\n\n    /**\n     * @dev Sets the values for {name} and {symbol}.\n     *\n     * The default value of {decimals} is 18. To select a different value for\n     * {decimals} you should overload it.\n     *\n     * All two of these values are immutable: they can only be set once during\n     * construction.\n     */\n    constructor(string memory name_, string memory symbol_) {\n        _name = name_;\n        _symbol = symbol_;\n    }\n\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() public view virtual override returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @dev Returns the symbol of the token, usually a shorter version of the\n     * name.\n     */\n    function symbol() public view virtual override returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @dev Returns the number of decimals used to get its user representation.\n     * For example, if `decimals` equals `2`, a balance of `505` tokens should\n     * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n     *\n     * Tokens usually opt for a value of 18, imitating the relationship between\n     * Ether and Wei. This is the value {ERC20} uses, unless this function is\n     * overridden;\n     *\n     * NOTE: This information is only used for _display_ purposes: it in\n     * no way affects any of the arithmetic of the contract, including\n     * {IERC20-balanceOf} and {IERC20-transfer}.\n     */\n    function decimals() public view virtual override returns (uint8) {\n        return 18;\n    }\n\n    /**\n     * @dev See {IERC20-totalSupply}.\n     */\n    function totalSupply() public view virtual override returns (uint256) {\n        return _totalSupply;\n    }\n\n    /**\n     * @dev See {IERC20-balanceOf}.\n     */\n    function balanceOf(address account) public view virtual override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @dev See {IERC20-transfer}.\n     *\n     * Requirements:\n     *\n     * - `recipient` cannot be the zero address.\n     * - the caller must have a balance of at least `amount`.\n     */\n    function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-allowance}.\n     */\n    function allowance(address owner, address spender) public view virtual override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @dev See {IERC20-approve}.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function approve(address spender, uint256 amount) public virtual override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @dev See {IERC20-transferFrom}.\n     *\n     * Emits an {Approval} event indicating the updated allowance. This is not\n     * required by the EIP. See the note at the beginning of {ERC20}.\n     *\n     * Requirements:\n     *\n     * - `sender` and `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     * - the caller must have allowance for ``sender``'s tokens of at least\n     * `amount`.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) public virtual override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Atomically increases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n        return true;\n    }\n\n    /**\n     * @dev Atomically decreases the allowance granted to `spender` by the caller.\n     *\n     * This is an alternative to {approve} that can be used as a mitigation for\n     * problems described in {IERC20-approve}.\n     *\n     * Emits an {Approval} event indicating the updated allowance.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `spender` must have allowance for the caller of at least\n     * `subtractedValue`.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @dev Moves `amount` of tokens from `sender` to `recipient`.\n     *\n     * This internal function is equivalent to {transfer}, and can be used to\n     * e.g. implement automatic token fees, slashing mechanisms, etc.\n     *\n     * Emits a {Transfer} event.\n     *\n     * Requirements:\n     *\n     * - `sender` cannot be the zero address.\n     * - `recipient` cannot be the zero address.\n     * - `sender` must have a balance of at least `amount`.\n     */\n    function _transfer(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) internal virtual {\n        require(sender != address(0), \"ERC20: transfer from the zero address\");\n        require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n        _beforeTokenTransfer(sender, recipient, amount);\n\n        uint256 senderBalance = _balances[sender];\n        require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n        unchecked {\n            _balances[sender] = senderBalance - amount;\n        }\n        _balances[recipient] += amount;\n\n        emit Transfer(sender, recipient, amount);\n\n        _afterTokenTransfer(sender, recipient, amount);\n    }\n\n    /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n     * the total supply.\n     *\n     * Emits a {Transfer} event with `from` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     */\n    function _mint(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: mint to the zero address\");\n\n        _beforeTokenTransfer(address(0), account, amount);\n\n        _totalSupply += amount;\n        _balances[account] += amount;\n        emit Transfer(address(0), account, amount);\n\n        _afterTokenTransfer(address(0), account, amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, reducing the\n     * total supply.\n     *\n     * Emits a {Transfer} event with `to` set to the zero address.\n     *\n     * Requirements:\n     *\n     * - `account` cannot be the zero address.\n     * - `account` must have at least `amount` tokens.\n     */\n    function _burn(address account, uint256 amount) internal virtual {\n        require(account != address(0), \"ERC20: burn from the zero address\");\n\n        _beforeTokenTransfer(account, address(0), amount);\n\n        uint256 accountBalance = _balances[account];\n        require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n        unchecked {\n            _balances[account] = accountBalance - amount;\n        }\n        _totalSupply -= amount;\n\n        emit Transfer(account, address(0), amount);\n\n        _afterTokenTransfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n     *\n     * This internal function is equivalent to `approve`, and can be used to\n     * e.g. set automatic allowances for certain subsystems, etc.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `owner` cannot be the zero address.\n     * - `spender` cannot be the zero address.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) internal virtual {\n        require(owner != address(0), \"ERC20: approve from the zero address\");\n        require(spender != address(0), \"ERC20: approve to the zero address\");\n\n        _allowances[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @dev Hook that is called before any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * will be transferred to `to`.\n     * - when `from` is zero, `amount` tokens will be minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _beforeTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n\n    /**\n     * @dev Hook that is called after any transfer of tokens. This includes\n     * minting and burning.\n     *\n     * Calling conditions:\n     *\n     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n     * has been transferred to `to`.\n     * - when `from` is zero, `amount` tokens have been minted for `to`.\n     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n     * - `from` and `to` are never both zero.\n     *\n     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n     */\n    function _afterTokenTransfer(\n        address from,\n        address to,\n        uint256 amount\n    ) internal virtual {}\n}\n"
    },
    "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": {
      "content": "// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 1000
    },
    "outputSelection": {
      "*": {
        "*": [
          "abi",
          "evm.bytecode",
          "evm.deployedBytecode",
          "evm.methodIdentifiers",
          "metadata",
          "devdoc",
          "userdoc",
          "storageLayout",
          "evm.gasEstimates"
        ],
        "": [
          "ast"
        ]
      }
    },
    "metadata": {
      "useLiteralContent": true
    }
  }
}