Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x48e5449d867868a9867B09dd615BF93694e2508a
Balance 0 ETH
Nonce 1
Code Size 18711 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

18711 bytes
0x608060408181526004908136101561001657600080fd5b600092833560e01c90816301ffc9a71461359157508063068cc514146134eb578063078fa9bc146134b0578063093cf18f146134145780630bd075a11461335b5780630d6680871461333d5780630e2be506146132e95780630e5c011e146132975780630e9ae42014613043578381630f4c3c4f14612fab575080631959a00214612f455780631f3a0e4114612f1e578063248a9ca314612ee65780632f2ff15d14612e5657806331d7a26214612c9557806336568abe14612c4e5780633a98ef3914612c2f5780634219816014612c06578063485cc9551461294a5780635a2f3d09146129175780635c975abb146128e65780635d90bad91461285d57806367755415146127d95780636abfd183146127ba5780636edd75901461279a578063736ec05c1461273057806375b238fc146127075780637a39b8d81461267a5780637da2a4a7146126465780638395206c1461230257806389919b71146122df5780638fd3ab80146120f257806391d148541461209f5780639336f40614611f7157806393b6b86c14611e5a57806398c6e76014611e32578063a217fddf14611e17578063a3bdd63214611d8a578063aa09d5b714611cf4578063aceda7f914611ccd578063ae04d45d14611c08578063af16d6e014611a43578063b150377414611a08578063ba61945714611954578063c2eb8eb9146118b3578063c321db571461188d578063c3dcfcf11461161d578063c4d87fe21461150d578063c4e5dacf146114e4578063d3e894831461149a578063d547741f1461144f578063db2e21bc14611257578063dcc3e06e1461122e578063de69b3aa146111f6578063dff8720314611119578063e08c5de114610fa4578063e0c8d9a514610f6357838163e19e716814610e2757508063e3161ddd14610e08578063e3824a3814610bd3578063f1daf24c14610953578063fd91db96146104cd5763fe30e7e6146102dd57600080fd5b346104c95760603660031901126104c9578135906102f96135fb565b60443593610305613c95565b61031760ff60015460a01c1615613708565b7f3b745c09aefb8f732a168ec71c3c87b50c0a4cfd1d104649ae3c04a4623b26bf918260005260209260008051602061486283398151915284528460002033600052845260ff856000205416156104ab5787526006835283872033600052835261038784600020544210156136bd565b600354845163172500a160e11b81526001600160a01b03838116858301908152602081018a905290948a9390918791849182900360400190829087908a165af19182156104a157839261046a575b50846001541691823b156104665760648492838a51958694859363fb6cb84760e01b85528401528c6024840152600160448401525af1801561045c57610444575b50507fa57c8f00bb515630e1e4af145f087299b8d5ac5d871605bb0a9c0479b7b2d65b93519586521693a380f35b61044d90613655565b610458578638610416565b8680fd5b86513d84823e3d90fd5b8380fd5b925090508482813d811161049a575b610483818361369b565b810103126104955788915190386103d5565b600080fd5b503d610479565b87513d85823e3d90fd5b845163e2517d3f60e01b815233818501526024810191909152604490fd5b8280fd5b5091903461094f57602092836003193601126104c95781359367ffffffffffffffff80861161094b573660238701121561094b57858401356024918111610939578060051b96845191610522858a018461369b565b825283820183819983010191368311610935578401905b8282106109165750505061055160055442101561374c565b610559613c95565b60ff9160019061057160ff60015460a01c1615613708565b7f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8060005260008051602061486283398151915286528660002033600052865260ff876000205416156108fc57506105c7613cc0565b60038054875163e5a6b10f60e01b8082526001600160a01b039a93949289908390869082908f165afa9182156108d3578c926108dd575b50888b6002541691858c518094819382525afa9081156108d3578b9182918e916108a6575b5016911603610864579086918a968a9461063b613a9d565b868b8a809881935b610786575b9450505050508792915060025416908115158061077d575b80610774575b6106e9575b505050505094806003541695855180935190999289905b8282106106d2575050505050807f2b1ab5aad08854cca1e3b3cd94bbb4acc5cf06bd794383289c30ae264d03121d949596970390209351908152a360016000805160206148a28339815191525580f35b845181168c529a87019a9387019390830190610682565b8b8b60035416916107268c5197889687958694631963b13960e21b86528501604091949392606082019560018060a01b0316825260208201520152565b03925af1801561076a57908591610741575b8481839261066b565b813d8311610763575b610754818361369b565b81010312610495578338610738565b503d61074a565b86513d8a823e3d90fd5b50841515610666565b50821515610660565b8b9c9496989192939597999c518610156108555791600888949288946107ad8f8a90613bd0565b511683525220015416610813579186828d979694886107ce8498968d613bd0565b51166107d99061452d565b509c9091826107e791613809565b9c6107f191613809565b986107fc838d613bd0565b511661080791613ff1565b018b8e8e8d9897610643565b8a5162461bcd60e51b81528087018b9052601a818701527f556e6f52653a20726f6c6c6f766572206973206e6f74207365740000000000006044820152606490fd5b8392919850849c999750610648565b875162461bcd60e51b8152918201879052601b908201527f556e6f52653a2063757272656e6379206e6f74206d61746368656400000000006044820152606490fd5b6108c691508b3d8d116108cc575b6108be818361369b565b810190613816565b38610623565b503d6108b4565b8a513d8e823e3d90fd5b6108f5919250893d8b116108cc576108be818361369b565b90386105fe565b865163e2517d3f60e01b815233818a015291820152604490fd5b81356001600160a01b0381168103610495578152908501908501610539565b8880fd5b50634e487b7160e01b85526041845284fd5b8480fd5b5080fd5b5090346104c957602091826003193601126104665781359161097960055442101561374c565b610981613c95565b610989613cc0565b8215610b7e57338552600884526109a382862054426137b3565b815411610b4857908492916109b733613cf0565b3380855260088652828520600201546003548451636ce40c7960e01b81528481019384526020840196909652949590946001600160a01b039285918891829003604001908290859087165af1928315610b3c5781968294610b07575b50826001541690813b156104c95784602484928389519586948593632da26abb60e11b85528401525af18015610afd5790879291610ae6575b5050610ab3907fced2424eb51507abd1611ac0d9893e5bc6b6d0a0596b53f86d24d31fc75a5d6095610aa0600b54670de0b6b3a7640000610a9981610a9184876137d6565b0492866137d6565b04906137b3565b338b5260088a526001878c2001556137b3565b3388526008875260028489200155600354169482519485528401523392a360016000805160206148a28339815191525580f35b610af1919250613655565b61045857848738610a4c565b85513d84823e3d90fd5b909350610b2b919650843d8611610b35575b610b23818361369b565b810190613a87565b9590959238610a13565b503d610b19565b508351903d90823e3d90fd5b83606492519162461bcd60e51b83528201526012602482015271556e6f52653a204c6f636b65642074696d6560701b6044820152fd5b83608492519162461bcd60e51b8352820152602b60248201527f576974686472617720616d6f756e742073686f756c642062652067726561746f60448201526a72207468616e207a65726f60a81b6064820152fd5b509060208060031936011261046657813592610bed613c95565b610bff60ff60015460a01c1615613708565b610c0d60055442101561374c565b610c15613cc0565b600354815163e5a6b10f60e01b81526001600160a01b039091169083818681855afa908115610dfe578791610de1575b508515610d9e5782516323b872dd60e01b8582019081523360248301526001600160a01b0393909316604482015260648082018890528152601f1992889283929091908390610c9560848261369b565b51925af1903d15610d96573d67ffffffffffffffff8111610d8357610cc385855193601f840116018361369b565b81523d878583013e5b81610d53575b5015610cf85784610ce33386613ff1565b60016000805160206148a28339815191525580f35b5162461bcd60e51b815291820152603160248201527f5472616e7366657248656c7065723a3a7472616e7366657246726f6d3a207472604482015270185b9cd9995c919c9bdb4819985a5b1959607a1b606482015260849150fd5b80518015925084908315610d6b575b50505038610cd2565b610d7b9350820181019101613966565b388381610d62565b634e487b7160e01b885260418652602488fd5b506060610ccc565b50505162461bcd60e51b815291820152601a60248201527f556e6f52653a207a65726f206465706f73697420616d6f756e74000000000000604482015260649150fd5b610df89150843d86116108cc576108be818361369b565b38610c45565b83513d89823e3d90fd5b8334610e245780600319360112610e2457610e21613a9d565b80f35b80fd5b80848434610f5f5782600319360112610f5f57610e42613cc0565b610e4a613c95565b610e5c60ff60015460a01c1615613708565b8260018060a01b03928284600354166024825180988193635d2cd2a760e01b835233878401525af1938415610f305782958395610f3a575b506001541690813b156104c957829160648392865194859384926305b71d5360e01b845230908401528a60248401528160448401525af18015610f3057610f1c575b50507f09c6481cb228ea7f61ceb67c8e708038eb74bbb68cfcc54a9cfca199087ecfb791815193845260208401523392a260016000805160206148a28339815191525580f35b610f2590613655565b610466578385610ed6565b83513d84823e3d90fd5b909450610f55919550833d8511610b3557610b23818361369b565b9490949387610e94565b5050fd5b5090346104c957816003193601126104c95781602093610f816135fb565b9235815260068552209060018060a01b0316600052825280600020549051908152f35b508234610e24576020928360031936011261094f57610fc16135e5565b60035484516318160ddd60e01b81526001600160a01b039291879082908690829087165afa90811561110f57908693929186916110de575b50600b5494600a54804311806110d5575b611054575b50505093670de0b6b3a764000061103c6001949361104d97169586845260088a52600285852001546137d6565b0493815260088752200154906137b3565b9051908152f35b611072919293979694955061106990436137b3565b600c54906137d6565b90670de0b6b3a7640000918281029281840414901517156110c2575061103c6001946110b789956110b161104d9a9996670de0b6b3a7640000966137e9565b90613809565b96939750939461100f565b634e487b7160e01b865260119052602485fd5b5082151561100a565b809450888092503d8311611108575b6110f7818361369b565b810103126104955785925188610ff9565b503d6110ed565b86513d87823e3d90fd5b50346104c957806003193601126104c9578135906111c86111386135fb565b611140613bfa565b6000805160206148c2833981519152865260066020528286203360005260205261117083600020544210156136bd565b611178613c95565b61118a60ff60015460a01c1615613708565b6001600160a01b038116946111ab906111a4871515613924565b5442613809565b848752600660205283872086600052602052836000205583613f06565b50519081527faa08bed1c8e2500452096c9af125a3944be2a139782a1853abaef7a74bd7dd5160203092a380f35b83823461094f57602036600319011261094f5760209181906001600160a01b0361121e6135e5565b1681526009845220549051908152f35b83823461094f578160031936011261094f5760025490516001600160a01b039091168152602090f35b50346104c957826003193601126104c957611270613cc0565b611278613c95565b60ff60015460a81c16156113fc573383526020906008825280842092815161129f8161367f565b84548152600185015484820152608082600287015496878685015260ff60038201541615156060850152015491015283156113bb573380865260088452828620868155600181018790556002810187905560038082018890559083018790555483516395ccea6760e01b8152928301918252602082018690529194939291839186916001600160a01b03169082908990829060400103925af19384156113b1577f5fafa99d0643513820be26656b45130b01e1c03062e1266bf36f88cbd3bd96959394611384575b50519283523392a260016000805160206148a28339815191525580f35b6113a390833d85116113aa575b61139b818361369b565b810190613966565b5038611367565b503d611391565b81513d87823e3d90fd5b82606492519162461bcd60e51b8352820152601760248201527f556e6f72653a205a65726f207573657220616d6f756e740000000000000000006044820152fd5b906020608492519162461bcd60e51b8352820152602760248201527f556e6f72653a20656d657267656e63795769746864726177206973206e6f7420604482015266185b1b1bddd95960ca1b6064820152fd5b50346104c957806003193601126104c957611496913561149160016114726135fb565b9383875260008051602061486283398151915260205286200154613c62565b613f8d565b5080f35b5090346104c95760203660031901126104c95760609282913581526007602052209060ff60018354930154825193845260018060a01b038116602085015260a01c16151590820152f35b83823461094f578160031936011261094f5760035490516001600160a01b039091168152602090f35b5090346104c95760603660031901126104c9576115286135e5565b918360243592611536613bfa565b6000805160206148c2833981519152825260066020528282203360005260205261156683600020544210156136bd565b60018060a01b039485811695868452600860205284842086600282015560016044359101556003541691823b15610466578451637e348b7d60e01b81526001600160a01b03909216908201908152602081018690529091839183919082908490829060400103925af18015610f3057611609575b5050519081527f465dd1981de2fdd0163048712ba5bbf7ff0ff09e5f6bd26f566a19079909594a60203092a380f35b61161290613655565b6104665783386115da565b5091903461094f576003199060c0368301126104c95767ffffffffffffffff93813585811161094b576116539036908401613627565b956024359081116118895761166b9036908501613627565b91611674613611565b6001600160a01b039660643594919391888616919082870361049557611698613cc0565b6116a0613bfa565b6000805160206148c28339815191528b528960209660068852898d203360005288526116d28a600020544210156136bd565b16938415611846579a89819d9461171e899795849e9f9560809661170f8f519c8d9b8c9a8b99632c10d8af60e01b8b528a01526084890191613a66565b92868403016024870152613a66565b90306044840152606483015203925af191821561183c5790879291879261181f575b5050166bffffffffffffffffffffffff60a01b600354161760035543600a5583600b55608435600c55846001541692833b1561094b578251633f14eb6160e11b8152309181019182526001600160a01b03909216602082015260a43560408201529092849184919082908490829060600103925af19081156118165750611802575b505060035416307f184d7691bf4a73930a21086fa1bdf0ee3075421531a60730288325fd583802178380a360016000805160206148a28339815191525580f35b61180b90613655565b61094f5781386117c2565b513d84823e3d90fd5b6118359250803d106108cc576108be818361369b565b3880611740565b84513d88823e3d90fd5b885162461bcd60e51b8152808b01889052601b60248201527f556e6f52653a207a65726f20666163746f7279206164647265737300000000006044820152606490fd5b8580fd5b83823461094f57602036600319011261094f5760209061104d6118ae6135e5565b61397e565b83823461094f57602036600319011261094f576119066118d16135e5565b916118da613bfa565b6000805160206148c28339815191528452600660205280842033600052602052600020544210156136bd565b6001600160a01b031661191a811515613924565b600180546001600160a01b03191682179055307fdf8e7a62b39a2ec070924d5c5dce9a1957d75476af59af5a7e7ce2ee48bc77748380a380f35b5091903461094f5760209182600319360112610e24576001600160a01b03918261197c6135e5565b1682526008845283600286842001549360035416865192838092627a9fd960e91b82525afa9182156119fd57916119ce575b506119c2670de0b6b3a764000091836137d6565b04918351928352820152f35b90508281813d83116119f6575b6119e5818361369b565b8101031261049557516119c26119ae565b503d6119db565b8551903d90823e3d90fd5b83823461094f578160031936011261094f57602090517f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b8152f35b5090346104c95760603660031901126104c957611a5e6135e5565b611a666135fb565b92611a6f613611565b93611a78613cc0565b611a80613bfa565b6000805160206148c2833981519152865260209360068552828720336000528552611ab183600020544210156136bd565b6001600160a01b03918216938415611bc7578216908115611b84578291606487928a809688519b8c9586946369ee745160e01b865285015216988960248401523060448401525af18015610f30577f6c409a36847a0a3870deae25f656f4300d45957d2643fc27faab145e19cfcf1b9495968391611b67575b50169160025490836bffffffffffffffffffffffff60a01b831617600255519485521617923092a360016000805160206148a28339815191525580f35b611b7e9150873d89116108cc576108be818361369b565b38611b2a565b835162461bcd60e51b8152908101869052601c60248201527f556e6f52653a207a65726f206f70657261746f722061646472657373000000006044820152606490fd5b606482878087519262461bcd60e51b845283015260248201527f556e6f52653a20726577617264657220666163746f7279206e6f2065786973746044820152fd5b50346104c95760203660031901126104c957813591611c25613bfa565b6000805160206148c28339815191528452600660205281842033600052602052611c5582600020544210156136bd565b8215611c8b57829055519081527f2c2c43c64e937ae35257af782c222986dc5adb4f56dc0881594e79bf83658d8c60203092a280f35b6020606492519162461bcd60e51b8352820152601f60248201527f556e6f52653a206e6f7420616c6c6f77207a65726f206c6f636b2074696d65006044820152fd5b83823461094f578160031936011261094f5760209060ff60015460a81c1690519015158152f35b83823461094f578160031936011261094f5760207f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25891611d32613bfa565b6000805160206148c2833981519152845260068252808420336000528252611d6081600020544210156136bd565b611d68613c95565b600080516020614882833981519152805460ff1916600117905551338152a180f35b5082903461094f578160031936011261094f57600354815163e95aa8d360e01b81529360209185919082906001600160a01b03165afa918215611e0c5791611dd7575b6020925051908152f35b90506020823d602011611e04575b81611df26020938361369b565b81010312610495576020915190611dcd565b3d9150611de5565b9051903d90823e3d90fd5b83823461094f578160031936011261094f5751908152602090f35b83823461094f578160031936011261094f57905490516001600160a01b039091168152602090f35b50346104c95760203660031901126104c957813591611e77613bfa565b6000805160206148c28339815191528452600660205281842033600052602052611ea782600020544210156136bd565b8215611f2f5760035484916001600160a01b0390911690813b156104c957846024849283875195869485936324edae1b60e21b85528401525af18015610f3057611f1b575b5050519081527f353ac2778fe09bc60cf3070bb11d548faf4037e4217a06977c16463087474aab60203092a280f35b611f2490613655565b6104c9578238611eec565b6020606492519162461bcd60e51b8352820152601b60248201527f556e6f52653a206e6f7420616c6c6f77207a65726f2076616c756500000000006044820152fd5b509134610e245760208060031936011261094f57611f8d6135e5565b6003548551627a9fd960e91b815295916001600160a01b0391821684888881845afa97881561183c578698612069575b506060929160249185519889948593631665744b60e11b855216908301525afa91821561205f5760809584958594612018575b50612004670de0b6b3a764000091876137d6565b049082519586528501528301526060820152f35b6120049650670de0b6b3a7640000955061204b91945060603d606011612058575b612043818361369b565b810190613798565b9591969095949150611ff0565b503d612039565b81513d85823e3d90fd5b9097508481819493943d8311612098575b612084818361369b565b810103126104955751969091906060611fbd565b503d61207a565b5090346104c957816003193601126104c957816020936120bd6135fb565b923581526000805160206148628339815191528552209060018060a01b0316600052825260ff81600020541690519015158152f35b5090346104c957826003193601126104c95761210c613cc0565b612114613c95565b61212660ff60015460a01c1615613708565b82546001600160a01b039061213e9082161515613924565b61214733613cf0565b3384526020600881528461215e85822054426137b3565b8454109382846003541695606486855416858a51998a948593633613302f60e01b85523389860152602485015260448401525af194851561045c5782956122ac575b508360015416803b156104c957828091606489518094819363fb6cb84760e01b83528b888401528160248401528160448401525af19081156104a1578391612298575b5054841690813b156104c9578291608483928951948593849263ed59344b60e01b845233908401528a6024840152606060448401528160648401525af1801561045c57612284575b50507ff0fee1f70845d356d6a3e0baa0944ce846437b6469ea89416dad2cd7067919a49133865260088252856001868220826002820155015585541693519283523392a360016000805160206148a28339815191525580f35b61228d90613655565b61094b57843861222b565b6122a190613655565b61094f5781386121e3565b83809296508193503d83116122d8575b6122c6818361369b565b810103126104955785905193386121a0565b503d6122bc565b83823461094f578160031936011261094f5760209051670de0b6b3a76400008152f35b5090346104c9576020908160031936011261046657803591612322613c95565b61233060055442101561374c565b612338613cc0565b61234133613cf0565b600154845163c139b04f60e01b815230818501908152602081018690526001600160a01b039492849183918716908290819060400103915afa90811561263c57879161261f575b50156125df5733865260088252848620600201546003548651627a9fd960e91b81529085169184828581865afa9182156125d55789926125a6575b508751631665744b60e11b8152338582015290606082602481875afa90811561259c576123f7928b92612579575b506137b3565b90670de0b6b3a7640000808802908882041488151715612566579061241b916137e9565b1161252457908187923b156104c95786516323de6d9560e11b815233838201908152602081018890529091849183919082908490829060400103925af19081156104a1578391612510575b5050338252600883524286832055836001541690813b156104c957829160648392895194859384926305b71d5360e01b845230908401528a6024840152600160448401525af1801561045c576124fc575b50507f940a14c75c418e7230a2e65567722d2dda5a6713cf71b369bd0fa219fdc1ac5e916003541693519283523392a360016000805160206148a28339815191525580f35b61250590613655565b61094b5784386124b7565b61251990613655565b61094f578138612466565b5060649185519162461bcd60e51b8352820152601f60248201527f556e6f52653a20776974686472617720616d6f756e74206f766572666c6f77006044820152fd5b634e487b7160e01b8a526011855260248afd5b61259391925060603d60601161205857612043818361369b565b505090386123f1565b89513d8c823e3d90fd5b9091508481813d83116125ce575b6125be818361369b565b81010312610495575190386123c3565b503d6125b4565b88513d8b823e3d90fd5b8160649286519262461bcd60e51b845283015260248201527f556e6f52653a206d696e696d756d206361706974616c20756e646572666c6f776044820152fd5b6126369150833d85116113aa5761139b818361369b565b38612388565b86513d89823e3d90fd5b83823461094f578160031936011261094f5733825260086020528120600301805460ff818116151660ff1990911617905580f35b83823461094f578160031936011261094f57612694613bfa565b6000805160206148c283398151915282526006602052808220336000526020526126c481600020544210156136bd565b6001805460ff60a01b1916600160a01b178155905190815233907f7c952f2e528aa25b4eaf8b6c07af29184b27ce591295e543ced0a27b167dc79490602090a280f35b83823461094f578160031936011261094f57602090516000805160206148c28339815191528152f35b83823461094f57602036600319011261094f5761274e6118d16135e5565b6001600160a01b0316612762811515613924565b81546001600160a01b03191681178255307f877238238dbd7134e89b00809ea73fabb50da117ace807a6b31c733bbf55d3698380a380f35b508234610e24576020366003190112610e24575061104d60209235613835565b83823461094f578160031936011261094f576020906005549051908152f35b83823461094f578160031936011261094f576127f3613bfa565b6000805160206148c2833981519152825260066020528082203360005260205261282381600020544210156136bd565b60ff60a01b1960015416600155518181527f77337fcf1b48e6e024b256962b66c49de98c9f606b2cd9937cc0edbc7a0fb70960203392a280f35b5090346104c95760203660031901126104c9576128b49061287c613bfa565b6000805160206148c283398151915284526006602052828420336000526020526128ac83600020544210156136bd565b429035613809565b9081600555519081527fa8aa08cc14eef7b97ab4cd52f37082e23f7526bccc98cf91e6a1d412494b905160203092a280f35b83823461094f578160031936011261094f5760209060ff600080516020614882833981519152541690519015158152f35b508234610e245780600319360112610e245750600a54600b54600c54925191825260208201526040810191909152606090f35b5090346104c957816003193601126104c9576129646135e5565b9061296d6135fb565b917ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a009283549260ff84871c16159267ffffffffffffffff851694851580612bff575b60018097149081612bf5575b159081612bec575b50612bdc5767ffffffffffffffff1981168617875584612bbd575b506001600160a01b039083821615612b6f5785546001600160a01b0319169116178455620d2f009055612a6090612a13614820565b612a1b614820565b836000805160206148a283398151915255612a34614820565b612a3c614820565b600080516020614882833981519152805460ff19169055612a5b614820565b613e56565b506000805160206148c2833981519152806000526000805160206148628339815191526020528285600020018181549155817fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff918183600080a4817f3b745c09aefb8f732a168ec71c3c87b50c0a4cfd1d104649ae3c04a4623b26bf8060005285886000200190828254925583600080a47f6d5c9827c1f410bbb61d3b2a0a34b6b30492d9a1fd38588edca7ec4562ab9c9b80600052848760002001918383549355600080a4612b2e578380f35b7fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29260209268ff000000000000000019815416905551908152a13880808380f35b875162461bcd60e51b8152602081850152602260248201527f556e6f52653a207a65726f206d756c746973696777616c6c6574206164647265604482015261737360f01b6064820152608490fd5b68ffffffffffffffffff191668010000000000000001178655386129de565b875163f92ee8a960e01b81528390fd5b905015386129c3565b303b1591506129bb565b50846129af565b83823461094f578160031936011261094f5760015490516001600160a01b039091168152602090f35b83823461094f578160031936011261094f57602090600d549051908152f35b5082903461094f578060031936011261094f57612c696135fb565b90336001600160a01b03831603612c865750611496919235613f8d565b5163334bd91960e11b81528390fd5b5091903461094f576020806003193601126104c957612cb26135e5565b9280928060018060a01b038481600354168951938480926318160ddd60e01b82525afa918215612e4c579084939291899592612e1a575b5087600b5492600a5480431180612e11575b612d92575b5050612d49670de0b6b3a7640000612d34620f424097956002612d699896612d4f96169a8b895260088d52882001546137d6565b048785526008895260018c86200154906137b3565b9861397e565b9482526009865288808320549260088852200154906137d6565b0490818111612d7f575b50508351928352820152f35b612d8a9293506137b3565b903880612d73565b611069919395969750612da69250436137b3565b670de0b6b3a764000090818102918183041490151715612dfe57612d49670de0b6b3a7640000612d348b6002612d69988f9b98612def906110b1620f42409d9a612d4f9a6137e9565b989a5096985050935050612d00565b634e487b7160e01b865260118552602486fd5b50811515612cfb565b945090508484813d8111612e45575b612e33818361369b565b81010312610495578793519038612ce9565b503d612e29565b88513d86823e3d90fd5b50346104c957806003193601126104c9576114969135612ee1612e776135fb565b92612e8a60ff60015460a01c1615613708565b612e92613c95565b82865260008051602061486283398151915280602052612eb760018389200154613c62565b838752602052600181872001548652600660205280862033600052602052600020544210156136bd565b613f06565b5090346104c95760203660031901126104c9578160209360019235815260008051602061486283398151915285522001549051908152f35b83823461094f578160031936011261094f5760209060ff60015460a01c1690519015158152f35b50346104c95760203660031901126104c95760a09281906001600160a01b03612f6c6135e5565b16815260086020522080549260018201549260028301549160ff6003850154169301549381519586526020860152840152151560608301526080820152f35b92905034610f5f576020366003190112610f5f57612fc7613bfa565b6000805160206148c283398151915283526006602052818320338452602052612ff5828420544210156136bd565b6003546001600160a01b0316803b1561303e57602484928451958693849263f3212d2960e01b84528035908401525af19081156118165750613035575080f35b610e2190613655565b505050fd5b50346104c95760603660031901126104c95761305d6135e5565b906130666135fb565b60443591613072613cc0565b61307a613c95565b61308c60ff60015460a01c1615613708565b6003546001600160a01b0394908516330361325457806130ac8692613cf0565b1693848752602092600884526002838920015496602460608460035416865192838092631665744b60e11b82528c878301525afa90811561324a5787916130fb918c91613229575b508a6137b3565b106131e65750908491600b549783670de0b6b3a7640000998a8061311f83866137d6565b049161312b90846137d6565b04613135916137b3565b898c5260088852868c206001015561314c916137b3565b878a5260088652848a206002015516958688528288206001015490600b5461317490846137d6565b0461317e91613809565b86885260088452828820906001820155600201549061319c91613809565b8587526008835281872060020155519182527fabc254a3e8b16a8605ce22e693a6e493e375434011c1a7ff082d09e2a84ad12191a360016000805160206148a28339815191525580f35b835162461bcd60e51b8152908101859052601760248201527f556e6f52653a2062616c616e6365206f766572666c6f770000000000000000006044820152606490fd5b613242915060603d60601161205857612043818361369b565b5050386130f4565b85513d8c823e3d90fd5b815162461bcd60e51b8152602081880181905260248201527f556e6f52653a206e6f7420616c6c6f77206f7468657273207472616e736665726044820152606490fd5b8334610e24576020366003190112610e2457610ce36132b46135e5565b6132bc613c95565b6132ce60ff60015460a01c1615613708565b6132dc60055442101561374c565b6132e4613cc0565b613cf0565b50346104c957806003193601126104c95761333090613306613bfa565b6000805160206148c2833981519152845260066020528084203385526020528320544210156136bd565b35600b55602435600a5580f35b5090346104c957826003193601126104c95760209250549051908152f35b50346104c95760203660031901126104c957813591613378613bfa565b6000805160206148c2833981519152845260066020528184203385526020526133a6828520544210156136bd565b82156133de575081600c55519081527fbd1dd13c6a5b4a28ebd27fdcb8fdd01aba6bbb9f67599306248f465bcdf9817f60203092a280f35b6020606492519162461bcd60e51b83528201526011602482015270556e6f52653a207a65726f2076616c756560781b6044820152fd5b83823461094f578160031936011261094f5761342e613bfa565b6000805160206148c28339815191528252600660205280822033835260205261345c818320544210156136bd565b60ff6001548160a81b828260a81c161560a81b16908260a81b1916179182600155519160a81c16151581527f4a1fbdd1e9ef46cfe9e097f622e1d79f51dcd6762c86122e6a8198c5394d640160203092a280f35b83823461094f578160031936011261094f57602090517f3b745c09aefb8f732a168ec71c3c87b50c0a4cfd1d104649ae3c04a4623b26bf8152f35b5090346104c957826003193601126104c957613505613bfa565b6000805160206148c283398151915283526006602052818320338452602052613533828420544210156136bd565b6000805160206148828339815191529081549060ff821615613583575060ff19169055513381527f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa90602090a180f35b8351638dfc202b60e01b8152fd5b849084346104c95760203660031901126104c9573563ffffffff60e01b81168091036104c95760209250637965db0b60e01b81149081156135d4575b5015158152f35b6301ffc9a760e01b149050836135cd565b600435906001600160a01b038216820361049557565b602435906001600160a01b038216820361049557565b604435906001600160a01b038216820361049557565b9181601f840112156104955782359167ffffffffffffffff8311610495576020838186019501011161049557565b67ffffffffffffffff811161366957604052565b634e487b7160e01b600052604160045260246000fd5b60a0810190811067ffffffffffffffff82111761366957604052565b90601f8019910116810190811067ffffffffffffffff82111761366957604052565b156136c457565b606460405162461bcd60e51b815260206004820152602060248201527f556e6f52653a20726f6c6c206c6f636b2074696d65206e6f74207061737365646044820152fd5b1561370f57565b60405162461bcd60e51b8152602060048201526015602482015274155b9bd4994e881c1bdbdb081a5cc81ada5b1b1959605a1b6044820152606490fd5b1561375357565b60405162461bcd60e51b815260206004820152601960248201527f556e6f52653a206e6f7420617661696c61626c652074696d65000000000000006044820152606490fd5b90816060910312610495578051916040602083015192015190565b919082039182116137c057565b634e487b7160e01b600052601160045260246000fd5b818102929181159184041417156137c057565b81156137f3570490565b634e487b7160e01b600052601260045260246000fd5b919082018092116137c057565b9081602091031261049557516001600160a01b03811681036104955790565b8015801561391a575b6139145760035460405163e5a6b10f60e01b81526020916001600160a01b03919083908290600490829086165afa80156138eb5783916000916138f7575b506004604051809481936337962c8560e11b8352165afa9182156138eb576000926138bb575b50506138b790670de0b6b3a7640000926137d6565b0490565b90809250813d83116138e4575b6138d2818361369b565b810103126104955751816138b76138a2565b503d6138c8565b6040513d6000823e3d90fd5b61390e9150823d84116108cc576108be818361369b565b3861387c565b50600090565b50600d541561383e565b1561392b57565b60405162461bcd60e51b8152602060048201526013602482015272556e6f52653a207a65726f206164647265737360681b6044820152606490fd5b90816020910312610495575180151581036104955790565b60018060a01b03806000921682526020906009825260408320549260048383600354166040519283809263e5a6b10f60e01b82525afa908115613a5b579084918391613a3e575b506004604051809581936337962c8560e11b8352165afa928315613a315781936139fb575b5050506138b790620f4240926137d6565b9091809350813d8311613a2a575b613a13818361369b565b81010312610e24575051816138b7620f42406139ea565b503d613a09565b50604051903d90823e3d90fd5b613a559150823d84116108cc576108be818361369b565b386139c5565b6040513d84823e3d90fd5b908060209392818452848401376000828201840152601f01601f1916010190565b9190826040910312610495576020825192015190565b600a54804311613aaa5750565b6003546040516318160ddd60e01b81529190602090839060049082906001600160a01b03165afa9182156138eb57600092613b9c575b5081613b38575b507f1f2d1a9fde053af46b5db3dc92a8aa8696e56a677998fdd1311b45be341f78539043600a55600b5490613b3360405192839243846040919493926060820195825260208201520152565b0390a1565b611069613b4591436137b3565b90600b5491670de0b6b3a7640000908181029181830414901517156137c0577f1f2d1a9fde053af46b5db3dc92a8aa8696e56a677998fdd1311b45be341f7853926110b183613b93936137e9565b600b5590613ae7565b90916020823d602011613bc8575b81613bb76020938361369b565b81010312610e245750519038613ae0565b3d9150613baa565b8051821015613be45760209160051b010190565b634e487b7160e01b600052603260045260246000fd5b3360009081527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c60205260409020546000805160206148c28339815191529060ff1615613c445750565b6044906040519063e2517d3f60e01b82523360048301526024820152fd5b8060005260008051602061486283398151915260205260406000203360005260205260ff6040600020541615613c445750565b60ff6000805160206148828339815191525416613cae57565b60405163d93c066560e01b8152600490fd5b6000805160206148a28339815191526002815414613cde5760029055565b604051633ee5aeb560e01b8152600490fd5b613cf8613a9d565b613d018161452d565b92919081613da8575b505081613d15575050565b6003546001600160a01b0391908216803b15610495576040516310a864c160e21b81526001600160a01b038316600482015260248101859052906000908290604490829084905af180156138eb57613d99575b5060405192835216907f620b7d23261ea8e4d67bef44fc8e31e2538ba7c32acb3e56ea727b34943e519560203392a3565b613da290613655565b38613d68565b600254604051631963b13960e21b81526001600160a01b038581166004830152602482018590526044820193909352906020908290606490829060009087165af180156138eb57613e2b575b506040519182528216907fa0306f61d3fafe13787b78e276cb6b644382854a66cb46daae14227d3ec2679760203392a33880613d0a565b602090813d8311613e4f575b613e41818361369b565b810103126104955738613df4565b503d613e37565b6001600160a01b031660008181527fb16e88c42fd4e48df2dd6a2eabd6bc9aec654ec170056b470819f8892cc6431c60205260408120549091906000805160206148c2833981519152906000805160206148628339815191529060ff16613f00578184526020526040832082845260205260408320600160ff198254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b50505090565b9060009180835260008051602061486283398151915280602052604084209260018060a01b03169283855260205260ff60408520541615600014613f00578184526020526040832082845260205260408320600160ff198254161790557f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d339380a4600190565b90613fee91613fa460ff60015460a01c1615613708565b613fac613c95565b613fe960406000838152600080516020614862833981519152602052600182822001548152600660205281812033825260205220544210156136bd565b61479d565b90565b90600082156144d35782670de0b6b3a7640000810204670de0b6b3a7640000036144bf5760035460405163e5a6b10f60e01b815290602090829060049082906001600160a01b03165afa908115613a5b5760049160209184916144a2575b506040516337962c8560e11b815292839182906001600160a01b03165afa908115613a5b578291614470575b5064e8d4a510009081810291818304149015171561445c576140a790670de0b6b3a764000085026137e9565b90811561440d576001600160a01b038316815260096020526040812080546140d0908490613809565b90556140de82600d54613809565b600d556140e9613a9d565b6003546001600160a01b0316803b1561094f57604051637e348b7d60e01b81526001600160a01b0385166004820152602481018690529082908290604490829084905af18015613a5b576143fe575b506001600160a01b03831681526008602052604080822090519060049061415e8361367f565b80548352600181015460208401526002810154604084015260ff60038201541615156060840152015460808201526004602060018060a01b036003541660405192838092627a9fd960e91b82525afa80156143f35783906143bf575b61420d91506141ef6020840151670de0b6b3a76400006141e8846141e38c84600b5491026137d6565b6137e9565b0490613809565b60208401526110b1604084015191670de0b6b3a764000089026137e9565b604082015260018060a01b0384168252600860205260046080604084209280518455602081015160018501556040810151600285015561426260608201511515600386019060ff801983541691151516179055565b015191015560035460405163e5a6b10f60e01b815290602090829060049082906001600160a01b03165afa908115613a5b5760049160209184916143a2575b506040516337962c8560e11b815292839182906001600160a01b03165afa908115613a5b578291614370575b506001600160a01b0384811683526008602052604083206004019190915560015416803b1561094f57818091602460405180948193638be5a39f60e01b83528a60048401525af18015613a5b5761435c575b50507f72be1d1287530282d96b5fbbb6f2a18a6ba1c7510d8516abcdb07e2f3e957e46916040918251948552602085015260018060a01b031692a2565b6143668291613655565b610e24578061431f565b90506020813d60201161439a575b8161438b6020938361369b565b810103126104955751386142cd565b3d915061437e565b6143b99150823d84116108cc576108be818361369b565b386142a1565b506020813d6020116143eb575b816143d96020938361369b565b810103126104955761420d90516141ba565b3d91506143cc565b6040513d85823e3d90fd5b61440790613655565b38614138565b60405162461bcd60e51b815260206004820152602160248201527f556e6f52653a20526573756c74696e672073686172657320746f6f20736d616c6044820152601b60fa1b6064820152608490fd5b634e487b7160e01b82526011600452602482fd5b90506020813d60201161449a575b8161448b6020938361369b565b8101031261094f57513861407b565b3d915061447e565b6144b99150823d84116108cc576108be818361369b565b3861404f565b634e487b7160e01b81526011600452602490fd5b60405162461bcd60e51b815260206004820152602c60248201527f556e6f52653a204465706f73697420616d6f756e74206d75737420626520677260448201526b06561746572207468616e20360a41b6064820152608490fd5b60035460408051631665744b60e11b81526001600160a01b03848116600480840182905296948216959391926060816024818a5afa90811561479257600091614770575b5061475e578060005260209060088252600283600020015497881561474a57670de0b6b3a76400006145a5600b548b6137d6565b049482600052600884526145c96145c36001876000200154886137b3565b9761397e565b918360005260098552620f42406145ef87600020546008885283896000200154906137d6565b049960009a808511614616575b505050505060019291600891600052526000200155929190565b84614629929394959c50979695976137b3565b998a116147075783829186519283809263e5a6b10f60e01b82525afa9081156146fc579084916000916146df575b50828651809581936337962c8560e11b8352165afa9182156146d45760009261469c575b509360089291600195826000528484528560002001559181939438806145fc565b9280925083819692963d83116146cd575b6146b7818361369b565b810103126104955791519193909190600161467b565b503d6146ad565b84513d6000823e3d90fd5b6146f69150823d84116108cc576108be818361369b565b38614657565b85513d6000823e3d90fd5b845162461bcd60e51b8152808301859052601f60248201527f496e76616c6964205553444d207265776172642063616c63756c6174696f6e006044820152606490fd5b505050505050915050600090600090600090565b50505050915050600090600090600090565b614789915060603d60601161205857612043818361369b565b50905038614571565b83513d6000823e3d90fd5b9060009180835260008051602061486283398151915280602052604084209260018060a01b03169283855260205260ff604085205416600014613f0057818452602052604083208284526020526040832060ff1981541690557ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b339380a4600190565b60ff7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a005460401c161561484f57565b604051631afcd79f60e31b8152600490fdfe02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800cd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f033009b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00a49807205ce4d355092ef5a8a18f56e8913cf4a201fbe287825b095693c21775a26469706673582212208b290c24fc4bc312935401af3d24aead0bc7f076cac2fa19e26eabc640a999d664736f6c63430008170033

