{"file_path":"contracts/Bridge.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"./libraries/PbBridge.sol\";\nimport \"./Pool.sol\";\n\ncontract Bridge is Pool {\n    using SafeERC20 for IERC20;\n\n    // liquidity events\n    event Send(\n        bytes32 transferId,\n        address sender,\n        address receiver,\n        address token,\n        uint256 amount,\n        uint64 dstChainId,\n        uint64 nonce,\n        uint32 maxSlippage\n    );\n    event Relay(\n        bytes32 transferId,\n        address sender,\n        address receiver,\n        address token,\n        uint256 amount,\n        uint64 srcChainId,\n        bytes32 srcTransferId\n    );\n    // gov events\n    event MinSendUpdated(address token, uint256 amount);\n    event MaxSendUpdated(address token, uint256 amount);\n\n    mapping(bytes32 => bool) public transfers;\n    mapping(address => uint256) public minSend; // send _amount must > minSend\n    mapping(address => uint256) public maxSend;\n\n    // min allowed max slippage uint32 value is slippage * 1M, eg. 0.5% -> 5000\n    uint32 public minimalMaxSlippage;\n\n    function send(\n        address _receiver,\n        address _token,\n        uint256 _amount,\n        uint64 _dstChainId,\n        uint64 _nonce,\n        uint32 _maxSlippage // slippage * 1M, eg. 0.5% -> 5000\n    ) external nonReentrant whenNotPaused {\n        bytes32 transferId = _send(_receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\n        IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n        emit Send(transferId, msg.sender, _receiver, _token, _amount, _dstChainId, _nonce, _maxSlippage);\n    }\n\n    function sendNative(\n        address _receiver,\n        uint256 _amount,\n        uint64 _dstChainId,\n        uint64 _nonce,\n        uint32 _maxSlippage\n    ) external payable nonReentrant whenNotPaused {\n        require(msg.value == _amount, \"Amount mismatch\");\n        require(nativeWrap != address(0), \"Native wrap not set\");\n        bytes32 transferId = _send(_receiver, nativeWrap, _amount, _dstChainId, _nonce, _maxSlippage);\n        IWETH(nativeWrap).deposit{value: _amount}();\n        emit Send(transferId, msg.sender, _receiver, nativeWrap, _amount, _dstChainId, _nonce, _maxSlippage);\n    }\n\n    function _send(\n        address _receiver,\n        address _token,\n        uint256 _amount,\n        uint64 _dstChainId,\n        uint64 _nonce,\n        uint32 _maxSlippage\n    ) private returns (bytes32) {\n        require(_amount > minSend[_token], \"amount too small\");\n        require(maxSend[_token] == 0 || _amount <= maxSend[_token], \"amount too large\");\n        require(_maxSlippage > minimalMaxSlippage, \"max slippage too small\");\n        bytes32 transferId = keccak256(\n            // uint64(block.chainid) for consistency as entire system uses uint64 for chain id\n            abi.encodePacked(msg.sender, _receiver, _token, _amount, _dstChainId, _nonce, uint64(block.chainid))\n        );\n        require(transfers[transferId] == false, \"transfer exists\");\n        transfers[transferId] = true;\n        return transferId;\n    }\n\n    function relay(\n        bytes calldata _relayRequest,\n        bytes[] calldata _sigs,\n        address[] calldata _signers,\n        uint256[] calldata _powers\n    ) external whenNotPaused {\n        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), \"Relay\"));\n        verifySigs(abi.encodePacked(domain, _relayRequest), _sigs, _signers, _powers);\n        PbBridge.Relay memory request = PbBridge.decRelay(_relayRequest);\n        bytes32 transferId = keccak256(\n            abi.encodePacked(\n                request.sender,\n                request.receiver,\n                request.token,\n                request.amount,\n                request.srcChainId,\n                request.dstChainId,\n                request.srcTransferId\n            )\n        );\n        require(transfers[transferId] == false, \"transfer exists\");\n        transfers[transferId] = true;\n        _updateVolume(request.token, request.amount);\n        uint256 delayThreshold = delayThresholds[request.token];\n        if (delayThreshold > 0 && request.amount > delayThreshold) {\n            _addDelayedTransfer(transferId, request.receiver, request.token, request.amount);\n        } else {\n            _sendToken(request.receiver, request.token, request.amount);\n        }\n\n        emit Relay(\n            transferId,\n            request.sender,\n            request.receiver,\n            request.token,\n            request.amount,\n            request.srcChainId,\n            request.srcTransferId\n        );\n    }\n\n    function setMinSend(address[] calldata _tokens, uint256[] calldata _amounts) external onlyGovernor {\n        require(_tokens.length == _amounts.length, \"length mismatch\");\n        for (uint256 i = 0; i < _tokens.length; i++) {\n            minSend[_tokens[i]] = _amounts[i];\n            emit MinSendUpdated(_tokens[i], _amounts[i]);\n        }\n    }\n\n    function setMaxSend(address[] calldata _tokens, uint256[] calldata _amounts) external onlyGovernor {\n        require(_tokens.length == _amounts.length, \"length mismatch\");\n        for (uint256 i = 0; i < _tokens.length; i++) {\n            maxSend[_tokens[i]] = _amounts[i];\n            emit MaxSendUpdated(_tokens[i], _amounts[i]);\n        }\n    }\n\n    function setMinimalMaxSlippage(uint32 _minimalMaxSlippage) external onlyGovernor {\n        minimalMaxSlippage = _minimalMaxSlippage;\n    }\n\n    // This is needed to receive ETH when calling `IWETH.withdraw`\n    receive() external payable {}\n}\n","deployed_bytecode":"0x60806040526004361061036f5760003560e01c806382dc1ec4116101c6578063ba2cb25c116100f7578063e43581b811610095578063f20c922a1161006f578063f20c922a14610acf578063f2fde38b14610aef578063f832138314610b0f578063f8b30d7d14610b3c57600080fd5b8063e43581b814610a56578063e999e5f414610a8f578063eecdac8814610aaf57600080fd5b8063d0790da9116100d1578063d0790da9146109cb578063e026049c146109e1578063e09ab428146109f6578063e3eece2614610a2657600080fd5b8063ba2cb25c1461095e578063ccde517a1461097e578063cdd1b25d146109ab57600080fd5b80639ff9001a11610164578063a7bdf45a1161013e578063a7bdf45a14610881578063adc0d57f146108a1578063b1c94d941461091b578063b5f2bc471461093157600080fd5b80639ff9001a14610821578063a21a928014610841578063a5977fbb1461086157600080fd5b806389e39127116101a057806389e39127146107935780638da5cb5b146107cd5780639b14d4c6146107eb5780639e25fc5c1461080157600080fd5b806382dc1ec41461073e5780638456cb591461075e578063878fe1ce1461077357600080fd5b806352532faa116102a057806365a114f11161023e5780636ef8d66d116102185780636ef8d66d146106d15780637044c89e146106e6578063715018a6146106f957806380f51c121461070e57600080fd5b806365a114f11461067b578063682dbc22146106915780636b2c0f55146106b157600080fd5b806357d775f81161027a57806357d775f8146105f35780635c975abb1461060957806360216b0014610621578063618ee0551461064e57600080fd5b806352532faa1461058657806354eea796146105b357806356688700146105d357600080fd5b80633d5721071161030d578063457bfa2f116102e7578063457bfa2f146104d557806346fbf68e1461050d57806347b16c6c14610546578063482341261461056657600080fd5b80633d5721071461048d5780633f2e5fc3146104ad5780633f4ba83a146104c057600080fd5b80632fd1b0a4116103495780632fd1b0a4146103d2578063370fb47b146104095780633c4a25d01461042d5780633c64f04b1461044d57600080fd5b8063089927411461037b57806317bdbae51461039d57806325c38b9f146103bd57600080fd5b3661037657005b600080fd5b34801561038757600080fd5b5061039b6103963660046147b9565b610b69565b005b3480156103a957600080fd5b5061039b6103b83660046147b9565b610d0c565b3480156103c957600080fd5b5061039b610ea3565b3480156103de57600080fd5b506017546103ef9063ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b34801561041557600080fd5b5061041f60025481565b604051908152602001610400565b34801561043957600080fd5b5061039b610448366004614841565b610f33565b34801561045957600080fd5b5061047d61046836600461485c565b60146020526000908152604090205460ff1681565b6040519015158152602001610400565b34801561049957600080fd5b5061039b6104a836600461485c565b610f87565b61039b6104bb3660046148a1565b61101b565b3480156104cc57600080fd5b5061039b611271565b3480156104e157600080fd5b506013546104f5906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b34801561051957600080fd5b5061047d610528366004614841565b6001600160a01b031660009081526007602052604090205460ff1690565b34801561055257600080fd5b5061039b6105613660046147b9565b6112da565b34801561057257600080fd5b5061039b6105813660046148ff565b611471565b34801561059257600080fd5b5061041f6105a1366004614841565b600e6020526000908152604090205481565b3480156105bf57600080fd5b5061039b6105ce36600461485c565b6114e5565b3480156105df57600080fd5b5061039b6105ee36600461491a565b611572565b3480156105ff57600080fd5b5061041f60095481565b34801561061557600080fd5b5060065460ff1661047d565b34801561062d57600080fd5b5061041f61063c366004614841565b600a6020526000908152604090205481565b34801561065a57600080fd5b5061041f610669366004614841565b60166020526000908152604090205481565b34801561068757600080fd5b5061041f60035481565b34801561069d57600080fd5b5061039b6106ac36600461495a565b611734565b3480156106bd57600080fd5b5061039b6106cc366004614841565b611820565b3480156106dd57600080fd5b5061039b611871565b61039b6106f436600461485c565b61187a565b34801561070557600080fd5b5061039b611b2c565b34801561071a57600080fd5b5061047d610729366004614841565b60076020526000908152604090205460ff1681565b34801561074a57600080fd5b5061039b610759366004614841565b611b7e565b34801561076a57600080fd5b5061039b611bcf565b34801561077f57600080fd5b5061039b61078e3660046147b9565b611c36565b34801561079f57600080fd5b506010546107b49067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610400565b3480156107d957600080fd5b506000546001600160a01b03166104f5565b3480156107f757600080fd5b5061041f60045481565b34801561080d57600080fd5b5061039b61081c36600461485c565b611dcd565b34801561082d57600080fd5b5061039b61083c366004614841565b611e3b565b34801561084d57600080fd5b5061039b61085c366004614a88565b611ea5565b34801561086d57600080fd5b5061039b61087c366004614b77565b6121ec565b34801561088d57600080fd5b5061039b61089c3660046147b9565b61233a565b3480156108ad57600080fd5b506108f06108bc36600461485c565b600d6020526000908152604090208054600182015460028301546003909301546001600160a01b0392831693919092169184565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610400565b34801561092757600080fd5b5061041f600f5481565b34801561093d57600080fd5b5061041f61094c366004614841565b600b6020526000908152604090205481565b34801561096a57600080fd5b5061039b610979366004614be4565b6123eb565b34801561098a57600080fd5b5061041f610999366004614841565b60116020526000908152604090205481565b3480156109b757600080fd5b5061039b6109c6366004614a88565b612541565b3480156109d757600080fd5b5061041f60015481565b3480156109ed57600080fd5b5061039b612866565b348015610a0257600080fd5b5061047d610a1136600461485c565b60126020526000908152604090205460ff1681565b348015610a3257600080fd5b5061047d610a41366004614841565b60086020526000908152604090205460ff1681565b348015610a6257600080fd5b5061047d610a71366004614841565b6001600160a01b031660009081526008602052604090205460ff1690565b348015610a9b57600080fd5b5061039b610aaa3660046147b9565b61286f565b348015610abb57600080fd5b5061039b610aca366004614841565b612a06565b348015610adb57600080fd5b5061039b610aea36600461485c565b612a57565b348015610afb57600080fd5b5061039b610b0a366004614841565b612b01565b348015610b1b57600080fd5b5061041f610b2a366004614841565b600c6020526000908152604090205481565b348015610b4857600080fd5b5061041f610b57366004614841565b60156020526000908152604090205481565b3360009081526008602052604090205460ff16610bc65760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b60448201526064015b60405180910390fd5b828114610c075760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110610c2457610c24614ce4565b9050602002013560156000878785818110610c4157610c41614ce4565b9050602002016020810190610c569190614841565b6001600160a01b031681526020810191909152604001600020557f8b59d386e660418a48d742213ad5ce7c4dd51ae81f30e4e2c387f17d907010c9858583818110610ca357610ca3614ce4565b9050602002016020810190610cb89190614841565b848484818110610cca57610cca614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180610cfd81614d10565b915050610c0a565b5050505050565b3360009081526008602052604090205460ff16610d645760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b828114610da55760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110610dc257610dc2614ce4565b90506020020135600e6000878785818110610ddf57610ddf614ce4565b9050602002016020810190610df49190614841565b6001600160a01b031681526020810191909152604001600020557fceaad6533bfb481492fb3e08ef19297f46611b8fa9de5ef4cf8dc23a56ad09ce858583818110610e4157610e41614ce4565b9050602002016020810190610e569190614841565b848484818110610e6857610e68614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180610e9b81614d10565b915050610da8565b6000546001600160a01b03163314610eeb5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b600454610ef89042614d2b565b60038190556040519081527f68e825132f7d4bc837dea2d64ac9fc19912bf0224b67f9317d8f1a917f5304a1906020015b60405180910390a1565b6000546001600160a01b03163314610f7b5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481612bce565b50565b3360009081526008602052604090205460ff16610fdf5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b600f8190556040518181527fc0a39f234199b125fb93713c4d067bdcebbf691087f87b79c0feb92b156ba8b6906020015b60405180910390a150565b6002600554141561106e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156110b95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b8334146110fa5760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840dad2e6dac2e8c6d608b1b6044820152606401610bbd565b6013546001600160a01b03166111525760405162461bcd60e51b815260206004820152601360248201527f4e61746976652077726170206e6f7420736574000000000000000000000000006044820152606401610bbd565b6013546000906111709087906001600160a01b031687878787612c8b565b9050601360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111c257600080fd5b505af11580156111d6573d6000803e3d6000fd5b5050601354604080518681523360208201526001600160a01b03808d1692820192909252911660608201526080810189905267ffffffffffffffff80891660a0830152871660c082015263ffffffff861660e08201527f89d8051e597ab4178a863a5190407b98abfeff406aa8db90c59af76612e58f01935061010001915061125c9050565b60405180910390a15050600160055550505050565b3360009081526007602052604090205460ff166112d05760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610bbd565b6112d8612ebe565b565b3360009081526008602052604090205460ff166113325760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b8281146113735760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d055782828281811061139057611390614ce4565b90506020020135600b60008787858181106113ad576113ad614ce4565b90506020020160208101906113c29190614841565b6001600160a01b031681526020810191909152604001600020557f608e49c22994f20b5d3496dca088b88dfd81b4a3e8cc3809ea1e10a320107e8985858381811061140f5761140f614ce4565b90506020020160208101906114249190614841565b84848481811061143657611436614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a18061146981614d10565b915050611376565b3360009081526008602052604090205460ff166114c95760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b6017805463ffffffff191663ffffffff92909216919091179055565b3360009081526008602052604090205460ff1661153d5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b60098190556040518181527f2664fec2ff76486ac58ed087310855b648b15b9d19f3de8529e95f7c46b7d6b390602001611010565b600260055414156115c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156116105760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6001600160a01b038216600090815260116020526040902054811161166a5760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b601080546001919060009061168a90849067ffffffffffffffff16614d43565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506116d0333083856001600160a01b0316612f55909392919063ffffffff16565b6010546040805167ffffffffffffffff90921682523360208301526001600160a01b0384168282015260608201839052517fd5d28426c3248963b1719df49aa4c665120372e02c8249bbea03d019c39ce7649181900360800190a150506001600555565b60008484848460405160200161174d9493929190614ddb565b60405160208183030381529060405280519060200120905080600154146117b65760405162461bcd60e51b815260206004820152601860248201527f4d69736d617463682063757272656e74207369676e65727300000000000000006044820152606401610bbd565b87516020808a0191909120604080517f19457468657265756d205369676e6564204d6573736167653a0a33320000000081850152603c8082019390935281518082039093018352605c019052805191012061181690888888888888612fed565b5050505050505050565b6000546001600160a01b031633146118685760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481613323565b6112d833613323565b600260055414156118cd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156119185760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b8034146119595760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840dad2e6dac2e8c6d608b1b6044820152606401610bbd565b6013546001600160a01b03166119b15760405162461bcd60e51b815260206004820152601360248201527f4e61746976652077726170206e6f7420736574000000000000000000000000006044820152606401610bbd565b6013546001600160a01b03166000908152601160205260409020548111611a0d5760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b6010805460019190600090611a2d90849067ffffffffffffffff16614d43565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550601360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b50506010546013546040805167ffffffffffffffff90931683523360208401526001600160a01b0390911690820152606081018590527fd5d28426c3248963b1719df49aa4c665120372e02c8249bbea03d019c39ce76493506080019150611b1c9050565b60405180910390a1506001600555565b6000546001600160a01b03163314611b745760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6112d860006133dc565b6000546001600160a01b03163314611bc65760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f848161342c565b3360009081526007602052604090205460ff16611c2e5760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610bbd565b6112d86134e9565b3360009081526008602052604090205460ff16611c8e5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b828114611ccf5760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110611cec57611cec614ce4565b9050602002013560166000878785818110611d0957611d09614ce4565b9050602002016020810190611d1e9190614841565b6001600160a01b031681526020810191909152604001600020557f4f12d1a5bfb3ccd3719255d4d299d808d50cdca9a0a5c2b3a5aaa7edde73052c858583818110611d6b57611d6b614ce4565b9050602002016020810190611d809190614841565b848484818110611d9257611d92614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180611dc581614d10565b915050611cd2565b60065460ff1615611e135760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6000611e1e82613564565b9050611e37816000015182602001518360400151613729565b5050565b6000546001600160a01b03163314611e835760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b60065460ff1615611eeb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b60004630604051602001611f4192919091825260601b6bffffffffffffffffffffffff191660208201527f57697468647261774d73670000000000000000000000000000000000000000006034820152603f0190565b604051602081830303815290604052805190602001209050611f8b818a8a604051602001611f7193929190614df2565b604051602081830303815290604052888888888888611734565b6000611fcc8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061385e92505050565b905060008160000151826020015183604001518460600151856080015160405160200161204595949392919060c095861b6001600160c01b031990811682529490951b9093166008850152606091821b6bffffffffffffffffffffffff199081166010860152911b166024830152603882015260580190565b60408051601f1981840301815291815281516020928301206000818152601290935291205490915060ff16156120bd5760405162461bcd60e51b815260206004820152601a60248201527f776974686472617720616c7265616479207375636365656465640000000000006044820152606401610bbd565b6000818152601260205260409020805460ff19166001179055606082015160808301516120ea91906139be565b60608201516001600160a01b03166000908152600e602052604090205480158015906121195750808360800151115b1561213b5761213682846040015185606001518660800151613ad6565b612152565b612152836040015184606001518560800151613729565b7f48a1ab26f3aa7b62bb6b6e8eed182f292b84eb7b006c0254386b268af20774be8284602001518560400151866060015187608001518860a001516040516121d69695949392919095865267ffffffffffffffff9490941660208601526001600160a01b03928316604086015291166060840152608083015260a082015260c00190565b60405180910390a1505050505050505050505050565b6002600554141561223f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff161561228a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b600061229a878787878787612c8b565b90506122b16001600160a01b038716333088612f55565b604080518281523360208201526001600160a01b0389811682840152881660608201526080810187905267ffffffffffffffff86811660a0830152851660c082015263ffffffff841660e082015290517f89d8051e597ab4178a863a5190407b98abfeff406aa8db90c59af76612e58f01918190036101000190a1505060016005555050505050565b6000546001600160a01b031633146123825760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b60035442116123d35760405162461bcd60e51b815260206004820152601460248201527f6e6f742072656163682072657365742074696d650000000000000000000000006044820152606401610bbd565b6000196003556123e584848484613be9565b50505050565b6002548b1161243c5760405162461bcd60e51b815260206004820152601e60248201527f547269676765722074696d65206973206e6f7420696e6372656173696e6700006044820152606401610bbd565b61244842610e10614d2b565b8b106124965760405162461bcd60e51b815260206004820152601960248201527f547269676765722074696d6520697320746f6f206c61726765000000000000006044820152606401610bbd565b600046306040516020016124ec92919091825260601b6bffffffffffffffffffffffff191660208201527f5570646174655369676e65727300000000000000000000000000000000000000603482015260410190565b604051602081830303815290604052805190602001209050612522818d8d8d8d8d604051602001611f7196959493929190614e0c565b61252e8b8b8b8b613be9565b5050506002989098555050505050505050565b60065460ff16156125875760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b600046306040516020016125dd92919091825260601b6bffffffffffffffffffffffff191660208201527f52656c6179000000000000000000000000000000000000000000000000000000603482015260390190565b60405160208183030381529060405280519060200120905061260d818a8a604051602001611f7193929190614df2565b600061264e8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d9392505050565b8051602080830151604080850151606080870151608088015160a089015160c0808b015187519a861b6bffffffffffffffffffffffff199081168c8c015298861b891660348c01529590941b9096166048890152605c880191909152811b6001600160c01b0319908116607c88015293901b9092166084850152608c808501929092528051808503909201825260ac909301835280519082012060008181526014909252919020549192509060ff161561273c5760405162461bcd60e51b815260206004820152600f60248201526e7472616e736665722065786973747360881b6044820152606401610bbd565b60008181526014602052604090819020805460ff19166001179055820151606083015161276991906139be565b6040808301516001600160a01b03166000908152600e602052205480158015906127965750808360600151115b156127b8576127b382846020015185604001518660600151613ad6565b6127cf565b6127cf836020015184604001518560600151613729565b7f79fa08de5149d912dce8e5e8da7a7c17ccdf23dd5d3bfe196802e6eb86347c7c82846000015185602001518660400151876060015188608001518960c001516040516121d697969594939291909687526001600160a01b0395861660208801529385166040870152919093166060850152608084019290925267ffffffffffffffff9190911660a083015260c082015260e00190565b6112d833613f0b565b3360009081526008602052604090205460ff166128c75760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b8281146129085760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d055782828281811061292557612925614ce4565b905060200201356011600087878581811061294257612942614ce4565b90506020020160208101906129579190614841565b6001600160a01b031681526020810191909152604001600020557fc56b0d14c4940515800d94ebbd0f3f5d8cc58ba1109c12536bd993b72e466e4f8585838181106129a4576129a4614ce4565b90506020020160208101906129b99190614841565b8484848181106129cb576129cb614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a1806129fe81614d10565b91505061290b565b6000546001600160a01b03163314612a4e5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481613f0b565b6000546001600160a01b03163314612a9f5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6004548111612afc5760405162461bcd60e51b815260206004820152602360248201527f6e6f7469636520706572696f642063616e206f6e6c7920626520696e637265616044820152621cd95960ea1b6064820152608401610bbd565b600455565b6000546001600160a01b03163314612b495760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6001600160a01b038116612bc55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610bbd565b610f84816133dc565b6001600160a01b03811660009081526008602052604090205460ff1615612c375760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f7200000000006044820152606401610bbd565b6001600160a01b038116600081815260086020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b59101611010565b6001600160a01b0385166000908152601560205260408120548511612ce55760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b6001600160a01b0386166000908152601660205260409020541580612d2257506001600160a01b0386166000908152601660205260409020548511155b612d6e5760405162461bcd60e51b815260206004820152601060248201527f616d6f756e7420746f6f206c61726765000000000000000000000000000000006044820152606401610bbd565b60175463ffffffff90811690831611612dc95760405162461bcd60e51b815260206004820152601660248201527f6d617820736c69707061676520746f6f20736d616c6c000000000000000000006044820152606401610bbd565b6040516bffffffffffffffffffffffff1933606090811b8216602084015289811b8216603484015288901b166048820152605c81018690526001600160c01b031960c086811b8216607c84015285811b8216608484015246901b16608c82015260009060940160408051601f1981840301815291815281516020928301206000818152601490935291205490915060ff1615612e995760405162461bcd60e51b815260206004820152600f60248201526e7472616e736665722065786973747360881b6044820152606401610bbd565b6000818152601460205260409020805460ff1916600117905590509695505050505050565b60065460ff16612f105760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610bbd565b6006805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b039091168152602001610f29565b6040516001600160a01b03808516602483015283166044820152606481018290526123e59085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613fc4565b8281146130485760405162461bcd60e51b815260206004820152602360248201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616044820152620e8c6d60eb1b6064820152608401610bbd565b6000805b8481101561308c5783838281811061306657613066614ce4565b90506020020135826130789190614d2b565b91508061308481614d10565b91505061304c565b506000600361309c836002614e34565b6130a69190614e53565b6130b1906001614d2b565b905060008080805b8a8110156132d157600061313c8d8d848181106130d8576130d8614ce4565b90506020028101906130ea9190614e75565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508f6140a990919063ffffffff16565b9050836001600160a01b0316816001600160a01b03161161319f5760405162461bcd60e51b815260206004820152601e60248201527f7369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610bbd565b8093505b8a8a848181106131b5576131b5614ce4565b90506020020160208101906131ca9190614841565b6001600160a01b0316816001600160a01b03161115613244576131ee600184614d2b565b925089831061323f5760405162461bcd60e51b815260206004820152601060248201527f7369676e6572206e6f7420666f756e64000000000000000000000000000000006044820152606401610bbd565b6131a3565b8a8a8481811061325657613256614ce4565b905060200201602081019061326b9190614841565b6001600160a01b0316816001600160a01b031614156132ab5788888481811061329657613296614ce4565b90506020020135856132a89190614d2b565b94505b8585106132be575050505050505061331a565b50806132c981614d10565b9150506130b9565b5060405162461bcd60e51b815260206004820152601260248201527f71756f72756d206e6f74207265616368656400000000000000000000000000006044820152606401610bbd565b50505050505050565b6001600160a01b03811660009081526007602052604090205460ff1661338b5760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610bbd565b6001600160a01b038116600081815260076020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e9101611010565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526007602052604090205460ff16156134955760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610bbd565b6001600160a01b038116600081815260076020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f89101611010565b60065460ff161561352f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6006805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612f3d3390565b6040805160808101825260008082526020820181905291810182905260608101919091526000828152600d6020908152604091829020825160808101845281546001600160a01b03908116825260018301541692810192909252600281015492820192909252600390910154606082018190526136235760405162461bcd60e51b815260206004820152601a60248201527f64656c61796564207472616e73666572206e6f742065786973740000000000006044820152606401610bbd565b600f5481606001516136359190614d2b565b42116136835760405162461bcd60e51b815260206004820152601d60248201527f64656c61796564207472616e73666572207374696c6c206c6f636b65640000006044820152606401610bbd565b6000838152600d6020908152604080832080546001600160a01b03199081168255600182018054909116905560028101849055600301929092558251908301518383015192517f3b40e5089937425d14cdd96947e5661868357e224af59bd8b24a4b8a330d44269361371b93889390929091909384526001600160a01b03928316602085015291166040830152606082015260800190565b60405180910390a192915050565b6013546001600160a01b038381169116141561384557601354604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561378557600080fd5b505af1158015613799573d6000803e3d6000fd5b505050506000836001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146137ef576040519150601f19603f3d011682016040523d82523d6000602084013e6137f4565b606091505b50509050806123e55760405162461bcd60e51b815260206004820152601b60248201527f6661696c656420746f2073656e64206e617469766520746f6b656e00000000006044820152606401610bbd565b6138596001600160a01b0383168483614153565b505050565b6040805160c08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905283518085019094528184528301849052909190805b602083015151835110156139b6576138bc83614183565b909250905081600114156138e4576138d3836141bd565b67ffffffffffffffff1684526138a5565b816002141561390a576138f6836141bd565b67ffffffffffffffff1660208501526138a5565b81600314156139375761392461391f8461423f565b6142fc565b6001600160a01b031660408501526138a5565b816004141561395f5761394c61391f8461423f565b6001600160a01b031660608501526138a5565b8160051415613983576139796139748461423f565b614307565b60808501526138a5565b81600614156139a75761399d6139988461423f565b61433e565b60a08501526138a5565b6139b18382614356565b6138a5565b505050919050565b6009546139c9575050565b6001600160a01b0382166000908152600b6020526040902054806139ec57505050565b6001600160a01b0383166000908152600a602052604081205460095490914291613a168184614e53565b613a209190614e34565b6001600160a01b0387166000908152600c6020526040902054909150811115613a4b57849250613a58565b613a558584614d2b565b92505b83831115613aa85760405162461bcd60e51b815260206004820152601260248201527f766f6c756d6520657863656564732063617000000000000000000000000000006044820152606401610bbd565b506001600160a01b039094166000908152600a6020908152604080832093909355600c905220929092555050565b6000848152600d602052604090206003015415613b355760405162461bcd60e51b815260206004820152601f60248201527f64656c61796564207472616e7366657220616c726561647920657869737473006044820152606401610bbd565b604080516080810182526001600160a01b0380861682528481166020808401918252838501868152426060860190815260008b8152600d90935291869020945185549085166001600160a01b031991821617865592516001860180549190951693169290921790925551600283015551600390910155517fcbcfffe5102114216a85d3aceb14ad4b81a3935b1b5c468fadf3889eb9c5dce690613bdb9086815260200190565b60405180910390a150505050565b828114613c445760405162461bcd60e51b815260206004820152602360248201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616044820152620e8c6d60eb1b6064820152608401610bbd565b6000805b84811015613d1d57816001600160a01b0316868683818110613c6c57613c6c614ce4565b9050602002016020810190613c819190614841565b6001600160a01b031611613ce25760405162461bcd60e51b815260206004820152602260248201527f4e6577207369676e657273206e6f7420696e20617363656e64696e67206f726460448201526132b960f11b6064820152608401610bbd565b858582818110613cf457613cf4614ce4565b9050602002016020810190613d099190614841565b915080613d1581614d10565b915050613c48565b5084848484604051602001613d359493929190614ddb565b60408051601f198184030181529082905280516020909101206001557ff126123539a68393c55697f617e7d1148e371988daed246c2f41da99965a23f890613d84908790879087908790614ebc565b60405180910390a15050505050565b6040805160e08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905283518085019094528184528301849052909190805b602083015151835110156139b657613df883614183565b90925090508160011415613e2257613e1261391f8461423f565b6001600160a01b03168452613de1565b8160021415613e4a57613e3761391f8461423f565b6001600160a01b03166020850152613de1565b8160031415613e7257613e5f61391f8461423f565b6001600160a01b03166040850152613de1565b8160041415613e9157613e876139748461423f565b6060850152613de1565b8160051415613eb757613ea3836141bd565b67ffffffffffffffff166080850152613de1565b8160061415613edd57613ec9836141bd565b67ffffffffffffffff1660a0850152613de1565b8160071415613efc57613ef26139988461423f565b60c0850152613de1565b613f068382614356565b613de1565b6001600160a01b03811660009081526008602052604090205460ff16613f735760405162461bcd60e51b815260206004820152601760248201527f4163636f756e74206973206e6f7420676f7665726e6f720000000000000000006044820152606401610bbd565b6001600160a01b038116600081815260086020908152604091829020805460ff1916905590519182527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9101611010565b6000614019826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143c89092919063ffffffff16565b80519091501561385957808060200190518101906140379190614f3e565b6138595760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bbd565b60008151604114156140dd5760208201516040830151606084015160001a6140d3868285856143e1565b935050505061414d565b81516040141561410557602082015160408301516140fc85838361458a565b9250505061414d565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610bbd565b92915050565b6040516001600160a01b03831660248201526044810182905261385990849063a9059cbb60e01b90606401612f89565b6000806000614191846141bd565b905061419e600882614e53565b92508060071660058111156141b5576141b5614f60565b915050915091565b602080820151825181019091015160009182805b600a8110156142395783811a91506141ea816007614e34565b82607f16901b8517945081608016600014156142275761420b816001614d2b565b8651879061421a908390614d2b565b9052509395945050505050565b8061423181614d10565b9150506141d1565b50600080fd5b6060600061424c836141bd565b905060008184600001516142609190614d2b565b905083602001515181111561427457600080fd5b8167ffffffffffffffff81111561428d5761428d614944565b6040519080825280601f01601f1916602001820160405280156142b7576020820181803683370190505b50602080860151865192955091818601919083010160005b858110156142f15781810151838201526142ea602082614d2b565b90506142cf565b505050935250919050565b600061414d826145cd565b600060208251111561431857600080fd5b602082015190508151602061432d9190614f76565b614338906008614e34565b1c919050565b6000815160201461434e57600080fd5b506020015190565b600081600581111561436a5761436a614f60565b141561437957613859826141bd565b600281600581111561438d5761438d614f60565b141561037657600061439e836141bd565b905080836000018181516143b29190614d2b565b9052506020830151518351111561385957600080fd5b60606143d784846000856145f5565b90505b9392505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561445e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bbd565b8360ff16601b148061447357508360ff16601c145b6144ca5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610bbd565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa15801561451e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166145815760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610bbd565b95945050505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821660ff83901c601b016145c3868287856143e1565b9695505050505050565b600081516014146145dd57600080fd5b50602001516c01000000000000000000000000900490565b60608247101561466d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610bbd565b843b6146bb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bbd565b600080866001600160a01b031685876040516146d79190614fb9565b60006040518083038185875af1925050503d8060008114614714576040519150601f19603f3d011682016040523d82523d6000602084013e614719565b606091505b5091509150614729828286614734565b979650505050505050565b606083156147435750816143da565b8251156147535782518084602001fd5b8160405162461bcd60e51b8152600401610bbd9190614fd5565b60008083601f84011261477f57600080fd5b50813567ffffffffffffffff81111561479757600080fd5b6020830191508360208260051b85010111156147b257600080fd5b9250929050565b600080600080604085870312156147cf57600080fd5b843567ffffffffffffffff808211156147e757600080fd5b6147f38883890161476d565b9096509450602087013591508082111561480c57600080fd5b506148198782880161476d565b95989497509550505050565b80356001600160a01b038116811461483c57600080fd5b919050565b60006020828403121561485357600080fd5b6143da82614825565b60006020828403121561486e57600080fd5b5035919050565b803567ffffffffffffffff8116811461483c57600080fd5b803563ffffffff8116811461483c57600080fd5b600080600080600060a086880312156148b957600080fd5b6148c286614825565b9450602086013593506148d760408701614875565b92506148e560608701614875565b91506148f36080870161488d565b90509295509295909350565b60006020828403121561491157600080fd5b6143da8261488d565b6000806040838503121561492d57600080fd5b61493683614825565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060006080888a03121561497557600080fd5b873567ffffffffffffffff8082111561498d57600080fd5b818a0191508a601f8301126149a157600080fd5b8135818111156149b3576149b3614944565b604051601f8201601f19908116603f011681019083821181831017156149db576149db614944565b816040528281528d60208487010111156149f457600080fd5b82602086016020830137600094508460208483010152809b5050505060208a013581811115614a21578283fd5b614a2d8c828d0161476d565b90995097505060408a013581811115614a44578283fd5b614a508c828d0161476d565b90975095505060608a013581811115614a67578283fd5b614a738c828d0161476d565b9a9d999c50979a509598949794955050505050565b6000806000806000806000806080898b031215614aa457600080fd5b883567ffffffffffffffff80821115614abc57600080fd5b818b0191508b601f830112614ad057600080fd5b813581811115614adf57600080fd5b8c6020828501011115614af157600080fd5b60209283019a509850908a01359080821115614b0c57600080fd5b614b188c838d0161476d565b909850965060408b0135915080821115614b3157600080fd5b614b3d8c838d0161476d565b909650945060608b0135915080821115614b5657600080fd5b50614b638b828c0161476d565b999c989b5096995094979396929594505050565b60008060008060008060c08789031215614b9057600080fd5b614b9987614825565b9550614ba760208801614825565b945060408701359350614bbc60608801614875565b9250614bca60808801614875565b9150614bd860a0880161488d565b90509295509295509295565b600080600080600080600080600080600060c08c8e031215614c0557600080fd5b8b359a5067ffffffffffffffff8060208e01351115614c2357600080fd5b614c338e60208f01358f0161476d565b909b50995060408d0135811015614c4957600080fd5b614c598e60408f01358f0161476d565b909950975060608d0135811015614c6f57600080fd5b614c7f8e60608f01358f0161476d565b909750955060808d0135811015614c9557600080fd5b614ca58e60808f01358f0161476d565b909550935060a08d0135811015614cbb57600080fd5b50614ccc8d60a08e01358e0161476d565b81935080925050509295989b509295989b9093969950565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415614d2457614d24614cfa565b5060010190565b60008219821115614d3e57614d3e614cfa565b500190565b600067ffffffffffffffff808316818516808303821115614d6657614d66614cfa565b01949350505050565b60008160005b84811015614da4576001600160a01b03614d8e83614825565b1686526020958601959190910190600101614d75565b5093949350505050565b60006001600160fb1b03831115614dc457600080fd5b8260051b8083863760009401938452509192915050565b60006145c3614deb838789614d6f565b8486614dae565b838152818360208301376000910160200190815292915050565b8681528560208201526000614e28614deb604084018789614d6f565b98975050505050505050565b6000816000190483118215151615614e4e57614e4e614cfa565b500290565b600082614e7057634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112614e8c57600080fd5b83018035915067ffffffffffffffff821115614ea757600080fd5b6020019150368190038213156147b257600080fd5b6040808252810184905260008560608301825b87811015614efd576001600160a01b03614ee884614825565b16825260209283019290910190600101614ecf565b5083810360208501528481526001600160fb1b03851115614f1d57600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b600060208284031215614f5057600080fd5b815180151581146143da57600080fd5b634e487b7160e01b600052602160045260246000fd5b600082821015614f8857614f88614cfa565b500390565b60005b83811015614fa8578181015183820152602001614f90565b838111156123e55750506000910152565b60008251614fcb818460208701614f8d565b9190910192915050565b6020815260008251806020840152614ff4816040850160208701614f8d565b601f01601f1916919091016040019291505056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a264697066735822122041c4c43a181078f6a3d94196af5f8c8b055bb458f7ac531bc9c6cf093842aa8264736f6c63430008090033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":800},"remappings":[]},"optimization_runs":800,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x5427FEFA711Eff984124bFBB1AB6fbf5E3DA1820/","decoded_constructor_args":null,"compiler_version":"0.8.9+commit.e5eed63a","is_verified_via_verifier_alliance":false,"verified_at":"2023-11-18T11:25:59.851885Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60806040523480156200001157600080fd5b506200001d3362000048565b60016005556006805460ff19169055620000373362000098565b620000423362000162565b62000222565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526007602052604090205460ff1615620001075760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c7265616479207061757365720000000000000060448201526064015b60405180910390fd5b6001600160a01b038116600081815260076020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f891015b60405180910390a150565b6001600160a01b03811660009081526008602052604090205460ff1615620001cd5760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f7200000000006044820152606401620000fe565b6001600160a01b038116600081815260086020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b5910162000157565b61505e80620002326000396000f3fe60806040526004361061036f5760003560e01c806382dc1ec4116101c6578063ba2cb25c116100f7578063e43581b811610095578063f20c922a1161006f578063f20c922a14610acf578063f2fde38b14610aef578063f832138314610b0f578063f8b30d7d14610b3c57600080fd5b8063e43581b814610a56578063e999e5f414610a8f578063eecdac8814610aaf57600080fd5b8063d0790da9116100d1578063d0790da9146109cb578063e026049c146109e1578063e09ab428146109f6578063e3eece2614610a2657600080fd5b8063ba2cb25c1461095e578063ccde517a1461097e578063cdd1b25d146109ab57600080fd5b80639ff9001a11610164578063a7bdf45a1161013e578063a7bdf45a14610881578063adc0d57f146108a1578063b1c94d941461091b578063b5f2bc471461093157600080fd5b80639ff9001a14610821578063a21a928014610841578063a5977fbb1461086157600080fd5b806389e39127116101a057806389e39127146107935780638da5cb5b146107cd5780639b14d4c6146107eb5780639e25fc5c1461080157600080fd5b806382dc1ec41461073e5780638456cb591461075e578063878fe1ce1461077357600080fd5b806352532faa116102a057806365a114f11161023e5780636ef8d66d116102185780636ef8d66d146106d15780637044c89e146106e6578063715018a6146106f957806380f51c121461070e57600080fd5b806365a114f11461067b578063682dbc22146106915780636b2c0f55146106b157600080fd5b806357d775f81161027a57806357d775f8146105f35780635c975abb1461060957806360216b0014610621578063618ee0551461064e57600080fd5b806352532faa1461058657806354eea796146105b357806356688700146105d357600080fd5b80633d5721071161030d578063457bfa2f116102e7578063457bfa2f146104d557806346fbf68e1461050d57806347b16c6c14610546578063482341261461056657600080fd5b80633d5721071461048d5780633f2e5fc3146104ad5780633f4ba83a146104c057600080fd5b80632fd1b0a4116103495780632fd1b0a4146103d2578063370fb47b146104095780633c4a25d01461042d5780633c64f04b1461044d57600080fd5b8063089927411461037b57806317bdbae51461039d57806325c38b9f146103bd57600080fd5b3661037657005b600080fd5b34801561038757600080fd5b5061039b6103963660046147b9565b610b69565b005b3480156103a957600080fd5b5061039b6103b83660046147b9565b610d0c565b3480156103c957600080fd5b5061039b610ea3565b3480156103de57600080fd5b506017546103ef9063ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b34801561041557600080fd5b5061041f60025481565b604051908152602001610400565b34801561043957600080fd5b5061039b610448366004614841565b610f33565b34801561045957600080fd5b5061047d61046836600461485c565b60146020526000908152604090205460ff1681565b6040519015158152602001610400565b34801561049957600080fd5b5061039b6104a836600461485c565b610f87565b61039b6104bb3660046148a1565b61101b565b3480156104cc57600080fd5b5061039b611271565b3480156104e157600080fd5b506013546104f5906001600160a01b031681565b6040516001600160a01b039091168152602001610400565b34801561051957600080fd5b5061047d610528366004614841565b6001600160a01b031660009081526007602052604090205460ff1690565b34801561055257600080fd5b5061039b6105613660046147b9565b6112da565b34801561057257600080fd5b5061039b6105813660046148ff565b611471565b34801561059257600080fd5b5061041f6105a1366004614841565b600e6020526000908152604090205481565b3480156105bf57600080fd5b5061039b6105ce36600461485c565b6114e5565b3480156105df57600080fd5b5061039b6105ee36600461491a565b611572565b3480156105ff57600080fd5b5061041f60095481565b34801561061557600080fd5b5060065460ff1661047d565b34801561062d57600080fd5b5061041f61063c366004614841565b600a6020526000908152604090205481565b34801561065a57600080fd5b5061041f610669366004614841565b60166020526000908152604090205481565b34801561068757600080fd5b5061041f60035481565b34801561069d57600080fd5b5061039b6106ac36600461495a565b611734565b3480156106bd57600080fd5b5061039b6106cc366004614841565b611820565b3480156106dd57600080fd5b5061039b611871565b61039b6106f436600461485c565b61187a565b34801561070557600080fd5b5061039b611b2c565b34801561071a57600080fd5b5061047d610729366004614841565b60076020526000908152604090205460ff1681565b34801561074a57600080fd5b5061039b610759366004614841565b611b7e565b34801561076a57600080fd5b5061039b611bcf565b34801561077f57600080fd5b5061039b61078e3660046147b9565b611c36565b34801561079f57600080fd5b506010546107b49067ffffffffffffffff1681565b60405167ffffffffffffffff9091168152602001610400565b3480156107d957600080fd5b506000546001600160a01b03166104f5565b3480156107f757600080fd5b5061041f60045481565b34801561080d57600080fd5b5061039b61081c36600461485c565b611dcd565b34801561082d57600080fd5b5061039b61083c366004614841565b611e3b565b34801561084d57600080fd5b5061039b61085c366004614a88565b611ea5565b34801561086d57600080fd5b5061039b61087c366004614b77565b6121ec565b34801561088d57600080fd5b5061039b61089c3660046147b9565b61233a565b3480156108ad57600080fd5b506108f06108bc36600461485c565b600d6020526000908152604090208054600182015460028301546003909301546001600160a01b0392831693919092169184565b604080516001600160a01b039586168152949093166020850152918301526060820152608001610400565b34801561092757600080fd5b5061041f600f5481565b34801561093d57600080fd5b5061041f61094c366004614841565b600b6020526000908152604090205481565b34801561096a57600080fd5b5061039b610979366004614be4565b6123eb565b34801561098a57600080fd5b5061041f610999366004614841565b60116020526000908152604090205481565b3480156109b757600080fd5b5061039b6109c6366004614a88565b612541565b3480156109d757600080fd5b5061041f60015481565b3480156109ed57600080fd5b5061039b612866565b348015610a0257600080fd5b5061047d610a1136600461485c565b60126020526000908152604090205460ff1681565b348015610a3257600080fd5b5061047d610a41366004614841565b60086020526000908152604090205460ff1681565b348015610a6257600080fd5b5061047d610a71366004614841565b6001600160a01b031660009081526008602052604090205460ff1690565b348015610a9b57600080fd5b5061039b610aaa3660046147b9565b61286f565b348015610abb57600080fd5b5061039b610aca366004614841565b612a06565b348015610adb57600080fd5b5061039b610aea36600461485c565b612a57565b348015610afb57600080fd5b5061039b610b0a366004614841565b612b01565b348015610b1b57600080fd5b5061041f610b2a366004614841565b600c6020526000908152604090205481565b348015610b4857600080fd5b5061041f610b57366004614841565b60156020526000908152604090205481565b3360009081526008602052604090205460ff16610bc65760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b60448201526064015b60405180910390fd5b828114610c075760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110610c2457610c24614ce4565b9050602002013560156000878785818110610c4157610c41614ce4565b9050602002016020810190610c569190614841565b6001600160a01b031681526020810191909152604001600020557f8b59d386e660418a48d742213ad5ce7c4dd51ae81f30e4e2c387f17d907010c9858583818110610ca357610ca3614ce4565b9050602002016020810190610cb89190614841565b848484818110610cca57610cca614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180610cfd81614d10565b915050610c0a565b5050505050565b3360009081526008602052604090205460ff16610d645760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b828114610da55760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110610dc257610dc2614ce4565b90506020020135600e6000878785818110610ddf57610ddf614ce4565b9050602002016020810190610df49190614841565b6001600160a01b031681526020810191909152604001600020557fceaad6533bfb481492fb3e08ef19297f46611b8fa9de5ef4cf8dc23a56ad09ce858583818110610e4157610e41614ce4565b9050602002016020810190610e569190614841565b848484818110610e6857610e68614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180610e9b81614d10565b915050610da8565b6000546001600160a01b03163314610eeb5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b600454610ef89042614d2b565b60038190556040519081527f68e825132f7d4bc837dea2d64ac9fc19912bf0224b67f9317d8f1a917f5304a1906020015b60405180910390a1565b6000546001600160a01b03163314610f7b5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481612bce565b50565b3360009081526008602052604090205460ff16610fdf5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b600f8190556040518181527fc0a39f234199b125fb93713c4d067bdcebbf691087f87b79c0feb92b156ba8b6906020015b60405180910390a150565b6002600554141561106e5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156110b95760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b8334146110fa5760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840dad2e6dac2e8c6d608b1b6044820152606401610bbd565b6013546001600160a01b03166111525760405162461bcd60e51b815260206004820152601360248201527f4e61746976652077726170206e6f7420736574000000000000000000000000006044820152606401610bbd565b6013546000906111709087906001600160a01b031687878787612c8b565b9050601360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0866040518263ffffffff1660e01b81526004016000604051808303818588803b1580156111c257600080fd5b505af11580156111d6573d6000803e3d6000fd5b5050601354604080518681523360208201526001600160a01b03808d1692820192909252911660608201526080810189905267ffffffffffffffff80891660a0830152871660c082015263ffffffff861660e08201527f89d8051e597ab4178a863a5190407b98abfeff406aa8db90c59af76612e58f01935061010001915061125c9050565b60405180910390a15050600160055550505050565b3360009081526007602052604090205460ff166112d05760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610bbd565b6112d8612ebe565b565b3360009081526008602052604090205460ff166113325760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b8281146113735760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d055782828281811061139057611390614ce4565b90506020020135600b60008787858181106113ad576113ad614ce4565b90506020020160208101906113c29190614841565b6001600160a01b031681526020810191909152604001600020557f608e49c22994f20b5d3496dca088b88dfd81b4a3e8cc3809ea1e10a320107e8985858381811061140f5761140f614ce4565b90506020020160208101906114249190614841565b84848481811061143657611436614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a18061146981614d10565b915050611376565b3360009081526008602052604090205460ff166114c95760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b6017805463ffffffff191663ffffffff92909216919091179055565b3360009081526008602052604090205460ff1661153d5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b60098190556040518181527f2664fec2ff76486ac58ed087310855b648b15b9d19f3de8529e95f7c46b7d6b390602001611010565b600260055414156115c55760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156116105760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6001600160a01b038216600090815260116020526040902054811161166a5760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b601080546001919060009061168a90849067ffffffffffffffff16614d43565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff1602179055506116d0333083856001600160a01b0316612f55909392919063ffffffff16565b6010546040805167ffffffffffffffff90921682523360208301526001600160a01b0384168282015260608201839052517fd5d28426c3248963b1719df49aa4c665120372e02c8249bbea03d019c39ce7649181900360800190a150506001600555565b60008484848460405160200161174d9493929190614ddb565b60405160208183030381529060405280519060200120905080600154146117b65760405162461bcd60e51b815260206004820152601860248201527f4d69736d617463682063757272656e74207369676e65727300000000000000006044820152606401610bbd565b87516020808a0191909120604080517f19457468657265756d205369676e6564204d6573736167653a0a33320000000081850152603c8082019390935281518082039093018352605c019052805191012061181690888888888888612fed565b5050505050505050565b6000546001600160a01b031633146118685760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481613323565b6112d833613323565b600260055414156118cd5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff16156119185760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b8034146119595760405162461bcd60e51b815260206004820152600f60248201526e082dadeeadce840dad2e6dac2e8c6d608b1b6044820152606401610bbd565b6013546001600160a01b03166119b15760405162461bcd60e51b815260206004820152601360248201527f4e61746976652077726170206e6f7420736574000000000000000000000000006044820152606401610bbd565b6013546001600160a01b03166000908152601160205260409020548111611a0d5760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b6010805460019190600090611a2d90849067ffffffffffffffff16614d43565b92506101000a81548167ffffffffffffffff021916908367ffffffffffffffff160217905550601360009054906101000a90046001600160a01b03166001600160a01b031663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b158015611aa357600080fd5b505af1158015611ab7573d6000803e3d6000fd5b50506010546013546040805167ffffffffffffffff90931683523360208401526001600160a01b0390911690820152606081018590527fd5d28426c3248963b1719df49aa4c665120372e02c8249bbea03d019c39ce76493506080019150611b1c9050565b60405180910390a1506001600555565b6000546001600160a01b03163314611b745760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6112d860006133dc565b6000546001600160a01b03163314611bc65760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f848161342c565b3360009081526007602052604090205460ff16611c2e5760405162461bcd60e51b815260206004820152601460248201527f43616c6c6572206973206e6f74207061757365720000000000000000000000006044820152606401610bbd565b6112d86134e9565b3360009081526008602052604090205460ff16611c8e5760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b828114611ccf5760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d0557828282818110611cec57611cec614ce4565b9050602002013560166000878785818110611d0957611d09614ce4565b9050602002016020810190611d1e9190614841565b6001600160a01b031681526020810191909152604001600020557f4f12d1a5bfb3ccd3719255d4d299d808d50cdca9a0a5c2b3a5aaa7edde73052c858583818110611d6b57611d6b614ce4565b9050602002016020810190611d809190614841565b848484818110611d9257611d92614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a180611dc581614d10565b915050611cd2565b60065460ff1615611e135760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6000611e1e82613564565b9050611e37816000015182602001518360400151613729565b5050565b6000546001600160a01b03163314611e835760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b601380546001600160a01b0319166001600160a01b0392909216919091179055565b60065460ff1615611eeb5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b60004630604051602001611f4192919091825260601b6bffffffffffffffffffffffff191660208201527f57697468647261774d73670000000000000000000000000000000000000000006034820152603f0190565b604051602081830303815290604052805190602001209050611f8b818a8a604051602001611f7193929190614df2565b604051602081830303815290604052888888888888611734565b6000611fcc8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061385e92505050565b905060008160000151826020015183604001518460600151856080015160405160200161204595949392919060c095861b6001600160c01b031990811682529490951b9093166008850152606091821b6bffffffffffffffffffffffff199081166010860152911b166024830152603882015260580190565b60408051601f1981840301815291815281516020928301206000818152601290935291205490915060ff16156120bd5760405162461bcd60e51b815260206004820152601a60248201527f776974686472617720616c7265616479207375636365656465640000000000006044820152606401610bbd565b6000818152601260205260409020805460ff19166001179055606082015160808301516120ea91906139be565b60608201516001600160a01b03166000908152600e602052604090205480158015906121195750808360800151115b1561213b5761213682846040015185606001518660800151613ad6565b612152565b612152836040015184606001518560800151613729565b7f48a1ab26f3aa7b62bb6b6e8eed182f292b84eb7b006c0254386b268af20774be8284602001518560400151866060015187608001518860a001516040516121d69695949392919095865267ffffffffffffffff9490941660208601526001600160a01b03928316604086015291166060840152608083015260a082015260c00190565b60405180910390a1505050505050505050505050565b6002600554141561223f5760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610bbd565b600260055560065460ff161561228a5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b600061229a878787878787612c8b565b90506122b16001600160a01b038716333088612f55565b604080518281523360208201526001600160a01b0389811682840152881660608201526080810187905267ffffffffffffffff86811660a0830152851660c082015263ffffffff841660e082015290517f89d8051e597ab4178a863a5190407b98abfeff406aa8db90c59af76612e58f01918190036101000190a1505060016005555050505050565b6000546001600160a01b031633146123825760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b60035442116123d35760405162461bcd60e51b815260206004820152601460248201527f6e6f742072656163682072657365742074696d650000000000000000000000006044820152606401610bbd565b6000196003556123e584848484613be9565b50505050565b6002548b1161243c5760405162461bcd60e51b815260206004820152601e60248201527f547269676765722074696d65206973206e6f7420696e6372656173696e6700006044820152606401610bbd565b61244842610e10614d2b565b8b106124965760405162461bcd60e51b815260206004820152601960248201527f547269676765722074696d6520697320746f6f206c61726765000000000000006044820152606401610bbd565b600046306040516020016124ec92919091825260601b6bffffffffffffffffffffffff191660208201527f5570646174655369676e65727300000000000000000000000000000000000000603482015260410190565b604051602081830303815290604052805190602001209050612522818d8d8d8d8d604051602001611f7196959493929190614e0c565b61252e8b8b8b8b613be9565b5050506002989098555050505050505050565b60065460ff16156125875760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b600046306040516020016125dd92919091825260601b6bffffffffffffffffffffffff191660208201527f52656c6179000000000000000000000000000000000000000000000000000000603482015260390190565b60405160208183030381529060405280519060200120905061260d818a8a604051602001611f7193929190614df2565b600061264e8a8a8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250613d9392505050565b8051602080830151604080850151606080870151608088015160a089015160c0808b015187519a861b6bffffffffffffffffffffffff199081168c8c015298861b891660348c01529590941b9096166048890152605c880191909152811b6001600160c01b0319908116607c88015293901b9092166084850152608c808501929092528051808503909201825260ac909301835280519082012060008181526014909252919020549192509060ff161561273c5760405162461bcd60e51b815260206004820152600f60248201526e7472616e736665722065786973747360881b6044820152606401610bbd565b60008181526014602052604090819020805460ff19166001179055820151606083015161276991906139be565b6040808301516001600160a01b03166000908152600e602052205480158015906127965750808360600151115b156127b8576127b382846020015185604001518660600151613ad6565b6127cf565b6127cf836020015184604001518560600151613729565b7f79fa08de5149d912dce8e5e8da7a7c17ccdf23dd5d3bfe196802e6eb86347c7c82846000015185602001518660400151876060015188608001518960c001516040516121d697969594939291909687526001600160a01b0395861660208801529385166040870152919093166060850152608084019290925267ffffffffffffffff9190911660a083015260c082015260e00190565b6112d833613f0b565b3360009081526008602052604090205460ff166128c75760405162461bcd60e51b815260206004820152601660248201527521b0b63632b91034b9903737ba1033b7bb32b93737b960511b6044820152606401610bbd565b8281146129085760405162461bcd60e51b815260206004820152600f60248201526e0d8cadccee8d040dad2e6dac2e8c6d608b1b6044820152606401610bbd565b60005b83811015610d055782828281811061292557612925614ce4565b905060200201356011600087878581811061294257612942614ce4565b90506020020160208101906129579190614841565b6001600160a01b031681526020810191909152604001600020557fc56b0d14c4940515800d94ebbd0f3f5d8cc58ba1109c12536bd993b72e466e4f8585838181106129a4576129a4614ce4565b90506020020160208101906129b99190614841565b8484848181106129cb576129cb614ce4565b604080516001600160a01b0390951685526020918202939093013590840152500160405180910390a1806129fe81614d10565b91505061290b565b6000546001600160a01b03163314612a4e5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b610f8481613f0b565b6000546001600160a01b03163314612a9f5760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6004548111612afc5760405162461bcd60e51b815260206004820152602360248201527f6e6f7469636520706572696f642063616e206f6e6c7920626520696e637265616044820152621cd95960ea1b6064820152608401610bbd565b600455565b6000546001600160a01b03163314612b495760405162461bcd60e51b815260206004820181905260248201526000805160206150098339815191526044820152606401610bbd565b6001600160a01b038116612bc55760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152608401610bbd565b610f84816133dc565b6001600160a01b03811660009081526008602052604090205460ff1615612c375760405162461bcd60e51b815260206004820152601b60248201527f4163636f756e7420697320616c726561647920676f7665726e6f7200000000006044820152606401610bbd565b6001600160a01b038116600081815260086020908152604091829020805460ff1916600117905590519182527fdc5a48d79e2e147530ff63ecdbed5a5a66adb9d5cf339384d5d076da197c40b59101611010565b6001600160a01b0385166000908152601560205260408120548511612ce55760405162461bcd60e51b815260206004820152601060248201526f185b5bdd5b9d081d1bdbc81cdb585b1b60821b6044820152606401610bbd565b6001600160a01b0386166000908152601660205260409020541580612d2257506001600160a01b0386166000908152601660205260409020548511155b612d6e5760405162461bcd60e51b815260206004820152601060248201527f616d6f756e7420746f6f206c61726765000000000000000000000000000000006044820152606401610bbd565b60175463ffffffff90811690831611612dc95760405162461bcd60e51b815260206004820152601660248201527f6d617820736c69707061676520746f6f20736d616c6c000000000000000000006044820152606401610bbd565b6040516bffffffffffffffffffffffff1933606090811b8216602084015289811b8216603484015288901b166048820152605c81018690526001600160c01b031960c086811b8216607c84015285811b8216608484015246901b16608c82015260009060940160408051601f1981840301815291815281516020928301206000818152601490935291205490915060ff1615612e995760405162461bcd60e51b815260206004820152600f60248201526e7472616e736665722065786973747360881b6044820152606401610bbd565b6000818152601460205260409020805460ff1916600117905590509695505050505050565b60065460ff16612f105760405162461bcd60e51b815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152606401610bbd565b6006805460ff191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa335b6040516001600160a01b039091168152602001610f29565b6040516001600160a01b03808516602483015283166044820152606481018290526123e59085906323b872dd60e01b906084015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613fc4565b8281146130485760405162461bcd60e51b815260206004820152602360248201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616044820152620e8c6d60eb1b6064820152608401610bbd565b6000805b8481101561308c5783838281811061306657613066614ce4565b90506020020135826130789190614d2b565b91508061308481614d10565b91505061304c565b506000600361309c836002614e34565b6130a69190614e53565b6130b1906001614d2b565b905060008080805b8a8110156132d157600061313c8d8d848181106130d8576130d8614ce4565b90506020028101906130ea9190614e75565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508f6140a990919063ffffffff16565b9050836001600160a01b0316816001600160a01b03161161319f5760405162461bcd60e51b815260206004820152601e60248201527f7369676e657273206e6f7420696e20617363656e64696e67206f7264657200006044820152606401610bbd565b8093505b8a8a848181106131b5576131b5614ce4565b90506020020160208101906131ca9190614841565b6001600160a01b0316816001600160a01b03161115613244576131ee600184614d2b565b925089831061323f5760405162461bcd60e51b815260206004820152601060248201527f7369676e6572206e6f7420666f756e64000000000000000000000000000000006044820152606401610bbd565b6131a3565b8a8a8481811061325657613256614ce4565b905060200201602081019061326b9190614841565b6001600160a01b0316816001600160a01b031614156132ab5788888481811061329657613296614ce4565b90506020020135856132a89190614d2b565b94505b8585106132be575050505050505061331a565b50806132c981614d10565b9150506130b9565b5060405162461bcd60e51b815260206004820152601260248201527f71756f72756d206e6f74207265616368656400000000000000000000000000006044820152606401610bbd565b50505050505050565b6001600160a01b03811660009081526007602052604090205460ff1661338b5760405162461bcd60e51b815260206004820152601560248201527f4163636f756e74206973206e6f742070617573657200000000000000000000006044820152606401610bbd565b6001600160a01b038116600081815260076020908152604091829020805460ff1916905590519182527fcd265ebaf09df2871cc7bd4133404a235ba12eff2041bb89d9c714a2621c7c7e9101611010565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6001600160a01b03811660009081526007602052604090205460ff16156134955760405162461bcd60e51b815260206004820152601960248201527f4163636f756e7420697320616c726561647920706175736572000000000000006044820152606401610bbd565b6001600160a01b038116600081815260076020908152604091829020805460ff1916600117905590519182527f6719d08c1888103bea251a4ed56406bd0c3e69723c8a1686e017e7bbe159b6f89101611010565b60065460ff161561352f5760405162461bcd60e51b815260206004820152601060248201526f14185d5cd8589b194e881c185d5cd95960821b6044820152606401610bbd565b6006805460ff191660011790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a258612f3d3390565b6040805160808101825260008082526020820181905291810182905260608101919091526000828152600d6020908152604091829020825160808101845281546001600160a01b03908116825260018301541692810192909252600281015492820192909252600390910154606082018190526136235760405162461bcd60e51b815260206004820152601a60248201527f64656c61796564207472616e73666572206e6f742065786973740000000000006044820152606401610bbd565b600f5481606001516136359190614d2b565b42116136835760405162461bcd60e51b815260206004820152601d60248201527f64656c61796564207472616e73666572207374696c6c206c6f636b65640000006044820152606401610bbd565b6000838152600d6020908152604080832080546001600160a01b03199081168255600182018054909116905560028101849055600301929092558251908301518383015192517f3b40e5089937425d14cdd96947e5661868357e224af59bd8b24a4b8a330d44269361371b93889390929091909384526001600160a01b03928316602085015291166040830152606082015260800190565b60405180910390a192915050565b6013546001600160a01b038381169116141561384557601354604051632e1a7d4d60e01b8152600481018390526001600160a01b0390911690632e1a7d4d90602401600060405180830381600087803b15801561378557600080fd5b505af1158015613799573d6000803e3d6000fd5b505050506000836001600160a01b03168261c35090604051600060405180830381858888f193505050503d80600081146137ef576040519150601f19603f3d011682016040523d82523d6000602084013e6137f4565b606091505b50509050806123e55760405162461bcd60e51b815260206004820152601b60248201527f6661696c656420746f2073656e64206e617469766520746f6b656e00000000006044820152606401610bbd565b6138596001600160a01b0383168483614153565b505050565b6040805160c08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905283518085019094528184528301849052909190805b602083015151835110156139b6576138bc83614183565b909250905081600114156138e4576138d3836141bd565b67ffffffffffffffff1684526138a5565b816002141561390a576138f6836141bd565b67ffffffffffffffff1660208501526138a5565b81600314156139375761392461391f8461423f565b6142fc565b6001600160a01b031660408501526138a5565b816004141561395f5761394c61391f8461423f565b6001600160a01b031660608501526138a5565b8160051415613983576139796139748461423f565b614307565b60808501526138a5565b81600614156139a75761399d6139988461423f565b61433e565b60a08501526138a5565b6139b18382614356565b6138a5565b505050919050565b6009546139c9575050565b6001600160a01b0382166000908152600b6020526040902054806139ec57505050565b6001600160a01b0383166000908152600a602052604081205460095490914291613a168184614e53565b613a209190614e34565b6001600160a01b0387166000908152600c6020526040902054909150811115613a4b57849250613a58565b613a558584614d2b565b92505b83831115613aa85760405162461bcd60e51b815260206004820152601260248201527f766f6c756d6520657863656564732063617000000000000000000000000000006044820152606401610bbd565b506001600160a01b039094166000908152600a6020908152604080832093909355600c905220929092555050565b6000848152600d602052604090206003015415613b355760405162461bcd60e51b815260206004820152601f60248201527f64656c61796564207472616e7366657220616c726561647920657869737473006044820152606401610bbd565b604080516080810182526001600160a01b0380861682528481166020808401918252838501868152426060860190815260008b8152600d90935291869020945185549085166001600160a01b031991821617865592516001860180549190951693169290921790925551600283015551600390910155517fcbcfffe5102114216a85d3aceb14ad4b81a3935b1b5c468fadf3889eb9c5dce690613bdb9086815260200190565b60405180910390a150505050565b828114613c445760405162461bcd60e51b815260206004820152602360248201527f7369676e65727320616e6420706f77657273206c656e677468206e6f74206d616044820152620e8c6d60eb1b6064820152608401610bbd565b6000805b84811015613d1d57816001600160a01b0316868683818110613c6c57613c6c614ce4565b9050602002016020810190613c819190614841565b6001600160a01b031611613ce25760405162461bcd60e51b815260206004820152602260248201527f4e6577207369676e657273206e6f7420696e20617363656e64696e67206f726460448201526132b960f11b6064820152608401610bbd565b858582818110613cf457613cf4614ce4565b9050602002016020810190613d099190614841565b915080613d1581614d10565b915050613c48565b5084848484604051602001613d359493929190614ddb565b60408051601f198184030181529082905280516020909101206001557ff126123539a68393c55697f617e7d1148e371988daed246c2f41da99965a23f890613d84908790879087908790614ebc565b60405180910390a15050505050565b6040805160e08101825260008082526020808301829052828401829052606083018290526080830182905260a0830182905260c0830182905283518085019094528184528301849052909190805b602083015151835110156139b657613df883614183565b90925090508160011415613e2257613e1261391f8461423f565b6001600160a01b03168452613de1565b8160021415613e4a57613e3761391f8461423f565b6001600160a01b03166020850152613de1565b8160031415613e7257613e5f61391f8461423f565b6001600160a01b03166040850152613de1565b8160041415613e9157613e876139748461423f565b6060850152613de1565b8160051415613eb757613ea3836141bd565b67ffffffffffffffff166080850152613de1565b8160061415613edd57613ec9836141bd565b67ffffffffffffffff1660a0850152613de1565b8160071415613efc57613ef26139988461423f565b60c0850152613de1565b613f068382614356565b613de1565b6001600160a01b03811660009081526008602052604090205460ff16613f735760405162461bcd60e51b815260206004820152601760248201527f4163636f756e74206973206e6f7420676f7665726e6f720000000000000000006044820152606401610bbd565b6001600160a01b038116600081815260086020908152604091829020805460ff1916905590519182527f1ebe834e73d60a5fec822c1e1727d34bc79f2ad977ed504581cc1822fe20fb5b9101611010565b6000614019826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166143c89092919063ffffffff16565b80519091501561385957808060200190518101906140379190614f3e565b6138595760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610bbd565b60008151604114156140dd5760208201516040830151606084015160001a6140d3868285856143e1565b935050505061414d565b81516040141561410557602082015160408301516140fc85838361458a565b9250505061414d565b60405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610bbd565b92915050565b6040516001600160a01b03831660248201526044810182905261385990849063a9059cbb60e01b90606401612f89565b6000806000614191846141bd565b905061419e600882614e53565b92508060071660058111156141b5576141b5614f60565b915050915091565b602080820151825181019091015160009182805b600a8110156142395783811a91506141ea816007614e34565b82607f16901b8517945081608016600014156142275761420b816001614d2b565b8651879061421a908390614d2b565b9052509395945050505050565b8061423181614d10565b9150506141d1565b50600080fd5b6060600061424c836141bd565b905060008184600001516142609190614d2b565b905083602001515181111561427457600080fd5b8167ffffffffffffffff81111561428d5761428d614944565b6040519080825280601f01601f1916602001820160405280156142b7576020820181803683370190505b50602080860151865192955091818601919083010160005b858110156142f15781810151838201526142ea602082614d2b565b90506142cf565b505050935250919050565b600061414d826145cd565b600060208251111561431857600080fd5b602082015190508151602061432d9190614f76565b614338906008614e34565b1c919050565b6000815160201461434e57600080fd5b506020015190565b600081600581111561436a5761436a614f60565b141561437957613859826141bd565b600281600581111561438d5761438d614f60565b141561037657600061439e836141bd565b905080836000018181516143b29190614d2b565b9052506020830151518351111561385957600080fd5b60606143d784846000856145f5565b90505b9392505050565b60007f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a082111561445e5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610bbd565b8360ff16601b148061447357508360ff16601c145b6144ca5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b6064820152608401610bbd565b6040805160008082526020820180845288905260ff871692820192909252606081018590526080810184905260019060a0016020604051602081039080840390855afa15801561451e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166145815760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610bbd565b95945050505050565b60007f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821660ff83901c601b016145c3868287856143e1565b9695505050505050565b600081516014146145dd57600080fd5b50602001516c01000000000000000000000000900490565b60608247101561466d5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610bbd565b843b6146bb5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610bbd565b600080866001600160a01b031685876040516146d79190614fb9565b60006040518083038185875af1925050503d8060008114614714576040519150601f19603f3d011682016040523d82523d6000602084013e614719565b606091505b5091509150614729828286614734565b979650505050505050565b606083156147435750816143da565b8251156147535782518084602001fd5b8160405162461bcd60e51b8152600401610bbd9190614fd5565b60008083601f84011261477f57600080fd5b50813567ffffffffffffffff81111561479757600080fd5b6020830191508360208260051b85010111156147b257600080fd5b9250929050565b600080600080604085870312156147cf57600080fd5b843567ffffffffffffffff808211156147e757600080fd5b6147f38883890161476d565b9096509450602087013591508082111561480c57600080fd5b506148198782880161476d565b95989497509550505050565b80356001600160a01b038116811461483c57600080fd5b919050565b60006020828403121561485357600080fd5b6143da82614825565b60006020828403121561486e57600080fd5b5035919050565b803567ffffffffffffffff8116811461483c57600080fd5b803563ffffffff8116811461483c57600080fd5b600080600080600060a086880312156148b957600080fd5b6148c286614825565b9450602086013593506148d760408701614875565b92506148e560608701614875565b91506148f36080870161488d565b90509295509295909350565b60006020828403121561491157600080fd5b6143da8261488d565b6000806040838503121561492d57600080fd5b61493683614825565b946020939093013593505050565b634e487b7160e01b600052604160045260246000fd5b60008060008060008060006080888a03121561497557600080fd5b873567ffffffffffffffff8082111561498d57600080fd5b818a0191508a601f8301126149a157600080fd5b8135818111156149b3576149b3614944565b604051601f8201601f19908116603f011681019083821181831017156149db576149db614944565b816040528281528d60208487010111156149f457600080fd5b82602086016020830137600094508460208483010152809b5050505060208a013581811115614a21578283fd5b614a2d8c828d0161476d565b90995097505060408a013581811115614a44578283fd5b614a508c828d0161476d565b90975095505060608a013581811115614a67578283fd5b614a738c828d0161476d565b9a9d999c50979a509598949794955050505050565b6000806000806000806000806080898b031215614aa457600080fd5b883567ffffffffffffffff80821115614abc57600080fd5b818b0191508b601f830112614ad057600080fd5b813581811115614adf57600080fd5b8c6020828501011115614af157600080fd5b60209283019a509850908a01359080821115614b0c57600080fd5b614b188c838d0161476d565b909850965060408b0135915080821115614b3157600080fd5b614b3d8c838d0161476d565b909650945060608b0135915080821115614b5657600080fd5b50614b638b828c0161476d565b999c989b5096995094979396929594505050565b60008060008060008060c08789031215614b9057600080fd5b614b9987614825565b9550614ba760208801614825565b945060408701359350614bbc60608801614875565b9250614bca60808801614875565b9150614bd860a0880161488d565b90509295509295509295565b600080600080600080600080600080600060c08c8e031215614c0557600080fd5b8b359a5067ffffffffffffffff8060208e01351115614c2357600080fd5b614c338e60208f01358f0161476d565b909b50995060408d0135811015614c4957600080fd5b614c598e60408f01358f0161476d565b909950975060608d0135811015614c6f57600080fd5b614c7f8e60608f01358f0161476d565b909750955060808d0135811015614c9557600080fd5b614ca58e60808f01358f0161476d565b909550935060a08d0135811015614cbb57600080fd5b50614ccc8d60a08e01358e0161476d565b81935080925050509295989b509295989b9093969950565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415614d2457614d24614cfa565b5060010190565b60008219821115614d3e57614d3e614cfa565b500190565b600067ffffffffffffffff808316818516808303821115614d6657614d66614cfa565b01949350505050565b60008160005b84811015614da4576001600160a01b03614d8e83614825565b1686526020958601959190910190600101614d75565b5093949350505050565b60006001600160fb1b03831115614dc457600080fd5b8260051b8083863760009401938452509192915050565b60006145c3614deb838789614d6f565b8486614dae565b838152818360208301376000910160200190815292915050565b8681528560208201526000614e28614deb604084018789614d6f565b98975050505050505050565b6000816000190483118215151615614e4e57614e4e614cfa565b500290565b600082614e7057634e487b7160e01b600052601260045260246000fd5b500490565b6000808335601e19843603018112614e8c57600080fd5b83018035915067ffffffffffffffff821115614ea757600080fd5b6020019150368190038213156147b257600080fd5b6040808252810184905260008560608301825b87811015614efd576001600160a01b03614ee884614825565b16825260209283019290910190600101614ecf565b5083810360208501528481526001600160fb1b03851115614f1d57600080fd5b8460051b915081866020830137600091016020019081529695505050505050565b600060208284031215614f5057600080fd5b815180151581146143da57600080fd5b634e487b7160e01b600052602160045260246000fd5b600082821015614f8857614f88614cfa565b500390565b60005b83811015614fa8578181015183820152602001614f90565b838111156123e55750506000910152565b60008251614fcb818460208701614f8d565b9190910192915050565b6020815260008251806020840152614ff4816040850160208701614f8d565b601f01601f1916919091016040019291505056fe4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572a264697066735822122041c4c43a181078f6a3d94196af5f8c8b055bb458f7ac531bc9c6cf093842aa8264736f6c63430008090033","name":"Bridge","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"@openzeppelin/contracts/access/Ownable.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/security/Pausable.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which allows children to implement an emergency stop\n * mechanism that can be triggered by an authorized account.\n *\n * This module is used through inheritance. It will make available the\n * modifiers `whenNotPaused` and `whenPaused`, which can be applied to\n * the functions of your contract. Note that they will not be pausable by\n * simply including this module, only once the modifiers are put in place.\n */\nabstract contract Pausable is Context {\n    /**\n     * @dev Emitted when the pause is triggered by `account`.\n     */\n    event Paused(address account);\n\n    /**\n     * @dev Emitted when the pause is lifted by `account`.\n     */\n    event Unpaused(address account);\n\n    bool private _paused;\n\n    /**\n     * @dev Initializes the contract in unpaused state.\n     */\n    constructor() {\n        _paused = false;\n    }\n\n    /**\n     * @dev Returns true if the contract is paused, and false otherwise.\n     */\n    function paused() public view virtual returns (bool) {\n        return _paused;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is not paused.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    modifier whenNotPaused() {\n        require(!paused(), \"Pausable: paused\");\n        _;\n    }\n\n    /**\n     * @dev Modifier to make a function callable only when the contract is paused.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    modifier whenPaused() {\n        require(paused(), \"Pausable: not paused\");\n        _;\n    }\n\n    /**\n     * @dev Triggers stopped state.\n     *\n     * Requirements:\n     *\n     * - The contract must not be paused.\n     */\n    function _pause() internal virtual whenNotPaused {\n        _paused = true;\n        emit Paused(_msgSender());\n    }\n\n    /**\n     * @dev Returns to normal state.\n     *\n     * Requirements:\n     *\n     * - The contract must be paused.\n     */\n    function _unpause() internal virtual whenPaused {\n        _paused = false;\n        emit Unpaused(_msgSender());\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/security/ReentrancyGuard.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuard {\n    // Booleans are more expensive than uint256 or any type that takes up a full\n    // word because each write operation emits an extra SLOAD to first read the\n    // slot's contents, replace the bits taken up by the boolean, and then write\n    // back. This is the compiler's defense against contract upgrades and\n    // pointer aliasing, and it cannot be disabled.\n\n    // The values being non-zero value makes deployment a bit more expensive,\n    // but in exchange the refund on every call to nonReentrant will be lower in\n    // amount. Since refunds are capped to a percentage of the total\n    // transaction's gas, it is best to keep them low in cases like this one, to\n    // increase the likelihood of the full refund coming into effect.\n    uint256 private constant _NOT_ENTERED = 1;\n    uint256 private constant _ENTERED = 2;\n\n    uint256 private _status;\n\n    constructor() {\n        _status = _NOT_ENTERED;\n    }\n\n    /**\n     * @dev Prevents a contract from calling itself, directly or indirectly.\n     * Calling a `nonReentrant` function from another `nonReentrant`\n     * function is not supported. It is possible to prevent this from happening\n     * by making the `nonReentrant` function external, and make it call a\n     * `private` function that does the actual work.\n     */\n    modifier nonReentrant() {\n        // On the first call to nonReentrant, _notEntered will be true\n        require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n        // Any calls to nonReentrant after this point will fail\n        _status = _ENTERED;\n\n        _;\n\n        // By storing the original value once again, a refund is triggered (see\n        // https://eips.ethereum.org/EIPS/eip-2200)\n        _status = _NOT_ENTERED;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Address.sol","source_code":"// 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    function _verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) private 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"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// 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"},{"file_path":"@openzeppelin/contracts/utils/cryptography/ECDSA.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n    /**\n     * @dev Returns the address that signed a hashed message (`hash`) with\n     * `signature`. This address can then be used for verification purposes.\n     *\n     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n     * this function rejects them by requiring the `s` value to be in the lower\n     * half order, and the `v` value to be either 27 or 28.\n     *\n     * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n     * verification to be secure: it is possible to craft signatures that\n     * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n     * this is by receiving a hash of the original message (which may otherwise\n     * be too long), and then calling {toEthSignedMessageHash} on it.\n     *\n     * Documentation for signature generation:\n     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n     */\n    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n        // Check the signature length\n        // - case 65: r,s,v signature (standard)\n        // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            return recover(hash, v, r, s);\n        } else if (signature.length == 64) {\n            bytes32 r;\n            bytes32 vs;\n            // ecrecover takes the signature parameters, and the only way to get them\n            // currently is to use assembly.\n            assembly {\n                r := mload(add(signature, 0x20))\n                vs := mload(add(signature, 0x40))\n            }\n            return recover(hash, r, vs);\n        } else {\n            revert(\"ECDSA: invalid signature length\");\n        }\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `r` and `vs` short-signature fields separately.\n     *\n     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n     *\n     * _Available since v4.2._\n     */\n    function recover(\n        bytes32 hash,\n        bytes32 r,\n        bytes32 vs\n    ) internal pure returns (address) {\n        bytes32 s;\n        uint8 v;\n        assembly {\n            s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n            v := add(shr(255, vs), 27)\n        }\n        return recover(hash, v, r, s);\n    }\n\n    /**\n     * @dev Overload of {ECDSA-recover} that receives the `v`, `r` and `s` signature fields separately.\n     */\n    function recover(\n        bytes32 hash,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal pure returns (address) {\n        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most\n        // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n        //\n        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n        // these malleable signatures as well.\n        require(\n            uint256(s) <= 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0,\n            \"ECDSA: invalid signature 's' value\"\n        );\n        require(v == 27 || v == 28, \"ECDSA: invalid signature 'v' value\");\n\n        // If the signature is valid (and not malleable), return the signer address\n        address signer = ecrecover(hash, v, r, s);\n        require(signer != address(0), \"ECDSA: invalid signature\");\n\n        return signer;\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n     * produces hash corresponding to the one signed with the\n     * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n     * JSON-RPC method as part of EIP-191.\n     *\n     * See {recover}.\n     */\n    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n        // 32 is the length in bytes of hash,\n        // enforced by the type signature above\n        return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n    }\n\n    /**\n     * @dev Returns an Ethereum Signed Typed Data, created from a\n     * `domainSeparator` and a `structHash`. This produces hash corresponding\n     * to the one signed with the\n     * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n     * JSON-RPC method as part of EIP-712.\n     *\n     * See {recover}.\n     */\n    function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n        return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n    }\n}\n"},{"file_path":"contracts/Pool.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/security/ReentrancyGuard.sol\";\nimport \"./interfaces/IWETH.sol\";\nimport \"./libraries/PbPool.sol\";\nimport \"./safeguard/Pauser.sol\";\nimport \"./safeguard/VolumeControl.sol\";\nimport \"./safeguard/DelayedTransfer.sol\";\nimport \"./Signers.sol\";\n\n// add liquidity and withdraw\n// withdraw can be used by user or liquidity provider\n\ncontract Pool is Signers, ReentrancyGuard, Pauser, VolumeControl, DelayedTransfer {\n    using SafeERC20 for IERC20;\n\n    uint64 public addseq; // ensure unique LiquidityAdded event, start from 1\n    mapping(address => uint256) public minAdd; // add _amount must > minAdd\n\n    // map of successful withdraws, if true means already withdrew money or added to delayedTransfers\n    mapping(bytes32 => bool) public withdraws;\n\n    // erc20 wrap of gas token of this chain, eg. WETH, when relay ie. pay out,\n    // if request.token equals this, will withdraw and send native token to receiver\n    // note we don't check whether it's zero address. when this isn't set, and request.token\n    // is all 0 address, guarantee fail\n    address public nativeWrap;\n\n    // liquidity events\n    event LiquidityAdded(\n        uint64 seqnum,\n        address provider,\n        address token,\n        uint256 amount // how many tokens were added\n    );\n    event WithdrawDone(\n        bytes32 withdrawId,\n        uint64 seqnum,\n        address receiver,\n        address token,\n        uint256 amount,\n        bytes32 refid\n    );\n    event MinAddUpdated(address token, uint256 amount);\n\n    function addLiquidity(address _token, uint256 _amount) external nonReentrant whenNotPaused {\n        require(_amount > minAdd[_token], \"amount too small\");\n        addseq += 1;\n        IERC20(_token).safeTransferFrom(msg.sender, address(this), _amount);\n        emit LiquidityAdded(addseq, msg.sender, _token, _amount);\n    }\n\n    function addNativeLiquidity(uint256 _amount) external payable nonReentrant whenNotPaused {\n        require(msg.value == _amount, \"Amount mismatch\");\n        require(nativeWrap != address(0), \"Native wrap not set\");\n        require(_amount > minAdd[nativeWrap], \"amount too small\");\n        addseq += 1;\n        IWETH(nativeWrap).deposit{value: _amount}();\n        emit LiquidityAdded(addseq, msg.sender, nativeWrap, _amount);\n    }\n\n    function withdraw(\n        bytes calldata _wdmsg,\n        bytes[] calldata _sigs,\n        address[] calldata _signers,\n        uint256[] calldata _powers\n    ) external whenNotPaused {\n        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), \"WithdrawMsg\"));\n        verifySigs(abi.encodePacked(domain, _wdmsg), _sigs, _signers, _powers);\n        // decode and check wdmsg\n        PbPool.WithdrawMsg memory wdmsg = PbPool.decWithdrawMsg(_wdmsg);\n        bytes32 wdId = keccak256(\n            abi.encodePacked(wdmsg.chainid, wdmsg.seqnum, wdmsg.receiver, wdmsg.token, wdmsg.amount)\n        );\n        require(withdraws[wdId] == false, \"withdraw already succeeded\");\n        withdraws[wdId] = true;\n        _updateVolume(wdmsg.token, wdmsg.amount);\n        uint256 delayThreshold = delayThresholds[wdmsg.token];\n        if (delayThreshold > 0 && wdmsg.amount > delayThreshold) {\n            _addDelayedTransfer(wdId, wdmsg.receiver, wdmsg.token, wdmsg.amount);\n        } else {\n            _sendToken(wdmsg.receiver, wdmsg.token, wdmsg.amount);\n        }\n        emit WithdrawDone(wdId, wdmsg.seqnum, wdmsg.receiver, wdmsg.token, wdmsg.amount, wdmsg.refid);\n    }\n\n    function executeDelayedTransfer(bytes32 id) external whenNotPaused {\n        delayedTransfer memory transfer = _executeDelayedTransfer(id);\n        _sendToken(transfer.receiver, transfer.token, transfer.amount);\n    }\n\n    function setMinAdd(address[] calldata _tokens, uint256[] calldata _amounts) external onlyGovernor {\n        require(_tokens.length == _amounts.length, \"length mismatch\");\n        for (uint256 i = 0; i < _tokens.length; i++) {\n            minAdd[_tokens[i]] = _amounts[i];\n            emit MinAddUpdated(_tokens[i], _amounts[i]);\n        }\n    }\n\n    function _sendToken(\n        address _receiver,\n        address _token,\n        uint256 _amount\n    ) internal {\n        if (_token == nativeWrap) {\n            // withdraw then transfer native to receiver\n            IWETH(nativeWrap).withdraw(_amount);\n            (bool sent, ) = _receiver.call{value: _amount, gas: 50000}(\"\");\n            require(sent, \"failed to send native token\");\n        } else {\n            IERC20(_token).safeTransfer(_receiver, _amount);\n        }\n    }\n\n    // set nativeWrap, for relay requests, if token == nativeWrap, will withdraw first then transfer native to receiver\n    function setWrap(address _weth) external onlyOwner {\n        nativeWrap = _weth;\n    }\n}\n"},{"file_path":"contracts/Signers.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"./interfaces/ISigsVerifier.sol\";\n\ncontract Signers is Ownable, ISigsVerifier {\n    using ECDSA for bytes32;\n\n    bytes32 public ssHash;\n    uint256 public triggerTime; // timestamp when last update was triggered\n\n    // reset can be called by the owner address for emergency recovery\n    uint256 public resetTime;\n    uint256 public noticePeriod; // advance notice period as seconds for reset\n    uint256 constant MAX_INT = 2**256 - 1;\n\n    event SignersUpdated(address[] _signers, uint256[] _powers);\n\n    event ResetNotification(uint256 resetTime);\n\n    /**\n     * @notice Verifies that a message is signed by a quorum among the signers\n     * The sigs must be sorted by signer addresses in ascending order.\n     * @param _msg signed message\n     * @param _sigs list of signatures sorted by signer addresses\n     * @param _signers sorted list of current signers\n     * @param _powers powers of current signers\n     */\n    function verifySigs(\n        bytes memory _msg,\n        bytes[] calldata _sigs,\n        address[] calldata _signers,\n        uint256[] calldata _powers\n    ) public view override {\n        bytes32 h = keccak256(abi.encodePacked(_signers, _powers));\n        require(ssHash == h, \"Mismatch current signers\");\n        _verifySignedPowers(keccak256(_msg).toEthSignedMessageHash(), _sigs, _signers, _powers);\n    }\n\n    /**\n     * @notice Update new signers.\n     * @param _newSigners sorted list of new signers\n     * @param _curPowers powers of new signers\n     * @param _sigs list of signatures sorted by signer addresses\n     * @param _curSigners sorted list of current signers\n     * @param _curPowers powers of current signers\n     */\n    function updateSigners(\n        uint256 _triggerTime,\n        address[] calldata _newSigners,\n        uint256[] calldata _newPowers,\n        bytes[] calldata _sigs,\n        address[] calldata _curSigners,\n        uint256[] calldata _curPowers\n    ) external {\n        // use trigger time for nonce protection, must be ascending\n        require(_triggerTime > triggerTime, \"Trigger time is not increasing\");\n        // make sure triggerTime is not too large, as it cannot be decreased once set\n        require(_triggerTime < block.timestamp + 3600, \"Trigger time is too large\");\n        bytes32 domain = keccak256(abi.encodePacked(block.chainid, address(this), \"UpdateSigners\"));\n        verifySigs(abi.encodePacked(domain, _triggerTime, _newSigners, _newPowers), _sigs, _curSigners, _curPowers);\n        _updateSigners(_newSigners, _newPowers);\n        triggerTime = _triggerTime;\n    }\n\n    /**\n     * @notice reset signers, only used for init setup and emergency recovery\n     */\n    function resetSigners(address[] calldata _signers, uint256[] calldata _powers) external onlyOwner {\n        require(block.timestamp > resetTime, \"not reach reset time\");\n        resetTime = MAX_INT;\n        _updateSigners(_signers, _powers);\n    }\n\n    function notifyResetSigners() external onlyOwner {\n        resetTime = block.timestamp + noticePeriod;\n        emit ResetNotification(resetTime);\n    }\n\n    function increaseNoticePeriod(uint256 period) external onlyOwner {\n        require(period > noticePeriod, \"notice period can only be increased\");\n        noticePeriod = period;\n    }\n\n    // separate from verifySigs func to avoid \"stack too deep\" issue\n    function _verifySignedPowers(\n        bytes32 _hash,\n        bytes[] calldata _sigs,\n        address[] calldata _signers,\n        uint256[] calldata _powers\n    ) private pure {\n        require(_signers.length == _powers.length, \"signers and powers length not match\");\n        uint256 totalPower; // sum of all signer.power\n        for (uint256 i = 0; i < _signers.length; i++) {\n            totalPower += _powers[i];\n        }\n        uint256 quorum = (totalPower * 2) / 3 + 1;\n\n        uint256 signedPower; // sum of signer powers who are in sigs\n        address prev = address(0);\n        uint256 index = 0;\n        for (uint256 i = 0; i < _sigs.length; i++) {\n            address signer = _hash.recover(_sigs[i]);\n            require(signer > prev, \"signers not in ascending order\");\n            prev = signer;\n            // now find match signer add its power\n            while (signer > _signers[index]) {\n                index += 1;\n                require(index < _signers.length, \"signer not found\");\n            }\n            if (signer == _signers[index]) {\n                signedPower += _powers[index];\n            }\n            if (signedPower >= quorum) {\n                // return early to save gas\n                return;\n            }\n        }\n        revert(\"quorum not reached\");\n    }\n\n    function _updateSigners(address[] calldata _signers, uint256[] calldata _powers) private {\n        require(_signers.length == _powers.length, \"signers and powers length not match\");\n        address prev = address(0);\n        for (uint256 i = 0; i < _signers.length; i++) {\n            require(_signers[i] > prev, \"New signers not in ascending order\");\n            prev = _signers[i];\n        }\n        ssHash = keccak256(abi.encodePacked(_signers, _powers));\n        emit SignersUpdated(_signers, _powers);\n    }\n}\n"},{"file_path":"contracts/interfaces/ISigsVerifier.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\ninterface ISigsVerifier {\n    /**\n     * @notice Verifies that a message is signed by a quorum among the signers.\n     * @param _msg signed message\n     * @param _sigs list of signatures sorted by signer addresses\n     * @param _signers sorted list of current signers\n     * @param _powers powers of current signers\n     */\n    function verifySigs(\n        bytes memory _msg,\n        bytes[] calldata _sigs,\n        address[] calldata _signers,\n        uint256[] calldata _powers\n    ) external view;\n}\n"},{"file_path":"contracts/interfaces/IWETH.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\ninterface IWETH {\n    function deposit() external payable;\n\n    function withdraw(uint256) external;\n}\n"},{"file_path":"contracts/libraries/Pb.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\n// runtime proto sol library\nlibrary Pb {\n    enum WireType {\n        Varint,\n        Fixed64,\n        LengthDelim,\n        StartGroup,\n        EndGroup,\n        Fixed32\n    }\n\n    struct Buffer {\n        uint256 idx; // the start index of next read. when idx=b.length, we're done\n        bytes b; // hold serialized proto msg, readonly\n    }\n\n    // create a new in-memory Buffer object from raw msg bytes\n    function fromBytes(bytes memory raw) internal pure returns (Buffer memory buf) {\n        buf.b = raw;\n        buf.idx = 0;\n    }\n\n    // whether there are unread bytes\n    function hasMore(Buffer memory buf) internal pure returns (bool) {\n        return buf.idx < buf.b.length;\n    }\n\n    // decode current field number and wiretype\n    function decKey(Buffer memory buf) internal pure returns (uint256 tag, WireType wiretype) {\n        uint256 v = decVarint(buf);\n        tag = v / 8;\n        wiretype = WireType(v & 7);\n    }\n\n    // count tag occurrences, return an array due to no memory map support\n    // have to create array for (maxtag+1) size. cnts[tag] = occurrences\n    // should keep buf.idx unchanged because this is only a count function\n    function cntTags(Buffer memory buf, uint256 maxtag) internal pure returns (uint256[] memory cnts) {\n        uint256 originalIdx = buf.idx;\n        cnts = new uint256[](maxtag + 1); // protobuf's tags are from 1 rather than 0\n        uint256 tag;\n        WireType wire;\n        while (hasMore(buf)) {\n            (tag, wire) = decKey(buf);\n            cnts[tag] += 1;\n            skipValue(buf, wire);\n        }\n        buf.idx = originalIdx;\n    }\n\n    // read varint from current buf idx, move buf.idx to next read, return the int value\n    function decVarint(Buffer memory buf) internal pure returns (uint256 v) {\n        bytes10 tmp; // proto int is at most 10 bytes (7 bits can be used per byte)\n        bytes memory bb = buf.b; // get buf.b mem addr to use in assembly\n        v = buf.idx; // use v to save one additional uint variable\n        assembly {\n            tmp := mload(add(add(bb, 32), v)) // load 10 bytes from buf.b[buf.idx] to tmp\n        }\n        uint256 b; // store current byte content\n        v = 0; // reset to 0 for return value\n        for (uint256 i = 0; i < 10; i++) {\n            assembly {\n                b := byte(i, tmp) // don't use tmp[i] because it does bound check and costs extra\n            }\n            v |= (b & 0x7F) << (i * 7);\n            if (b & 0x80 == 0) {\n                buf.idx += i + 1;\n                return v;\n            }\n        }\n        revert(); // i=10, invalid varint stream\n    }\n\n    // read length delimited field and return bytes\n    function decBytes(Buffer memory buf) internal pure returns (bytes memory b) {\n        uint256 len = decVarint(buf);\n        uint256 end = buf.idx + len;\n        require(end <= buf.b.length); // avoid overflow\n        b = new bytes(len);\n        bytes memory bufB = buf.b; // get buf.b mem addr to use in assembly\n        uint256 bStart;\n        uint256 bufBStart = buf.idx;\n        assembly {\n            bStart := add(b, 32)\n            bufBStart := add(add(bufB, 32), bufBStart)\n        }\n        for (uint256 i = 0; i < len; i += 32) {\n            assembly {\n                mstore(add(bStart, i), mload(add(bufBStart, i)))\n            }\n        }\n        buf.idx = end;\n    }\n\n    // return packed ints\n    function decPacked(Buffer memory buf) internal pure returns (uint256[] memory t) {\n        uint256 len = decVarint(buf);\n        uint256 end = buf.idx + len;\n        require(end <= buf.b.length); // avoid overflow\n        // array in memory must be init w/ known length\n        // so we have to create a tmp array w/ max possible len first\n        uint256[] memory tmp = new uint256[](len);\n        uint256 i = 0; // count how many ints are there\n        while (buf.idx < end) {\n            tmp[i] = decVarint(buf);\n            i++;\n        }\n        t = new uint256[](i); // init t with correct length\n        for (uint256 j = 0; j < i; j++) {\n            t[j] = tmp[j];\n        }\n        return t;\n    }\n\n    // move idx pass current value field, to beginning of next tag or msg end\n    function skipValue(Buffer memory buf, WireType wire) internal pure {\n        if (wire == WireType.Varint) {\n            decVarint(buf);\n        } else if (wire == WireType.LengthDelim) {\n            uint256 len = decVarint(buf);\n            buf.idx += len; // skip len bytes value data\n            require(buf.idx <= buf.b.length); // avoid overflow\n        } else {\n            revert();\n        } // unsupported wiretype\n    }\n\n    // type conversion help utils\n    function _bool(uint256 x) internal pure returns (bool v) {\n        return x != 0;\n    }\n\n    function _uint256(bytes memory b) internal pure returns (uint256 v) {\n        require(b.length <= 32); // b's length must be smaller than or equal to 32\n        assembly {\n            v := mload(add(b, 32))\n        } // load all 32bytes to v\n        v = v >> (8 * (32 - b.length)); // only first b.length is valid\n    }\n\n    function _address(bytes memory b) internal pure returns (address v) {\n        v = _addressPayable(b);\n    }\n\n    function _addressPayable(bytes memory b) internal pure returns (address payable v) {\n        require(b.length == 20);\n        //load 32bytes then shift right 12 bytes\n        assembly {\n            v := div(mload(add(b, 32)), 0x1000000000000000000000000)\n        }\n    }\n\n    function _bytes32(bytes memory b) internal pure returns (bytes32 v) {\n        require(b.length == 32);\n        assembly {\n            v := mload(add(b, 32))\n        }\n    }\n\n    // uint[] to uint8[]\n    function uint8s(uint256[] memory arr) internal pure returns (uint8[] memory t) {\n        t = new uint8[](arr.length);\n        for (uint256 i = 0; i < t.length; i++) {\n            t[i] = uint8(arr[i]);\n        }\n    }\n\n    function uint32s(uint256[] memory arr) internal pure returns (uint32[] memory t) {\n        t = new uint32[](arr.length);\n        for (uint256 i = 0; i < t.length; i++) {\n            t[i] = uint32(arr[i]);\n        }\n    }\n\n    function uint64s(uint256[] memory arr) internal pure returns (uint64[] memory t) {\n        t = new uint64[](arr.length);\n        for (uint256 i = 0; i < t.length; i++) {\n            t[i] = uint64(arr[i]);\n        }\n    }\n\n    function bools(uint256[] memory arr) internal pure returns (bool[] memory t) {\n        t = new bool[](arr.length);\n        for (uint256 i = 0; i < t.length; i++) {\n            t[i] = arr[i] != 0;\n        }\n    }\n}\n"},{"file_path":"contracts/libraries/PbBridge.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\n// Code generated by protoc-gen-sol. DO NOT EDIT.\n// source: bridge.proto\npragma solidity 0.8.9;\nimport \"./Pb.sol\";\n\nlibrary PbBridge {\n    using Pb for Pb.Buffer; // so we can call Pb funcs on Buffer obj\n\n    struct Relay {\n        address sender; // tag: 1\n        address receiver; // tag: 2\n        address token; // tag: 3\n        uint256 amount; // tag: 4\n        uint64 srcChainId; // tag: 5\n        uint64 dstChainId; // tag: 6\n        bytes32 srcTransferId; // tag: 7\n    } // end struct Relay\n\n    function decRelay(bytes memory raw) internal pure returns (Relay memory m) {\n        Pb.Buffer memory buf = Pb.fromBytes(raw);\n\n        uint256 tag;\n        Pb.WireType wire;\n        while (buf.hasMore()) {\n            (tag, wire) = buf.decKey();\n            if (false) {}\n            // solidity has no switch/case\n            else if (tag == 1) {\n                m.sender = Pb._address(buf.decBytes());\n            } else if (tag == 2) {\n                m.receiver = Pb._address(buf.decBytes());\n            } else if (tag == 3) {\n                m.token = Pb._address(buf.decBytes());\n            } else if (tag == 4) {\n                m.amount = Pb._uint256(buf.decBytes());\n            } else if (tag == 5) {\n                m.srcChainId = uint64(buf.decVarint());\n            } else if (tag == 6) {\n                m.dstChainId = uint64(buf.decVarint());\n            } else if (tag == 7) {\n                m.srcTransferId = Pb._bytes32(buf.decBytes());\n            } else {\n                buf.skipValue(wire);\n            } // skip value of unknown tag\n        }\n    } // end decoder Relay\n}\n"},{"file_path":"contracts/libraries/PbPool.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\n// Code generated by protoc-gen-sol. DO NOT EDIT.\n// source: contracts/libraries/proto/pool.proto\npragma solidity 0.8.9;\nimport \"./Pb.sol\";\n\nlibrary PbPool {\n    using Pb for Pb.Buffer; // so we can call Pb funcs on Buffer obj\n\n    struct WithdrawMsg {\n        uint64 chainid; // tag: 1\n        uint64 seqnum; // tag: 2\n        address receiver; // tag: 3\n        address token; // tag: 4\n        uint256 amount; // tag: 5\n        bytes32 refid; // tag: 6\n    } // end struct WithdrawMsg\n\n    function decWithdrawMsg(bytes memory raw) internal pure returns (WithdrawMsg memory m) {\n        Pb.Buffer memory buf = Pb.fromBytes(raw);\n\n        uint256 tag;\n        Pb.WireType wire;\n        while (buf.hasMore()) {\n            (tag, wire) = buf.decKey();\n            if (false) {}\n            // solidity has no switch/case\n            else if (tag == 1) {\n                m.chainid = uint64(buf.decVarint());\n            } else if (tag == 2) {\n                m.seqnum = uint64(buf.decVarint());\n            } else if (tag == 3) {\n                m.receiver = Pb._address(buf.decBytes());\n            } else if (tag == 4) {\n                m.token = Pb._address(buf.decBytes());\n            } else if (tag == 5) {\n                m.amount = Pb._uint256(buf.decBytes());\n            } else if (tag == 6) {\n                m.refid = Pb._bytes32(buf.decBytes());\n            } else {\n                buf.skipValue(wire);\n            } // skip value of unknown tag\n        }\n    } // end decoder WithdrawMsg\n}\n"},{"file_path":"contracts/safeguard/DelayedTransfer.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"./Governor.sol\";\n\nabstract contract DelayedTransfer is Governor {\n    struct delayedTransfer {\n        address receiver;\n        address token;\n        uint256 amount;\n        uint256 timestamp;\n    }\n    mapping(bytes32 => delayedTransfer) public delayedTransfers;\n    mapping(address => uint256) public delayThresholds;\n    uint256 public delayPeriod; // in seconds\n\n    event DelayedTransferAdded(bytes32 id);\n    event DelayedTransferExecuted(bytes32 id, address receiver, address token, uint256 amount);\n\n    event DelayPeriodUpdated(uint256 period);\n    event DelayThresholdUpdated(address token, uint256 threshold);\n\n    function setDelayThresholds(address[] calldata _tokens, uint256[] calldata _thresholds) external onlyGovernor {\n        require(_tokens.length == _thresholds.length, \"length mismatch\");\n        for (uint256 i = 0; i < _tokens.length; i++) {\n            delayThresholds[_tokens[i]] = _thresholds[i];\n            emit DelayThresholdUpdated(_tokens[i], _thresholds[i]);\n        }\n    }\n\n    function setDelayPeriod(uint256 _period) external onlyGovernor {\n        delayPeriod = _period;\n        emit DelayPeriodUpdated(_period);\n    }\n\n    function _addDelayedTransfer(\n        bytes32 id,\n        address receiver,\n        address token,\n        uint256 amount\n    ) internal {\n        require(delayedTransfers[id].timestamp == 0, \"delayed transfer already exists\");\n        delayedTransfers[id] = delayedTransfer({\n            receiver: receiver,\n            token: token,\n            amount: amount,\n            timestamp: block.timestamp\n        });\n        emit DelayedTransferAdded(id);\n    }\n\n    // caller needs to do the actual token transfer\n    function _executeDelayedTransfer(bytes32 id) internal returns (delayedTransfer memory) {\n        delayedTransfer memory transfer = delayedTransfers[id];\n        require(transfer.timestamp > 0, \"delayed transfer not exist\");\n        require(block.timestamp > transfer.timestamp + delayPeriod, \"delayed transfer still locked\");\n        delete delayedTransfers[id];\n        emit DelayedTransferExecuted(id, transfer.receiver, transfer.token, transfer.amount);\n        return transfer;\n    }\n}\n"},{"file_path":"contracts/safeguard/Governor.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nabstract contract Governor is Ownable {\n    mapping(address => bool) public governors;\n\n    event GovernorAdded(address account);\n    event GovernorRemoved(address account);\n\n    modifier onlyGovernor() {\n        require(isGovernor(msg.sender), \"Caller is not governor\");\n        _;\n    }\n\n    constructor() {\n        _addGovernor(msg.sender);\n    }\n\n    function isGovernor(address _account) public view returns (bool) {\n        return governors[_account];\n    }\n\n    function addGovernor(address _account) public onlyOwner {\n        _addGovernor(_account);\n    }\n\n    function removeGovernor(address _account) public onlyOwner {\n        _removeGovernor(_account);\n    }\n\n    function renounceGovernor() public {\n        _removeGovernor(msg.sender);\n    }\n\n    function _addGovernor(address _account) private {\n        require(!isGovernor(_account), \"Account is already governor\");\n        governors[_account] = true;\n        emit GovernorAdded(_account);\n    }\n\n    function _removeGovernor(address _account) private {\n        require(isGovernor(_account), \"Account is not governor\");\n        governors[_account] = false;\n        emit GovernorRemoved(_account);\n    }\n}\n"},{"file_path":"contracts/safeguard/Pauser.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\nimport \"@openzeppelin/contracts/security/Pausable.sol\";\n\nabstract contract Pauser is Ownable, Pausable {\n    mapping(address => bool) public pausers;\n\n    event PauserAdded(address account);\n    event PauserRemoved(address account);\n\n    constructor() {\n        _addPauser(msg.sender);\n    }\n\n    modifier onlyPauser() {\n        require(isPauser(msg.sender), \"Caller is not pauser\");\n        _;\n    }\n\n    function pause() public onlyPauser {\n        _pause();\n    }\n\n    function unpause() public onlyPauser {\n        _unpause();\n    }\n\n    function isPauser(address account) public view returns (bool) {\n        return pausers[account];\n    }\n\n    function addPauser(address account) public onlyOwner {\n        _addPauser(account);\n    }\n\n    function removePauser(address account) public onlyOwner {\n        _removePauser(account);\n    }\n\n    function renouncePauser() public {\n        _removePauser(msg.sender);\n    }\n\n    function _addPauser(address account) private {\n        require(!isPauser(account), \"Account is already pauser\");\n        pausers[account] = true;\n        emit PauserAdded(account);\n    }\n\n    function _removePauser(address account) private {\n        require(isPauser(account), \"Account is not pauser\");\n        pausers[account] = false;\n        emit PauserRemoved(account);\n    }\n}\n"},{"file_path":"contracts/safeguard/VolumeControl.sol","source_code":"// SPDX-License-Identifier: GPL-3.0-only\n\npragma solidity 0.8.9;\n\nimport \"./Governor.sol\";\n\nabstract contract VolumeControl is Governor {\n    uint256 public epochLength; // seconds\n    mapping(address => uint256) public epochVolumes; // key is token\n    mapping(address => uint256) public epochVolumeCaps; // key is token\n    mapping(address => uint256) public lastOpTimestamps; // key is token\n\n    event EpochLengthUpdated(uint256 length);\n    event EpochVolumeUpdated(address token, uint256 cap);\n\n    function setEpochLength(uint256 _length) external onlyGovernor {\n        epochLength = _length;\n        emit EpochLengthUpdated(_length);\n    }\n\n    function setEpochVolumeCaps(address[] calldata _tokens, uint256[] calldata _caps) external onlyGovernor {\n        require(_tokens.length == _caps.length, \"length mismatch\");\n        for (uint256 i = 0; i < _tokens.length; i++) {\n            epochVolumeCaps[_tokens[i]] = _caps[i];\n            emit EpochVolumeUpdated(_tokens[i], _caps[i]);\n        }\n    }\n\n    function _updateVolume(address _token, uint256 _amount) internal {\n        if (epochLength == 0) {\n            return;\n        }\n        uint256 cap = epochVolumeCaps[_token];\n        if (cap == 0) {\n            return;\n        }\n        uint256 volume = epochVolumes[_token];\n        uint256 timestamp = block.timestamp;\n        uint256 epochStartTime = (timestamp / epochLength) * epochLength;\n        if (lastOpTimestamps[_token] < epochStartTime) {\n            volume = _amount;\n        } else {\n            volume += _amount;\n        }\n        require(volume <= cap, \"volume exceeds cap\");\n        epochVolumes[_token] = volume;\n        lastOpTimestamps[_token] = timestamp;\n    }\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"period","type":"uint256"}],"name":"DelayPeriodUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"threshold","type":"uint256"}],"name":"DelayThresholdUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"DelayedTransferAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"DelayedTransferExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"length","type":"uint256"}],"name":"EpochLengthUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"cap","type":"uint256"}],"name":"EpochVolumeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"GovernorAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"GovernorRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"seqnum","type":"uint64"},{"indexed":false,"internalType":"address","name":"provider","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LiquidityAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MaxSendUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinAddUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinSendUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"PauserRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"srcChainId","type":"uint64"},{"indexed":false,"internalType":"bytes32","name":"srcTransferId","type":"bytes32"}],"name":"Relay","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"resetTime","type":"uint256"}],"name":"ResetNotification","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"dstChainId","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"nonce","type":"uint64"},{"indexed":false,"internalType":"uint32","name":"maxSlippage","type":"uint32"}],"name":"Send","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"_signers","type":"address[]"},{"indexed":false,"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"SignersUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"withdrawId","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"seqnum","type":"uint64"},{"indexed":false,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"refid","type":"bytes32"}],"name":"WithdrawDone","type":"event"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"addGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"addNativeLiquidity","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"addPauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"addseq","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delayPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delayThresholds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"delayedTransfers","outputs":[{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"epochVolumeCaps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"epochVolumes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"executeDelayedTransfer","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"governors","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"period","type":"uint256"}],"name":"increaseNoticePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"isPauser","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"lastOpTimestamps","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"maxSend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minAdd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minSend","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimalMaxSlippage","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nativeWrap","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"noticePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"notifyResetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"pausers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_relayRequest","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"relay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_account","type":"address"}],"name":"removeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"removePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renouncePauser","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"resetSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resetTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint64","name":"_dstChainId","type":"uint64"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"uint32","name":"_maxSlippage","type":"uint32"}],"name":"send","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint64","name":"_dstChainId","type":"uint64"},{"internalType":"uint64","name":"_nonce","type":"uint64"},{"internalType":"uint32","name":"_maxSlippage","type":"uint32"}],"name":"sendNative","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_period","type":"uint256"}],"name":"setDelayPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_thresholds","type":"uint256[]"}],"name":"setDelayThresholds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_length","type":"uint256"}],"name":"setEpochLength","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_caps","type":"uint256[]"}],"name":"setEpochVolumeCaps","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"setMaxSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"setMinAdd","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"name":"setMinSend","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint32","name":"_minimalMaxSlippage","type":"uint32"}],"name":"setMinimalMaxSlippage","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_weth","type":"address"}],"name":"setWrap","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"ssHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transfers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"triggerTime","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_triggerTime","type":"uint256"},{"internalType":"address[]","name":"_newSigners","type":"address[]"},{"internalType":"uint256[]","name":"_newPowers","type":"uint256[]"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_curSigners","type":"address[]"},{"internalType":"uint256[]","name":"_curPowers","type":"uint256[]"}],"name":"updateSigners","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_msg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"verifySigs","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_wdmsg","type":"bytes"},{"internalType":"bytes[]","name":"_sigs","type":"bytes[]"},{"internalType":"address[]","name":"_signers","type":"address[]"},{"internalType":"uint256[]","name":"_powers","type":"uint256[]"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"withdraws","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":null}