{"file_path":"contracts/msd/MSD.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol\";\n\nimport \"../library/Initializable.sol\";\nimport \"../library/Ownable.sol\";\nimport \"../library/ERC20.sol\";\n\n/**\n * @title dForce's Multi-currency Stable Debt Token\n * @author dForce\n */\ncontract MSD is Initializable, Ownable, ERC20 {\n    using EnumerableSetUpgradeable for EnumerableSetUpgradeable.AddressSet;\n\n    bytes32 public DOMAIN_SEPARATOR;\n    // keccak256(\"Permit(address owner,address spender,uint256 chainId, uint256 value,uint256 nonce,uint256 deadline)\");\n    bytes32 public constant PERMIT_TYPEHASH =\n        0x576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf;\n    mapping(address => uint256) public nonces;\n\n    /// @dev EnumerableSet of minters\n    EnumerableSetUpgradeable.AddressSet internal minters;\n\n    /**\n     * @dev Emitted when `minter` is added as `minter`.\n     */\n    event MinterAdded(address minter);\n\n    /**\n     * @dev Emitted when `minter` is removed from `minters`.\n     */\n    event MinterRemoved(address minter);\n\n    /**\n     * @notice Expects to call only once to initialize the MSD token.\n     * @param _name Token name.\n     * @param _symbol Token symbol.\n     */\n    function initialize(\n        string memory _name,\n        string memory _symbol,\n        uint8 _decimals\n    ) external initializer {\n        __Ownable_init();\n        __ERC20_init(_name, _symbol, _decimals);\n\n        DOMAIN_SEPARATOR = keccak256(\n            abi.encode(\n                keccak256(\n                    \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n                ),\n                keccak256(bytes(_name)),\n                keccak256(bytes(\"1\")),\n                _getChainId(),\n                address(this)\n            )\n        );\n    }\n\n    /**\n     * @dev Throws if called by any account other than the minters.\n     */\n    modifier onlyMinter() {\n        require(\n            minters.contains(msg.sender),\n            \"onlyMinter: caller is not minter\"\n        );\n        _;\n    }\n\n    /**\n     * @notice Add `minter` into minters.\n     * If `minter` have not been a minter, emits a `MinterAdded` event.\n     *\n     * @param _minter The minter to add\n     *\n     * Requirements:\n     * - the caller must be `owner`.\n     */\n    function _addMinter(address _minter) external onlyOwner {\n        require(_minter != address(0), \"_addMinter: _minter the zero address\");\n        if (minters.add(_minter)) {\n            emit MinterAdded(_minter);\n        }\n    }\n\n    /**\n     * @notice Remove `minter` from minters.\n     * If `minter` is a minter, emits a `MinterRemoved` event.\n     *\n     * @param _minter The minter to remove\n     *\n     * Requirements:\n     * - the caller must be `owner`.\n     */\n    function _removeMinter(address _minter) external onlyOwner {\n        require(\n            _minter != address(0),\n            \"_removeMinter: _minter the zero address\"\n        );\n        if (minters.remove(_minter)) {\n            emit MinterRemoved(_minter);\n        }\n    }\n\n    function mint(address to, uint256 amount) external onlyMinter {\n        _mint(to, amount);\n    }\n\n    function burn(address from, uint256 amount) external {\n        _burnFrom(from, amount);\n    }\n\n    function _getChainId() internal pure returns (uint256) {\n        uint256 chainId;\n        assembly {\n            chainId := chainid()\n        }\n        return chainId;\n    }\n\n    /**\n     * @dev EIP2612 permit function. For more details, please look at here:\n     * https://eips.ethereum.org/EIPS/eip-2612\n     * @param _owner The owner of the funds.\n     * @param _spender The spender.\n     * @param _value The amount.\n     * @param _deadline The deadline timestamp, type(uint256).max for max deadline.\n     * @param _v Signature param.\n     * @param _s Signature param.\n     * @param _r Signature param.\n     */\n    function permit(\n        address _owner,\n        address _spender,\n        uint256 _value,\n        uint256 _deadline,\n        uint8 _v,\n        bytes32 _r,\n        bytes32 _s\n    ) external {\n        require(_deadline >= block.timestamp, \"permit: EXPIRED!\");\n        uint256 _currentNonce = nonces[_owner];\n        bytes32 _digest =\n            keccak256(\n                abi.encodePacked(\n                    \"\\x19\\x01\",\n                    DOMAIN_SEPARATOR,\n                    keccak256(\n                        abi.encode(\n                            PERMIT_TYPEHASH,\n                            _owner,\n                            _spender,\n                            _getChainId(),\n                            _value,\n                            _currentNonce,\n                            _deadline\n                        )\n                    )\n                )\n            );\n        address _recoveredAddress = ecrecover(_digest, _v, _r, _s);\n        require(\n            _recoveredAddress != address(0) && _recoveredAddress == _owner,\n            \"permit: INVALID_SIGNATURE!\"\n        );\n        nonces[_owner] = _currentNonce.add(1);\n        _approve(_owner, _spender, _value);\n    }\n\n    /**\n     * @notice Return all minters of this MSD token\n     * @return _minters The list of minter addresses\n     */\n    function getMinters() public view returns (address[] memory _minters) {\n        uint256 _len = minters.length();\n        _minters = new address[](_len);\n        for (uint256 i = 0; i < _len; i++) {\n            _minters[i] = minters.at(i);\n        }\n    }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106101735760003560e01c80636b32810b116100de5780639dc29fac11610097578063d505accf11610071578063d505accf14610605578063dd62ed3e14610656578063e30c397814610684578063fc4d33f91461068c57610173565b80639dc29fac14610581578063a457c2d7146105ad578063a9059cbb146105d957610173565b80636b32810b1461048b5780636e96dfd7146104e357806370a08231146105095780637ecebe001461052f5780638da5cb5b1461055557806395d89b411461057957610173565b806323b872dd1161013057806323b872dd146103cf57806330adf81f14610405578063313ce5671461040d5780633644e5151461042b578063395093511461043357806340c10f191461045f57610173565b806303c7bce11461017857806306fdde03146101a0578063095ea7b31461021d5780631624f6c61461025d57806318160ddd1461038f578063210c5a56146103a9575b600080fd5b61019e6004803603602081101561018e57600080fd5b50356001600160a01b0316610694565b005b6101a8610777565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101e25781810151838201526020016101ca565b50505050905090810190601f16801561020f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102496004803603604081101561023357600080fd5b506001600160a01b038135169060200135610805565b604080519115158252519081900360200190f35b61019e6004803603606081101561027357600080fd5b81019060208101813564010000000081111561028e57600080fd5b8201836020820111156102a057600080fd5b803590602001918460018302840111640100000000831117156102c257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561031557600080fd5b82018360208201111561032757600080fd5b8035906020019184600183028401116401000000008311171561034957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061081c9050565b610397610919565b60408051918252519081900360200190f35b61019e600480360360208110156103bf57600080fd5b50356001600160a01b031661091f565b610249600480360360608110156103e557600080fd5b506001600160a01b03813581169160208101359091169060400135610a01565b610397610a52565b610415610a76565b6040805160ff9092168252519081900360200190f35b610397610a7f565b6102496004803603604081101561044957600080fd5b506001600160a01b038135169060200135610a85565b61019e6004803603604081101561047557600080fd5b506001600160a01b038135169060200135610abb565b610493610b25565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104cf5781810151838201526020016104b7565b505050509050019250505060405180910390f35b61019e600480360360208110156104f957600080fd5b50356001600160a01b0316610bc0565b6103976004803603602081101561051f57600080fd5b50356001600160a01b0316610cc1565b6103976004803603602081101561054557600080fd5b50356001600160a01b0316610cd3565b61055d610ce5565b604080516001600160a01b039092168252519081900360200190f35b6101a8610cf9565b61019e6004803603604081101561059757600080fd5b506001600160a01b038135169060200135610d54565b610249600480360360408110156105c357600080fd5b506001600160a01b038135169060200135610d5e565b610249600480360360408110156105ef57600080fd5b506001600160a01b038135169060200135610d94565b61019e600480360360e081101561061b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610da1565b6103976004803603604081101561066c57600080fd5b506001600160a01b0381358116916020013516610fe4565b61055d611001565b61019e611010565b60005461010090046001600160a01b031633146106e25760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b0381166107275760405162461bcd60e51b8152600401808060200182810382526024815260200180611b096024913960400191505060405180910390fd5b610732606e82611107565b1561077457604080516001600160a01b038316815290517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69181900360200190a15b50565b6037805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107fd5780601f106107d2576101008083540402835291602001916107fd565b820191906000526020600020905b8154815290600101906020018083116107e057829003601f168201915b505050505081565b6000610812338484611123565b5060015b92915050565b60005460ff161561085e5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a4f602e913960400191505060405180910390fd5b61086661120f565b610871838383611257565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8380519060200120604051806040016040528060018152602001603160f81b815250805190602001206108c3611297565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c090920190528051910120606c5550506000805460ff1916600117905550565b60365481565b60005461010090046001600160a01b0316331461096d5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b0381166109b25760405162461bcd60e51b8152600401808060200182810382526027815260200180611a286027913960400191505060405180910390fd5b6109bd606e8261129b565b1561077457604080516001600160a01b038316815290517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929181900360200190a150565b6000610a0e8484846112b0565b6001600160a01b038416600090815260356020908152604080832033808552925290912054610a48918691610a4390866113e8565b611123565b5060019392505050565b7f576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf81565b60395460ff1681565b606c5481565b3360008181526035602090815260408083206001600160a01b03871684529091528120549091610812918590610a43908661142a565b610ac6606e33611484565b610b17576040805162461bcd60e51b815260206004820181905260248201527f6f6e6c794d696e7465723a2063616c6c6572206973206e6f74206d696e746572604482015290519081900360640190fd5b610b218282611499565b5050565b60606000610b33606e61157f565b90508067ffffffffffffffff81118015610b4c57600080fd5b50604051908082528060200260200182016040528015610b76578160200160208202803683370190505b50915060005b81811015610bbb57610b8f606e8261158a565b838281518110610b9b57fe5b6001600160a01b0390921660209283029190910190910152600101610b7c565b505090565b60005461010090046001600160a01b03163314610c0e5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b03811615801590610c3457506001546001600160a01b03828116911614155b610c6f5760405162461bcd60e51b815260040180806020018281038252604b8152602001806119bb604b913960600191505060405180910390fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b60346020526000908152604090205481565b606d6020526000908152604090205481565b60005461010090046001600160a01b031681565b6038805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107fd5780601f106107d2576101008083540402835291602001916107fd565b610b218282611596565b3360008181526035602090815260408083206001600160a01b03871684529091528120549091610812918590610a4390866113e8565b60006108123384846112b0565b42841015610de9576040805162461bcd60e51b815260206004820152601060248201526f7065726d69743a20455850495245442160801b604482015290519081900360640190fd5b6001600160a01b0387166000908152606d6020526040812054606c549091907f576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf8a8a610e33611297565b604080516020808201969096526001600160a01b0394851681830152929093166060830152608082015260a081018b905260c0810186905260e08082018b9052825180830390910181526101008201835280519084012061190160f01b61012083015261012282019490945261014280820194909452815180820390940184526101628101808352845194840194909420600094859052610182820180845281905260ff8a166101a28301526101c282018990526101e282018890529151919450600192610202808301939192601f198301929081900390910190855afa158015610f22573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610f585750896001600160a01b0316816001600160a01b0316145b610fa9576040805162461bcd60e51b815260206004820152601a60248201527f7065726d69743a20494e56414c49445f5349474e415455524521000000000000604482015290519081900360640190fd5b610fb483600161142a565b6001600160a01b038b166000908152606d6020526040902055610fd88a8a8a611123565b50505050505050505050565b603560209081526000928352604080842090915290825290205481565b6001546001600160a01b031681565b6001546001600160a01b031633146110595760405162461bcd60e51b8152600401808060200182810382526025815260200180611b2d6025913960400191505060405180910390fd5b60008054600180546001600160a01b03818116610100818102610100600160a81b03198716178088556001600160a01b031990941690945560405194849004821695909493909204169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b600061111c836001600160a01b0384166115e5565b9392505050565b6001600160a01b0383166111685760405162461bcd60e51b8152600401808060200182810382526024815260200180611ae56024913960400191505060405180910390fd5b6001600160a01b0382166111ad5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a066022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008054610100600160a81b0319163361010081029190911782556040519091907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b2364908290a3565b825161126a9060379060208601906118e2565b50815161127e9060389060208501906118e2565b506039805460ff191660ff929092169190911790555050565b4690565b600061111c836001600160a01b03841661162f565b6001600160a01b0383166112f55760405162461bcd60e51b8152600401808060200182810382526025815260200180611ac06025913960400191505060405180910390fd5b6001600160a01b03821661133a5760405162461bcd60e51b81526004018080602001828103825260238152602001806119986023913960400191505060405180910390fd5b6001600160a01b03831660009081526034602052604090205461135d90826113e8565b6001600160a01b03808516600090815260346020526040808220939093559084168152205461138c908261142a565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600061111c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506116f5565b60008282018381101561111c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061111c836001600160a01b03841661178c565b6001600160a01b0382166114f4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b603654611501908261142a565b6036556001600160a01b038216600090815260346020526040902054611527908261142a565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000610816826117a4565b600061111c83836117a8565b336001600160a01b038316146115db576001600160a01b0382166000908152603560209081526040808320338085529252909120546115db918491610a4390856113e8565b610b21828261180c565b60006115f1838361178c565b61162757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610816565b506000610816565b600081815260018301602052604081205480156116eb578354600019808301919081019060009087908390811061166257fe5b906000526020600020015490508087600001848154811061167f57fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806116af57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610816565b6000915050610816565b600081848411156117845760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611749578181015183820152602001611731565b50505050905090810190601f1680156117765780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60009081526001919091016020526040902054151590565b5490565b815460009082106117ea5760405162461bcd60e51b81526004018080602001828103825260228152602001806119766022913960400191505060405180910390fd5b8260000182815481106117f957fe5b9060005260206000200154905092915050565b6001600160a01b0382166118515760405162461bcd60e51b8152600401808060200182810382526021815260200180611a9f6021913960400191505060405180910390fd5b6001600160a01b03821660009081526034602052604090205461187490826113e8565b6001600160a01b03831660009081526034602052604090205560365461189a90826113e8565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061192357805160ff1916838001178555611950565b82800160010185558215611950579182015b82811115611950578251825591602001919060010190611935565b5061195c929150611960565b5090565b5b8082111561195c576000815560010161196156fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f20616464726573735f73657450656e64696e674f776e65723a204e6577206f77656e722063616e206e6f74206265207a65726f206164647265737320616e64206f776e657220686173206265656e207365742145524332303a20617070726f766520746f20746865207a65726f20616464726573735f72656d6f76654d696e7465723a205f6d696e74657220746865207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65646f6e6c794f776e65723a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735f6164644d696e7465723a205f6d696e74657220746865207a65726f20616464726573735f6163636570744f776e65723a204f6e6c7920666f722070656e64696e67206f776e657221a2646970667358221220e4fcf12e6c2347a91f1f7a1a55c126363adf4032ec10a644249c6a3080b5265764736f6c634300060c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"istanbul","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0xE3ec7De9375bFc22F4481C4605431d67ED5Bd260/","decoded_constructor_args":null,"compiler_version":"0.6.12+commit.27d51765","is_verified_via_verifier_alliance":false,"verified_at":"2024-11-28T15:21:23.440902Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x608060405234801561001057600080fd5b50611b87806100206000396000f3fe608060405234801561001057600080fd5b50600436106101735760003560e01c80636b32810b116100de5780639dc29fac11610097578063d505accf11610071578063d505accf14610605578063dd62ed3e14610656578063e30c397814610684578063fc4d33f91461068c57610173565b80639dc29fac14610581578063a457c2d7146105ad578063a9059cbb146105d957610173565b80636b32810b1461048b5780636e96dfd7146104e357806370a08231146105095780637ecebe001461052f5780638da5cb5b1461055557806395d89b411461057957610173565b806323b872dd1161013057806323b872dd146103cf57806330adf81f14610405578063313ce5671461040d5780633644e5151461042b578063395093511461043357806340c10f191461045f57610173565b806303c7bce11461017857806306fdde03146101a0578063095ea7b31461021d5780631624f6c61461025d57806318160ddd1461038f578063210c5a56146103a9575b600080fd5b61019e6004803603602081101561018e57600080fd5b50356001600160a01b0316610694565b005b6101a8610777565b6040805160208082528351818301528351919283929083019185019080838360005b838110156101e25781810151838201526020016101ca565b50505050905090810190601f16801561020f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6102496004803603604081101561023357600080fd5b506001600160a01b038135169060200135610805565b604080519115158252519081900360200190f35b61019e6004803603606081101561027357600080fd5b81019060208101813564010000000081111561028e57600080fd5b8201836020820111156102a057600080fd5b803590602001918460018302840111640100000000831117156102c257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929594936020810193503591505064010000000081111561031557600080fd5b82018360208201111561032757600080fd5b8035906020019184600183028401116401000000008311171561034957600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295505050903560ff16915061081c9050565b610397610919565b60408051918252519081900360200190f35b61019e600480360360208110156103bf57600080fd5b50356001600160a01b031661091f565b610249600480360360608110156103e557600080fd5b506001600160a01b03813581169160208101359091169060400135610a01565b610397610a52565b610415610a76565b6040805160ff9092168252519081900360200190f35b610397610a7f565b6102496004803603604081101561044957600080fd5b506001600160a01b038135169060200135610a85565b61019e6004803603604081101561047557600080fd5b506001600160a01b038135169060200135610abb565b610493610b25565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156104cf5781810151838201526020016104b7565b505050509050019250505060405180910390f35b61019e600480360360208110156104f957600080fd5b50356001600160a01b0316610bc0565b6103976004803603602081101561051f57600080fd5b50356001600160a01b0316610cc1565b6103976004803603602081101561054557600080fd5b50356001600160a01b0316610cd3565b61055d610ce5565b604080516001600160a01b039092168252519081900360200190f35b6101a8610cf9565b61019e6004803603604081101561059757600080fd5b506001600160a01b038135169060200135610d54565b610249600480360360408110156105c357600080fd5b506001600160a01b038135169060200135610d5e565b610249600480360360408110156105ef57600080fd5b506001600160a01b038135169060200135610d94565b61019e600480360360e081101561061b57600080fd5b506001600160a01b03813581169160208101359091169060408101359060608101359060ff6080820135169060a08101359060c00135610da1565b6103976004803603604081101561066c57600080fd5b506001600160a01b0381358116916020013516610fe4565b61055d611001565b61019e611010565b60005461010090046001600160a01b031633146106e25760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b0381166107275760405162461bcd60e51b8152600401808060200182810382526024815260200180611b096024913960400191505060405180910390fd5b610732606e82611107565b1561077457604080516001600160a01b038316815290517f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f69181900360200190a15b50565b6037805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107fd5780601f106107d2576101008083540402835291602001916107fd565b820191906000526020600020905b8154815290600101906020018083116107e057829003601f168201915b505050505081565b6000610812338484611123565b5060015b92915050565b60005460ff161561085e5760405162461bcd60e51b815260040180806020018281038252602e815260200180611a4f602e913960400191505060405180910390fd5b61086661120f565b610871838383611257565b7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8380519060200120604051806040016040528060018152602001603160f81b815250805190602001206108c3611297565b6040805160208082019690965280820194909452606084019290925260808301523060a0808401919091528151808403909101815260c090920190528051910120606c5550506000805460ff1916600117905550565b60365481565b60005461010090046001600160a01b0316331461096d5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b0381166109b25760405162461bcd60e51b8152600401808060200182810382526027815260200180611a286027913960400191505060405180910390fd5b6109bd606e8261129b565b1561077457604080516001600160a01b038316815290517fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb666929181900360200190a150565b6000610a0e8484846112b0565b6001600160a01b038416600090815260356020908152604080832033808552925290912054610a48918691610a4390866113e8565b611123565b5060019392505050565b7f576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf81565b60395460ff1681565b606c5481565b3360008181526035602090815260408083206001600160a01b03871684529091528120549091610812918590610a43908661142a565b610ac6606e33611484565b610b17576040805162461bcd60e51b815260206004820181905260248201527f6f6e6c794d696e7465723a2063616c6c6572206973206e6f74206d696e746572604482015290519081900360640190fd5b610b218282611499565b5050565b60606000610b33606e61157f565b90508067ffffffffffffffff81118015610b4c57600080fd5b50604051908082528060200260200182016040528015610b76578160200160208202803683370190505b50915060005b81811015610bbb57610b8f606e8261158a565b838281518110610b9b57fe5b6001600160a01b0390921660209283029190910190910152600101610b7c565b505090565b60005461010090046001600160a01b03163314610c0e5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a7d6022913960400191505060405180910390fd5b6001600160a01b03811615801590610c3457506001546001600160a01b03828116911614155b610c6f5760405162461bcd60e51b815260040180806020018281038252604b8152602001806119bb604b913960600191505060405180910390fd5b600180546001600160a01b038381166001600160a01b0319831681179093556040519116919082907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b60346020526000908152604090205481565b606d6020526000908152604090205481565b60005461010090046001600160a01b031681565b6038805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156107fd5780601f106107d2576101008083540402835291602001916107fd565b610b218282611596565b3360008181526035602090815260408083206001600160a01b03871684529091528120549091610812918590610a4390866113e8565b60006108123384846112b0565b42841015610de9576040805162461bcd60e51b815260206004820152601060248201526f7065726d69743a20455850495245442160801b604482015290519081900360640190fd5b6001600160a01b0387166000908152606d6020526040812054606c549091907f576144ed657c8304561e56ca632e17751956250114636e8c01f64a7f2c6d98cf8a8a610e33611297565b604080516020808201969096526001600160a01b0394851681830152929093166060830152608082015260a081018b905260c0810186905260e08082018b9052825180830390910181526101008201835280519084012061190160f01b61012083015261012282019490945261014280820194909452815180820390940184526101628101808352845194840194909420600094859052610182820180845281905260ff8a166101a28301526101c282018990526101e282018890529151919450600192610202808301939192601f198301929081900390910190855afa158015610f22573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811615801590610f585750896001600160a01b0316816001600160a01b0316145b610fa9576040805162461bcd60e51b815260206004820152601a60248201527f7065726d69743a20494e56414c49445f5349474e415455524521000000000000604482015290519081900360640190fd5b610fb483600161142a565b6001600160a01b038b166000908152606d6020526040902055610fd88a8a8a611123565b50505050505050505050565b603560209081526000928352604080842090915290825290205481565b6001546001600160a01b031681565b6001546001600160a01b031633146110595760405162461bcd60e51b8152600401808060200182810382526025815260200180611b2d6025913960400191505060405180910390fd5b60008054600180546001600160a01b03818116610100818102610100600160a81b03198716178088556001600160a01b031990941690945560405194849004821695909493909204169184917f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b236491a36001546040516001600160a01b03918216918316907fb3d55174552271a4f1aaf36b72f50381e892171636b3fb5447fe00e995e7a37b90600090a35050565b600061111c836001600160a01b0384166115e5565b9392505050565b6001600160a01b0383166111685760405162461bcd60e51b8152600401808060200182810382526024815260200180611ae56024913960400191505060405180910390fd5b6001600160a01b0382166111ad5760405162461bcd60e51b8152600401808060200182810382526022815260200180611a066022913960400191505060405180910390fd5b6001600160a01b03808416600081815260356020908152604080832094871680845294825291829020859055815185815291517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9259281900390910190a3505050565b60008054610100600160a81b0319163361010081029190911782556040519091907f70aea8d848e8a90fb7661b227dc522eb6395c3dac71b63cb59edd5c9899b2364908290a3565b825161126a9060379060208601906118e2565b50815161127e9060389060208501906118e2565b506039805460ff191660ff929092169190911790555050565b4690565b600061111c836001600160a01b03841661162f565b6001600160a01b0383166112f55760405162461bcd60e51b8152600401808060200182810382526025815260200180611ac06025913960400191505060405180910390fd5b6001600160a01b03821661133a5760405162461bcd60e51b81526004018080602001828103825260238152602001806119986023913960400191505060405180910390fd5b6001600160a01b03831660009081526034602052604090205461135d90826113e8565b6001600160a01b03808516600090815260346020526040808220939093559084168152205461138c908261142a565b6001600160a01b0380841660008181526034602090815260409182902094909455805185815290519193928716927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92918290030190a3505050565b600061111c83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506116f5565b60008282018381101561111c576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b600061111c836001600160a01b03841661178c565b6001600160a01b0382166114f4576040805162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604482015290519081900360640190fd5b603654611501908261142a565b6036556001600160a01b038216600090815260346020526040902054611527908261142a565b6001600160a01b03831660008181526034602090815260408083209490945583518581529351929391927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9281900390910190a35050565b6000610816826117a4565b600061111c83836117a8565b336001600160a01b038316146115db576001600160a01b0382166000908152603560209081526040808320338085529252909120546115db918491610a4390856113e8565b610b21828261180c565b60006115f1838361178c565b61162757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610816565b506000610816565b600081815260018301602052604081205480156116eb578354600019808301919081019060009087908390811061166257fe5b906000526020600020015490508087600001848154811061167f57fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806116af57fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050610816565b6000915050610816565b600081848411156117845760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b83811015611749578181015183820152602001611731565b50505050905090810190601f1680156117765780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b505050900390565b60009081526001919091016020526040902054151590565b5490565b815460009082106117ea5760405162461bcd60e51b81526004018080602001828103825260228152602001806119766022913960400191505060405180910390fd5b8260000182815481106117f957fe5b9060005260206000200154905092915050565b6001600160a01b0382166118515760405162461bcd60e51b8152600401808060200182810382526021815260200180611a9f6021913960400191505060405180910390fd5b6001600160a01b03821660009081526034602052604090205461187490826113e8565b6001600160a01b03831660009081526034602052604090205560365461189a90826113e8565b6036556040805182815290516000916001600160a01b038516917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9181900360200190a35050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f1061192357805160ff1916838001178555611950565b82800160010185558215611950579182015b82811115611950578251825591602001919060010190611935565b5061195c929150611960565b5090565b5b8082111561195c576000815560010161196156fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e647345524332303a207472616e7366657220746f20746865207a65726f20616464726573735f73657450656e64696e674f776e65723a204e6577206f77656e722063616e206e6f74206265207a65726f206164647265737320616e64206f776e657220686173206265656e207365742145524332303a20617070726f766520746f20746865207a65726f20616464726573735f72656d6f76654d696e7465723a205f6d696e74657220746865207a65726f2061646472657373496e697469616c697a61626c653a20636f6e747261637420697320616c726561647920696e697469616c697a65646f6e6c794f776e65723a2063616c6c6572206973206e6f7420746865206f776e657245524332303a206275726e2066726f6d20746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f20616464726573735f6164644d696e7465723a205f6d696e74657220746865207a65726f20616464726573735f6163636570744f776e65723a204f6e6c7920666f722070656e64696e67206f776e657221a2646970667358221220e4fcf12e6c2347a91f1f7a1a55c126363adf4032ec10a644249c6a3080b5265764736f6c634300060c0033","name":"MSD","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"istanbul","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMathUpgradeable {\n    /**\n     * @dev Returns the addition of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `+` operator.\n     *\n     * Requirements:\n     *\n     * - Addition cannot overflow.\n     */\n    function add(uint256 a, uint256 b) internal pure returns (uint256) {\n        uint256 c = a + b;\n        require(c >= a, \"SafeMath: addition overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n        return sub(a, b, \"SafeMath: subtraction overflow\");\n    }\n\n    /**\n     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n     * overflow (when the result is negative).\n     *\n     * Counterpart to Solidity's `-` operator.\n     *\n     * Requirements:\n     *\n     * - Subtraction cannot overflow.\n     */\n    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b <= a, errorMessage);\n        uint256 c = a - b;\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the multiplication of two unsigned integers, reverting on\n     * overflow.\n     *\n     * Counterpart to Solidity's `*` operator.\n     *\n     * Requirements:\n     *\n     * - Multiplication cannot overflow.\n     */\n    function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n        // benefit is lost if 'b' is also tested.\n        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n        if (a == 0) {\n            return 0;\n        }\n\n        uint256 c = a * b;\n        require(c / a == b, \"SafeMath: multiplication overflow\");\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b) internal pure returns (uint256) {\n        return div(a, b, \"SafeMath: division by zero\");\n    }\n\n    /**\n     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n     * division by zero. The result is rounded towards zero.\n     *\n     * Counterpart to Solidity's `/` operator. Note: this function uses a\n     * `revert` opcode (which leaves remaining gas untouched) while Solidity\n     * uses an invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b > 0, errorMessage);\n        uint256 c = a / b;\n        // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n        return c;\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n        return mod(a, b, \"SafeMath: modulo by zero\");\n    }\n\n    /**\n     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n     * Reverts with custom message when dividing by zero.\n     *\n     * Counterpart to Solidity's `%` operator. This function uses a `revert`\n     * opcode (which leaves remaining gas untouched) while Solidity uses an\n     * invalid opcode to revert (consuming all remaining gas).\n     *\n     * Requirements:\n     *\n     * - The divisor cannot be zero.\n     */\n    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n        require(b != 0, errorMessage);\n        return a % b;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts-upgradeable/utils/EnumerableSetUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity >=0.6.0 <0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n *     // Add the library methods\n *     using EnumerableSet for EnumerableSet.AddressSet;\n *\n *     // Declare a set state variable\n *     EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n */\nlibrary EnumerableSetUpgradeable {\n    // To implement this library for multiple types with as little code\n    // repetition as possible, we write it in terms of a generic Set type with\n    // bytes32 values.\n    // The Set implementation uses private functions, and user-facing\n    // implementations (such as AddressSet) are just wrappers around the\n    // underlying Set.\n    // This means that we can only create new EnumerableSets for types that fit\n    // in bytes32.\n\n    struct Set {\n        // Storage of set values\n        bytes32[] _values;\n\n        // Position of the value in the `values` array, plus 1 because index 0\n        // means a value is not in the set.\n        mapping (bytes32 => uint256) _indexes;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function _add(Set storage set, bytes32 value) private returns (bool) {\n        if (!_contains(set, value)) {\n            set._values.push(value);\n            // The value is stored at length-1, but we add 1 to all indexes\n            // and use 0 as a sentinel value\n            set._indexes[value] = set._values.length;\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function _remove(Set storage set, bytes32 value) private returns (bool) {\n        // We read and store the value's index to prevent multiple reads from the same storage slot\n        uint256 valueIndex = set._indexes[value];\n\n        if (valueIndex != 0) { // Equivalent to contains(set, value)\n            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n            // the array, and then remove the last element (sometimes called as 'swap and pop').\n            // This modifies the order of the array, as noted in {at}.\n\n            uint256 toDeleteIndex = valueIndex - 1;\n            uint256 lastIndex = set._values.length - 1;\n\n            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs\n            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.\n\n            bytes32 lastvalue = set._values[lastIndex];\n\n            // Move the last value to the index where the value to delete is\n            set._values[toDeleteIndex] = lastvalue;\n            // Update the index for the moved value\n            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based\n\n            // Delete the slot where the moved value was stored\n            set._values.pop();\n\n            // Delete the index for the deleted slot\n            delete set._indexes[value];\n\n            return true;\n        } else {\n            return false;\n        }\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function _contains(Set storage set, bytes32 value) private view returns (bool) {\n        return set._indexes[value] != 0;\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function _length(Set storage set) private view returns (uint256) {\n        return set._values.length;\n    }\n\n   /**\n    * @dev Returns the value stored at position `index` in the set. O(1).\n    *\n    * Note that there are no guarantees on the ordering of values inside the\n    * array, and it may change when more values are added or removed.\n    *\n    * Requirements:\n    *\n    * - `index` must be strictly less than {length}.\n    */\n    function _at(Set storage set, uint256 index) private view returns (bytes32) {\n        require(set._values.length > index, \"EnumerableSet: index out of bounds\");\n        return set._values[index];\n    }\n\n    // Bytes32Set\n\n    struct Bytes32Set {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _add(set._inner, value);\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n        return _remove(set._inner, value);\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n        return _contains(set._inner, value);\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(Bytes32Set storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n   /**\n    * @dev Returns the value stored at position `index` in the set. O(1).\n    *\n    * Note that there are no guarantees on the ordering of values inside the\n    * array, and it may change when more values are added or removed.\n    *\n    * Requirements:\n    *\n    * - `index` must be strictly less than {length}.\n    */\n    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n        return _at(set._inner, index);\n    }\n\n    // AddressSet\n\n    struct AddressSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(AddressSet storage set, address value) internal returns (bool) {\n        return _add(set._inner, bytes32(uint256(value)));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(AddressSet storage set, address value) internal returns (bool) {\n        return _remove(set._inner, bytes32(uint256(value)));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(AddressSet storage set, address value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(uint256(value)));\n    }\n\n    /**\n     * @dev Returns the number of values in the set. O(1).\n     */\n    function length(AddressSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n   /**\n    * @dev Returns the value stored at position `index` in the set. O(1).\n    *\n    * Note that there are no guarantees on the ordering of values inside the\n    * array, and it may change when more values are added or removed.\n    *\n    * Requirements:\n    *\n    * - `index` must be strictly less than {length}.\n    */\n    function at(AddressSet storage set, uint256 index) internal view returns (address) {\n        return address(uint256(_at(set._inner, index)));\n    }\n\n\n    // UintSet\n\n    struct UintSet {\n        Set _inner;\n    }\n\n    /**\n     * @dev Add a value to a set. O(1).\n     *\n     * Returns true if the value was added to the set, that is if it was not\n     * already present.\n     */\n    function add(UintSet storage set, uint256 value) internal returns (bool) {\n        return _add(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Removes a value from a set. O(1).\n     *\n     * Returns true if the value was removed from the set, that is if it was\n     * present.\n     */\n    function remove(UintSet storage set, uint256 value) internal returns (bool) {\n        return _remove(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns true if the value is in the set. O(1).\n     */\n    function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n        return _contains(set._inner, bytes32(value));\n    }\n\n    /**\n     * @dev Returns the number of values on the set. O(1).\n     */\n    function length(UintSet storage set) internal view returns (uint256) {\n        return _length(set._inner);\n    }\n\n   /**\n    * @dev Returns the value stored at position `index` in the set. O(1).\n    *\n    * Note that there are no guarantees on the ordering of values inside the\n    * array, and it may change when more values are added or removed.\n    *\n    * Requirements:\n    *\n    * - `index` must be strictly less than {length}.\n    */\n    function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n        return uint256(_at(set._inner, index));\n    }\n}\n"},{"file_path":"contracts/library/ERC20.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\nimport \"@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.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 guidelines: functions revert instead\n * of returning `false` on failure. This behavior is nonetheless conventional\n * and does not conflict with the expectations of ERC20 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 {\n    using SafeMathUpgradeable for uint256;\n\n    mapping(address => uint256) public balanceOf;\n    mapping(address => mapping(address => uint256)) public allowance;\n    uint256 public totalSupply;\n\n    string public name;\n    string public symbol;\n    uint8 public decimals;\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(\n        address indexed owner,\n        address indexed spender,\n        uint256 value\n    );\n\n    /**\n     * @dev Sets the values for {name} and {symbol}, initializes {decimals} with\n     * a default value of 18.\n     *\n     * To select a different value for {decimals}, use {_setupDecimals}.\n     *\n     * All three of these values are immutable: they can only be set once during\n     * construction.\n     */\n    function __ERC20_init(\n        string memory name_,\n        string memory symbol_,\n        uint8 decimals_\n    ) internal {\n        name = name_;\n        symbol = symbol_;\n        decimals = decimals_;\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)\n        public\n        virtual\n        returns (bool)\n    {\n        _transfer(msg.sender, recipient, amount);\n        return true;\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)\n        public\n        virtual\n        returns (bool)\n    {\n        _approve(msg.sender, 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 returns (bool) {\n        _transfer(sender, recipient, amount);\n        _approve(sender, msg.sender, allowance[sender][msg.sender].sub(amount));\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)\n        public\n        virtual\n        returns (bool)\n    {\n        _approve(\n            msg.sender,\n            spender,\n            allowance[msg.sender][spender].add(addedValue)\n        );\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)\n        public\n        virtual\n        returns (bool)\n    {\n        _approve(\n            msg.sender,\n            spender,\n            allowance[msg.sender][spender].sub(subtractedValue)\n        );\n        return true;\n    }\n\n    /**\n     * @dev Moves tokens `amount` from `sender` to `recipient`.\n     *\n     * This is 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        balanceOf[sender] = balanceOf[sender].sub(amount);\n        balanceOf[recipient] = balanceOf[recipient].add(amount);\n        emit Transfer(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     * - `to` 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        totalSupply = totalSupply.add(amount);\n        balanceOf[account] = balanceOf[account].add(amount);\n        emit Transfer(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        balanceOf[account] = balanceOf[account].sub(amount);\n        totalSupply = totalSupply.sub(amount);\n        emit Transfer(account, address(0), amount);\n    }\n\n    /**\n     * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n     * allowance if caller is not the `account`.\n     *\n     * See {ERC20-_burn} and {ERC20-allowance}.\n     *\n     * Requirements:\n     *\n     * - the caller other than `msg.sender` must have allowance for ``accounts``'s tokens of at least\n     * `amount`.\n     */\n    function _burnFrom(address account, uint256 amount) internal virtual {\n        if (msg.sender != account)\n            _approve(\n                account,\n                msg.sender,\n                allowance[account][msg.sender].sub(amount)\n            );\n\n        _burn(account, 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        allowance[owner][spender] = amount;\n        emit Approval(owner, spender, amount);\n    }\n\n    uint256[50] private __gap;\n}\n"},{"file_path":"contracts/library/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {UpgradeableProxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     */\n    bool private _initialized;\n\n    /**\n     * @dev Modifier to protect an initializer function from being invoked twice.\n     */\n    modifier initializer() {\n        require(\n            !_initialized,\n            \"Initializable: contract is already initialized\"\n        );\n\n        _;\n\n        _initialized = true;\n    }\n}\n"},{"file_path":"contracts/library/Ownable.sol","source_code":"//SPDX-License-Identifier: MIT\npragma solidity 0.6.12;\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 {_setPendingOwner} and {_acceptOwner}.\n */\ncontract Ownable {\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    address payable public owner;\n\n    /**\n     * @dev Returns the address of the current pending owner.\n     */\n    address payable public pendingOwner;\n\n    event NewOwner(address indexed previousOwner, address indexed newOwner);\n    event NewPendingOwner(\n        address indexed oldPendingOwner,\n        address indexed newPendingOwner\n    );\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner == msg.sender, \"onlyOwner: caller is not the owner\");\n        _;\n    }\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    function __Ownable_init() internal {\n        owner = msg.sender;\n        emit NewOwner(address(0), msg.sender);\n    }\n\n    /**\n     * @notice Base on the inputing parameter `newPendingOwner` to check the exact error reason.\n     * @dev Transfer contract control to a new owner. The newPendingOwner must call `_acceptOwner` to finish the transfer.\n     * @param newPendingOwner New pending owner.\n     */\n    function _setPendingOwner(address payable newPendingOwner)\n        external\n        onlyOwner\n    {\n        require(\n            newPendingOwner != address(0) && newPendingOwner != pendingOwner,\n            \"_setPendingOwner: New owenr can not be zero address and owner has been set!\"\n        );\n\n        // Gets current owner.\n        address oldPendingOwner = pendingOwner;\n\n        // Sets new pending owner.\n        pendingOwner = newPendingOwner;\n\n        emit NewPendingOwner(oldPendingOwner, newPendingOwner);\n    }\n\n    /**\n     * @dev Accepts the admin rights, but only for pendingOwenr.\n     */\n    function _acceptOwner() external {\n        require(\n            msg.sender == pendingOwner,\n            \"_acceptOwner: Only for pending owner!\"\n        );\n\n        // Gets current values for events.\n        address oldOwner = owner;\n        address oldPendingOwner = pendingOwner;\n\n        // Set the new contract owner.\n        owner = pendingOwner;\n\n        // Clear the pendingOwner.\n        pendingOwner = address(0);\n\n        emit NewOwner(oldOwner, owner);\n        emit NewPendingOwner(oldPendingOwner, pendingOwner);\n    }\n\n    uint256[50] private __gap;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"}],"name":"MinterAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"}],"name":"MinterRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"_acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"_addMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"}],"name":"_removeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"newPendingOwner","type":"address"}],"name":"_setPendingOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getMinters","outputs":[{"internalType":"address[]","name":"_minters","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_decimals","type":"uint8"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_spender","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"},{"internalType":"uint8","name":"_v","type":"uint8"},{"internalType":"bytes32","name":"_r","type":"bytes32"},{"internalType":"bytes32","name":"_s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}