Verified Source Code Full Match

Compiler: v0.8.23+commit.f704f362 EVM: paris Optimization: Yes (200 runs)
SingleSidedInsurancePoolUSDM.sol 655 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/utils/PausableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";

import "./interfaces/ICapitalAgent.sol";
import "./interfaces/IMigration.sol";
import "./interfaces/IRewarderFactory.sol";
import "./interfaces/IRiskPoolFactory.sol";
import "./interfaces/ISingleSidedInsurancePool.sol";
import "./interfaces/IRewarder.sol";
import "./interfaces/IRiskPoolUSDM.sol";
import "./libraries/TransferHelper.sol";
import "./interfaces/IUSDM.sol";

contract SingleSidedInsurancePoolUSDM is
    ISingleSidedInsurancePool,
    ReentrancyGuardUpgradeable,
    PausableUpgradeable,
    AccessControlUpgradeable
{
    bytes32 public constant CLAIM_PROCESSOR_ROLE = keccak256("CLAIM_PROCESSOR_ROLE");
    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
    bytes32 public constant BOT_ROLE = keccak256("BOT_ROLE");

    uint256 public constant ACC_UNO_PRECISION = 1e18;

    address public migrateTo;
    address public capitalAgent;

    bool public killed;
    bool public emergencyWithdrawAllowed;
    address public rewarder;

    address public override riskPool;

    uint256 public lockTime;
    uint256 public stakingStartTime;

    struct PoolInfo {
        uint256 lastRewardBlock;
        uint256 accUnoPerShare;
        uint256 unoMultiplierPerBlock;
    }

    struct UserInfo {
        uint256 lastWithdrawTime;
        uint256 rewardDebt;
        uint256 amount;
        bool isNotRollOver;
        uint256 lastRewardMultiplier;
    }

    struct Policy {
        uint256 insuranceAmount;
        address payoutAddress;
        bool settled;
    }

    mapping(bytes32 => mapping(address => uint256)) public roleLockTime;

    mapping(uint256 => Policy) public policies;

    mapping(address => UserInfo) public userInfo;

    mapping(address => uint256) public userShares;

    PoolInfo public poolInfo;
    uint256 public totalShares;

    event RiskPoolCreated(address indexed _SSIP, address indexed _pool);
    event StakedInPool(address indexed user, uint256 amount, uint256 shares);
    event LeftPool(address indexed _staker, address indexed _pool, uint256 _requestAmount);
    event LogUpdatePool(uint256 _lastRewardBlock, uint256 _lpSupply, uint256 _accUnoPerShare);
    event Harvest(address indexed _user, address indexed _receiver, uint256 _amount);
    event LogLeaveFromPendingSSIP(
        address indexed _user,
        address indexed _riskPool,
        uint256 _withdrawLpAmount,
        uint256 _withdrawUnoAmount
    );
    event PolicyClaim(address indexed _user, uint256 _claimAmount);
    event LogLpTransferInSSIP(address indexed _from, address indexed _to, uint256 _amount);
    event LogCreateRewarder(address indexed _SSIP, address indexed _rewarder, address _currency);
    event LogCancelWithdrawRequest(address indexed _user, uint256 _cancelAmount, uint256 _cancelAmountInUno);
    event LogMigrate(address indexed _user, address indexed _migrateTo, uint256 _migratedAmount);
    event LogSetCapitalAgent(address indexed _SSIP, address indexed _capitalAgent);
    event LogSetRewardMultiplier(address indexed _SSIP, uint256 _rewardPerBlock);
    event LogSetRole(address indexed _SSIP, bytes32 _role, address indexed _account);
    event LogSetMigrateTo(address indexed _SSIP, address indexed _migrateTo);
    event LogSetMinLPCapital(address indexed _SSIP, uint256 _minLPCapital);
    event LogSetLockTime(address indexed _SSIP, uint256 _lockTime);
    event LogSetStakingStartTime(address indexed _SSIP, uint256 _startTime);
    event PoolAlived(address indexed _owner, bool _alive);
    event PoolFailed(address indexed _owner, bool _fail);
    event KillPool(address indexed _owner, bool _killed);
    event InsurancePayoutSettled(uint256 indexed policyId, address indexed payout, uint256 amount);
    event RollOverReward(address[] indexed _staker, address indexed _pool, uint256 _amount);
    event EmergencyWithdraw(address indexed user, uint256 amount);
    event EmergencyWithdrawToggled(address indexed user, bool EmergencyWithdraw);
    event LogUserUpdated(address indexed pool, address indexed user, uint256 amount);
    event USDMRewardHarvested(address indexed caller, address indexed user, uint256 amount);

    function initialize(address _capitalAgent, address _multiSigWallet) external initializer {
        require(_multiSigWallet != address(0), "UnoRe: zero multisigwallet address");
        capitalAgent = _capitalAgent;
        lockTime = 10 days;
        __ReentrancyGuard_init();
        __Pausable_init();
        __AccessControl_init();
        _grantRole(ADMIN_ROLE, _multiSigWallet);
        _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE);
        _setRoleAdmin(CLAIM_PROCESSOR_ROLE, ADMIN_ROLE);
        _setRoleAdmin(BOT_ROLE, ADMIN_ROLE);
    }

    modifier isStartTime() {
        require(block.timestamp >= stakingStartTime, "UnoRe: not available time");
        _;
    }

    modifier roleLockTimePassed(bytes32 _role) {
        require(block.timestamp >= roleLockTime[_role][msg.sender], "UnoRe: roll lock time not passed");
        _;
    }

    modifier isAlive() {
        require(!killed, "UnoRe: pool is killed");
        _;
    }

    /**
     * @dev pause pool to restrict pool functionality, can only by called by admin role
     */
    function pausePool() external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        _pause();
    }

    /**
     * @dev unpause pool, can only by called by admin role
     */
    function unpausePool() external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        _unpause();
    }

    /**
     * @dev kill pool to restrict pool functionality, can only by called by admin role
     */
    function killPool() external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        killed = true;
        emit KillPool(msg.sender, true);
    }

    /**
     * @dev revive pool, can only by called by admin role
     */
    function revivePool() external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        killed = false;
        emit PoolAlived(msg.sender, false);
    }

    function setRole(
        bytes32 _role,
        address _account
    ) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) whenNotPaused isAlive {
        require(_account != address(0), "UnoRe: zero address");
        roleLockTime[_role][_account] = block.timestamp + lockTime;
        _grantRole(_role, _account);
        emit LogSetRole(address(this), _role, _account);
    }

    /**
     * @dev set new capital agent, can only by called by admin role
     * @param _capitalAgent new capital agent address
     */
    function setCapitalAgent(address _capitalAgent) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_capitalAgent != address(0), "UnoRe: zero address");
        capitalAgent = _capitalAgent;
        emit LogSetCapitalAgent(address(this), _capitalAgent);
    }

    /**
     * @dev update reward muiltiplier, can only by called by admin role
     * @param _rewardMultiplier value to set
     */
    function setRewardMultiplier(uint256 _rewardMultiplier) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_rewardMultiplier > 0, "UnoRe: zero value");
        poolInfo.unoMultiplierPerBlock = _rewardMultiplier;
        emit LogSetRewardMultiplier(address(this), _rewardMultiplier);
    }

    /**
     * @dev set migrate address, can only by called by admin role
     * @param _migrateTo new migrate address
     */
    function setMigrateTo(address _migrateTo) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_migrateTo != address(0), "UnoRe: zero address");
        migrateTo = _migrateTo;
        emit LogSetMigrateTo(address(this), _migrateTo);
    }

    /**
     * @dev update min lp capital, only admin role call this function
     */
    function setMinLPCapital(uint256 _minLPCapital) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_minLPCapital > 0, "UnoRe: not allow zero value");
        IRiskPoolUSDM(riskPool).setMinLPCapital(_minLPCapital);
        emit LogSetMinLPCapital(address(this), _minLPCapital);
    }

    /**
     * @dev lock time, only admin role call this function
     */
    function setLockTime(uint256 _lockTime) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_lockTime > 0, "UnoRe: not allow zero lock time");
        lockTime = _lockTime;
        emit LogSetLockTime(address(this), _lockTime);
    }

    /**
     * @dev set staking start time, only admin role call this function
     */
    function setStakingStartTime(uint256 _startTime) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        stakingStartTime = _startTime + block.timestamp;
        emit LogSetStakingStartTime(address(this), stakingStartTime);
    }

    /**
     * @dev toggle emergency withdraw bool to restrict or use this emergency withdraw,
     * only admin role call this function
     */
    function toggleEmergencyWithdraw() external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        emergencyWithdrawAllowed = !emergencyWithdrawAllowed;
        emit EmergencyWithdrawToggled(address(this), emergencyWithdrawAllowed);
    }

    /**
     * @dev create Risk pool with UNO from SSIP owner
     */
    function createRiskPool(
        string calldata _name,
        string calldata _symbol,
        address _factory,
        address _currency,
        uint256 _rewardMultiplier,
        uint256 _SCR
    ) external nonReentrant onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_factory != address(0), "UnoRe: zero factory address");
        riskPool = IRiskPoolFactory(_factory).newRiskPoolUSDM(_name, _symbol, address(this), _currency);
        poolInfo.lastRewardBlock = block.number;
        poolInfo.accUnoPerShare = 0;
        poolInfo.unoMultiplierPerBlock = _rewardMultiplier;
        ICapitalAgent(capitalAgent).addPool(address(this), _currency, _SCR);
        emit RiskPoolCreated(address(this), riskPool);
    }

    /**
     * @dev create rewarder with UNO token
     */
    function createRewarder(
        address _operator,
        address _factory,
        address _currency
    ) external nonReentrant onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        require(_factory != address(0), "UnoRe: rewarder factory no exist");
        require(_operator != address(0), "UnoRe: zero operator address");
        rewarder = IRewarderFactory(_factory).newRewarder(_operator, _currency, address(this));
        emit LogCreateRewarder(address(this), rewarder, _currency);
    }

    /**
     * @dev migrate user to new version
     */
    function migrate() external nonReentrant whenNotPaused isAlive {
        require(migrateTo != address(0), "UnoRe: zero address");
        _harvest(msg.sender);
        bool isUnLocked = block.timestamp - userInfo[msg.sender].lastWithdrawTime > lockTime;
        uint256 migratedAmount = IRiskPoolUSDM(riskPool).migrateLP(msg.sender, migrateTo, isUnLocked);
        ICapitalAgent(capitalAgent).SSIPPolicyCaim(migratedAmount, 0, false);
        IMigration(migrateTo).onMigration(msg.sender, migratedAmount, "");
        userInfo[msg.sender].amount = 0;
        userInfo[msg.sender].rewardDebt = 0;
        emit LogMigrate(msg.sender, migrateTo, migratedAmount);
    }

    /**
     * @dev return pending uno to claim of `_to` address
     */
    function pendingUno(address _to) external view returns (uint256 pending) {
        uint256 tokenSupply = IERC20(riskPool).totalSupply();
        uint256 accUnoPerShare = poolInfo.accUnoPerShare;
        if (block.number > poolInfo.lastRewardBlock && tokenSupply != 0) {
            uint256 blocks = block.number - uint256(poolInfo.lastRewardBlock);
            uint256 unoReward = blocks * poolInfo.unoMultiplierPerBlock;
            accUnoPerShare = accUnoPerShare + (unoReward * ACC_UNO_PRECISION) / tokenSupply;
        }
        uint256 userBalance = userInfo[_to].amount;
        pending = (userBalance * uint256(accUnoPerShare)) / ACC_UNO_PRECISION - userInfo[_to].rewardDebt;
    }

    /**
     * @dev update pool last reward and accumulated uno per share,
     * update every time when use enter, withdraw from pool
     */
    function updatePool() public override {
        if (block.number > poolInfo.lastRewardBlock) {
            uint256 tokenSupply = IERC20(riskPool).totalSupply();
            if (tokenSupply > 0) {
                uint256 blocks = block.number - uint256(poolInfo.lastRewardBlock);
                uint256 unoReward = blocks * poolInfo.unoMultiplierPerBlock;
                poolInfo.accUnoPerShare = poolInfo.accUnoPerShare + ((unoReward * ACC_UNO_PRECISION) / tokenSupply);
            }
            poolInfo.lastRewardBlock = block.number;
            emit LogUpdatePool(poolInfo.lastRewardBlock, tokenSupply, poolInfo.accUnoPerShare);
        }
    }

    /**
     * @dev stake user collateral, update user reward per block
     * @param _amount amount to deposit to pool
     */
    function enterInPool(uint256 _amount) external payable override whenNotPaused isAlive isStartTime nonReentrant {
        _depositIn(_amount);
        _enterInPool(_amount, msg.sender);
    }

    /**
     * @dev WR will be in pending for 10 days at least
     */
    function leaveFromPoolInPending(uint256 _amount) external override whenNotPaused isStartTime nonReentrant {
        _harvest(msg.sender);
        require(ICapitalAgent(capitalAgent).checkCapitalByMCR(address(this), _amount), "UnoRe: minimum capital underflow");
        // Withdraw desired amount from pool
        uint256 amount = userInfo[msg.sender].amount;
        uint256 lpPriceUno = IRiskPoolUSDM(riskPool).lpPriceUno();
        (uint256 pendingAmount, , ) = IRiskPoolUSDM(riskPool).getWithdrawRequest(msg.sender);
        require(amount - pendingAmount >= (_amount * 1e18) / lpPriceUno, "UnoRe: withdraw amount overflow");
        IRiskPoolUSDM(riskPool).leaveFromPoolInPending(msg.sender, _amount);

        userInfo[msg.sender].lastWithdrawTime = block.timestamp;
        //As user is starting the withdraw we add the value to pending capital
        ICapitalAgent(capitalAgent).updatePoolWithdrawPendingCapital(address(this), _amount, true);
        emit LeftPool(msg.sender, riskPool, _amount);
    }

    /**
     * @dev user can submit claim again and receive his funds into his wallet after 10 days since last WR.
     */
    function leaveFromPending(uint256 _amount) external override isStartTime whenNotPaused nonReentrant {
        require(_amount > 0, "Withdraw amount should be greator than zero");
        require(block.timestamp - userInfo[msg.sender].lastWithdrawTime >= lockTime, "UnoRe: Locked time");
        _harvest(msg.sender);
        uint256 amount = userInfo[msg.sender].amount;

        (uint256 withdrawAmount, uint256 withdrawAmountInUNO) = IRiskPoolUSDM(riskPool).leaveFromPending(msg.sender, _amount);

        ICapitalAgent(capitalAgent).SSIPWithdraw(withdrawAmountInUNO);

        uint256 accumulatedUno = (amount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION;
        userInfo[msg.sender].rewardDebt =
            accumulatedUno -
            ((withdrawAmount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION);

        userInfo[msg.sender].amount = amount - withdrawAmount;

        emit LogLeaveFromPendingSSIP(msg.sender, riskPool, withdrawAmount, withdrawAmountInUNO);
    }

    function emergencyWithdraw() public nonReentrant whenNotPaused {
        require(emergencyWithdrawAllowed, "Unore: emergencyWithdraw is not allowed");
        UserInfo memory user = userInfo[msg.sender];
        uint256 amount = user.amount;
        require(amount > 0, "Unore: Zero user amount");
        delete userInfo[msg.sender];
        IRiskPoolUSDM(riskPool).emergencyWithdraw(msg.sender, amount);
        emit EmergencyWithdraw(msg.sender, amount);
    }

    function lpTransfer(address _from, address _to, uint256 _amount) external override nonReentrant whenNotPaused isAlive {
        require(msg.sender == address(riskPool), "UnoRe: not allow others transfer");
        _harvest(_from);
        uint256 amount = userInfo[_from].amount;
        (uint256 pendingAmount, , ) = IRiskPoolUSDM(riskPool).getWithdrawRequest(_from);
        require(amount - pendingAmount >= _amount, "UnoRe: balance overflow");
        uint256 accumulatedUno = (amount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION;
        userInfo[_from].rewardDebt = accumulatedUno - ((_amount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION);
        userInfo[_from].amount = amount - _amount;

        userInfo[_to].rewardDebt = userInfo[_to].rewardDebt + ((_amount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION);
        userInfo[_to].amount = userInfo[_to].amount + _amount;

        emit LogLpTransferInSSIP(_from, _to, _amount);
    }

    /**
     * @dev withdraw user pending uno & USDM
     * @param _to user address
     */
    function harvest(address _to) external override whenNotPaused isAlive isStartTime nonReentrant {
        _harvest(_to);
    }

    /**
     * @dev withdraw user pending uno & USDM
     * @param _to user address
     */
    function _harvest(address _to) private {
        updatePool();

        (uint256 _pendingUno, uint256 _amount, uint256 _pendingUSDM) = _updateReward(_to);

        if (_pendingUno != 0) {
            IRewarder(rewarder).onReward(_to, _pendingUno, _amount);
            emit Harvest(msg.sender, _to, _pendingUno);
        }

        // Send USDM rewards directly
        if (_pendingUSDM != 0) {
            IRiskPoolUSDM(riskPool).transferUSDMReward(_to, _pendingUSDM);
            emit USDMRewardHarvested(msg.sender, _to, _pendingUSDM);
        }
    }

    function _updateReward(address _to) internal returns (uint256, uint256, uint256) {
        uint256 requestTime;
        (, requestTime, ) = IRiskPoolUSDM(riskPool).getWithdrawRequest(_to);
        if (requestTime > 0) {
            return (0, 0, 0);
        }

        uint256 amount = userInfo[_to].amount;
        if (amount == 0) {
            return (0, 0, 0);
        }

        // Calculate UNO rewards
        uint256 accumulatedUno = (amount * uint256(poolInfo.accUnoPerShare)) / ACC_UNO_PRECISION;
        uint256 _pendingUno = accumulatedUno - userInfo[_to].rewardDebt;

        // Calculate USDM rewards
        uint256 currentUSDMValue = getUserUSDMAmount(_to);
        uint256 previousUSDMValue = (userShares[_to] * userInfo[_to].lastRewardMultiplier) / 1e6;

        uint256 _pendingUSDM = 0;
        if (currentUSDMValue > previousUSDMValue) {
            _pendingUSDM = currentUSDMValue - previousUSDMValue;
            require(_pendingUSDM <= currentUSDMValue, "Invalid USDM reward calculation");

            // Get current multiplier and update only when there are USDM rewards
            uint256 currentMultiplier = IUSDM(IRiskPoolUSDM(riskPool).currency()).rewardMultiplier();
            userInfo[_to].lastRewardMultiplier = currentMultiplier;
        }

        // Effects
        userInfo[_to].rewardDebt = accumulatedUno;

        return (_pendingUno, amount, _pendingUSDM);
    }

    /**
     * @dev return pending uno and USDM to claim of `_to` address
     */
    function pendingRewards(address _to) external view returns (uint256 unoRewards, uint256 pendingUSDM) {
        uint256 tokenSupply = IERC20(riskPool).totalSupply();
        uint256 accUnoPerShare = poolInfo.accUnoPerShare;
        if (block.number > poolInfo.lastRewardBlock && tokenSupply != 0) {
            uint256 blocks = block.number - uint256(poolInfo.lastRewardBlock);
            uint256 unoReward = blocks * poolInfo.unoMultiplierPerBlock;
            accUnoPerShare = accUnoPerShare + (unoReward * ACC_UNO_PRECISION) / tokenSupply;
        }
        uint256 userBalance = userInfo[_to].amount;
        unoRewards = (userBalance * uint256(accUnoPerShare)) / ACC_UNO_PRECISION - userInfo[_to].rewardDebt;

        // Calculate pending USDM rewards
        uint256 currentUSDMValue = getUserUSDMAmount(_to);
        uint256 previousUSDMValue = (userShares[_to] * userInfo[_to].lastRewardMultiplier) / 1e6;
        if (currentUSDMValue > previousUSDMValue) {
            pendingUSDM = currentUSDMValue - previousUSDMValue;
        }
    }

    /**
     * @dev user can toggle its roll over bool
     */
    function toggleRollOver() external {
        userInfo[msg.sender].isNotRollOver = !userInfo[msg.sender].isNotRollOver;
    }

    /**
     * @dev user roll over its pending uno to stake
     */
    function rollOverReward(address[] memory _to) external isStartTime whenNotPaused isAlive onlyRole(BOT_ROLE) nonReentrant {
        require(IRiskPoolUSDM(riskPool).currency() == IRewarder(rewarder).currency(), "UnoRe: currency not matched");
        updatePool();
        uint256 _totalPendingUno;
        uint256 _accumulatedAmount;
        for (uint256 i; i < _to.length; i++) {
            require(!userInfo[_to[i]].isNotRollOver, "UnoRe: rollover is not set");

            (uint256 _pendingUno, uint256 _amount, ) = _updateReward(_to[i]);
            _totalPendingUno += _pendingUno;
            _accumulatedAmount += _amount;
            _enterInPool(_pendingUno, _to[i]);
        }

        if (rewarder != address(0) && _totalPendingUno != 0 && _accumulatedAmount > 0) {
            IRewarder(rewarder).onReward(riskPool, _totalPendingUno, _accumulatedAmount);
        }
        emit RollOverReward(_to, riskPool, _totalPendingUno);
    }

    /**
     * @dev user can cancel its pending withdraw request
     */
    function cancelWithdrawRequest() external nonReentrant whenNotPaused isAlive {
        (uint256 cancelAmount, uint256 cancelAmountInUno) = IRiskPoolUSDM(riskPool).cancelWithdrawRequest(msg.sender);

        //if user return the pending value into staking again by canceling withdraw,
        //we remove the amount from the pending capital
        ICapitalAgent(capitalAgent).updatePoolWithdrawPendingCapital(address(this), cancelAmount, false);

        emit LogCancelWithdrawRequest(msg.sender, cancelAmount, cancelAmountInUno);
    }

    /**
     * @dev return user staked currency corresponding to current lp price of uno
     */
    function getStakedAmountPerUser(address _to) external view returns (uint256 unoAmount, uint256 lpAmount) {
        lpAmount = userInfo[_to].amount;
        uint256 lpPriceUno = IRiskPoolUSDM(riskPool).lpPriceUno();
        unoAmount = (lpAmount * lpPriceUno) / 1e18;
    }

    /**
     * @dev get withdraw request amount in pending per user in UNO
     */
    function getWithdrawRequestPerUser(
        address _user
    ) external view returns (uint256 pendingAmount, uint256 pendingAmountInUno, uint256 originUnoAmount, uint256 requestTime) {
        uint256 lpPriceUno = IRiskPoolUSDM(riskPool).lpPriceUno();
        (pendingAmount, requestTime, originUnoAmount) = IRiskPoolUSDM(riskPool).getWithdrawRequest(_user);
        pendingAmountInUno = (pendingAmount * lpPriceUno) / 1e18;
    }

    /**
     * @dev get total withdraw request amount in pending for the risk pool in UNO
     */
    function getTotalWithdrawPendingAmount() external view returns (uint256) {
        return IRiskPoolUSDM(riskPool).getTotalWithdrawRequestAmount();
    }

    /**
     * @dev claim policy to payout, can only be called by claim processor role
     */
    function settlePayout(
        uint256 _policyId,
        address _payout,
        uint256 _amount
    ) public whenNotPaused isAlive onlyRole(CLAIM_PROCESSOR_ROLE) roleLockTimePassed(CLAIM_PROCESSOR_ROLE) {
        uint256 realClaimAmount = IRiskPoolUSDM(riskPool).policyClaim(_payout, _amount);
        ICapitalAgent(capitalAgent).SSIPPolicyCaim(realClaimAmount, uint256(_policyId), true);

        emit InsurancePayoutSettled(_policyId, _payout, _amount);
    }

    function setUserDetails(
        address _user,
        uint256 _amount,
        uint256 _rewardDebt
    ) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        userInfo[_user].amount = _amount;
        userInfo[_user].rewardDebt = _rewardDebt;
        IRiskPoolUSDM(riskPool).enter(_user, _amount);

        emit LogUserUpdated(address(this), _user, _amount);
    }

    function setLpPriceInRiskPool(uint256 _lpPriceUno) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        IRiskPoolUSDM(riskPool).setLpPriceUno(_lpPriceUno);
    }

    function setAccUnoPerShare(
        uint256 _accUnoPerShare,
        uint256 _lastRewardBlock
    ) external onlyRole(ADMIN_ROLE) roleLockTimePassed(ADMIN_ROLE) {
        poolInfo.accUnoPerShare = _accUnoPerShare;
        poolInfo.lastRewardBlock = _lastRewardBlock;
    }

    function grantRole(
        bytes32 role,
        address account
    ) public override isAlive whenNotPaused onlyRole(getRoleAdmin(role)) roleLockTimePassed(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    function _revokeRole(
        bytes32 role,
        address account
    ) internal override isAlive whenNotPaused roleLockTimePassed(getRoleAdmin(role)) returns (bool) {
        return super._revokeRole(role, account);
    }

    function _depositIn(uint256 _amount) internal {
        address token = IRiskPoolUSDM(riskPool).currency();

        require(_amount > 0, "UnoRe: zero deposit amount");
        TransferHelper.safeTransferFrom(token, msg.sender, riskPool, _amount);
    }

    function _enterInPool(uint256 _amount, address _to) internal {
        require(_amount != 0, "UnoRe: Deposit amount must be greater than 0");

        // Calculate shares based on USDM reward multiplier
        uint256 sharesToMint = (_amount * 1e18) / (IUSDM(IRiskPoolUSDM(riskPool).currency()).rewardMultiplier() * 1e12);
        require(sharesToMint > 0, "UnoRe: Resulting shares too small");

        // Update user shares and total shares
        userShares[_to] += sharesToMint;
        totalShares += sharesToMint;

        updatePool();

        // Mint LP tokens in RiskPool
        IRiskPoolUSDM(riskPool).enter(_to, _amount);
        UserInfo memory _userInfo = userInfo[_to];

        uint256 lpPriceUno = IRiskPoolUSDM(riskPool).lpPriceUno();
        _userInfo.rewardDebt =
            _userInfo.rewardDebt +
            ((_amount * 1e18 * uint256(poolInfo.accUnoPerShare)) / lpPriceUno) /
            ACC_UNO_PRECISION;
        _userInfo.amount = _userInfo.amount + ((_amount * 1e18) / lpPriceUno);
        userInfo[_to] = _userInfo;
        userInfo[_to].lastRewardMultiplier = IUSDM(IRiskPoolUSDM(riskPool).currency()).rewardMultiplier();

        ICapitalAgent(capitalAgent).SSIPStaking(_amount);

        emit StakedInPool(_to, _amount, sharesToMint);
    }

    function getUserUSDMAmount(address _user) public view returns (uint256) {
        uint256 userShareAmount = userShares[_user];
        uint256 usdmMultiplier = IUSDM(IRiskPoolUSDM(riskPool).currency()).rewardMultiplier();
        return (userShareAmount * usdmMultiplier) / 1e6;
    }

    function getShareValue(uint256 _shares) public view returns (uint256) {
        if (_shares == 0 || totalShares == 0) return 0;
        return (_shares * IUSDM(IRiskPoolUSDM(riskPool).currency()).rewardMultiplier()) / 1e18;
    }
}
ICapitalAgent.sol 36 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;

interface ICapitalAgent {
    function addPool(address _ssip, address _currency, uint256 _scr) external;

    function setPolicy(address _policy) external;

    function SSIPWithdraw(uint256 _withdrawAmount) external;

    function SSIPStaking(uint256 _stakingAmount) external;

    function SSIPPolicyCaim(uint256 _withdrawAmount, uint256 _policyId, bool _isMigrate) external;

    function checkCapitalByMCR(address _pool, uint256 _withdrawAmount) external view returns (bool);

    function checkCoverageByMLR(uint256 _coverageAmount) external view returns (bool);

    function policySale(uint256 _coverageAmount) external;

    function updatePolicyStatus(uint256 _policyId) external;

    function getPolicyInfo() external returns (address, uint256, bool);

    function claimedAmount(address _policy, uint256 _policyId) external returns (uint256);

    function exchangeAgent() external view returns (address);

    function getPoolInfo(address _pool) external view returns (uint256, uint256, address, bool, uint256);

    function updatePoolWithdrawPendingCapital(address _pool, uint256 _amount, bool) external;

    function addPoolWhiteList(address _pool) external;

    function poolWhiteList(address _pool) external view returns (bool);
}
IMigration.sol 6 lines
// SPDX-License-Identifier: MIT
pragma solidity =0.8.23;

interface IMigration {
    function onMigration(address who_, uint256 amount_, bytes memory data_) external;
}
IRewarder.sol 9 lines
// SPDX-License-Identifier: MIT

pragma solidity =0.8.23;

interface IRewarder {
    function currency() external view returns (address);

    function onReward(address to, uint256 unoAmount, uint256 accumulatedAmount) external payable returns (uint256);
}
IRewarderFactory.sol 6 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

interface IRewarderFactory {
    function newRewarder(address _operator, address _currency, address _pool) external returns (address);
}
IRiskPoolFactory.sol 18 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

interface IRiskPoolFactory {
    function newRiskPool(
        string calldata _name,
        string calldata _symbol,
        address _pool,
        address _currency
    ) external returns (address);

    function newRiskPoolUSDM(
        string calldata _name,
        string calldata _symbol,
        address _cohort,
        address _currency
    ) external returns (address);
}
IRiskPoolUSDM.sol 34 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

interface IRiskPoolUSDM {
    function enter(address _from, uint256 _amount) external;

    function leaveFromPoolInPending(address _to, uint256 _amount) external;

    function leaveFromPending(address _to, uint256 _amount) external returns (uint256, uint256);

    function cancelWithdrawRequest(address _to) external returns (uint256, uint256);

    function policyClaim(address _to, uint256 _amount) external returns (uint256 realClaimAmount);

    function migrateLP(address _to, address _migrateTo, bool _isUnLocked) external returns (uint256);

    function setMinLPCapital(uint256 _minLPCapital) external;

    function currency() external view returns (address);

    function getTotalWithdrawRequestAmount() external view returns (uint256);

    function getWithdrawRequest(address _to) external view returns (uint256, uint256, uint256);

    function lpPriceUno() external view returns (uint256);

    function emergencyWithdraw(address _to, uint256 _amount) external returns (bool);

    function setLpPriceUno(uint256 _lpPriceUno) external;

    function transferUSDMReward(address _to, uint256 _amount) external;

    function balanceOf(address _to) external view returns (uint256);
}
ISingleSidedInsurancePool.sol 20 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

interface ISingleSidedInsurancePool {
    function updatePool() external;

    function enterInPool(uint256 _amount) external payable;

    function leaveFromPoolInPending(uint256 _amount) external;

    function leaveFromPending(uint256 _amount) external;

    function harvest(address _to) external;

    function lpTransfer(address _from, address _to, uint256 _amount) external;

    function riskPool() external view returns (address);

    function settlePayout(uint256 _policyId, address _payout, uint256 _amount) external;
}
IUSDM.sol 8 lines
// SPDX-License-Identifier: GPL-3.0
pragma solidity =0.8.23;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

interface IUSDM is IERC20 {
    function rewardMultiplier() external view returns (uint256);
}
TransferHelper.sol 28 lines
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity =0.8.23;

// from Uniswap TransferHelper library
library TransferHelper {
    function safeApprove(address token, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeApprove: approve failed");
    }

    function safeTransfer(address token, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::safeTransfer: transfer failed");
    }

    function safeTransferFrom(address token, address from, address to, uint256 value) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), "TransferHelper::transferFrom: transferFrom failed");
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, "TransferHelper::safeTransferETH: ETH transfer failed");
    }
}
AccessControlUpgradeable.sol 233 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol";
import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {ERC165Upgradeable} from "../utils/introspection/ERC165Upgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```solidity
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```solidity
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControlUpgradeable is Initializable, ContextUpgradeable, IAccessControl, ERC165Upgradeable {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;


    /// @custom:storage-location erc7201:openzeppelin.storage.AccessControl
    struct AccessControlStorage {
        mapping(bytes32 role => RoleData) _roles;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.AccessControl")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant AccessControlStorageLocation = 0x02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800;

    function _getAccessControlStorage() private pure returns (AccessControlStorage storage $) {
        assembly {
            $.slot := AccessControlStorageLocation
        }
    }

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    function __AccessControl_init() internal onlyInitializing {
    }

    function __AccessControl_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view virtual returns (bytes32) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        return $._roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        AccessControlStorage storage $ = _getAccessControlStorage();
        bytes32 previousAdminRole = getRoleAdmin(role);
        $._roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (!hasRole(role, account)) {
            $._roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        AccessControlStorage storage $ = _getAccessControlStorage();
        if (hasRole(role, account)) {
            $._roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}
Initializable.sol 228 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)

pragma solidity ^0.8.20;

/**
 * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
 * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
 * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
 * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
 *
 * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
 * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
 * case an upgrade adds a module that needs to be initialized.
 *
 * For example:
 *
 * [.hljs-theme-light.nopadding]
 * ```solidity
 * contract MyToken is ERC20Upgradeable {
 *     function initialize() initializer public {
 *         __ERC20_init("MyToken", "MTK");
 *     }
 * }
 *
 * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
 *     function initializeV2() reinitializer(2) public {
 *         __ERC20Permit_init("MyToken");
 *     }
 * }
 * ```
 *
 * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
 * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
 *
 * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
 * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
 *
 * [CAUTION]
 * ====
 * Avoid leaving a contract uninitialized.
 *
 * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
 * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
 * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
 *
 * [.hljs-theme-light.nopadding]
 * ```
 * /// @custom:oz-upgrades-unsafe-allow constructor
 * constructor() {
 *     _disableInitializers();
 * }
 * ```
 * ====
 */
abstract contract Initializable {
    /**
     * @dev Storage of the initializable contract.
     *
     * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
     * when using with upgradeable contracts.
     *
     * @custom:storage-location erc7201:openzeppelin.storage.Initializable
     */
    struct InitializableStorage {
        /**
         * @dev Indicates that the contract has been initialized.
         */
        uint64 _initialized;
        /**
         * @dev Indicates that the contract is in the process of being initialized.
         */
        bool _initializing;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;

    /**
     * @dev The contract is already initialized.
     */
    error InvalidInitialization();

    /**
     * @dev The contract is not initializing.
     */
    error NotInitializing();

    /**
     * @dev Triggered when the contract has been initialized or reinitialized.
     */
    event Initialized(uint64 version);

    /**
     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
     * `onlyInitializing` functions can be used to initialize parent contracts.
     *
     * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
     * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
     * production.
     *
     * Emits an {Initialized} event.
     */
    modifier initializer() {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        // Cache values to avoid duplicated sloads
        bool isTopLevelCall = !$._initializing;
        uint64 initialized = $._initialized;

        // Allowed calls:
        // - initialSetup: the contract is not in the initializing state and no previous version was
        //                 initialized
        // - construction: the contract is initialized at version 1 (no reininitialization) and the
        //                 current contract is just being deployed
        bool initialSetup = initialized == 0 && isTopLevelCall;
        bool construction = initialized == 1 && address(this).code.length == 0;

        if (!initialSetup && !construction) {
            revert InvalidInitialization();
        }
        $._initialized = 1;
        if (isTopLevelCall) {
            $._initializing = true;
        }
        _;
        if (isTopLevelCall) {
            $._initializing = false;
            emit Initialized(1);
        }
    }

    /**
     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
     * used to initialize parent contracts.
     *
     * A reinitializer may be used after the original initialization step. This is essential to configure modules that
     * are added through upgrades and that require initialization.
     *
     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
     * cannot be nested. If one is invoked in the context of another, execution will revert.
     *
     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
     * a contract, executing them in the right order is up to the developer or operator.
     *
     * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
     *
     * Emits an {Initialized} event.
     */
    modifier reinitializer(uint64 version) {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing || $._initialized >= version) {
            revert InvalidInitialization();
        }
        $._initialized = version;
        $._initializing = true;
        _;
        $._initializing = false;
        emit Initialized(version);
    }

    /**
     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
     * {initializer} and {reinitializer} modifiers, directly or indirectly.
     */
    modifier onlyInitializing() {
        _checkInitializing();
        _;
    }

    /**
     * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
     */
    function _checkInitializing() internal view virtual {
        if (!_isInitializing()) {
            revert NotInitializing();
        }
    }

    /**
     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
     * through proxies.
     *
     * Emits an {Initialized} event the first time it is successfully executed.
     */
    function _disableInitializers() internal virtual {
        // solhint-disable-next-line var-name-mixedcase
        InitializableStorage storage $ = _getInitializableStorage();

        if ($._initializing) {
            revert InvalidInitialization();
        }
        if ($._initialized != type(uint64).max) {
            $._initialized = type(uint64).max;
            emit Initialized(type(uint64).max);
        }
    }

    /**
     * @dev Returns the highest version that has been initialized. See {reinitializer}.
     */
    function _getInitializedVersion() internal view returns (uint64) {
        return _getInitializableStorage()._initialized;
    }

    /**
     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
     */
    function _isInitializing() internal view returns (bool) {
        return _getInitializableStorage()._initializing;
    }

    /**
     * @dev Returns a pointer to the storage namespace.
     */
    // solhint-disable-next-line var-name-mixedcase
    function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
        assembly {
            $.slot := INITIALIZABLE_STORAGE
        }
    }
}
ContextUpgradeable.sol 34 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract ContextUpgradeable is Initializable {
    function __Context_init() internal onlyInitializing {
    }

    function __Context_init_unchained() internal onlyInitializing {
    }
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
PausableUpgradeable.sol 140 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Pausable.sol)

pragma solidity ^0.8.20;

import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract PausableUpgradeable is Initializable, ContextUpgradeable {
    /// @custom:storage-location erc7201:openzeppelin.storage.Pausable
    struct PausableStorage {
        bool _paused;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Pausable")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant PausableStorageLocation = 0xcd5ed15c6e187e77e9aee88184c21f4f2182ab5827cb3b7e07fbedcd63f03300;

    function _getPausableStorage() private pure returns (PausableStorage storage $) {
        assembly {
            $.slot := PausableStorageLocation
        }
    }

    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    /**
     * @dev The operation failed because the contract is paused.
     */
    error EnforcedPause();

    /**
     * @dev The operation failed because the contract is not paused.
     */
    error ExpectedPause();

    /**
     * @dev Initializes the contract in unpaused state.
     */
    function __Pausable_init() internal onlyInitializing {
        __Pausable_init_unchained();
    }

    function __Pausable_init_unchained() internal onlyInitializing {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        _requireNotPaused();
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        _requirePaused();
        _;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        PausableStorage storage $ = _getPausableStorage();
        return $._paused;
    }

    /**
     * @dev Throws if the contract is paused.
     */
    function _requireNotPaused() internal view virtual {
        if (paused()) {
            revert EnforcedPause();
        }
    }

    /**
     * @dev Throws if the contract is not paused.
     */
    function _requirePaused() internal view virtual {
        if (!paused()) {
            revert ExpectedPause();
        }
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        PausableStorage storage $ = _getPausableStorage();
        $._paused = false;
        emit Unpaused(_msgSender());
    }
}
ReentrancyGuardUpgradeable.sol 105 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;
import {Initializable} from "../proxy/utils/Initializable.sol";

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuardUpgradeable is Initializable {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard
    struct ReentrancyGuardStorage {
        uint256 _status;
    }

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) {
        assembly {
            $.slot := ReentrancyGuardStorageLocation
        }
    }

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    function __ReentrancyGuard_init() internal onlyInitializing {
        __ReentrancyGuard_init_unchained();
    }

    function __ReentrancyGuard_init_unchained() internal onlyInitializing {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        $._status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if ($._status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        $._status = ENTERED;
    }

    function _nonReentrantAfter() private {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        $._status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage();
        return $._status == ENTERED;
    }
}
ERC165Upgradeable.sol 33 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
import {Initializable} from "../../proxy/utils/Initializable.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 */
abstract contract ERC165Upgradeable is Initializable, IERC165 {
    function __ERC165_init() internal onlyInitializing {
    }

    function __ERC165_init_unchained() internal onlyInitializing {
    }
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}
IAccessControl.sol 98 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

Read Contract

ACC_UNO_PRECISION 0x89919b71 → uint256
ADMIN_ROLE 0x75b238fc → bytes32
BOT_ROLE 0xb1503774 → bytes32
CLAIM_PROCESSOR_ROLE 0x078fa9bc → bytes32
DEFAULT_ADMIN_ROLE 0xa217fddf → bytes32
capitalAgent 0x42198160 → address
emergencyWithdrawAllowed 0xaceda7f9 → bool
getRoleAdmin 0x248a9ca3 → bytes32
getShareValue 0x6edd7590 → uint256
getStakedAmountPerUser 0xba619457 → uint256, uint256
getTotalWithdrawPendingAmount 0xa3bdd632 → uint256
getUserUSDMAmount 0xc321db57 → uint256
getWithdrawRequestPerUser 0x9336f406 → uint256, uint256, uint256, uint256
hasRole 0x91d14854 → bool
killed 0x1f3a0e41 → bool
lockTime 0x0d668087 → uint256
migrateTo 0x98c6e760 → address
paused 0x5c975abb → bool
pendingRewards 0x31d7a262 → uint256, uint256
pendingUno 0xe08c5de1 → uint256
policies 0xd3e89483 → uint256, address, bool
poolInfo 0x5a2f3d09 → uint256, uint256, uint256
rewarder 0xdcc3e06e → address
riskPool 0xc4e5dacf → address
roleLockTime 0xe0c8d9a5 → uint256
stakingStartTime 0x6abfd183 → uint256
supportsInterface 0x01ffc9a7 → bool
totalShares 0x3a98ef39 → uint256
userInfo 0x1959a002 → uint256, uint256, uint256, bool, uint256
userShares 0xde69b3aa → uint256

Write Contract 33 functions

These functions modify contract state and require a wallet transaction to execute.

cancelWithdrawRequest 0xe19e7168
No parameters
createRewarder 0xaf16d6e0
address _operator
address _factory
address _currency
createRiskPool 0xc3dcfcf1
string _name
string _symbol
address _factory
address _currency
uint256 _rewardMultiplier
uint256 _SCR
emergencyWithdraw 0xdb2e21bc
No parameters
enterInPool 0xe3824a38
uint256 _amount
grantRole 0x2f2ff15d
bytes32 role
address account
harvest 0x0e5c011e
address _to
initialize 0x485cc955
address _capitalAgent
address _multiSigWallet
killPool 0x7a39b8d8
No parameters
leaveFromPending 0xf1daf24c
uint256 _amount
leaveFromPoolInPending 0x8395206c
uint256 _amount
lpTransfer 0x0e9ae420
address _from
address _to
uint256 _amount
migrate 0x8fd3ab80
No parameters
pausePool 0xaa09d5b7
No parameters
renounceRole 0x36568abe
bytes32 role
address callerConfirmation
revivePool 0x67755415
No parameters
revokeRole 0xd547741f
bytes32 role
address account
rollOverReward 0xfd91db96
address[] _to
setAccUnoPerShare 0x0e2be506
uint256 _accUnoPerShare
uint256 _lastRewardBlock
setCapitalAgent 0xc2eb8eb9
address _capitalAgent
setLockTime 0xae04d45d
uint256 _lockTime
setLpPriceInRiskPool 0x0f4c3c4f
uint256 _lpPriceUno
setMigrateTo 0x736ec05c
address _migrateTo
setMinLPCapital 0x93b6b86c
uint256 _minLPCapital
setRewardMultiplier 0x0bd075a1
uint256 _rewardMultiplier
setRole 0xdff87203
bytes32 _role
address _account
setStakingStartTime 0x5d90bad9
uint256 _startTime
setUserDetails 0xc4d87fe2
address _user
uint256 _amount
uint256 _rewardDebt
settlePayout 0xfe30e7e6
uint256 _policyId
address _payout
uint256 _amount
toggleEmergencyWithdraw 0x093cf18f
No parameters
toggleRollOver 0x7da2a4a7
No parameters
unpausePool 0x068cc514
No parameters
updatePool 0xe3161ddd
No parameters

Recent Transactions

No transactions found for this address