{"file_path":"contracts/gateway/MintingHubGateway.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {MintingHub} from \"../MintingHubV2/MintingHub.sol\";\nimport {IFrontendGateway} from \"./interface/IFrontendGateway.sol\";\nimport {IMintingHubGateway} from \"./interface/IMintingHubGateway.sol\";\n\ncontract MintingHubGateway is MintingHub, IMintingHubGateway {\n    IFrontendGateway public immutable GATEWAY;\n\n    constructor(\n        address _deuro,\n        address _leadrate,\n        address _roller,\n        address _factory,\n        address _gateway\n    ) MintingHub(_deuro, _leadrate, _roller, _factory) {\n        GATEWAY = IFrontendGateway(_gateway);\n    }\n\n    function openPosition(\n        address _collateralAddress,\n        uint256 _minCollateral,\n        uint256 _initialCollateral,\n        uint256 _mintingMaximum,\n        uint40 _initPeriodSeconds,\n        uint40 _expirationSeconds,\n        uint40 _challengeSeconds,\n        uint24 _riskPremium,\n        uint256 _liqPrice,\n        uint24 _reservePPM,\n        bytes32 _frontendCode\n    ) public returns (address) {\n        address position = openPosition(\n            _collateralAddress,\n            _minCollateral,\n            _initialCollateral,\n            _mintingMaximum,\n            _initPeriodSeconds,\n            _expirationSeconds,\n            _challengeSeconds,\n            _riskPremium,\n            _liqPrice,\n            _reservePPM\n        );\n        GATEWAY.registerPosition(position, _frontendCode);\n        return position;\n    }\n\n    function clone(\n        address parent,\n        uint256 _initialCollateral,\n        uint256 _initialMint,\n        uint40 expiration,\n        bytes32 frontendCode\n    ) public returns (address) {\n        return clone(msg.sender, parent, _initialCollateral, _initialMint, expiration, frontendCode);\n    }\n\n    /**\n     * @notice Clones an existing position and immediately tries to mint the specified amount using the given collateral.\n     * @dev This needs an allowance to be set on the collateral contract such that the minting hub can get the collateral.\n     */\n    function clone(\n        address owner,\n        address parent,\n        uint256 _initialCollateral,\n        uint256 _initialMint,\n        uint40 expiration,\n        bytes32 frontendCode\n    ) public returns (address) {\n        address position = clone(owner, parent, _initialCollateral, _initialMint, expiration);\n        GATEWAY.registerPosition(position, frontendCode);\n        return position;\n    }\n\n    function notifyInterestPaid(uint256 amount) external validPos(msg.sender) {\n        GATEWAY.updatePositionRewards(msg.sender, amount);\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n        return interfaceId == type(IMintingHubGateway).interfaceId || super.supportsInterface(interfaceId);\n    }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b506004361061014d5760003560e01c80637d0ea02d116100c3578063c14a9f051161007c578063c14a9f0514610332578063dbe8a4c214610345578063e6ac5ea41461036c578063e6ca1df21461037f578063e85cde6f14610392578063f09e9e3a146103a557600080fd5b80637d0ea02d146102905780637eb81bb3146102a55780638f1d3776146102b857806393a83a24146103035780639d8ff2a614610316578063af5806b61461032957600080fd5b8063338c537111610115578063338c5371146101de57806335a4b349146102055780633bb84940146102185780634cb959141461022b578063643745fb1461023e578063664e97041461026957600080fd5b806301ffc9a7146101525780630f2f8e861461017a57806325e28124146101905780632bf78dd8146101a35780632e2c6314146101b3575b600080fd5b6101656101603660046128d7565b6103cc565b60405190151581526020015b60405180910390f35b610182600a81565b604051908152602001610171565b61018261019e366004612919565b6103f7565b610182683635c9adc5dea0000081565b6101c66101c1366004612958565b610643565b6040516001600160a01b039091168152602001610171565b6101c67f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a18099481565b6101c66102133660046129ba565b61065b565b6101c6610226366004612a60565b610c09565b6101c6610239366004612ab2565b610c23565b61018261024c366004612b69565b600160209081526000928352604080842090915290825290205481565b6101c67f000000000000000000000000073493d73258c4beb6542e8dd3e1b2891c97230381565b6102a361029e366004612ba2565b610ccc565b005b6102a36102b3366004612bdb565b610e04565b6102cb6102c6366004612ba2565b610ff9565b604080516001600160a01b03958616815264ffffffffff94909416602085015291909316908201526060810191909152608001610171565b6101c6610311366004612c1d565b61104b565b6101c6610324366004612c84565b6110ea565b610182614e2081565b610182610340366004612ce3565b61158e565b6101c67f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea81565b61018261037a366004612d18565b61194e565b61018261038d366004612d35565b611b5b565b6102a36103a0366004612b69565b611c68565b6101c67f0000000000000000000000004ce0ab2fc21bd27a47a64f594fdf7654ea57dc7981565b60006001600160e01b03198216632464e41b60e21b14806103f157506103f182611cfe565b92915050565b600080836001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045c9190612d52565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa1580156104a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c89190612d6f565b905060008184116104d957836104db565b815b905060006104e88661194e565b90506000670de0b6b3a76400006104ff8484612d9e565b6105099190612db5565b905060006105178486612dd7565b1180156105525750683635c9adc5dea00000670de0b6b3a764000061053c8587612dd7565b6105469085612d9e565b6105509190612db5565b105b15610586576105618385612dd7565b60405163f658c6cf60e01b815260040161057d91815260200190565b60405180910390fd5b60405163211d798360e01b815233600482015260248101849052604481018290526001600160a01b0388169063211d798390606401600060405180830381600087803b1580156105d557600080fd5b505af11580156105e9573d6000803e3d6000fd5b5050604080516001600160a01b038b168152602081018790529081018590527f67a660133c1fb4c0bb0480a5e4a9919216684052f13f0713e88fa2fbbc81d0829250606001905060405180910390a1509095945050505050565b600061065233868686866110ea565b95945050505050565b6000620f42408462ffffff1611156106865760405163b2772c5d60e01b815260040160405180910390fd5b8162ffffff16614e2011806106a25750620f42408262ffffff16115b156106c057604051633a3626e360e21b815260040160405180910390fd5b60188b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107249190612dea565b60ff161115610746576040516325dd4a5560e21b815260040160405180910390fd5b620151808564ffffffffff1610156107715760405163fc8c61b960e01b815260040160405180910390fd5b6203f4808764ffffffffff16101561079c5760405163f979252f60e01b815260040160405180910390fd5b60008b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108009190612d6f565b61080b906001612e0d565b60405163a9059cbb60e01b81529091506001600160a01b038d169063a9059cbb9061083e90610123908590600401612e20565b6020604051808303816000875af1925050508015610879575060408051601f3d908101601f1916820190925261087691810190612e39565b60015b6108f957610885612e56565b806308c379a0036108aa5750610899612ead565b806108a457506108c3565b50610913565b634e487b71036108c3576108bc612f32565b906108a457505b3d8080156108ed576040519150601f19603f3d011682016040523d82523d6000602084013e6108f2565b606091505b5050610913565b506040516343befb6960e11b815260040160405180910390fd5b8a8a101561093457604051633a23d82560e01b815260040160405180910390fd5b700eb194f8e1ae525fd5dcfab08000000000610950858d612d9e565b101561096f57604051633a23d82560e01b815260040160405180910390fd5b5060007f000000000000000000000000167144d66ac1d02eaafca3649ef3305ea31ee5a86001600160a01b0316635d824f76337f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea8f8f8e8e8e8e8e8e8e6040518c63ffffffff1660e01b81526004016109f29b9a99989796959493929190612f52565b6020604051808303816000875af1158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190612d52565b60405163b52c696d60e01b81526001600160a01b0380831660048301529192507f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea9091169063b52c696d90602401600060405180830381600087803b158015610a9d57600080fd5b505af1158015610ab1573d6000803e3d6000fd5b505060405163375edc7760e11b81526001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea169250636ebdb8ee9150610b0c903390683635c9adc5dea0000090600401612e20565b600060405180830381600087803b158015610b2657600080fd5b505af1158015610b3a573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b038f1692506323b872dd9150610b6e90339085908f90600401612fd3565b6020604051808303816000875af1158015610b8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb19190612e39565b50604080516001600160a01b03808416808352908f1660208301529133917fc9b570ab9d98bdf3e38a40fd71b20edafca42449f23ca51f0bdcbf40e8ffe175910160405180910390a39b9a5050505050505050505050565b6000610c1933878787878761104b565b9695505050505050565b600080610c388d8d8d8d8d8d8d8d8d8d61065b565b604051635039bbbb60e11b81529091506001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994169063a073777690610c899084908790600401612e20565b600060405180830381600087803b158015610ca357600080fd5b505af1158015610cb7573d6000803e3d6000fd5b50929f9e505050505050505050505050505050565b60405163aa5dd7f160e01b815233600482018190529030906001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea169063aa5dd7f190602401602060405180830381865afa158015610d35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d599190612d52565b6001600160a01b031614610d80576040516369229ba760e01b815260040160405180910390fd5b604051632a5e323160e01b81526001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a1809941690632a5e323190610dce9033908690600401612e20565b600060405180830381600087803b158015610de857600080fd5b505af1158015610dfc573d6000803e3d6000fd5b505050505050565b6000808463ffffffff1681548110610e1e57610e1e612ff7565b600091825260208083206040805160808101825260039490940290910180546001600160a01b038082168652600160a01b90910464ffffffffff169385019390935260018101549092168382018190526002909201546060840152805163194c325560e11b81528151939550849363329864aa926004808401939192918290030181865afa158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061300d565b9150915084836060015110610eed5784610ef3565b82606001515b9450808360200151610f059190613033565b64ffffffffff164211610f7257610f1e83878488611d33565b604080840151815163ffffffff89168152602081018890526001600160a01b03909116917f1eee30d91b773ac47d7485a3acb6bcd8c7c9cd8d95301b1af361baf5f0991d2e910160405180910390a2610dfc565b610f7e83878787611ffc565b600080610f8b858861210f565b604080880151815163ffffffff8d16815260208101849052918201849052606082018b90529294509092506001600160a01b03909116907f7d3a26e8d43c5b70f86266bfa26c212e3c097716ff7240ccb6a9034e48754e239060800160405180910390a25050505050505050565b6000818154811061100957600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b038083169450600160a01b90920464ffffffffff1692919091169084565b60008061105b88888888886110ea565b604051635039bbbb60e11b81529091506001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994169063a0737776906110ac9084908790600401612e20565b600060405180830381600087803b1580156110c657600080fd5b505af11580156110da573d6000803e3d6000fd5b50929a9950505050505050505050565b60405163aa5dd7f160e01b81526001600160a01b038581166004830152600091869130917f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea9091169063aa5dd7f190602401602060405180830381865afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612d52565b6001600160a01b0316146111a4576040516369229ba760e01b815260040160405180910390fd5b604051630167d12360e71b81526001600160a01b0387811660048301526000917f000000000000000000000000167144d66ac1d02eaafca3649ef3305ea31ee5a89091169063b3e89180906024016020604051808303816000875af1158015611211573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190612d52565b6040516336a3a4fd60e11b81526001600160a01b03898116600483015264ffffffffff871660248301529192508291821690636d4749fa90604401600060405180830381600087803b15801561128a57600080fd5b505af115801561129e573d6000803e3d6000fd5b505060405163b52c696d60e01b81526001600160a01b0385811660048301527f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea16925063b52c696d9150602401600060405180830381600087803b15801561130557600080fd5b505af1158015611319573d6000803e3d6000fd5b505050506000816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190612d52565b9050816001600160a01b031663babe7c746040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e59190612d6f565b88101561140557604051633a23d82560e01b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038216906323b872dd9061143590339087908d90600401612fd3565b6020604051808303816000875af1158015611454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114789190612e39565b50604080516001600160a01b038b81168252838116602083015280861692908d16917fc9b570ab9d98bdf3e38a40fd71b20edafca42449f23ca51f0bdcbf40e8ffe175910160405180910390a36040516340c10f1960e01b81526001600160a01b038316906340c10f19906114f3908d908b90600401612e20565b600060405180830381600087803b15801561150d57600080fd5b505af1158015611521573d6000803e3d6000fd5b505060405163f2fde38b60e01b81526001600160a01b038d811660048301528516925063f2fde38b9150602401600060405180830381600087803b15801561156857600080fd5b505af115801561157c573d6000803e3d6000fd5b50949c9b505050505050505050505050565b60405163aa5dd7f160e01b81526001600160a01b038481166004830152600091859130917f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea9091169063aa5dd7f190602401602060405180830381865afa1580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116219190612d52565b6001600160a01b031614611648576040516369229ba760e01b815260040160405180910390fd5b60008590506000816001600160a01b0316638ea875f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561168d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b19190612d6f565b9050848110156116d457604051630d57523160e11b815260040160405180910390fd5b816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015611712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117369190612d52565b6001600160a01b03166323b872dd3330896040518463ffffffff1660e01b815260040161176593929190612fd3565b6020604051808303816000875af1158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612e39565b50600080546040805160808101825233815264ffffffffff428116602083019081526001600160a01b03888116848601818152606086018f8152600189018a559880529451600388027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563810180549551909616600160a01b026001600160c81b0319909516918416919091179390931790935592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482018054919094166001600160a01b0319919091161790925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5659091015551632e38909b60e21b815290919063b8e2426c906118cb908a908690600401918252602082015260400190565b600060405180830381600087803b1580156118e557600080fd5b505af11580156118f9573d6000803e3d6000fd5b5050604080518a8152602081018590526001600160a01b03871693503392507fc4b384b2c5ca32c8e77081f4083be594a1ea9ba34f208a9f9a458f70608585f5910160405180910390a3979650505050505050565b600080826001600160a01b0316638ea875f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561198f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b39190612d6f565b90506000836001600160a01b0316634665096d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a199190613050565b64ffffffffff169050804211611a3c57611a3482600a612d9e565b949350505050565b6000846001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa09190613050565b64ffffffffff1690506000611ab58342612dd7565b9050818111611b0e576000611aca8284612dd7565b9050828186611adb6001600a612dd7565b611ae59190612d9e565b611aef9190612d9e565b611af99190612db5565b611b039086612e0d565b979650505050505050565b611b19826002612d9e565b811015611b4f57600081611b2e846002612d9e565b611b389190612dd7565b905082611b458287612d9e565b611b039190612db5565b50600095945050505050565b60008060008363ffffffff1681548110611b7757611b77612ff7565b60009182526020918290206040805160808101825260039390930290910180546001600160a01b03808216808652600160a01b90920464ffffffffff16958501959095526001820154909416918301919091526002015460608201529150611be25750600092915050565b60008082604001516001600160a01b031663329864aa6040518163ffffffff1660e01b81526004016040805180830381865afa158015611c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4a919061300d565b91509150610652818460200151611c619190613033565b828461269f565b6001600160a01b038216600081815260016020908152604080832033845290915280822080549290555163a9059cbb60e01b815290919063a9059cbb90611cb59085908590600401612e20565b6020604051808303816000875af1158015611cd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf89190612e39565b50505050565b60006001600160e01b03198216637913206560e01b14806103f157506301ffc9a760e01b6001600160e01b03198316146103f1565b836020015164ffffffffff164203611d4a57600080fd5b83516001600160a01b03163314611e105783516001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea16906323b872dd903390670de0b6b3a7640000611da38787612d9e565b611dad9190612db5565b6040518463ffffffff1660e01b8152600401611dcb93929190612fd3565b6020604051808303816000875af1158015611dea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0e9190612e39565b505b83604001516001600160a01b03166349746f10826040518263ffffffff1660e01b8152600401611e4291815260200190565b600060405180830381600087803b158015611e5c57600080fd5b505af1158015611e70573d6000803e3d6000fd5b5050505083604001516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015611eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eda9190612d52565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401611f07929190612e20565b6020604051808303816000875af1158015611f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4a9190612e39565b508360600151811015611f9a57808460600151611f679190612dd7565b60008463ffffffff1681548110611f8057611f80612ff7565b906000526020600020906003020160020181905550611cf8565b83606001518114611faa57600080fd5b60008363ffffffff1681548110611fc357611fc3612ff7565b60009182526020822060039091020180546001600160c81b03191681556001810180546001600160a01b03191690556002015550505050565b61206e84604001516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190612d52565b8551848461272d565b818460600151036120ca5760008363ffffffff168154811061209257612092612ff7565b60009182526020822060039091020180546001600160c81b03191681556001810180546001600160a01b031916905560020155611cf8565b8160008463ffffffff16815481106120e4576120e4612ff7565b906000526020600020906003020160020160008282546121049190612dd7565b909155505050505050565b600080600080600080600088604001516001600160a01b0316637ccd4f71896040518263ffffffff1660e01b815260040161214c91815260200190565b60a0604051808303816000875af115801561216b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218f919061306d565b9450945094509450945060006121a58a86612831565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea16906323b872dd906121f890339030908690600401612fd3565b6020604051808303816000875af1158015612217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223b9190612e39565b506000620f424061224e614e2084612d9e565b6122589190612db5565b8b5160405163a9059cbb60e01b81529192506001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea169163a9059cbb916122a9918590600401612e20565b6020604051808303816000875af11580156122c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ec9190612e39565b5060006122f98284612dd7565b90506123058587612e0d565b81111561247d576000620f42408661231d8985612dd7565b6123279190612dd7565b6123379063ffffffff8816612d9e565b6123419190612db5565b60405163375edc7760e11b81529091506001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea1690636ebdb8ee906123929030908590600401612e20565b600060405180830381600087803b1580156123ac57600080fd5b505af11580156123c0573d6000803e3d6000fd5b505050507f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea6001600160a01b031663a9059cbb8a83898b876124029190612dd7565b61240c9190612dd7565b6124169190612dd7565b6040518363ffffffff1660e01b8152600401612433929190612e20565b6020604051808303816000875af1158015612452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124769190612e39565b5050612523565b6124878587612e0d565b811015612523576001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea1663d1fa5e9830836124c9898b612e0d565b6124d39190612dd7565b6040518363ffffffff1660e01b81526004016124f0929190612e20565b600060405180830381600087803b15801561250a57600080fd5b505af115801561251e573d6000803e3d6000fd5b505050505b6040516363b20c3360e11b81526004810187905263ffffffff851660248201527f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea6001600160a01b03169063c764186690604401600060405180830381600087803b15801561259157600080fd5b505af11580156125a5573d6000803e3d6000fd5b505060405163375edc7760e11b81526001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea169250636ebdb8ee91506125f79030908990600401612e20565b600060405180830381600087803b15801561261157600080fd5b505af1158015612625573d6000803e3d6000fd5b505050508b604001516001600160a01b0316631dbcff2633896040518363ffffffff1660e01b815260040161265b929190612e20565b600060405180830381600087803b15801561267557600080fd5b505af1158015612689573d6000803e3d6000fd5b50989e949d50939b505050505050505050505050565b60004264ffffffffff808616908216116126bc5782915050612726565b6126c68486613033565b64ffffffffff168164ffffffffff16106126e4576000915050612726565b60006126f086836130b7565b6126fa90866130b7565b64ffffffffff169050808564ffffffffff16856127179190612db5565b6127219190612d9e565b925050505b9392505050565b80156127b9576001600160a01b0380851660009081526001602090815260408083209387168352929052908120805484929061276a908490612e0d565b92505081905550826001600160a01b03167f8dbeeabb7d576986689d0bff912a01b9736f03d95739a5603e59301a50141c5c85846040516127ac929190612e20565b60405180910390a2611cf8565b60405163a9059cbb60e01b81526001600160a01b0385169063a9059cbb906127e79086908690600401612e20565b6020604051808303816000875af1158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a9190612e39565b5050505050565b600080600084604001516001600160a01b031663329864aa6040518163ffffffff1660e01b81526004016040805180830381865afa158015612877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289b919061300d565b91509150670de0b6b3a7640000846128c38388602001516128bc9190613033565b848661269f565b6128cd9190612d9e565b6106529190612db5565b6000602082840312156128e957600080fd5b81356001600160e01b03198116811461272657600080fd5b6001600160a01b038116811461291657600080fd5b50565b6000806040838503121561292c57600080fd5b823561293781612901565b946020939093013593505050565b64ffffffffff8116811461291657600080fd5b6000806000806080858703121561296e57600080fd5b843561297981612901565b93506020850135925060408501359150606085013561299781612945565b939692955090935050565b803562ffffff811681146129b557600080fd5b919050565b6000806000806000806000806000806101408b8d0312156129da57600080fd5b8a356129e581612901565b995060208b0135985060408b0135975060608b0135965060808b0135612a0a81612945565b955060a08b0135612a1a81612945565b945060c08b0135612a2a81612945565b9350612a3860e08c016129a2565b92506101008b01359150612a4f6101208c016129a2565b90509295989b9194979a5092959850565b600080600080600060a08688031215612a7857600080fd5b8535612a8381612901565b945060208601359350604086013592506060860135612aa181612945565b949793965091946080013592915050565b60008060008060008060008060008060006101608c8e031215612ad457600080fd5b8b35612adf81612901565b9a5060208c0135995060408c0135985060608c0135975060808c0135612b0481612945565b965060a08c0135612b1481612945565b955060c08c0135612b2481612945565b9450612b3260e08d016129a2565b93506101008c01359250612b496101208d016129a2565b915060006101408d01359050809150509295989b509295989b9093969950565b60008060408385031215612b7c57600080fd5b8235612b8781612901565b91506020830135612b9781612901565b809150509250929050565b600060208284031215612bb457600080fd5b5035919050565b63ffffffff8116811461291657600080fd5b801515811461291657600080fd5b600080600060608486031215612bf057600080fd5b8335612bfb81612bbb565b9250602084013591506040840135612c1281612bcd565b809150509250925092565b60008060008060008060c08789031215612c3657600080fd5b8635612c4181612901565b95506020870135612c5181612901565b945060408701359350606087013592506080870135612c6f81612945565b9598949750929591949360a090920135925050565b600080600080600060a08688031215612c9c57600080fd5b8535612ca781612901565b94506020860135612cb781612901565b935060408601359250606086013591506080860135612cd581612945565b809150509295509295909350565b600080600060608486031215612cf857600080fd5b8335612d0381612901565b95602085013595506040909401359392505050565b600060208284031215612d2a57600080fd5b813561272681612901565b600060208284031215612d4757600080fd5b813561272681612bbb565b600060208284031215612d6457600080fd5b815161272681612901565b600060208284031215612d8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176103f1576103f1612d88565b600082612dd257634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156103f1576103f1612d88565b600060208284031215612dfc57600080fd5b815160ff8116811461272657600080fd5b808201808211156103f1576103f1612d88565b6001600160a01b03929092168252602082015260400190565b600060208284031215612e4b57600080fd5b815161272681612bcd565b600060033d1115612e6f5760046000803e5060005160e01c5b90565b601f8201601f1916810167ffffffffffffffff81118282101715612ea657634e487b7160e01b600052604160045260246000fd5b6040525050565b600060443d1015612ebb5790565b6040513d600319016004823e80513d602482011167ffffffffffffffff82111715612ee557505090565b808201805167ffffffffffffffff811115612f01575050505090565b3d8401600319018282016020011115612f1b575050505090565b612f2a60208285010185612e72565b509392505050565b60008060233d1115612f4e576020600460003e50506000516001905b9091565b6001600160a01b038c811682528b811660208301528a166040820152606081018990526080810188905264ffffffffff87811660a083015286811660c0830152851660e082015262ffffff8416610100820152610160810183610120830152612fc361014083018462ffffff169052565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603260045260246000fd5b6000806040838503121561302057600080fd5b82516020840151909250612b9781612945565b64ffffffffff81811683821601908111156103f1576103f1612d88565b60006020828403121561306257600080fd5b815161272681612945565b600080600080600060a0868803121561308557600080fd5b855161309081612901565b60208701516040880151606089015160808a015193985091965094509250612cd581612bbb565b64ffffffffff82811682821603908111156103f1576103f1612d8856fea264697066735822122024516afca31250962e458e40651cc003681ff2be7cf5fa814b688bd47baa3d5d64736f6c634300081a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"paris","libraries":{},"metadata":{"bytecodeHash":"ipfs","useLiteralContent":true},"optimizer":{"enabled":true,"runs":200},"remappings":[]},"optimization_runs":200,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0x8B3c41c649B9c7085C171CbB82337889b3604618/","decoded_constructor_args":[["0xbA3f535bbCcCcA2A154b573Ca6c5A49BAAE0a3ea",{"internalType":"address","name":"_deuro","type":"address"}],["0x073493d73258C4BEb6542e8dd3e1b2891C972303",{"internalType":"address","name":"_leadrate","type":"address"}],["0x4CE0AB2FC21Bd27a47A64F594Fdf7654Ea57Dc79",{"internalType":"address","name":"_roller","type":"address"}],["0x167144d66AC1D02EAAFCa3649ef3305ea31Ee5A8",{"internalType":"address","name":"_factory","type":"address"}],["0x5c49C00f897bD970d964BFB8c3065ae65a180994",{"internalType":"address","name":"_gateway","type":"address"}]],"compiler_version":"0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":false,"verified_at":"2025-06-26T05:58:36.947807Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x61012060405234801561001157600080fd5b506040516132ac3803806132ac83398101604081905261003091610074565b6001600160a01b0394851660a05292841660e0528316608052821660c05216610100526100d9565b80516001600160a01b038116811461006f57600080fd5b919050565b600080600080600060a0868803121561008c57600080fd5b61009586610058565b94506100a360208701610058565b93506100b160408701610058565b92506100bf60608701610058565b91506100cd60808701610058565b90509295509295909350565b60805160a05160c05160e0516101005161310a6101a2600039600081816101e301528181610c5201528181610d9701526110750152600061026e015260006103aa01526000818161034a015281816109a401528181610a5701528181610aca01528181610cee01528181611110015281816112bf015281816115b401528181611d67015281816121bf015281816122740152818161235b015281816123c6015281816124980152818161254501526125be01526000818161097401526111c6015261310a6000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c80637d0ea02d116100c3578063c14a9f051161007c578063c14a9f0514610332578063dbe8a4c214610345578063e6ac5ea41461036c578063e6ca1df21461037f578063e85cde6f14610392578063f09e9e3a146103a557600080fd5b80637d0ea02d146102905780637eb81bb3146102a55780638f1d3776146102b857806393a83a24146103035780639d8ff2a614610316578063af5806b61461032957600080fd5b8063338c537111610115578063338c5371146101de57806335a4b349146102055780633bb84940146102185780634cb959141461022b578063643745fb1461023e578063664e97041461026957600080fd5b806301ffc9a7146101525780630f2f8e861461017a57806325e28124146101905780632bf78dd8146101a35780632e2c6314146101b3575b600080fd5b6101656101603660046128d7565b6103cc565b60405190151581526020015b60405180910390f35b610182600a81565b604051908152602001610171565b61018261019e366004612919565b6103f7565b610182683635c9adc5dea0000081565b6101c66101c1366004612958565b610643565b6040516001600160a01b039091168152602001610171565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b6101c66102133660046129ba565b61065b565b6101c6610226366004612a60565b610c09565b6101c6610239366004612ab2565b610c23565b61018261024c366004612b69565b600160209081526000928352604080842090915290825290205481565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b6102a361029e366004612ba2565b610ccc565b005b6102a36102b3366004612bdb565b610e04565b6102cb6102c6366004612ba2565b610ff9565b604080516001600160a01b03958616815264ffffffffff94909416602085015291909316908201526060810191909152608001610171565b6101c6610311366004612c1d565b61104b565b6101c6610324366004612c84565b6110ea565b610182614e2081565b610182610340366004612ce3565b61158e565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b61018261037a366004612d18565b61194e565b61018261038d366004612d35565b611b5b565b6102a36103a0366004612b69565b611c68565b6101c67f000000000000000000000000000000000000000000000000000000000000000081565b60006001600160e01b03198216632464e41b60e21b14806103f157506103f182611cfe565b92915050565b600080836001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015610438573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061045c9190612d52565b6040516370a0823160e01b81526001600160a01b03868116600483015291909116906370a0823190602401602060405180830381865afa1580156104a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104c89190612d6f565b905060008184116104d957836104db565b815b905060006104e88661194e565b90506000670de0b6b3a76400006104ff8484612d9e565b6105099190612db5565b905060006105178486612dd7565b1180156105525750683635c9adc5dea00000670de0b6b3a764000061053c8587612dd7565b6105469085612d9e565b6105509190612db5565b105b15610586576105618385612dd7565b60405163f658c6cf60e01b815260040161057d91815260200190565b60405180910390fd5b60405163211d798360e01b815233600482015260248101849052604481018290526001600160a01b0388169063211d798390606401600060405180830381600087803b1580156105d557600080fd5b505af11580156105e9573d6000803e3d6000fd5b5050604080516001600160a01b038b168152602081018790529081018590527f67a660133c1fb4c0bb0480a5e4a9919216684052f13f0713e88fa2fbbc81d0829250606001905060405180910390a1509095945050505050565b600061065233868686866110ea565b95945050505050565b6000620f42408462ffffff1611156106865760405163b2772c5d60e01b815260040160405180910390fd5b8162ffffff16614e2011806106a25750620f42408262ffffff16115b156106c057604051633a3626e360e21b815260040160405180910390fd5b60188b6001600160a01b031663313ce5676040518163ffffffff1660e01b8152600401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107249190612dea565b60ff161115610746576040516325dd4a5560e21b815260040160405180910390fd5b620151808564ffffffffff1610156107715760405163fc8c61b960e01b815260040160405180910390fd5b6203f4808764ffffffffff16101561079c5760405163f979252f60e01b815260040160405180910390fd5b60008b6001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156107dc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108009190612d6f565b61080b906001612e0d565b60405163a9059cbb60e01b81529091506001600160a01b038d169063a9059cbb9061083e90610123908590600401612e20565b6020604051808303816000875af1925050508015610879575060408051601f3d908101601f1916820190925261087691810190612e39565b60015b6108f957610885612e56565b806308c379a0036108aa5750610899612ead565b806108a457506108c3565b50610913565b634e487b71036108c3576108bc612f32565b906108a457505b3d8080156108ed576040519150601f19603f3d011682016040523d82523d6000602084013e6108f2565b606091505b5050610913565b506040516343befb6960e11b815260040160405180910390fd5b8a8a101561093457604051633a23d82560e01b815260040160405180910390fd5b700eb194f8e1ae525fd5dcfab08000000000610950858d612d9e565b101561096f57604051633a23d82560e01b815260040160405180910390fd5b5060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316635d824f76337f00000000000000000000000000000000000000000000000000000000000000008f8f8e8e8e8e8e8e8e6040518c63ffffffff1660e01b81526004016109f29b9a99989796959493929190612f52565b6020604051808303816000875af1158015610a11573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a359190612d52565b60405163b52c696d60e01b81526001600160a01b0380831660048301529192507f00000000000000000000000000000000000000000000000000000000000000009091169063b52c696d90602401600060405180830381600087803b158015610a9d57600080fd5b505af1158015610ab1573d6000803e3d6000fd5b505060405163375edc7760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250636ebdb8ee9150610b0c903390683635c9adc5dea0000090600401612e20565b600060405180830381600087803b158015610b2657600080fd5b505af1158015610b3a573d6000803e3d6000fd5b50506040516323b872dd60e01b81526001600160a01b038f1692506323b872dd9150610b6e90339085908f90600401612fd3565b6020604051808303816000875af1158015610b8d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bb19190612e39565b50604080516001600160a01b03808416808352908f1660208301529133917fc9b570ab9d98bdf3e38a40fd71b20edafca42449f23ca51f0bdcbf40e8ffe175910160405180910390a39b9a5050505050505050505050565b6000610c1933878787878761104b565b9695505050505050565b600080610c388d8d8d8d8d8d8d8d8d8d61065b565b604051635039bbbb60e11b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a073777690610c899084908790600401612e20565b600060405180830381600087803b158015610ca357600080fd5b505af1158015610cb7573d6000803e3d6000fd5b50929f9e505050505050505050505050505050565b60405163aa5dd7f160e01b815233600482018190529030906001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063aa5dd7f190602401602060405180830381865afa158015610d35573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d599190612d52565b6001600160a01b031614610d80576040516369229ba760e01b815260040160405180910390fd5b604051632a5e323160e01b81526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690632a5e323190610dce9033908690600401612e20565b600060405180830381600087803b158015610de857600080fd5b505af1158015610dfc573d6000803e3d6000fd5b505050505050565b6000808463ffffffff1681548110610e1e57610e1e612ff7565b600091825260208083206040805160808101825260039490940290910180546001600160a01b038082168652600160a01b90910464ffffffffff169385019390935260018101549092168382018190526002909201546060840152805163194c325560e11b81528151939550849363329864aa926004808401939192918290030181865afa158015610eb4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ed8919061300d565b9150915084836060015110610eed5784610ef3565b82606001515b9450808360200151610f059190613033565b64ffffffffff164211610f7257610f1e83878488611d33565b604080840151815163ffffffff89168152602081018890526001600160a01b03909116917f1eee30d91b773ac47d7485a3acb6bcd8c7c9cd8d95301b1af361baf5f0991d2e910160405180910390a2610dfc565b610f7e83878787611ffc565b600080610f8b858861210f565b604080880151815163ffffffff8d16815260208101849052918201849052606082018b90529294509092506001600160a01b03909116907f7d3a26e8d43c5b70f86266bfa26c212e3c097716ff7240ccb6a9034e48754e239060800160405180910390a25050505050505050565b6000818154811061100957600080fd5b60009182526020909120600390910201805460018201546002909201546001600160a01b038083169450600160a01b90920464ffffffffff1692919091169084565b60008061105b88888888886110ea565b604051635039bbbb60e11b81529091506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a0737776906110ac9084908790600401612e20565b600060405180830381600087803b1580156110c657600080fd5b505af11580156110da573d6000803e3d6000fd5b50929a9950505050505050505050565b60405163aa5dd7f160e01b81526001600160a01b038581166004830152600091869130917f00000000000000000000000000000000000000000000000000000000000000009091169063aa5dd7f190602401602060405180830381865afa158015611159573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061117d9190612d52565b6001600160a01b0316146111a4576040516369229ba760e01b815260040160405180910390fd5b604051630167d12360e71b81526001600160a01b0387811660048301526000917f00000000000000000000000000000000000000000000000000000000000000009091169063b3e89180906024016020604051808303816000875af1158015611211573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112359190612d52565b6040516336a3a4fd60e11b81526001600160a01b03898116600483015264ffffffffff871660248301529192508291821690636d4749fa90604401600060405180830381600087803b15801561128a57600080fd5b505af115801561129e573d6000803e3d6000fd5b505060405163b52c696d60e01b81526001600160a01b0385811660048301527f000000000000000000000000000000000000000000000000000000000000000016925063b52c696d9150602401600060405180830381600087803b15801561130557600080fd5b505af1158015611319573d6000803e3d6000fd5b505050506000816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113819190612d52565b9050816001600160a01b031663babe7c746040518163ffffffff1660e01b8152600401602060405180830381865afa1580156113c1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e59190612d6f565b88101561140557604051633a23d82560e01b815260040160405180910390fd5b6040516323b872dd60e01b81526001600160a01b038216906323b872dd9061143590339087908d90600401612fd3565b6020604051808303816000875af1158015611454573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114789190612e39565b50604080516001600160a01b038b81168252838116602083015280861692908d16917fc9b570ab9d98bdf3e38a40fd71b20edafca42449f23ca51f0bdcbf40e8ffe175910160405180910390a36040516340c10f1960e01b81526001600160a01b038316906340c10f19906114f3908d908b90600401612e20565b600060405180830381600087803b15801561150d57600080fd5b505af1158015611521573d6000803e3d6000fd5b505060405163f2fde38b60e01b81526001600160a01b038d811660048301528516925063f2fde38b9150602401600060405180830381600087803b15801561156857600080fd5b505af115801561157c573d6000803e3d6000fd5b50949c9b505050505050505050505050565b60405163aa5dd7f160e01b81526001600160a01b038481166004830152600091859130917f00000000000000000000000000000000000000000000000000000000000000009091169063aa5dd7f190602401602060405180830381865afa1580156115fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116219190612d52565b6001600160a01b031614611648576040516369229ba760e01b815260040160405180910390fd5b60008590506000816001600160a01b0316638ea875f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561168d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116b19190612d6f565b9050848110156116d457604051630d57523160e11b815260040160405180910390fd5b816001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015611712573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117369190612d52565b6001600160a01b03166323b872dd3330896040518463ffffffff1660e01b815260040161176593929190612fd3565b6020604051808303816000875af1158015611784573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117a89190612e39565b50600080546040805160808101825233815264ffffffffff428116602083019081526001600160a01b03888116848601818152606086018f8152600189018a559880529451600388027f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563810180549551909616600160a01b026001600160c81b0319909516918416919091179390931790935592517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56482018054919094166001600160a01b0319919091161790925593517f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5659091015551632e38909b60e21b815290919063b8e2426c906118cb908a908690600401918252602082015260400190565b600060405180830381600087803b1580156118e557600080fd5b505af11580156118f9573d6000803e3d6000fd5b5050604080518a8152602081018590526001600160a01b03871693503392507fc4b384b2c5ca32c8e77081f4083be594a1ea9ba34f208a9f9a458f70608585f5910160405180910390a3979650505050505050565b600080826001600160a01b0316638ea875f36040518163ffffffff1660e01b8152600401602060405180830381865afa15801561198f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119b39190612d6f565b90506000836001600160a01b0316634665096d6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156119f5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a199190613050565b64ffffffffff169050804211611a3c57611a3482600a612d9e565b949350505050565b6000846001600160a01b031663f3f480d96040518163ffffffff1660e01b8152600401602060405180830381865afa158015611a7c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa09190613050565b64ffffffffff1690506000611ab58342612dd7565b9050818111611b0e576000611aca8284612dd7565b9050828186611adb6001600a612dd7565b611ae59190612d9e565b611aef9190612d9e565b611af99190612db5565b611b039086612e0d565b979650505050505050565b611b19826002612d9e565b811015611b4f57600081611b2e846002612d9e565b611b389190612dd7565b905082611b458287612d9e565b611b039190612db5565b50600095945050505050565b60008060008363ffffffff1681548110611b7757611b77612ff7565b60009182526020918290206040805160808101825260039390930290910180546001600160a01b03808216808652600160a01b90920464ffffffffff16958501959095526001820154909416918301919091526002015460608201529150611be25750600092915050565b60008082604001516001600160a01b031663329864aa6040518163ffffffff1660e01b81526004016040805180830381865afa158015611c26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c4a919061300d565b91509150610652818460200151611c619190613033565b828461269f565b6001600160a01b038216600081815260016020908152604080832033845290915280822080549290555163a9059cbb60e01b815290919063a9059cbb90611cb59085908590600401612e20565b6020604051808303816000875af1158015611cd4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cf89190612e39565b50505050565b60006001600160e01b03198216637913206560e01b14806103f157506301ffc9a760e01b6001600160e01b03198316146103f1565b836020015164ffffffffff164203611d4a57600080fd5b83516001600160a01b03163314611e105783516001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd903390670de0b6b3a7640000611da38787612d9e565b611dad9190612db5565b6040518463ffffffff1660e01b8152600401611dcb93929190612fd3565b6020604051808303816000875af1158015611dea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e0e9190612e39565b505b83604001516001600160a01b03166349746f10826040518263ffffffff1660e01b8152600401611e4291815260200190565b600060405180830381600087803b158015611e5c57600080fd5b505af1158015611e70573d6000803e3d6000fd5b5050505083604001516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015611eb6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611eda9190612d52565b6001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401611f07929190612e20565b6020604051808303816000875af1158015611f26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f4a9190612e39565b508360600151811015611f9a57808460600151611f679190612dd7565b60008463ffffffff1681548110611f8057611f80612ff7565b906000526020600020906003020160020181905550611cf8565b83606001518114611faa57600080fd5b60008363ffffffff1681548110611fc357611fc3612ff7565b60009182526020822060039091020180546001600160c81b03191681556001810180546001600160a01b03191690556002015550505050565b61206e84604001516001600160a01b031663d8dfeb456040518163ffffffff1660e01b8152600401602060405180830381865afa158015612041573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120659190612d52565b8551848461272d565b818460600151036120ca5760008363ffffffff168154811061209257612092612ff7565b60009182526020822060039091020180546001600160c81b03191681556001810180546001600160a01b031916905560020155611cf8565b8160008463ffffffff16815481106120e4576120e4612ff7565b906000526020600020906003020160020160008282546121049190612dd7565b909155505050505050565b600080600080600080600088604001516001600160a01b0316637ccd4f71896040518263ffffffff1660e01b815260040161214c91815260200190565b60a0604051808303816000875af115801561216b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061218f919061306d565b9450945094509450945060006121a58a86612831565b6040516323b872dd60e01b81529091506001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906323b872dd906121f890339030908690600401612fd3565b6020604051808303816000875af1158015612217573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061223b9190612e39565b506000620f424061224e614e2084612d9e565b6122589190612db5565b8b5160405163a9059cbb60e01b81529192506001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169163a9059cbb916122a9918590600401612e20565b6020604051808303816000875af11580156122c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906122ec9190612e39565b5060006122f98284612dd7565b90506123058587612e0d565b81111561247d576000620f42408661231d8985612dd7565b6123279190612dd7565b6123379063ffffffff8816612d9e565b6123419190612db5565b60405163375edc7760e11b81529091506001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690636ebdb8ee906123929030908590600401612e20565b600060405180830381600087803b1580156123ac57600080fd5b505af11580156123c0573d6000803e3d6000fd5b505050507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663a9059cbb8a83898b876124029190612dd7565b61240c9190612dd7565b6124169190612dd7565b6040518363ffffffff1660e01b8152600401612433929190612e20565b6020604051808303816000875af1158015612452573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124769190612e39565b5050612523565b6124878587612e0d565b811015612523576001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663d1fa5e9830836124c9898b612e0d565b6124d39190612dd7565b6040518363ffffffff1660e01b81526004016124f0929190612e20565b600060405180830381600087803b15801561250a57600080fd5b505af115801561251e573d6000803e3d6000fd5b505050505b6040516363b20c3360e11b81526004810187905263ffffffff851660248201527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03169063c764186690604401600060405180830381600087803b15801561259157600080fd5b505af11580156125a5573d6000803e3d6000fd5b505060405163375edc7760e11b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169250636ebdb8ee91506125f79030908990600401612e20565b600060405180830381600087803b15801561261157600080fd5b505af1158015612625573d6000803e3d6000fd5b505050508b604001516001600160a01b0316631dbcff2633896040518363ffffffff1660e01b815260040161265b929190612e20565b600060405180830381600087803b15801561267557600080fd5b505af1158015612689573d6000803e3d6000fd5b50989e949d50939b505050505050505050505050565b60004264ffffffffff808616908216116126bc5782915050612726565b6126c68486613033565b64ffffffffff168164ffffffffff16106126e4576000915050612726565b60006126f086836130b7565b6126fa90866130b7565b64ffffffffff169050808564ffffffffff16856127179190612db5565b6127219190612d9e565b925050505b9392505050565b80156127b9576001600160a01b0380851660009081526001602090815260408083209387168352929052908120805484929061276a908490612e0d565b92505081905550826001600160a01b03167f8dbeeabb7d576986689d0bff912a01b9736f03d95739a5603e59301a50141c5c85846040516127ac929190612e20565b60405180910390a2611cf8565b60405163a9059cbb60e01b81526001600160a01b0385169063a9059cbb906127e79086908690600401612e20565b6020604051808303816000875af1158015612806573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061282a9190612e39565b5050505050565b600080600084604001516001600160a01b031663329864aa6040518163ffffffff1660e01b81526004016040805180830381865afa158015612877573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061289b919061300d565b91509150670de0b6b3a7640000846128c38388602001516128bc9190613033565b848661269f565b6128cd9190612d9e565b6106529190612db5565b6000602082840312156128e957600080fd5b81356001600160e01b03198116811461272657600080fd5b6001600160a01b038116811461291657600080fd5b50565b6000806040838503121561292c57600080fd5b823561293781612901565b946020939093013593505050565b64ffffffffff8116811461291657600080fd5b6000806000806080858703121561296e57600080fd5b843561297981612901565b93506020850135925060408501359150606085013561299781612945565b939692955090935050565b803562ffffff811681146129b557600080fd5b919050565b6000806000806000806000806000806101408b8d0312156129da57600080fd5b8a356129e581612901565b995060208b0135985060408b0135975060608b0135965060808b0135612a0a81612945565b955060a08b0135612a1a81612945565b945060c08b0135612a2a81612945565b9350612a3860e08c016129a2565b92506101008b01359150612a4f6101208c016129a2565b90509295989b9194979a5092959850565b600080600080600060a08688031215612a7857600080fd5b8535612a8381612901565b945060208601359350604086013592506060860135612aa181612945565b949793965091946080013592915050565b60008060008060008060008060008060006101608c8e031215612ad457600080fd5b8b35612adf81612901565b9a5060208c0135995060408c0135985060608c0135975060808c0135612b0481612945565b965060a08c0135612b1481612945565b955060c08c0135612b2481612945565b9450612b3260e08d016129a2565b93506101008c01359250612b496101208d016129a2565b915060006101408d01359050809150509295989b509295989b9093969950565b60008060408385031215612b7c57600080fd5b8235612b8781612901565b91506020830135612b9781612901565b809150509250929050565b600060208284031215612bb457600080fd5b5035919050565b63ffffffff8116811461291657600080fd5b801515811461291657600080fd5b600080600060608486031215612bf057600080fd5b8335612bfb81612bbb565b9250602084013591506040840135612c1281612bcd565b809150509250925092565b60008060008060008060c08789031215612c3657600080fd5b8635612c4181612901565b95506020870135612c5181612901565b945060408701359350606087013592506080870135612c6f81612945565b9598949750929591949360a090920135925050565b600080600080600060a08688031215612c9c57600080fd5b8535612ca781612901565b94506020860135612cb781612901565b935060408601359250606086013591506080860135612cd581612945565b809150509295509295909350565b600080600060608486031215612cf857600080fd5b8335612d0381612901565b95602085013595506040909401359392505050565b600060208284031215612d2a57600080fd5b813561272681612901565b600060208284031215612d4757600080fd5b813561272681612bbb565b600060208284031215612d6457600080fd5b815161272681612901565b600060208284031215612d8157600080fd5b5051919050565b634e487b7160e01b600052601160045260246000fd5b80820281158282048414176103f1576103f1612d88565b600082612dd257634e487b7160e01b600052601260045260246000fd5b500490565b818103818111156103f1576103f1612d88565b600060208284031215612dfc57600080fd5b815160ff8116811461272657600080fd5b808201808211156103f1576103f1612d88565b6001600160a01b03929092168252602082015260400190565b600060208284031215612e4b57600080fd5b815161272681612bcd565b600060033d1115612e6f5760046000803e5060005160e01c5b90565b601f8201601f1916810167ffffffffffffffff81118282101715612ea657634e487b7160e01b600052604160045260246000fd5b6040525050565b600060443d1015612ebb5790565b6040513d600319016004823e80513d602482011167ffffffffffffffff82111715612ee557505090565b808201805167ffffffffffffffff811115612f01575050505090565b3d8401600319018282016020011115612f1b575050505090565b612f2a60208285010185612e72565b509392505050565b60008060233d1115612f4e576020600460003e50506000516001905b9091565b6001600160a01b038c811682528b811660208301528a166040820152606081018990526080810188905264ffffffffff87811660a083015286811660c0830152851660e082015262ffffff8416610100820152610160810183610120830152612fc361014083018462ffffff169052565b9c9b505050505050505050505050565b6001600160a01b039384168152919092166020820152604081019190915260600190565b634e487b7160e01b600052603260045260246000fd5b6000806040838503121561302057600080fd5b82516020840151909250612b9781612945565b64ffffffffff81811683821601908111156103f1576103f1612d88565b60006020828403121561306257600080fd5b815161272681612945565b600080600080600060a0868803121561308557600080fd5b855161309081612901565b60208701516040880151606089015160808a015193985091965094509250612cd581612bbb565b64ffffffffff82811682821603908111156103f1576103f1612d8856fea264697066735822122024516afca31250962e458e40651cc003681ff2be7cf5fa814b688bd47baa3d5d64736f6c634300081a0033000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea000000000000000000000000073493d73258c4beb6542e8dd3e1b2891c9723030000000000000000000000004ce0ab2fc21bd27a47a64f594fdf7654ea57dc79000000000000000000000000167144d66ac1d02eaafca3649ef3305ea31ee5a80000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994","name":"MintingHubGateway","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"paris","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// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)\n\npragma solidity ^0.8.20;\n\nimport {Context} from \"../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 * The initial owner is set to the address provided by the deployer. This can\n * 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    /**\n     * @dev The caller account is not authorized to perform an operation.\n     */\n    error OwnableUnauthorizedAccount(address account);\n\n    /**\n     * @dev The owner is not a valid owner account. (eg. `address(0)`)\n     */\n    error OwnableInvalidOwner(address owner);\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.\n     */\n    constructor(address initialOwner) {\n        if (initialOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(initialOwner);\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\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 the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        if (owner() != _msgSender()) {\n            revert OwnableUnauthorizedAccount(_msgSender());\n        }\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(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        if (newOwner == address(0)) {\n            revert OwnableInvalidOwner(address(0));\n        }\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-20 standard as defined in the ERC.\n */\ninterface IERC20 {\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    /**\n     * @dev Returns the value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC-20 standard.\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)\n\npragma solidity ^0.8.20;\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    function _contextSuffixLength() internal view virtual returns (uint256) {\n        return 0;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/ERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC165} from \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n */\nabstract contract ERC165 is IERC165 {\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {\n        return interfaceId == type(IERC165).interfaceId;\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/utils/introspection/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.20;\n\n/**\n * @dev Interface of the ERC-165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[ERC].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"contracts/MintingHubV2/MintingHub.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {ERC165} from \"@openzeppelin/contracts/utils/introspection/ERC165.sol\";\nimport {IDecentralizedEURO} from \"../interface/IDecentralizedEURO.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {ILeadrate} from \"../interface/ILeadrate.sol\";\nimport {IMintingHub} from \"./interface/IMintingHub.sol\";\nimport {IPositionFactory} from \"./interface/IPositionFactory.sol\";\nimport {IPosition} from \"./interface/IPosition.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\nimport {PositionRoller} from \"./PositionRoller.sol\";\n\n/**\n * @title Minting Hub\n * @notice The central hub for creating, cloning, and challenging collateralized DecentralizedEURO positions.\n * @dev Only one instance of this contract is required, whereas every new position comes with a new position\n * contract. Pending challenges are stored as structs in an array.\n */\ncontract MintingHub is IMintingHub, ERC165 {\n    /**\n     * @notice Irrevocable fee in deur when proposing a new position (but not when cloning an existing one).\n     */\n    uint256 public constant OPENING_FEE = 1000 * 10 ** 18;\n\n    /**\n     * @notice The challenger reward in parts per million (ppm) relative to the challenged amount, whereas\n     * challenged amount is defined as the challenged collateral amount times the liquidation price.\n     */\n    uint256 public constant CHALLENGER_REWARD = 20000; // 2%\n    uint256 public constant EXPIRED_PRICE_FACTOR = 10;\n\n    IPositionFactory private immutable POSITION_FACTORY; // position contract to clone\n\n    IDecentralizedEURO public immutable DEURO; // currency\n    PositionRoller public immutable ROLLER; // helper to roll positions\n    ILeadrate public immutable RATE; // to determine the interest rate\n\n    Challenge[] public challenges; // list of open challenges\n\n    /**\n     * @notice Map to remember pending postponed collateral returns.\n     * @dev It maps collateral => beneficiary => amount.\n     */\n    mapping(address collateral => mapping(address owner => uint256 amount)) public pendingReturns;\n\n    struct Challenge {\n        address challenger; // the address from which the challenge was initiated\n        uint40 start; // the start of the challenge\n        IPosition position; // the position that was challenged\n        uint256 size; // how much collateral the challenger provided\n    }\n\n    event PositionOpened(address indexed owner, address indexed position, address original, address collateral);\n    event ChallengeStarted(address indexed challenger, address indexed position, uint256 size, uint256 number);\n    event ChallengeAverted(address indexed position, uint256 number, uint256 size);\n    event ChallengeSucceeded(\n        address indexed position,\n        uint256 number,\n        uint256 bid,\n        uint256 acquiredCollateral,\n        uint256 challengeSize\n    );\n    event PostponedReturn(address collateral, address indexed beneficiary, uint256 amount);\n    event ForcedSale(address pos, uint256 amount, uint256 priceE36MinusDecimals);\n\n    error UnexpectedPrice();\n    error InvalidPos();\n    error IncompatibleCollateral();\n    error InsufficientCollateral();\n    error LeaveNoDust(uint256 amount);\n    error InvalidRiskPremium();\n    error InvalidReservePPM();\n    error InvalidCollateralDecimals();\n    error ChallengeTimeTooShort();\n    error InitPeriodTooShort();\n\n    modifier validPos(address position) {\n        if (DEURO.getPositionParent(position) != address(this)) revert InvalidPos();\n        _;\n    }\n\n    constructor(address _deur, address _leadrate, address _roller, address _factory) {\n        DEURO = IDecentralizedEURO(_deur);\n        RATE = ILeadrate(_leadrate);\n        POSITION_FACTORY = IPositionFactory(_factory);\n        ROLLER = PositionRoller(_roller);\n    }\n\n    /**\n     * @notice Open a collateralized loan position. See also https://docs.dEURO.com/positions/open .\n     * @dev For a successful call, you must set an allowance for the collateral token, allowing\n     * the minting hub to transfer the initial collateral amount to the newly created position and to\n     * withdraw the fees.\n     *\n     * @param _collateralAddress  address of collateral token\n     * @param _minCollateral      minimum collateral required to prevent dust amounts\n     * @param _initialCollateral  amount of initial collateral to be deposited\n     * @param _mintingMaximum     maximal amount of deur that can be minted by the position owner\n     * @param _initPeriodSeconds  initial period in seconds\n     * @param _expirationSeconds  position tenor in seconds from 'now'\n     * @param _challengeSeconds   challenge period. Longer for less liquid collateral.\n     * @param _riskPremium        ppm of minted amount that is added to the applicable minting fee as a risk premium\n     * @param _liqPrice           Liquidation price with (36 - token decimals) decimals,\n     *                            e.g. 18 decimals for an 18 dec collateral, 36 decs for a 0 dec collateral.\n     * @param _reservePPM         ppm of minted amount that is locked as borrower's reserve, e.g. 20%\n     * @return address            address of created position\n     */\n    function openPosition(\n        address _collateralAddress,\n        uint256 _minCollateral,\n        uint256 _initialCollateral,\n        uint256 _mintingMaximum,\n        uint40 _initPeriodSeconds,\n        uint40 _expirationSeconds,\n        uint40 _challengeSeconds,\n        uint24 _riskPremium,\n        uint256 _liqPrice,\n        uint24 _reservePPM\n    ) public returns (address) {\n        {\n            if (_riskPremium > 1_000_000) revert InvalidRiskPremium();\n            if (CHALLENGER_REWARD > _reservePPM || _reservePPM > 1_000_000) revert InvalidReservePPM();\n            if (IERC20Metadata(_collateralAddress).decimals() > 24) revert InvalidCollateralDecimals(); // leaves 12 digits for price\n            if (_challengeSeconds < 1 days) revert ChallengeTimeTooShort();\n            if (_initPeriodSeconds < 3 days) revert InitPeriodTooShort();\n            uint256 invalidAmount = IERC20(_collateralAddress).totalSupply() + 1;\n            try IERC20(_collateralAddress).transfer(address(0x123), invalidAmount) {\n                revert IncompatibleCollateral(); // we need a collateral that reverts on failed transfers\n            } catch Error(string memory /*reason*/) {} catch Panic(uint /*errorCode*/) {} catch (\n                bytes memory /*lowLevelData*/\n            ) {}\n            if (_initialCollateral < _minCollateral) revert InsufficientCollateral();\n            // must start with at least 5000 deur worth of collateral\n            if (_minCollateral * _liqPrice < 5000 ether * 10 ** 18) revert InsufficientCollateral();\n        }\n        IPosition pos = IPosition(\n            POSITION_FACTORY.createNewPosition(\n                msg.sender,\n                address(DEURO),\n                _collateralAddress,\n                _minCollateral,\n                _mintingMaximum,\n                _initPeriodSeconds,\n                _expirationSeconds,\n                _challengeSeconds,\n                _riskPremium,\n                _liqPrice,\n                _reservePPM\n            )\n        );\n        DEURO.registerPosition(address(pos));\n        DEURO.collectProfits(msg.sender, OPENING_FEE);\n        IERC20(_collateralAddress).transferFrom(msg.sender, address(pos), _initialCollateral);\n\n        emit PositionOpened(msg.sender, address(pos), address(pos), _collateralAddress);\n        return address(pos);\n    }\n\n    function clone(\n        address parent,\n        uint256 _initialCollateral,\n        uint256 _initialMint,\n        uint40 expiration\n    ) public returns (address) {\n        return clone(msg.sender, parent, _initialCollateral, _initialMint, expiration);\n    }\n\n    /**\n     * @notice Clones an existing position and immediately tries to mint the specified amount using the given collateral.\n     * @dev This needs an allowance to be set on the collateral contract such that the minting hub can get the collateral.\n     */\n    function clone(\n        address owner,\n        address parent,\n        uint256 _initialCollateral,\n        uint256 _initialMint,\n        uint40 expiration\n    ) public validPos(parent) returns (address) {\n        address pos = POSITION_FACTORY.clonePosition(parent);\n        IPosition child = IPosition(pos);\n        child.initialize(parent, expiration);\n        DEURO.registerPosition(pos);\n        IERC20 collateral = child.collateral();\n        if (_initialCollateral < child.minimumCollateral()) revert InsufficientCollateral();\n        collateral.transferFrom(msg.sender, pos, _initialCollateral); // collateral must still come from sender for security\n        emit PositionOpened(owner, address(pos), parent, address(collateral));\n        child.mint(owner, _initialMint);\n        Ownable(address(child)).transferOwnership(owner);\n        return address(pos);\n    }\n\n    /**\n     * @notice Launch a challenge (Dutch auction) on a position\n     * @param _positionAddr address of the position we want to challenge\n     * @param _collateralAmount amount of the collateral we want to challenge\n     * @param minimumPrice guards against the minter front-running with a price change\n     * @return index of the challenge in the challenge-array\n     */\n    function challenge(\n        address _positionAddr,\n        uint256 _collateralAmount,\n        uint256 minimumPrice\n    ) external validPos(_positionAddr) returns (uint256) {\n        IPosition position = IPosition(_positionAddr);\n        // challenger should be ok if front-run by owner with a higher price\n        // in case owner front-runs challenger with small price decrease to prevent challenge,\n        // the challenger should set minimumPrice to market price\n        uint256 liqPrice = position.virtualPrice();\n        if (liqPrice < minimumPrice) revert UnexpectedPrice();\n        IERC20(position.collateral()).transferFrom(msg.sender, address(this), _collateralAmount);\n        uint256 pos = challenges.length;\n        challenges.push(Challenge(msg.sender, uint40(block.timestamp), position, _collateralAmount));\n        position.notifyChallengeStarted(_collateralAmount, liqPrice);\n        emit ChallengeStarted(msg.sender, address(position), _collateralAmount, pos);\n        return pos;\n    }\n\n    /**\n     * @notice Post a bid in deur given an open challenge.\n     *\n     * @dev In case that the collateral cannot be transferred back to the challenger (i.e. because the collateral token\n     * has a blacklist and the challenger is on it), it is possible to postpone the return of the collateral.\n     *\n     * @param _challengeNumber          index of the challenge as broadcast in the event\n     * @param size                      how much of the collateral the caller wants to bid for at most\n     *                                  (automatically reduced to the available amount)\n     * @param postponeCollateralReturn  To postpone the return of the collateral to the challenger. Usually false.\n     */\n    function bid(uint32 _challengeNumber, uint256 size, bool postponeCollateralReturn) external {\n        Challenge memory _challenge = challenges[_challengeNumber];\n        (uint256 liqPrice, uint40 phase) = _challenge.position.challengeData();\n        size = _challenge.size < size ? _challenge.size : size; // cannot bid for more than the size of the challenge\n\n        if (block.timestamp <= _challenge.start + phase) {\n            _avertChallenge(_challenge, _challengeNumber, liqPrice, size);\n            emit ChallengeAverted(address(_challenge.position), _challengeNumber, size);\n        } else {\n            _returnChallengerCollateral(_challenge, _challengeNumber, size, postponeCollateralReturn);\n            (uint256 transferredCollateral, uint256 offer) = _finishChallenge(_challenge, size);\n            emit ChallengeSucceeded(address(_challenge.position), _challengeNumber, offer, transferredCollateral, size);\n        }\n    }\n\n    function _finishChallenge(\n        Challenge memory _challenge,\n        uint256 size\n    ) internal returns (uint256, uint256) {\n        // Repayments depend on what was actually minted, whereas bids depend on the available collateral\n        (address owner, uint256 collateral, uint256 repayment, uint256 interest, uint32 reservePPM) = _challenge\n            .position\n            .notifyChallengeSucceeded(size);\n\n        // No overflow possible thanks to invariant (col * price <= limit * 10**18)\n        // enforced in Position.setPrice and knowing that collateral <= col.\n        uint256 offer = _calculateOffer(_challenge, collateral);\n\n        DEURO.transferFrom(msg.sender, address(this), offer); // get money from bidder \n        uint256 reward = (offer * CHALLENGER_REWARD) / 1_000_000; \n        DEURO.transfer(_challenge.challenger, reward); // pay out the challenger reward\n        uint256 fundsAvailable = offer - reward; // funds available after reward\n\n        // Example: available funds are 90, repayment is 50, reserve 20%. Then 20%*(90-50)=16 are collected as profits\n        // and the remaining 34 are sent to the position owner. If the position owner maxed out debt before the challenge\n        // started and the liquidation price was 100, they would be slightly better off as they would get away with 80\n        // instead of 40+36 = 76 in this example.\n        if (fundsAvailable > repayment + interest) {\n            // The excess amount is distributed between the system and the owner using the reserve ratio\n            // At this point, we cannot rely on the liquidation price because the challenge might have been started as a\n            // response to an unreasonable increase of the liquidation price, such that we have to use this heuristic\n            // for excess fund distribution, which make position owners that maxed out their positions slightly better\n            // off in comparison to those who did not.\n            uint256 profits = (reservePPM * (fundsAvailable - repayment - interest)) / 1_000_000;\n            DEURO.collectProfits(address(this), profits);\n            DEURO.transfer(owner, fundsAvailable - repayment - interest - profits);\n        } else if (fundsAvailable < repayment + interest) {\n            DEURO.coverLoss(address(this), repayment + interest - fundsAvailable); // ensure we have enough to pay everything\n        }\n        DEURO.burnWithoutReserve(repayment, reservePPM); // Repay the challenged part, example: 50 deur leading to 10 deur in implicit profits\n        DEURO.collectProfits(address(this), interest); // Collect interest as profits\n        _challenge.position.transferChallengedCollateral(msg.sender, collateral); // transfer the collateral to the bidder\n        return (collateral, offer);\n    }\n\n    function _avertChallenge(Challenge memory _challenge, uint32 number, uint256 liqPrice, uint256 size) internal {\n        require(block.timestamp != _challenge.start); // do not allow to avert the challenge in the same transaction, see CS-ZCHF-037\n        if (msg.sender == _challenge.challenger) {\n            // allow challenger to cancel challenge without paying themselves\n        } else {\n            DEURO.transferFrom(msg.sender, _challenge.challenger, (size * liqPrice) / (10 ** 18));\n        }\n\n        _challenge.position.notifyChallengeAverted(size);\n        _challenge.position.collateral().transfer(msg.sender, size);\n        if (size < _challenge.size) {\n            challenges[number].size = _challenge.size - size;\n        } else {\n            require(size == _challenge.size);\n            delete challenges[number];\n        }\n    }\n\n    /**\n     * @notice Returns 'amount' of the collateral to the challenger and reduces or deletes the relevant challenge.\n     */\n    function _returnChallengerCollateral(\n        Challenge memory _challenge,\n        uint32 number,\n        uint256 amount,\n        bool postpone\n    ) internal {\n        _returnCollateral(_challenge.position.collateral(), _challenge.challenger, amount, postpone);\n        if (_challenge.size == amount) {\n            // bid on full amount\n            delete challenges[number];\n        } else {\n            // bid on partial amount\n            challenges[number].size -= amount;\n        }\n    }\n\n    /**\n     * @notice Calculates the current Dutch auction price.\n     * @dev Starts at the full price at time 'start' and linearly goes to 0 as 'phase2' passes.\n     */\n    function _calculatePrice(uint40 start, uint40 phase2, uint256 liqPrice) internal view returns (uint256) {\n        uint40 timeNow = uint40(block.timestamp);\n        if (timeNow <= start) {\n            return liqPrice;\n        } else if (timeNow >= start + phase2) {\n            return 0;\n        } else {\n            uint256 timeLeft = phase2 - (timeNow - start);\n            return (liqPrice / phase2) * timeLeft;\n        }\n    }\n\n    /**\n     * @notice Calculates the offer amount for the given challenge.\n     * @dev The offer is calculated as the current price times the collateral amount.\n     */\n    function _calculateOffer(Challenge memory _challenge, uint256 collateral) internal view returns (uint256) {\n        (uint256 liqPrice, uint40 phase) = _challenge.position.challengeData();\n        return (_calculatePrice(_challenge.start + phase, phase, liqPrice) * collateral) / 10 ** 18;\n    }\n\n    /**\n     * @notice Get the price per unit of the collateral for the given challenge.\n     * @dev The price comes with (36 - collateral.decimals()) digits, so multiplying it with the raw collateral amount\n     * always yields a price with 36 digits, or 18 digits after dividing by 10**18 again.\n     */\n    function price(uint32 challengeNumber) public view returns (uint256) {\n        Challenge memory _challenge = challenges[challengeNumber];\n        if (_challenge.challenger == address(0x0)) {\n            return 0;\n        } else {\n            (uint256 liqPrice, uint40 phase) = _challenge.position.challengeData();\n            return _calculatePrice(_challenge.start + phase, phase, liqPrice);\n        }\n    }\n\n    /**\n     * @notice Challengers can call this method to withdraw collateral whose return was postponed.\n     */\n    function returnPostponedCollateral(address collateral, address target) external {\n        uint256 amount = pendingReturns[collateral][msg.sender];\n        delete pendingReturns[collateral][msg.sender];\n        IERC20(collateral).transfer(target, amount);\n    }\n\n    function _returnCollateral(IERC20 collateral, address recipient, uint256 amount, bool postpone) internal {\n        if (postpone) {\n            // Postponing helps in case the challenger was blacklisted or otherwise cannot receive at the moment.\n            pendingReturns[address(collateral)][recipient] += amount;\n            emit PostponedReturn(address(collateral), recipient, amount);\n        } else {\n            collateral.transfer(recipient, amount); // return the challenger's collateral\n        }\n    }\n\n    /**\n     * The applicable purchase price when forcing the sale of collateral of an expired position.\n     *\n     * The price starts at 10x the liquidation price at the expiration time, linearly declines to\n     * 1x liquidation price over the course of one challenge period, and then linearly declines\n     * less steeply to 0 over the course of another challenge period.\n     */\n    function expiredPurchasePrice(IPosition pos) public view returns (uint256) {\n        uint256 liqprice = pos.virtualPrice();\n        uint256 expiration = pos.expiration();\n        if (block.timestamp <= expiration) {\n            return EXPIRED_PRICE_FACTOR * liqprice;\n        } else {\n            uint256 challengePeriod = pos.challengePeriod();\n            uint256 timePassed = block.timestamp - expiration;\n            if (timePassed <= challengePeriod) {\n                // from 10x liquidation price to 1x in first phase\n                uint256 timeLeft = challengePeriod - timePassed;\n                return liqprice + (((EXPIRED_PRICE_FACTOR - 1) * liqprice * timeLeft) / challengePeriod);\n            } else if (timePassed < 2 * challengePeriod) {\n                // from 1x liquidation price to 0 in second phase\n                uint256 timeLeft = 2 * challengePeriod - timePassed;\n                return (liqprice  * timeLeft) / challengePeriod;\n            } else {\n                // get collateral for free after both phases passed\n                return 0;\n            }\n        }\n    }\n\n    /**\n     * Buys up to the desired amount of the collateral asset from the given expired position using\n     * the applicable 'expiredPurchasePrice' at that instant.\n     *\n     * To prevent dust either the remaining collateral needs to be bought or collateral with a value\n     * of at least OPENING_FEE (1000 dEURO) needs to remain in the position for a different buyer\n     */\n    function buyExpiredCollateral(IPosition pos, uint256 upToAmount) external returns (uint256) {\n        uint256 max = pos.collateral().balanceOf(address(pos));\n        uint256 amount = upToAmount > max ? max : upToAmount;\n        uint256 forceSalePrice = expiredPurchasePrice(pos);\n\n        uint256 costs = (forceSalePrice * amount) / 10 ** 18;\n\n        if (max - amount > 0 && ((forceSalePrice * (max - amount)) / 10 ** 18) < OPENING_FEE) {\n            revert LeaveNoDust(max - amount);\n        }\n\n        pos.forceSale(msg.sender, amount, costs);\n        emit ForcedSale(address(pos), amount, forceSalePrice);\n        return amount;\n    }\n\n    /**\n     * @dev See {IERC165-supportsInterface}.\n     */\n    function supportsInterface(bytes4 interfaceId) public view override virtual returns (bool) {\n        return\n            interfaceId == type(IMintingHub).interfaceId ||\n            super.supportsInterface(interfaceId);\n    }\n}\n"},{"file_path":"contracts/MintingHubV2/PositionRoller.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IDecentralizedEURO} from \"../interface/IDecentralizedEURO.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IMintingHubGateway} from \"../gateway/interface/IMintingHubGateway.sol\";\nimport {IMintingHub} from \"./interface/IMintingHub.sol\";\nimport {IPosition} from \"./interface/IPosition.sol\";\nimport {IReserve} from \"../interface/IReserve.sol\";\nimport {Ownable} from \"@openzeppelin/contracts/access/Ownable.sol\";\n\n/**\n * @title PositionRoller\n *\n * Helper to roll over a debt from an old position to a new one.\n * Both positions should have the same collateral. Otherwise, it does not make much sense.\n */\ncontract PositionRoller {\n    IDecentralizedEURO private deuro;\n\n    error NotOwner(address pos);\n    error NotPosition(address pos);\n    error Log(uint256, uint256, uint256);\n\n    event Roll(address source, uint256 collWithdraw, uint256 repay, address target, uint256 collDeposit, uint256 mint);\n\n    constructor(address deuro_) {\n        deuro = IDecentralizedEURO(deuro_);\n    }\n\n    /**\n     * Convenience method to roll an old position into a new one.\n     *\n     * Pre-condition: an allowance for the roller to spend the collateral asset on behalf of the caller,\n     * i.e., one should set collateral.approve(roller, collateral.balanceOf(sourcePosition)).\n     *\n     * The following is assumed:\n     * - If the limit of the target position permits, the user wants to roll everything.\n     * - The user does not want to add additional collateral, but excess collateral is returned.\n     * - If not enough can be minted in the new position, it is acceptable for the roller to use dEURO from the msg.sender.\n     */\n    function rollFully(IPosition source, IPosition target) external {\n        rollFullyWithExpiration(source, target, target.expiration());\n    }\n\n    /**\n     * Like rollFully, but with a custom expiration date for the new position.\n     */\n    function rollFullyWithExpiration(IPosition source, IPosition target, uint40 expiration) public {\n        require(source.collateral() == target.collateral());\n        uint256 principal = source.principal();\n        uint256 interest = source.getInterest();\n        uint256 usableMint = source.getUsableMint(principal) + interest; // Roll interest into principal\n        uint256 mintAmount = target.getMintAmount(usableMint);\n        uint256 collateralToWithdraw = IERC20(source.collateral()).balanceOf(address(source));\n        uint256 targetPrice = target.price();\n        uint256 depositAmount = (mintAmount * 10 ** 18 + targetPrice - 1) / targetPrice; // round up\n        if (depositAmount > collateralToWithdraw) {\n            // If we need more collateral than available from the old position, we opt for taking\n            // the missing funds from the caller instead of requiring additional collateral.\n            depositAmount = collateralToWithdraw;\n            mintAmount = (depositAmount * target.price()) / 10 ** 18; // round down, rest will be taken from caller\n        }\n\n        roll(source, principal + interest, collateralToWithdraw, target, mintAmount, depositAmount, expiration);\n    }\n\n    /**\n     * Rolls the source position into the target position using a flash loan.\n     * Both the source and the target position must recognize this roller.\n     * It is the responsibility of the caller to ensure that both positions are valid contracts.\n     *\n     * @param source The source position, must be owned by the msg.sender.\n     * @param repay The amount of principal to repay from the source position using a flash loan, freeing up some or all collateral .\n     * @param collWithdraw Collateral to move from the source position to the msg.sender.\n     * @param target The target position. If not owned by msg.sender or if it does not have the desired expiration,\n     *               it is cloned to create a position owned by the msg.sender.\n     * @param mint The amount to be minted from the target position using collateral from msg.sender.\n     * @param collDeposit The amount of collateral to be sent from msg.sender to the target position.\n     * @param expiration The desired expiration date for the target position.\n     */\n    function roll(\n        IPosition source,\n        uint256 repay,\n        uint256 collWithdraw,\n        IPosition target,\n        uint256 mint,\n        uint256 collDeposit,\n        uint40 expiration\n    ) public valid(source) valid(target) own(source) {\n        deuro.mint(address(this), repay); // take a flash loan\n        uint256 used = source.repay(repay);\n        source.withdrawCollateral(msg.sender, collWithdraw);\n        if (mint > 0) {\n            IERC20 targetCollateral = IERC20(target.collateral());\n            if (Ownable(address(target)).owner() != msg.sender || expiration != target.expiration()) {\n                targetCollateral.transferFrom(msg.sender, address(this), collDeposit); // get the new collateral\n                targetCollateral.approve(target.hub(), collDeposit); // approve the new collateral and clone:\n                target = _cloneTargetPosition(target, source, collDeposit, mint, expiration);\n            } else {\n                // We can roll into the provided existing position.\n                // We do not verify whether the target position was created by the known minting hub in order\n                // to allow positions to be rolled into future versions of the minting hub.\n                targetCollateral.transferFrom(msg.sender, address(target), collDeposit);\n                target.mint(msg.sender, mint);\n            }\n        }\n\n        // Transfer remaining flash loan to caller for repayment\n        if (repay > used) {\n            deuro.transfer(msg.sender, repay - used);\n        }\n\n        deuro.burnFrom(msg.sender, repay); // repay the flash loan\n        emit Roll(address(source), collWithdraw, repay, address(target), collDeposit, mint);\n    }\n\n    /**\n     * Clones the target position and mints the specified amount using the given collateral.\n     */\n    function _cloneTargetPosition (\n        IPosition target,\n        IPosition source,\n        uint256 collDeposit,\n        uint256 mint,\n        uint40 expiration\n    ) internal returns (IPosition) {\n        if (IERC165(target.hub()).supportsInterface(type(IMintingHubGateway).interfaceId)) {\n            bytes32 frontendCode = IMintingHubGateway(target.hub()).GATEWAY().getPositionFrontendCode(\n                address(source)\n            );\n            return IPosition(\n                IMintingHubGateway(target.hub()).clone(\n                    msg.sender,\n                    address(target),\n                    collDeposit,\n                    mint,\n                    expiration,\n                    frontendCode // use the same frontend code\n                )\n            );\n        } else {\n            return IPosition(\n                IMintingHub(target.hub()).clone(msg.sender, address(target), collDeposit, mint, expiration)\n            );\n        }\n    }\n\n    modifier own(IPosition pos) {\n        if (Ownable(address(pos)).owner() != msg.sender) revert NotOwner(address(pos));\n        _;\n    }\n\n    modifier valid(IPosition pos) {\n        if (deuro.getPositionParent(address(pos)) == address(0x0)) revert NotPosition(address(pos));\n        _;\n    }\n}\n"},{"file_path":"contracts/MintingHubV2/interface/IMintingHub.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {ILeadrate} from \"../../interface/ILeadrate.sol\";\nimport {IPosition} from \"./IPosition.sol\";\nimport {PositionRoller} from \"../PositionRoller.sol\";\n\ninterface IMintingHub {\n    function RATE() external view returns (ILeadrate);\n\n    function ROLLER() external view returns (PositionRoller);\n\n    function challenge(\n        address _positionAddr,\n        uint256 _collateralAmount,\n        uint256 minimumPrice\n    ) external returns (uint256);\n\n    function bid(uint32 _challengeNumber, uint256 size, bool postponeCollateralReturn) external;\n\n    function returnPostponedCollateral(address collateral, address target) external;\n\n    function buyExpiredCollateral(IPosition pos, uint256 upToAmount) external returns (uint256);\n\n    function clone(address owner, address parent, uint256 _initialCollateral, uint256 _initialMint, uint40 expiration) external returns (address);\n}\n"},{"file_path":"contracts/MintingHubV2/interface/IPosition.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IPosition {\n    function hub() external view returns (address);\n\n    function collateral() external view returns (IERC20);\n\n    function minimumCollateral() external view returns (uint256);\n\n    function price() external view returns (uint256);\n\n    function virtualPrice() external view returns (uint256);\n\n    function challengedAmount() external view returns (uint256);\n\n    function original() external view returns (address);\n\n    function expiration() external view returns (uint40);\n\n    function cooldown() external view returns (uint40);\n\n    function limit() external view returns (uint256);\n\n    function challengePeriod() external view returns (uint40);\n\n    function start() external view returns (uint40);\n\n    function riskPremiumPPM() external view returns (uint24);\n\n    function reserveContribution() external view returns (uint24);\n\n    function principal() external view returns (uint256);\n\n    function interest() external view returns (uint256);\n\n    function lastAccrual() external view returns (uint40);\n\n    function initialize(address parent, uint40 _expiration) external;\n\n    function assertCloneable() external;\n\n    function notifyMint(uint256 mint_) external;\n\n    function notifyRepaid(uint256 repaid_) external;\n\n    function availableForClones() external view returns (uint256);\n\n    function availableForMinting() external view returns (uint256);\n\n    function deny(address[] calldata helpers, string calldata message) external;\n\n    function getUsableMint(uint256 totalMint) external view returns (uint256);\n\n    function getMintAmount(uint256 usableMint) external view returns (uint256);\n\n    function adjust(uint256 newMinted, uint256 newCollateral, uint256 newPrice) external;\n\n    function adjustPrice(uint256 newPrice) external;\n\n    function mint(address target, uint256 amount) external;\n\n    function getDebt() external view returns (uint256);\n\n    function getInterest() external view returns (uint256);\n\n    function repay(uint256 amount) external returns (uint256);\n\n    function repayFull() external returns (uint256);\n\n    function forceSale(address buyer, uint256 colAmount, uint256 proceeds) external;\n\n    function withdraw(address token, address target, uint256 amount) external;\n\n    function withdrawCollateral(address target, uint256 amount) external;\n\n    function transferChallengedCollateral(address target, uint256 amount) external;\n\n    function challengeData() external view returns (uint256 liqPrice, uint40 phase);\n\n    function notifyChallengeStarted(uint256 size, uint256 _price) external;\n\n    function notifyChallengeAverted(uint256 size) external;\n\n    function notifyChallengeSucceeded(\n        uint256 _size\n    ) external returns (address, uint256, uint256, uint256, uint32);\n}\n"},{"file_path":"contracts/MintingHubV2/interface/IPositionFactory.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IPositionFactory {\n    function createNewPosition(\n        address _owner,\n        address _deuro,\n        address _collateral,\n        uint256 _minCollateral,\n        uint256 _initialLimit,\n        uint40 _initPeriod,\n        uint40 _duration,\n        uint40 _challengePeriod,\n        uint24 _riskPremiumPPM,\n        uint256 _liqPrice,\n        uint24 _reserve\n    ) external returns (address);\n\n    function clonePosition(address _parent) external returns (address);\n}\n"},{"file_path":"contracts/gateway/interface/IFrontendGateway.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface IFrontendGateway {\n    struct FrontendCode {\n        uint256 balance;\n        address owner;\n    }\n\n    event FrontendCodeRegistered(address owner, bytes32 frontendCode);\n    event FrontendCodeTransferred(address from, address to, bytes32 frontendCode);\n    event FrontendCodeRewardsWithdrawn(address to, uint256 amount, bytes32 frontendCode);\n    event NewPositionRegistered(address position, bytes32 frontendCode);\n    event RateChangesProposed(address who, uint24 nextFeeRate, uint24 nextSavingsFeeRate, uint24 nextMintingFeeRate, uint256 nextChange);\n    event RateChangesExecuted(address who, uint24 nextFeeRate, uint24 nextSavingsFeeRate, uint24 nextMintingFeeRate);\n    \n    event InvestRewardAdded(bytes32 frontendCode, address user, uint256 amount, uint256 reward);\n    event RedeemRewardAdded(bytes32 frontendCode, address user, uint256 amount, uint256 reward);\n    event UnwrapAndSellRewardAdded(bytes32 frontendCode, address user, uint256 amount, uint256 reward);\n    event SavingsRewardAdded(bytes32 frontendCode, address saver, uint256 interest, uint256 reward);\n    event PositionRewardAdded(bytes32 frontendCode, address position, uint256 amount, uint256 reward);\n\n    error FrontendCodeAlreadyExists();\n    error NotFrontendCodeOwner();\n    error NotGatewayService();\n    error ProposedChangesToHigh();\n    error NoOpenChanges();\n    error NotDoneWaiting(uint256 minmumExecutionTime);\n    error EquityTooLow();\n\n    function invest(uint256 amount, uint256 expectedShares, bytes32 frontendCode) external returns (uint256);\n    function redeem(address target, uint256 shares, uint256 expectedProceeds, bytes32 frontendCode) external returns (uint256);\n    function unwrapAndSell(uint256 amount, bytes32 frontendCode) external returns (uint256);\n\n    function updateSavingCode(address savingsOwner, bytes32 frontendCode) external;\n    function updateSavingRewards(address saver, uint256 interest) external;\n\n    function registerPosition(address position, bytes32 frontendCode) external;\n    function updatePositionRewards(address position, uint256 amount) external;\n    function getPositionFrontendCode(address position)view external  returns(bytes32);\n\n    // Frontend Code Logic\n    function registerFrontendCode(bytes32 frontendCode) external returns (bool);\n    function transferFrontendCode(bytes32 frontendCode, address to) external returns (bool);\n    function withdrawRewards(bytes32 frontendCode) external returns (uint256);\n    function withdrawRewardsTo(bytes32 frontendCode, address to) external returns (uint256);\n\n    // Governance\n    function proposeChanges(uint24 newFeeRatePPM_, uint24 newSavingsFeeRatePPM_, uint24 newMintingFeeRatePPM_, address[] calldata helpers) external;\n    function executeChanges() external;\n}\n"},{"file_path":"contracts/gateway/interface/IMintingHubGateway.sol","source_code":"// SPDX-License-Identifier: UNLICENSED\npragma solidity ^0.8.10;\n\nimport {IMintingHub} from \"../../MintingHubV2/interface/IMintingHub.sol\";\nimport {IFrontendGateway} from \"./IFrontendGateway.sol\";\n\ninterface IMintingHubGateway {\n    function GATEWAY() external view returns (IFrontendGateway);\n    function notifyInterestPaid(uint256 amount) external;\n    function openPosition(address _collateralAddress, uint256 _minCollateral, uint256 _initialCollateral, uint256 _mintingMaximum, uint40 _initPeriodSeconds, uint40 _expirationSeconds, uint40 _challengeSeconds, uint24 _riskPremium, uint256 _liqPrice, uint24 _reservePPM, bytes32 _frontendCode) external returns (address);\n    function clone(address owner, address parent, uint256 _initialCollateral, uint256 _initialMint, uint40 expiration, bytes32 frontendCode) external returns (address);\n}\n"},{"file_path":"contracts/interface/IDecentralizedEURO.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IReserve} from \"./IReserve.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IDecentralizedEURO is IERC20 {\n    function suggestMinter(\n        address _minter,\n        uint256 _applicationPeriod,\n        uint256 _applicationFee,\n        string calldata _message\n    ) external;\n\n    function registerPosition(address position) external;\n\n    function denyMinter(address minter, address[] calldata helpers, string calldata message) external;\n\n    function reserve() external view returns (IReserve);\n\n    function minterReserve() external view returns (uint256);\n\n    function calculateAssignedReserve(uint256 mintedAmount, uint32 _reservePPM) external view returns (uint256);\n\n    function calculateFreedAmount(uint256 amountExcludingReserve, uint32 _reservePPM) external view returns (uint256);\n\n    function equity() external view returns (uint256);\n\n    function isMinter(address minter) external view returns (bool);\n\n    function getPositionParent(address position) external view returns (address);\n\n    function mint(address target, uint256 amount) external;\n\n    function mintWithReserve(address target, uint256 amount, uint32 reservePPM) external;\n\n    function burn(uint256 amount) external;\n\n    function burnFrom(address target, uint256 amount) external;\n\n    function burnWithoutReserve(uint256 amount, uint32 reservePPM) external;\n\n    function burnFromWithReserve(\n        address payer,\n        uint256 targetTotalBurnAmount,\n        uint32 reservePPM\n    ) external returns (uint256);\n\n    function coverLoss(address source, uint256 amount) external;\n\n    function distributeProfits(address recipient, uint256 amount) external;\n\n    function collectProfits(address source, uint256 _amount) external;\n}\n"},{"file_path":"contracts/interface/ILeadrate.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\ninterface ILeadrate {\n   function currentRatePPM() external view returns (uint24);\n   function currentTicks() external view returns (uint64);\n}"},{"file_path":"contracts/interface/IReserve.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IReserve is IERC20 {\n    function invest(uint256 amount, uint256 expected) external returns (uint256);\n    function checkQualified(address sender, address[] calldata helpers) external view;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_deuro","type":"address"},{"internalType":"address","name":"_leadrate","type":"address"},{"internalType":"address","name":"_roller","type":"address"},{"internalType":"address","name":"_factory","type":"address"},{"internalType":"address","name":"_gateway","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ChallengeTimeTooShort","type":"error"},{"inputs":[],"name":"IncompatibleCollateral","type":"error"},{"inputs":[],"name":"InitPeriodTooShort","type":"error"},{"inputs":[],"name":"InsufficientCollateral","type":"error"},{"inputs":[],"name":"InvalidCollateralDecimals","type":"error"},{"inputs":[],"name":"InvalidPos","type":"error"},{"inputs":[],"name":"InvalidReservePPM","type":"error"},{"inputs":[],"name":"InvalidRiskPremium","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"LeaveNoDust","type":"error"},{"inputs":[],"name":"UnexpectedPrice","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"position","type":"address"},{"indexed":false,"internalType":"uint256","name":"number","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"}],"name":"ChallengeAverted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challenger","type":"address"},{"indexed":true,"internalType":"address","name":"position","type":"address"},{"indexed":false,"internalType":"uint256","name":"size","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"number","type":"uint256"}],"name":"ChallengeStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"position","type":"address"},{"indexed":false,"internalType":"uint256","name":"number","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"bid","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"acquiredCollateral","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"challengeSize","type":"uint256"}],"name":"ChallengeSucceeded","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"pos","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"priceE36MinusDecimals","type":"uint256"}],"name":"ForcedSale","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"position","type":"address"},{"indexed":false,"internalType":"address","name":"original","type":"address"},{"indexed":false,"internalType":"address","name":"collateral","type":"address"}],"name":"PositionOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"collateral","type":"address"},{"indexed":true,"internalType":"address","name":"beneficiary","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"PostponedReturn","type":"event"},{"inputs":[],"name":"CHALLENGER_REWARD","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEURO","outputs":[{"internalType":"contract IDecentralizedEURO","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXPIRED_PRICE_FACTOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GATEWAY","outputs":[{"internalType":"contract IFrontendGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"OPENING_FEE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"RATE","outputs":[{"internalType":"contract ILeadrate","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROLLER","outputs":[{"internalType":"contract PositionRoller","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_challengeNumber","type":"uint32"},{"internalType":"uint256","name":"size","type":"uint256"},{"internalType":"bool","name":"postponeCollateralReturn","type":"bool"}],"name":"bid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPosition","name":"pos","type":"address"},{"internalType":"uint256","name":"upToAmount","type":"uint256"}],"name":"buyExpiredCollateral","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_positionAddr","type":"address"},{"internalType":"uint256","name":"_collateralAmount","type":"uint256"},{"internalType":"uint256","name":"minimumPrice","type":"uint256"}],"name":"challenge","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"challenges","outputs":[{"internalType":"address","name":"challenger","type":"address"},{"internalType":"uint40","name":"start","type":"uint40"},{"internalType":"contract IPosition","name":"position","type":"address"},{"internalType":"uint256","name":"size","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"parent","type":"address"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialMint","type":"uint256"},{"internalType":"uint40","name":"expiration","type":"uint40"}],"name":"clone","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"parent","type":"address"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialMint","type":"uint256"},{"internalType":"uint40","name":"expiration","type":"uint40"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"clone","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"parent","type":"address"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialMint","type":"uint256"},{"internalType":"uint40","name":"expiration","type":"uint40"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"clone","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"parent","type":"address"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialMint","type":"uint256"},{"internalType":"uint40","name":"expiration","type":"uint40"}],"name":"clone","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IPosition","name":"pos","type":"address"}],"name":"expiredPurchasePrice","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"notifyInterestPaid","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralAddress","type":"address"},{"internalType":"uint256","name":"_minCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_mintingMaximum","type":"uint256"},{"internalType":"uint40","name":"_initPeriodSeconds","type":"uint40"},{"internalType":"uint40","name":"_expirationSeconds","type":"uint40"},{"internalType":"uint40","name":"_challengeSeconds","type":"uint40"},{"internalType":"uint24","name":"_riskPremium","type":"uint24"},{"internalType":"uint256","name":"_liqPrice","type":"uint256"},{"internalType":"uint24","name":"_reservePPM","type":"uint24"}],"name":"openPosition","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_collateralAddress","type":"address"},{"internalType":"uint256","name":"_minCollateral","type":"uint256"},{"internalType":"uint256","name":"_initialCollateral","type":"uint256"},{"internalType":"uint256","name":"_mintingMaximum","type":"uint256"},{"internalType":"uint40","name":"_initPeriodSeconds","type":"uint40"},{"internalType":"uint40","name":"_expirationSeconds","type":"uint40"},{"internalType":"uint40","name":"_challengeSeconds","type":"uint40"},{"internalType":"uint24","name":"_riskPremium","type":"uint24"},{"internalType":"uint256","name":"_liqPrice","type":"uint256"},{"internalType":"uint24","name":"_reservePPM","type":"uint24"},{"internalType":"bytes32","name":"_frontendCode","type":"bytes32"}],"name":"openPosition","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"pendingReturns","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"challengeNumber","type":"uint32"}],"name":"price","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"collateral","type":"address"},{"internalType":"address","name":"target","type":"address"}],"name":"returnPostponedCollateral","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea000000000000000000000000073493d73258c4beb6542e8dd3e1b2891c9723030000000000000000000000004ce0ab2fc21bd27a47a64f594fdf7654ea57dc79000000000000000000000000167144d66ac1d02eaafca3649ef3305ea31ee5a80000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994"}