{"file_path":"contracts/gateway/SavingsGateway.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.10;\n\nimport {IFrontendGateway} from \"./interface/IFrontendGateway.sol\";\nimport {Context} from \"@openzeppelin/contracts/utils/Context.sol\";\nimport {IDecentralizedEURO} from \"../interface/IDecentralizedEURO.sol\";\nimport {Savings} from \"../Savings.sol\";\n\ncontract SavingsGateway is Savings, Context {\n    IFrontendGateway public immutable GATEWAY;\n\n    constructor(IDecentralizedEURO deuro_, uint24 initialRatePPM, address gateway_) Savings(deuro_, initialRatePPM) {\n        GATEWAY = IFrontendGateway(gateway_);\n    }\n\n    function refresh(address accountOwner) internal override returns (Account storage) {\n        Account storage account = savings[accountOwner];\n        uint64 ticks = currentTicks();\n        if (ticks > account.ticks) {\n            uint192 earnedInterest = calculateInterest(account, ticks);\n            if (earnedInterest > 0) {\n                // collect interest as you go and trigger accounting event\n                (IDecentralizedEURO(address(deuro))).distributeProfits(address(this), earnedInterest);\n                account.saved += earnedInterest;\n                GATEWAY.updateSavingRewards(accountOwner, earnedInterest);\n                emit InterestCollected(accountOwner, earnedInterest);\n            }\n            account.ticks = ticks;\n        }\n        return account;\n    }\n\n    function save(uint192 amount, bytes32 frontendCode) public {\n        save(_msgSender(), amount, frontendCode);\n    }\n\n    function save(address owner, uint192 amount, bytes32 frontendCode) public {\n        GATEWAY.updateSavingCode(_msgSender(), frontendCode);\n        save(owner, amount);\n    }\n\n    function adjust(uint192 targetAmount, bytes32 frontendCode) public {\n        GATEWAY.updateSavingCode(_msgSender(), frontendCode);\n        adjust(targetAmount);\n    }\n\n    function withdraw(address target, uint192 amount, bytes32 frontendCode) public returns (uint256) {\n        GATEWAY.updateSavingCode(_msgSender(), frontendCode);\n        return withdraw(target, amount);\n    }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106101585760003560e01c806382b8eaf5116100c3578063b6f83c171161007c578063b6f83c171461038d578063b77cd1c7146103bb578063bdc65152146103ce578063c1983610146103e1578063cbcf9676146103f4578063fd449c141461040757600080fd5b806382b8eaf51461030957806385bd12d11461033057806391a0ac6a146103385780639e2363dc1461035f578063a696399d14610372578063b079f1631461038557600080fd5b80634e65037e116101155780634e65037e14610272578063534cb30d1461027a578063753ef93c146102a557806377267ec3146102b85780637915ce20146102e3578063829a0476146102f657600080fd5b806306a7b3761461015d5780631791dc5e146101855780631de252e4146101a65780631f7cdd5f146101bb5780632e4b20ab1461021d578063338c537114610233575b600080fd5b60005461016c9062ffffff1681565b60405162ffffff90911681526020015b60405180910390f35b6101986101933660046110e9565b61041a565b60405190815260200161017c565b6101b96101b436600461111c565b610585565b005b6101f66101c93660046111ac565b6001602052600090815260409020546001600160c01b03811690600160c01b90046001600160401b031682565b604080516001600160c01b0390931683526001600160401b0390911660208301520161017c565b60005461016c906301000000900462ffffff1681565b61025a7f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a18099481565b6040516001600160a01b03909116815260200161017c565b6101b96106ad565b61028d6102883660046111ce565b610817565b6040516001600160401b03909116815260200161017c565b6101b96102b33660046111e7565b610861565b6102cb6102c63660046111ac565b6108fe565b6040516001600160c01b03909116815260200161017c565b6102cb6102f1366004611228565b61090a565b6101986103043660046112a8565b610a43565b61025a7f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea81565b6102cb610ae7565b61025a7f000000000000000000000000c71104001a3ccda1bef1177d765831bd1bfe8ee681565b6101b961036d3660046111e7565b610af7565b6102cb6103803660046112e5565b610b02565b61028d610b56565b6000546103a590600160301b900464ffffffffff1681565b60405164ffffffffff909116815260200161017c565b6102cb6103c93660046111ac565b610b61565b6101b96103dc366004611301565b610b7c565b6101b96103ef3660046110e9565b610bee565b6101b96104023660046112a8565b610dd3565b6101b9610415366004611301565b610e6d565b60008061042633610e7a565b80549091506001600160c01b0390811690841610610460578054336000908152600160205260408120556001600160c01b031692506104a2565b80548390829060009061047d9084906001600160c01b0316611332565b92506101000a8154816001600160c01b0302191690836001600160c01b031602179055505b60405163a9059cbb60e01b81526001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea169063a9059cbb906104f09087908790600401611351565b6020604051808303816000875af115801561050f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105339190611373565b506040516001600160c01b038416815233907f47cf194f5e559cca0413017d38814a7843cc6f3052bc43c8085938774ae581519060200160405180910390a250506001600160c01b0381165b92915050565b60405163352e3a8360e01b81526001600160a01b037f000000000000000000000000c71104001a3ccda1bef1177d765831bd1bfe8ee6169063352e3a83906105d590339086908690600401611395565b60006040518083038186803b1580156105ed57600080fd5b505afa158015610601573d6000803e3d6000fd5b50506000805465ffffff0000001916630100000062ffffff8816021790555061062f90504262093a806113f1565b600080546affffffffff0000000000001916600160301b64ffffffffff93841681029190911791829055604080513381526301000000840462ffffff16602082015291909204909216908201527e4964f2e48bd8a460fb41883098593956d335f36fdded4ca9cbac9252d72b2f9060600160405180910390a1505050565b60005462ffffff6301000000820481169116036106dd5760405163147fde5f60e31b815260040160405180910390fd5b600054429064ffffffffff600160301b90910481169082161015610714576040516301b3782160e21b815260040160405180910390fd5b60005462ffffff81169061073690600160581b900464ffffffffff1683611404565b6107409190611421565b64ffffffffff16600060108282829054906101000a90046001600160401b031661076a9190611441565b82546101009290920a6001600160401b038181021990931691909216919091021790555060008054630100000064ffffffffff60581b198216600160581b64ffffffffff8616029081179190910462ffffff166fffffffffff0000000000000000ffffff1990921662ffffff19919091161781179091556040519081527fd76dfbd4c35cffe2a846b6488bc677c511aa4337e1551f3a360427ac7a78de7b9060200160405180910390a150565b6000805462ffffff81169061083a90600160581b900464ffffffffff1684611460565b610844919061147f565b60005461057f9190600160801b90046001600160401b0316611441565b6001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a1809941663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b1580156108d957600080fd5b505af11580156108ed573d6000803e3d6000fd5b505050506108fa82610b7c565b5050565b600061057f8242610b02565b600082602001516001600160401b0316826001600160401b031611158061093c575060208301516001600160401b0316155b156109495750600061057f565b60006301e13380620f424085600001516001600160c01b03168660200151866109729190611460565b6001600160401b031661098591906114a1565b61098f91906114b8565b61099991906114b8565b905060007f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea6001600160a01b03166391a0ac6a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1f91906114da565b905080826001600160c01b03161115610a3b57915061057f9050565b50905061057f565b60006001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a1809941663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401600060405180830381600087803b158015610abd57600080fd5b505af1158015610ad1573d6000803e3d6000fd5b50505050610adf848461041a565b949350505050565b6000610af233610b61565b905090565b6108fa338383610dd3565b6001600160a01b03821660009081526001602090815260408083208151808301909252546001600160c01b0381168252600160c01b90046001600160401b031691810191909152610adf816102f185610817565b6000610af242610817565b6000610b6c82610e7a565b546001600160c01b031692915050565b6000610b8733610e7a565b80549091506001600160c01b0380841691161015610bb85780546108fa90610415906001600160c01b031684611332565b80546001600160c01b03808416911611156108fa578054610be99033906101939085906001600160c01b0316611332565b505050565b6000805462ffffff169003610c1657604051630dbfe5fd60e31b815260040160405180910390fd5b6000546301000000900462ffffff16158015610c43575060005442600160301b90910464ffffffffff1611155b15610c6157604051630dbfe5fd60e31b815260040160405180910390fd5b6000610c6c83610e7a565b6040516323b872dd60e01b81523360048201523060248201526001600160c01b03841660448201529091507f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea6001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0e9190611373565b50610d17610b56565b81546001600160401b03918216600160c01b9091049091161015610d3d57610d3d6114f3565b805482908290600090610d5a9084906001600160c01b0316611509565b92506101000a8154816001600160c01b0302191690836001600160c01b03160217905550826001600160a01b03167ff195ce54b48d5147da31c1fc525c8828b8836088b505a329e5de2b35da6731e283604051610dc691906001600160c01b0391909116815260200190565b60405180910390a2505050565b6001600160a01b037f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a1809941663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015610e4b57600080fd5b505af1158015610e5f573d6000803e3d6000fd5b50505050610be98383610bee565b610e773382610bee565b50565b6001600160a01b038116600090815260016020526040812081610e9b610b56565b82549091506001600160401b03600160c01b909104811690821611156110af576040805180820190915282546001600160c01b0381168252600160c01b90046001600160401b03166020820152600090610ef5908361090a565b90506001600160c01b0381161561108f576040516308b8bb4b60e01b81526001600160a01b037f000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea16906308b8bb4b90610f549030908590600401611351565b600060405180830381600087803b158015610f6e57600080fd5b505af1158015610f82573d6000803e3d6000fd5b50508454839250859150600090610fa39084906001600160c01b0316611509565b92506101000a8154816001600160c01b0302191690836001600160c01b031602179055507f0000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a1809946001600160a01b03166331266ff586836040518363ffffffff1660e01b8152600401611015929190611351565b600060405180830381600087803b15801561102f57600080fd5b505af1158015611043573d6000803e3d6000fd5b50506040516001600160c01b03841681526001600160a01b03881692507fed3bc1b58411ea8e764b3ef8fa6b654877bc1e796a5a1a2373dfc8f1c0e0ea48915060200160405180910390a25b5081546001600160c01b0316600160c01b6001600160401b038316021782555b5092915050565b80356001600160a01b03811681146110cd57600080fd5b919050565b80356001600160c01b03811681146110cd57600080fd5b600080604083850312156110fc57600080fd5b611105836110b6565b9150611113602084016110d2565b90509250929050565b60008060006040848603121561113157600080fd5b833562ffffff8116811461114457600080fd5b925060208401356001600160401b0381111561115f57600080fd5b8401601f8101861361117057600080fd5b80356001600160401b0381111561118657600080fd5b8660208260051b840101111561119b57600080fd5b939660209190910195509293505050565b6000602082840312156111be57600080fd5b6111c7826110b6565b9392505050565b6000602082840312156111e057600080fd5b5035919050565b600080604083850312156111fa57600080fd5b611203836110d2565b946020939093013593505050565b80356001600160401b03811681146110cd57600080fd5b600080828403606081121561123c57600080fd5b604081121561124a57600080fd5b50604051604081018181106001600160401b038211171561127b57634e487b7160e01b600052604160045260246000fd5b604052611287846110d2565b815261129560208501611211565b6020820152915061111360408401611211565b6000806000606084860312156112bd57600080fd5b6112c6846110b6565b92506112d4602085016110d2565b929592945050506040919091013590565b600080604083850312156112f857600080fd5b611203836110b6565b60006020828403121561131357600080fd5b6111c7826110d2565b634e487b7160e01b600052601160045260246000fd5b6001600160c01b03828116828216039081111561057f5761057f61131c565b6001600160a01b039290921682526001600160c01b0316602082015260400190565b60006020828403121561138557600080fd5b815180151581146111c757600080fd5b6001600160a01b0384168152604060208201819052810182905260008360608301825b858110156113e6576001600160a01b036113d1846110b6565b168252602092830192909101906001016113b8565b509695505050505050565b8082018082111561057f5761057f61131c565b64ffffffffff828116828216039081111561057f5761057f61131c565b64ffffffffff81811683821602908116908181146110af576110af61131c565b6001600160401b03818116838216019081111561057f5761057f61131c565b6001600160401b03828116828216039081111561057f5761057f61131c565b6001600160401b0381811683821602908116908181146110af576110af61131c565b808202811582820484141761057f5761057f61131c565b6000826114d557634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156114ec57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b6001600160c01b03818116838216019081111561057f5761057f61131c56fea26469706673582212200f0e1de6e63adb4e43523449d0d32fe01bc7a7e35f2273e1f5b48dc9767c034864736f6c634300081a0033","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/0x073493d73258C4BEb6542e8dd3e1b2891C972303/","decoded_constructor_args":[["0xbA3f535bbCcCcA2A154b573Ca6c5A49BAAE0a3ea",{"internalType":"contract IDecentralizedEURO","name":"deuro_","type":"address"}],["100000",{"internalType":"uint24","name":"initialRatePPM","type":"uint24"}],["0x5c49C00f897bD970d964BFB8c3065ae65a180994",{"internalType":"address","name":"gateway_","type":"address"}]],"compiler_version":"0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":false,"verified_at":"2025-04-29T16:01:01.659754Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60e060405234801561001057600080fd5b506040516117d03803806117d083398101604081905261002f9161018b565b8282816001600160a01b031663cd3293de6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561006f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061009391906101e0565b6001600160a01b03811660805260008054600160801b600160c01b03196b010000000000000000000000660100000000000064ffffffffff42811682026affffffffff000000ffffff1962ffffff8a1663010000008102919091166001600160581b031990971696909617861717918204169190910291909116600160581b600160c01b0319919091161790915560405190815282907fd76dfbd4c35cffe2a846b6488bc677c511aa4337e1551f3a360427ac7a78de7b9060200160405180910390a15050506001600160a01b0390811660a0521660c052506102049050565b6001600160a01b038116811461018857600080fd5b50565b6000806000606084860312156101a057600080fd5b83516101ab81610173565b602085015190935062ffffff811681146101c457600080fd5b60408501519092506101d581610173565b809150509250925092565b6000602082840312156101f257600080fd5b81516101fd81610173565b9392505050565b60805160a05160c05161155e610272600039600081816102380152818161086b01528181610a4f01528181610ddd0152610fc901526000818161030e015281816104b90152818161099f01528181610c990152610f1d01526000818161033d015261059c015261155e6000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806382b8eaf5116100c3578063b6f83c171161007c578063b6f83c171461038d578063b77cd1c7146103bb578063bdc65152146103ce578063c1983610146103e1578063cbcf9676146103f4578063fd449c141461040757600080fd5b806382b8eaf51461030957806385bd12d11461033057806391a0ac6a146103385780639e2363dc1461035f578063a696399d14610372578063b079f1631461038557600080fd5b80634e65037e116101155780634e65037e14610272578063534cb30d1461027a578063753ef93c146102a557806377267ec3146102b85780637915ce20146102e3578063829a0476146102f657600080fd5b806306a7b3761461015d5780631791dc5e146101855780631de252e4146101a65780631f7cdd5f146101bb5780632e4b20ab1461021d578063338c537114610233575b600080fd5b60005461016c9062ffffff1681565b60405162ffffff90911681526020015b60405180910390f35b6101986101933660046110e9565b61041a565b60405190815260200161017c565b6101b96101b436600461111c565b610585565b005b6101f66101c93660046111ac565b6001602052600090815260409020546001600160c01b03811690600160c01b90046001600160401b031682565b604080516001600160c01b0390931683526001600160401b0390911660208301520161017c565b60005461016c906301000000900462ffffff1681565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161017c565b6101b96106ad565b61028d6102883660046111ce565b610817565b6040516001600160401b03909116815260200161017c565b6101b96102b33660046111e7565b610861565b6102cb6102c63660046111ac565b6108fe565b6040516001600160c01b03909116815260200161017c565b6102cb6102f1366004611228565b61090a565b6101986103043660046112a8565b610a43565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b6102cb610ae7565b61025a7f000000000000000000000000000000000000000000000000000000000000000081565b6101b961036d3660046111e7565b610af7565b6102cb6103803660046112e5565b610b02565b61028d610b56565b6000546103a590600160301b900464ffffffffff1681565b60405164ffffffffff909116815260200161017c565b6102cb6103c93660046111ac565b610b61565b6101b96103dc366004611301565b610b7c565b6101b96103ef3660046110e9565b610bee565b6101b96104023660046112a8565b610dd3565b6101b9610415366004611301565b610e6d565b60008061042633610e7a565b80549091506001600160c01b0390811690841610610460578054336000908152600160205260408120556001600160c01b031692506104a2565b80548390829060009061047d9084906001600160c01b0316611332565b92506101000a8154816001600160c01b0302191690836001600160c01b031602179055505b60405163a9059cbb60e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906104f09087908790600401611351565b6020604051808303816000875af115801561050f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105339190611373565b506040516001600160c01b038416815233907f47cf194f5e559cca0413017d38814a7843cc6f3052bc43c8085938774ae581519060200160405180910390a250506001600160c01b0381165b92915050565b60405163352e3a8360e01b81526001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000169063352e3a83906105d590339086908690600401611395565b60006040518083038186803b1580156105ed57600080fd5b505afa158015610601573d6000803e3d6000fd5b50506000805465ffffff0000001916630100000062ffffff8816021790555061062f90504262093a806113f1565b600080546affffffffff0000000000001916600160301b64ffffffffff93841681029190911791829055604080513381526301000000840462ffffff16602082015291909204909216908201527e4964f2e48bd8a460fb41883098593956d335f36fdded4ca9cbac9252d72b2f9060600160405180910390a1505050565b60005462ffffff6301000000820481169116036106dd5760405163147fde5f60e31b815260040160405180910390fd5b600054429064ffffffffff600160301b90910481169082161015610714576040516301b3782160e21b815260040160405180910390fd5b60005462ffffff81169061073690600160581b900464ffffffffff1683611404565b6107409190611421565b64ffffffffff16600060108282829054906101000a90046001600160401b031661076a9190611441565b82546101009290920a6001600160401b038181021990931691909216919091021790555060008054630100000064ffffffffff60581b198216600160581b64ffffffffff8616029081179190910462ffffff166fffffffffff0000000000000000ffffff1990921662ffffff19919091161781179091556040519081527fd76dfbd4c35cffe2a846b6488bc677c511aa4337e1551f3a360427ac7a78de7b9060200160405180910390a150565b6000805462ffffff81169061083a90600160581b900464ffffffffff1684611460565b610844919061147f565b60005461057f9190600160801b90046001600160401b0316611441565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b1580156108d957600080fd5b505af11580156108ed573d6000803e3d6000fd5b505050506108fa82610b7c565b5050565b600061057f8242610b02565b600082602001516001600160401b0316826001600160401b031611158061093c575060208301516001600160401b0316155b156109495750600061057f565b60006301e13380620f424085600001516001600160c01b03168660200151866109729190611460565b6001600160401b031661098591906114a1565b61098f91906114b8565b61099991906114b8565b905060007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166391a0ac6a6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109fb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a1f91906114da565b905080826001600160c01b03161115610a3b57915061057f9050565b50905061057f565b60006001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101859052604401600060405180830381600087803b158015610abd57600080fd5b505af1158015610ad1573d6000803e3d6000fd5b50505050610adf848461041a565b949350505050565b6000610af233610b61565b905090565b6108fa338383610dd3565b6001600160a01b03821660009081526001602090815260408083208151808301909252546001600160c01b0381168252600160c01b90046001600160401b031691810191909152610adf816102f185610817565b6000610af242610817565b6000610b6c82610e7a565b546001600160c01b031692915050565b6000610b8733610e7a565b80549091506001600160c01b0380841691161015610bb85780546108fa90610415906001600160c01b031684611332565b80546001600160c01b03808416911611156108fa578054610be99033906101939085906001600160c01b0316611332565b505050565b6000805462ffffff169003610c1657604051630dbfe5fd60e31b815260040160405180910390fd5b6000546301000000900462ffffff16158015610c43575060005442600160301b90910464ffffffffff1611155b15610c6157604051630dbfe5fd60e31b815260040160405180910390fd5b6000610c6c83610e7a565b6040516323b872dd60e01b81523360048201523060248201526001600160c01b03841660448201529091507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af1158015610cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0e9190611373565b50610d17610b56565b81546001600160401b03918216600160c01b9091049091161015610d3d57610d3d6114f3565b805482908290600090610d5a9084906001600160c01b0316611509565b92506101000a8154816001600160c01b0302191690836001600160c01b03160217905550826001600160a01b03167ff195ce54b48d5147da31c1fc525c8828b8836088b505a329e5de2b35da6731e283604051610dc691906001600160c01b0391909116815260200190565b60405180910390a2505050565b6001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001663423bf674336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015260248101849052604401600060405180830381600087803b158015610e4b57600080fd5b505af1158015610e5f573d6000803e3d6000fd5b50505050610be98383610bee565b610e773382610bee565b50565b6001600160a01b038116600090815260016020526040812081610e9b610b56565b82549091506001600160401b03600160c01b909104811690821611156110af576040805180820190915282546001600160c01b0381168252600160c01b90046001600160401b03166020820152600090610ef5908361090a565b90506001600160c01b0381161561108f576040516308b8bb4b60e01b81526001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016906308b8bb4b90610f549030908590600401611351565b600060405180830381600087803b158015610f6e57600080fd5b505af1158015610f82573d6000803e3d6000fd5b50508454839250859150600090610fa39084906001600160c01b0316611509565b92506101000a8154816001600160c01b0302191690836001600160c01b031602179055507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166331266ff586836040518363ffffffff1660e01b8152600401611015929190611351565b600060405180830381600087803b15801561102f57600080fd5b505af1158015611043573d6000803e3d6000fd5b50506040516001600160c01b03841681526001600160a01b03881692507fed3bc1b58411ea8e764b3ef8fa6b654877bc1e796a5a1a2373dfc8f1c0e0ea48915060200160405180910390a25b5081546001600160c01b0316600160c01b6001600160401b038316021782555b5092915050565b80356001600160a01b03811681146110cd57600080fd5b919050565b80356001600160c01b03811681146110cd57600080fd5b600080604083850312156110fc57600080fd5b611105836110b6565b9150611113602084016110d2565b90509250929050565b60008060006040848603121561113157600080fd5b833562ffffff8116811461114457600080fd5b925060208401356001600160401b0381111561115f57600080fd5b8401601f8101861361117057600080fd5b80356001600160401b0381111561118657600080fd5b8660208260051b840101111561119b57600080fd5b939660209190910195509293505050565b6000602082840312156111be57600080fd5b6111c7826110b6565b9392505050565b6000602082840312156111e057600080fd5b5035919050565b600080604083850312156111fa57600080fd5b611203836110d2565b946020939093013593505050565b80356001600160401b03811681146110cd57600080fd5b600080828403606081121561123c57600080fd5b604081121561124a57600080fd5b50604051604081018181106001600160401b038211171561127b57634e487b7160e01b600052604160045260246000fd5b604052611287846110d2565b815261129560208501611211565b6020820152915061111360408401611211565b6000806000606084860312156112bd57600080fd5b6112c6846110b6565b92506112d4602085016110d2565b929592945050506040919091013590565b600080604083850312156112f857600080fd5b611203836110b6565b60006020828403121561131357600080fd5b6111c7826110d2565b634e487b7160e01b600052601160045260246000fd5b6001600160c01b03828116828216039081111561057f5761057f61131c565b6001600160a01b039290921682526001600160c01b0316602082015260400190565b60006020828403121561138557600080fd5b815180151581146111c757600080fd5b6001600160a01b0384168152604060208201819052810182905260008360608301825b858110156113e6576001600160a01b036113d1846110b6565b168252602092830192909101906001016113b8565b509695505050505050565b8082018082111561057f5761057f61131c565b64ffffffffff828116828216039081111561057f5761057f61131c565b64ffffffffff81811683821602908116908181146110af576110af61131c565b6001600160401b03818116838216019081111561057f5761057f61131c565b6001600160401b03828116828216039081111561057f5761057f61131c565b6001600160401b0381811683821602908116908181146110af576110af61131c565b808202811582820484141761057f5761057f61131c565b6000826114d557634e487b7160e01b600052601260045260246000fd5b500490565b6000602082840312156114ec57600080fd5b5051919050565b634e487b7160e01b600052600160045260246000fd5b6001600160c01b03818116838216019081111561057f5761057f61131c56fea26469706673582212200f0e1de6e63adb4e43523449d0d32fe01bc7a7e35f2273e1f5b48dc9767c034864736f6c634300081a0033000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea00000000000000000000000000000000000000000000000000000000000186a00000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994","name":"SavingsGateway","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/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/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":"contracts/Leadrate.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IReserve} from \"./interface/IReserve.sol\";\n\n/**\n * @title Leadrate (attempt at translating the concise German term 'Leitzins')\n *\n * A module that can provide other modules with the leading interest rate for the system.\n *\n **/\ncontract Leadrate {\n    IReserve public immutable equity;\n\n    // The following five variables are less than 256 bits, so they should be stored\n    // in the same slot, making them cheaper to access together, right?\n\n    uint24 public currentRatePPM; // 24 bits allows rates of up to ~1670% per year\n    uint24 public nextRatePPM;\n    uint40 public nextChange;\n\n    uint40 private anchorTime; // 40 bits for time in seconds spans up to 1000 human generations\n    uint64 private ticksAnchor; // in bips * seconds\n\n    event RateProposed(address who, uint24 nextRate, uint40 nextChange);\n    event RateChanged(uint24 newRate);\n\n    error NoPendingChange();\n    error ChangeNotReady();\n\n    constructor(IReserve equity_, uint24 initialRatePPM) {\n        equity = equity_;\n        nextRatePPM = initialRatePPM;\n        currentRatePPM = initialRatePPM;\n        nextChange = uint40(block.timestamp);\n        anchorTime = nextChange;\n        ticksAnchor = 0;\n        emit RateChanged(initialRatePPM); // emit for initialization indexing, if desired\n    }\n\n    /**\n     * Proposes a new interest rate that will automatically be applied after seven days.\n     * To cancel a proposal, just overwrite it with a new one proposing the current rate.\n     */\n    function proposeChange(uint24 newRatePPM_, address[] calldata helpers) external {\n        equity.checkQualified(msg.sender, helpers);\n        nextRatePPM = newRatePPM_;\n        nextChange = uint40(block.timestamp + 7 days);\n        emit RateProposed(msg.sender, nextRatePPM, nextChange);\n    }\n\n    /**\n     * Setting a previously proposed interest rate change into force.\n     */\n    function applyChange() external {\n        if (currentRatePPM == nextRatePPM) revert NoPendingChange();\n        uint40 timeNow = uint40(block.timestamp);\n        if (timeNow < nextChange) revert ChangeNotReady();\n        ticksAnchor += (timeNow - anchorTime) * currentRatePPM;\n        anchorTime = timeNow;\n        currentRatePPM = nextRatePPM;\n        emit RateChanged(currentRatePPM);\n    }\n\n    /**\n     * Total accumulated 'interest ticks' since this contract was deployed.\n     * One 'tick' is a ppm-second, so one month of 12% annual interest is\n     *   120000*30*24*3600 = 311040000000 ticks.\n     * Two months of 6% annual interest would result in the same number of\n     * ticks. For simplicity, this is linear, so there is no \"interest on interest\".\n     */\n    function currentTicks() public view returns (uint64) {\n        return ticks(block.timestamp);\n    }\n\n    function ticks(uint256 timestamp) public view returns (uint64) {\n        return ticksAnchor + (uint64(timestamp) - anchorTime) * currentRatePPM;\n    }\n}\n"},{"file_path":"contracts/Savings.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IDecentralizedEURO} from \"./interface/IDecentralizedEURO.sol\";\nimport {IReserve} from \"./interface/IReserve.sol\";\nimport {Leadrate} from \"./Leadrate.sol\";\n\n/**\n * @title Savings\n *\n * Module to enable savings based on a Leadrate (\"Leitzins\") module.\n *\n * As the interest rate changes, the speed at which 'ticks' are accumulated is\n * adjusted. The ticks counter serves as the basis for calculating the interest\n * due for the individual accounts.\n */\ncontract Savings is Leadrate {\n    IERC20 public immutable deuro;\n\n    mapping(address => Account) public savings;\n\n    struct Account {\n        uint192 saved;\n        uint64 ticks;\n    }\n\n    event Saved(address indexed account, uint192 amount);\n    event InterestCollected(address indexed account, uint256 interest);\n    event Withdrawn(address indexed account, uint192 amount);\n\n    // The module is considered disabled if the interest is zero or about to become zero within three days.\n    error ModuleDisabled();\n\n    constructor(IDecentralizedEURO deuro_, uint24 initialRatePPM) Leadrate(IReserve(deuro_.reserve()), initialRatePPM) {\n        deuro = IERC20(deuro_);\n    }\n\n    /**\n     * Shortcut for refreshBalance(msg.sender)\n     */\n    function refreshMyBalance() public returns (uint192) {\n        return refreshBalance(msg.sender);\n    }\n\n    /**\n     * Collects the accrued interest and adds it to the account.\n     *\n     * It can be beneficial to do so every now and then in order to start collecting\n     * interest on the accrued interest.\n     */\n    function refreshBalance(address owner) public returns (uint192) {\n        return refresh(owner).saved;\n    }\n\n    function refresh(address accountOwner) virtual internal returns (Account storage) {\n        Account storage account = savings[accountOwner];\n        uint64 ticks = currentTicks();\n        if (ticks > account.ticks) {\n            uint192 earnedInterest = calculateInterest(account, ticks);\n            if (earnedInterest > 0) {\n                // collect interest as you go and trigger accounting event\n                (IDecentralizedEURO(address(deuro))).distributeProfits(address(this), earnedInterest);\n                account.saved += earnedInterest;\n                emit InterestCollected(accountOwner, earnedInterest);\n            }\n            account.ticks = ticks;\n        }\n        return account;\n    }\n\n    function accruedInterest(address accountOwner) public view returns (uint192) {\n        return accruedInterest(accountOwner, block.timestamp);\n    }\n\n    function accruedInterest(address accountOwner, uint256 timestamp) public view returns (uint192) {\n        Account memory account = savings[accountOwner];\n        return calculateInterest(account, ticks(timestamp));\n    }\n\n    function calculateInterest(Account memory account, uint64 ticks) public view returns (uint192) {\n        if (ticks <= account.ticks || account.ticks == 0) {\n            return 0;\n        } else {\n            uint192 earnedInterest = uint192((uint256(ticks - account.ticks) * account.saved) / 1_000_000 / 365 days);\n            uint256 equity = IDecentralizedEURO(address(deuro)).equity();\n            if (earnedInterest > equity) {\n                return uint192(equity); // safe conversion as equity is smaller than uint192 earnedInterest\n            } else {\n                return earnedInterest;\n            }\n        }\n    }\n\n    /**\n     * Save 'amount'.\n     */\n    function save(uint192 amount) public {\n        save(msg.sender, amount);\n    }\n\n    function adjust(uint192 targetAmount) public {\n        Account storage balance = refresh(msg.sender);\n        if (balance.saved < targetAmount) {\n            save(targetAmount - balance.saved);\n        } else if (balance.saved > targetAmount) {\n            withdraw(msg.sender, balance.saved - targetAmount);\n        }\n    }\n\n    /**\n     * Send 'amount' to the account of the provided owner.\n     */\n    function save(address owner, uint192 amount) public {\n        if (currentRatePPM == 0) revert ModuleDisabled();\n        if (nextRatePPM == 0 && (nextChange <= block.timestamp)) revert ModuleDisabled();\n        Account storage balance = refresh(owner);\n        deuro.transferFrom(msg.sender, address(this), amount);\n        assert(balance.ticks >= currentTicks()); // @dev: should not differ, since there is no shift of interests\n        balance.saved += amount;\n        emit Saved(owner, amount);\n    }\n\n    /**\n     * Withdraw up to 'amount' to the target address.\n     * When trying to withdraw more than available, all that is available is withdrawn.\n     * Returns the actually transferred amount.\n     */\n    function withdraw(address target, uint192 amount) public returns (uint256) {\n        Account storage account = refresh(msg.sender);\n        if (amount >= account.saved) {\n            amount = account.saved;\n            delete savings[msg.sender];\n        } else {\n            account.saved -= amount;\n        }\n        deuro.transfer(target, amount);\n        emit Withdrawn(msg.sender, amount);\n        return amount;\n    }\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/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/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":"contract IDecentralizedEURO","name":"deuro_","type":"address"},{"internalType":"uint24","name":"initialRatePPM","type":"uint24"},{"internalType":"address","name":"gateway_","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ChangeNotReady","type":"error"},{"inputs":[],"name":"ModuleDisabled","type":"error"},{"inputs":[],"name":"NoPendingChange","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"interest","type":"uint256"}],"name":"InterestCollected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint24","name":"newRate","type":"uint24"}],"name":"RateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"who","type":"address"},{"indexed":false,"internalType":"uint24","name":"nextRate","type":"uint24"},{"indexed":false,"internalType":"uint40","name":"nextChange","type":"uint40"}],"name":"RateProposed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint192","name":"amount","type":"uint192"}],"name":"Saved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint192","name":"amount","type":"uint192"}],"name":"Withdrawn","type":"event"},{"inputs":[],"name":"GATEWAY","outputs":[{"internalType":"contract IFrontendGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountOwner","type":"address"}],"name":"accruedInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"accountOwner","type":"address"},{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"accruedInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint192","name":"targetAmount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"adjust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"targetAmount","type":"uint192"}],"name":"adjust","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"applyChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint192","name":"saved","type":"uint192"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"internalType":"struct Savings.Account","name":"account","type":"tuple"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"name":"calculateInterest","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRatePPM","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentTicks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"deuro","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"equity","outputs":[{"internalType":"contract IReserve","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextChange","outputs":[{"internalType":"uint40","name":"","type":"uint40"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextRatePPM","outputs":[{"internalType":"uint24","name":"","type":"uint24"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint24","name":"newRatePPM_","type":"uint24"},{"internalType":"address[]","name":"helpers","type":"address[]"}],"name":"proposeChange","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"refreshBalance","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"refreshMyBalance","outputs":[{"internalType":"uint192","name":"","type":"uint192"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"save","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"savings","outputs":[{"internalType":"uint192","name":"saved","type":"uint192"},{"internalType":"uint64","name":"ticks","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"ticks","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint192","name":"amount","type":"uint192"},{"internalType":"bytes32","name":"frontendCode","type":"bytes32"}],"name":"withdraw","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000ba3f535bbcccca2a154b573ca6c5a49baae0a3ea00000000000000000000000000000000000000000000000000000000000186a00000000000000000000000005c49c00f897bd970d964bfb8c3065ae65a180994"}