Address Contract Verified
Address
0x267dF6b637DdCaa7763d94b64eBe09F01b07cB36
Balance
0 ETH
Nonce
1
Code Size
21233 bytes
Creator
0x44820497...3da3 at tx 0xb23f6561...1e873a
Indexed Transactions
0
Contract Bytecode
21233 bytes
0x60806040526004361015610011575f80fd5b5f5f3560e01c8062f714ce1461425757806306fdde031461410e5780630956e5a6146140d3578063095ea7b3146140265780630e84563414613fd557806316efd94114613f8457806318160ddd14613f495780631c30e68214613d4657806323b872dd14613bb25780632859398414613b5a5780632e8ebaae14613b145780632ed6b75d14613ac35780632f278fe81461389b5780633066bb271461384a578063313ce5671461375f57806333a100ca1461353957806339b70e38146134e7578063465fc5d2146134955780634956eaf0146130c15780634f5e80851461306f5780634f908e7f14612e7457806357c44f8e14612c5357806358e7544014612b6057806359746aab146128eb5780635c966646146127ca5780635d83f0931461278e5780635e1816551461264f57806361d027b3146125fd57806370a082311461259b57806375efcf77146124a257806378e808d5146124505780637a801f53146123fe5780637b9282b01461231857806382beee891461225a57806389fe02cb146122215780638c05b4721461202a578063958da91814611fc757806395d89b4114611e65578063999927df14611c5557806399f428cf146116ec5780639aefaff8146113fa578063a25db8ce146113b8578063a9059cbb14611368578063aec48f5014611251578063afa92945146111f8578063b6b55f2514610e83578063c0cbbca614610bfc578063c7c4ff4614610baa578063d211fd1814610b6e578063d574ea3d14610b00578063d8b5138a146109df578063dd62ed3e14610966578063e322ad2b14610925578063e357e92e14610740578063edf1d2b3146105d9578063f0f442601461048e578063f2c098b7146103a1578063f905c15a14610365578063fbe85f061461031e5763fc0c546a146102ad575f80fd5b3461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7168152f35b80fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602060043561035b614d99565b1015604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576020600554604051908152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576103d9614890565b73ffffffffffffffffffffffffffffffffffffffff60085416330361046657602073ffffffffffffffffffffffffffffffffffffffff7ff112f2fd3f9db4cbbd348d7d8948ad19988985c74b787d6f0fb8f62ba25f9e0e9216807fffffffffffffffffffffffff0000000000000000000000000000000000000000600e541617600e55604051908152a180f35b6004827f980bf844000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576104c6614890565b73ffffffffffffffffffffffffffffffffffffffff600a5416908133036105b15773ffffffffffffffffffffffffffffffffffffffff1690811561058957600b80547fffffffffffffffffffffffff0000000000000000000000000000000000000000811684179091556040805173ffffffffffffffffffffffffffffffffffffffff938416815291851690931790911660208201527f74826a97c225ebfc6ae4d01aa55f9846d00bb141717acca3947f3778534be5a191819081015b0390a180f35b6004837fed2a1062000000000000000000000000000000000000000000000000000000008152fd5b6004837f6b7bc451000000000000000000000000000000000000000000000000000000008152fd5b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5773ffffffffffffffffffffffffffffffffffffffff600854163314158061071e575b6106f657600b5473ffffffffffffffffffffffffffffffffffffffff8116801561058957600a54918173ffffffffffffffffffffffffffffffffffffffff8416146106ce577fffffffffffffffffffffffff00000000000000000000000000000000000000008084168317600a5516600b556040519183161781527f1f54d231bb9d500b1923e4a1cb25e600f366a8368873d9af7c1c623814df19fc90602090a180f35b6004847f281a0b0a000000000000000000000000000000000000000000000000000000008152fd5b807f7fa76e940000000000000000000000000000000000000000000000000000000060049252fd5b5073ffffffffffffffffffffffffffffffffffffffff6006541633141561062a565b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57610778614890565b60243591610784614fba565b73ffffffffffffffffffffffffffffffffffffffff6006541633036108fd576107ac82614a3a565b156108d557604051917fcb27acfd0000000000000000000000000000000000000000000000000000000083528360048401526020836024818573ffffffffffffffffffffffffffffffffffffffff86165af19283156108ca578293610891575b506040805133815273ffffffffffffffffffffffffffffffffffffffff909216602083810191909152908201949094527fb093bd21cacddf175c466449524962624f8edabfc8497212c45b6ce70c90bfe29080606081015b0390a17f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d604051908152f35b9092506020813d6020116108c2575b816108ad6020938361493b565b810103126108be575191602061080c565b5f80fd5b3d91506108a0565b6040513d84823e3d90fd5b807fe83f2cde0000000000000000000000000000000000000000000000000000000060049252fd5b807fbbab12130000000000000000000000000000000000000000000000000000000060049252fd5b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602061095e614d99565b604051908152f35b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5773ffffffffffffffffffffffffffffffffffffffff60406109b5614890565b92826109bf61486d565b9416815260016020522091165f52602052602060405f2054604051908152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57610a17614890565b73ffffffffffffffffffffffffffffffffffffffff6006541690813303610ad85773ffffffffffffffffffffffffffffffffffffffff1690811561058957600780547fffffffffffffffffffffffff0000000000000000000000000000000000000000811684179091556040805173ffffffffffffffffffffffffffffffffffffffff938416815291851690931790911660208201527f9199036abbe383a5a535e02e8f65421079bb3fa71d03495a107b8b0231b616f29181908101610583565b6004837fbbab1213000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576004359060105482101561031b57602073ffffffffffffffffffffffffffffffffffffffff610b5e846148f6565b90549060031b1c16604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576020600254604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff600e5416604051908152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5760043573ffffffffffffffffffffffffffffffffffffffff6008541633036104665760105480821015610e5b5773ffffffffffffffffffffffffffffffffffffffff610c77836148f6565b90549060031b1c169182845260116020526040842054610e33577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8201918211610e0657818103610da1575b50506010548015610d74577f206dcdb9e6d573bb19797ecdc31f426bc49808caf16879b86cee1ba682e3881f917fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6105839201610d1f816148f6565b73ffffffffffffffffffffffffffffffffffffffff82549160031b1b19169055601055604051918291338390929173ffffffffffffffffffffffffffffffffffffffff60209181604085019616845216910152565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526031600452fd5b610dd373ffffffffffffffffffffffffffffffffffffffff610dc5610dff946148f6565b90549060031b1c16916148f6565b90919073ffffffffffffffffffffffffffffffffffffffff8084549260031b9316831b921b1916179055565b5f80610cc3565b6024847f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004847fe83f2cde000000000000000000000000000000000000000000000000000000008152fd5b6004837f5979b5d3000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57600435610ebe614fba565b73ffffffffffffffffffffffffffffffffffffffff600d5416331415806111d6575b6111ae578015611186578173ffffffffffffffffffffffffffffffffffffffff600f5416806110cb575b505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7166040517f23b872dd00000000000000000000000000000000000000000000000000000000845233600452306024528260445260208460648180865af19060018551148216156110aa575b604052836060521561107f575033156110535761102a81610fd17fe1fffcc4923d04b559f4d29a8bfc6cda04eb5b0d3c460751c2402c5c5cc9109c93600254614aa0565b600255335f525f60205260405f208181540190556040518181525f7fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60203393a360408051338152602081019290925290918291820190565b0390a1807f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d80f35b6024827fec442f0500000000000000000000000000000000000000000000000000000000815280600452fd5b7f5274afe7000000000000000000000000000000000000000000000000000000008352600452602482fd5b9060018115166110c257823b15153d15161690610f8d565b503d84823e3d90fd5b6110d3614b0a565b90803b15611182576040517fa69fe8630000000000000000000000000000000000000000000000000000000081527f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff16600482015260248101859052604481019290925290919081908390606490829084905af1611167575b90610f0a565b6111709161493b565b815f1261117e575f82611161565b5080fd5b8280fd5b6004827f8dc3160f000000000000000000000000000000000000000000000000000000008152fd5b6004827f52644c18000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff600e5416331415610ee0565b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5760209060043590611237614d99565b90508181111561124a5750604051908152f35b905061095e565b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5773ffffffffffffffffffffffffffffffffffffffff600a541633141580611346575b6106f65760095473ffffffffffffffffffffffffffffffffffffffff8116801561058957600854918173ffffffffffffffffffffffffffffffffffffffff8416146106ce577fffffffffffffffffffffffff00000000000000000000000000000000000000008084168317600855166009556040519183161781527f1d71beb956329ce4bda4b6a3cf409eae37dca995fe985253f39c49f5dd3bf3c790602090a180f35b5073ffffffffffffffffffffffffffffffffffffffff600654163314156112a2565b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576113ad6113a3614890565b60243590336151c5565b602060405160018152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602061095e6113f5614890565b614c75565b503461031b5760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57611432614890565b61143a61486d565b906064359167ffffffffffffffff83116116e857366023840112156116e857826004013567ffffffffffffffff81116116e45736602482860101116116e45773ffffffffffffffffffffffffffffffffffffffff60065416331415806116c2575b61169a576114a883614a3a565b15611672579173ffffffffffffffffffffffffffffffffffffffff85816084602497957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f89869a6040519c8d9b8c9a8b977fb61d27f6000000000000000000000000000000000000000000000000000000008952166004880152604435828801526060604488015282606488015201868601378685828601015201168101030193165af19182156116665780918193611582575b505061157e604051928392151583526040602084015260408301906148b3565b0390f35b915091503d8083833e611595818361493b565b81019160408284031261031b576115ab826149a9565b9160208101519067ffffffffffffffff8211611182570183601f8201121561117e5780519067ffffffffffffffff8211611639576040519461161560207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f860116018761493b565b8286526020838301011161118257908060208093018387015e840101525f8061155e565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526041600452fd5b604051903d90823e3d90fd5b6004857fe83f2cde000000000000000000000000000000000000000000000000000000008152fd5b6004857f7158b7f3000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff600c541633141561149b565b8480fd5b8380fd5b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5760043561172761486d565b90611730614fba565b73ffffffffffffffffffffffffffffffffffffffff600d541633141580611c33575b611c0b578273ffffffffffffffffffffffffffffffffffffffff600f541680611af5575b5050809160105490826117e7575b505081611790916149d3565b906111865761102a817fe66f2a5f859e75187ec8381862cf2edc4124d6ea89f5fa1a7b66035121bd4461926117d8575b60408051338152602081019290925290918291820190565b6117e2813361502e565b6117c0565b91849391935b84811080611aec575b15611add57856024602073ffffffffffffffffffffffffffffffffffffffff61181e856148f6565b90549060031b1c16604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa9081156108ca578291611aa9575b5080156118e25784811115611aa45750835b602073ffffffffffffffffffffffffffffffffffffffff611898856148f6565b90549060031b1c166024604051809581937f1071a2900000000000000000000000000000000000000000000000000000000083528660048401525af1889281611a71575b506118f2575b50506118ed90614a0d565b6117ed565b81156118e257829473ffffffffffffffffffffffffffffffffffffffff61191c61198f94956148f6565b90549060031b1c168952601160205260408920548083115f14611a6a575b73ffffffffffffffffffffffffffffffffffffffff611958886148f6565b90549060031b1c168a52601160205260408a206119768282546149d3565b90556005549081811115611a59575050886005556149d3565b926004602073ffffffffffffffffffffffffffffffffffffffff6119b2846148f6565b90549060031b1c16604051928380927f5037b7e90000000000000000000000000000000000000000000000000000000082525afa928315611a4e578673ffffffffffffffffffffffffffffffffffffffff6118ed95611a19948c91611a20575b5016615104565b905f6118e2565b611a41915060203d8111611a47575b611a39818361493b565b810190614aad565b5f611a12565b503d611a2f565b6040513d8a823e3d90fd5b611a62916149d3565b6005556149d3565b508161193a565b9092506020813d8211611a9c575b81611a8c6020938361493b565b810103126108be5751915f6118dc565b3d9150611a7f565b611878565b9150506020813d8211611ad5575b81611ac46020938361493b565b810103126108be578690515f611866565b3d9150611ab7565b50819350611790925091611784565b508215156117f6565b611b80604091611b03614b0a565b83519485809481937f0f3482f4000000000000000000000000000000000000000000000000000000008352897f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec76004850160409194939273ffffffffffffffffffffffffffffffffffffffff606083019616825260208201520152565b03925af1908185918693611bd8575b50611b9d575b849150611776565b15611ba85780611b95565b83906044927f1bbc0205000000000000000000000000000000000000000000000000000000008352600452602452fd5b909250611bfd915060403d604011611c04575b611bf5818361493b565b8101906149b6565b915f611b8f565b503d611beb565b6004837f52644c18000000000000000000000000000000000000000000000000000000008152fd5b5073ffffffffffffffffffffffffffffffffffffffff600e5416331415611752565b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57611c8d614890565b9073ffffffffffffffffffffffffffffffffffffffff6006541633141580611e43575b611e1b57611cbd82614a3a565b156108d557602073ffffffffffffffffffffffffffffffffffffffff92602484600a54168460405196879485937f999927df0000000000000000000000000000000000000000000000000000000085526004850152165af1918215611e0e578192611dda575b508115611db2576020827ff3055bc8d92d9c8d2f12b45d112dd345cd2cfd17292b8d65c5642ac6f912dfd760405180611da7847f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7338473ffffffffffffffffffffffffffffffffffffffff6040929594938160608401971683521660208201520152565b0390a1604051908152f35b807f524b3c6c0000000000000000000000000000000000000000000000000000000060049252fd5b9091506020813d602011611e06575b81611df66020938361493b565b810103126108be5751905f611d23565b3d9150611de9565b50604051903d90823e3d90fd5b807f7158b7f30000000000000000000000000000000000000000000000000000000060049252fd5b5073ffffffffffffffffffffffffffffffffffffffff600c5416331415611cb0565b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576040519080600454908160011c91600181168015611fbd575b602084108114611f9057838652908115611f4b5750600114611eee575b61157e84611eda8186038261493b565b6040519182916020835260208301906148b3565b600481527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b939250905b808210611f3157509091508101602001611eda82611eca565b919260018160209254838588010152019101909291611f18565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208087019190915292151560051b85019092019250611eda9150839050611eca565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526022600452fd5b92607f1692611ead565b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57604060209173ffffffffffffffffffffffffffffffffffffffff612019614890565b168152601183522054604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57612061614fba565b73ffffffffffffffffffffffffffffffffffffffff60065416331415806121ff575b611e1b577f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec773ffffffffffffffffffffffffffffffffffffffff8116906040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa9081156121f45784916121c2575b50600254908181111561219a5792602094926121437fe33b3f29026207fc167007711d41e9edd78750b0051defa03f1e4ea002accd6a93612166966149d3565b9485809373ffffffffffffffffffffffffffffffffffffffff600a541690615104565b6040805133815273ffffffffffffffffffffffffffffffffffffffff90921660208301528101919091528060608101610864565b6004857f524b3c6c000000000000000000000000000000000000000000000000000000008152fd5b90506020813d6020116121ec575b816121dd6020938361493b565b810103126108be57515f612103565b3d91506121d0565b6040513d86823e3d90fd5b5073ffffffffffffffffffffffffffffffffffffffff600c5416331415612083565b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602061095e614b0a565b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57612292614890565b73ffffffffffffffffffffffffffffffffffffffff6008541633036104665773ffffffffffffffffffffffffffffffffffffffff16807fffffffffffffffffffffffff0000000000000000000000000000000000000000600f541617600f557f576d39e65c913b7fedc16b28e8563e891fb6d44bcf0c1c29495375595cd79b658280a280f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57604051907f70a0823100000000000000000000000000000000000000000000000000000000825230600483015260208260248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7165afa90811561166657906123cb575b602090604051908152f35b506020813d6020116123f6575b816123e56020938361493b565b810103126108be57602090516123c0565b3d91506123d8565b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff60075416604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff60065416604051908152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576124da614890565b73ffffffffffffffffffffffffffffffffffffffff6006541690813303610ad85773ffffffffffffffffffffffffffffffffffffffff1690811561058957600c80547fffffffffffffffffffffffff0000000000000000000000000000000000000000811684179091556040805173ffffffffffffffffffffffffffffffffffffffff938416815291851690931790911660208201527f68d1aa5e9bdbf0db52fe140cc136ad3a30d9010e7d2f048eaf1ab0dad87c59759181908101610583565b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57604060209173ffffffffffffffffffffffffffffffffffffffff6125ed614890565b1681528083522054604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff600a5416604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5773ffffffffffffffffffffffffffffffffffffffff600a54163314158061276c575b6127445760075473ffffffffffffffffffffffffffffffffffffffff8116801561058957600654918173ffffffffffffffffffffffffffffffffffffffff8416146106ce577fffffffffffffffffffffffff00000000000000000000000000000000000000008084168317600655166007556040519183161781527f6c6266c4ca096dc11256cb3c5a2f481d4ebfc848b647e04ba395e5e02cde9a1d90602090a180f35b807f7acfd5970000000000000000000000000000000000000000000000000000000060049252fd5b5073ffffffffffffffffffffffffffffffffffffffff600854163314156126a0565b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576020601354604051908152f35b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57612802614890565b73ffffffffffffffffffffffffffffffffffffffff60085416908133036128c35773ffffffffffffffffffffffffffffffffffffffff1690811561058957600980547fffffffffffffffffffffffff0000000000000000000000000000000000000000811684179091556040805173ffffffffffffffffffffffffffffffffffffffff938416815291851690931790911660208201527f229906f503462bb4f822a3a5c8a143331ba9ca0b25dd7de323cf57b842eb0c849181908101610583565b6004837f980bf844000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5760043567ffffffffffffffff811161117e573660238201121561117e5780600401359067ffffffffffffffff8211611182576024810190602436918460051b0101116111825773ffffffffffffffffffffffffffffffffffffffff6008541633036128c357601054808303612ae357835b818110612a5d5750835b818110612a1f575050604051918060208401602085525260408301919084905b8082106129e757857faaeeacfd3dbf7ee886e6df5ff129be2537f1886a93f3a104d6bba8b305fc52b186860387a180f35b90919283359073ffffffffffffffffffffffffffffffffffffffff82168092036108be576020816001938293520194019201906129b6565b80612a5773ffffffffffffffffffffffffffffffffffffffff612a4d612a486001958989614ad9565b614ae9565b16610dd3836148f6565b01612996565b612a73612a6e612a48838787614ad9565b614a3a565b15612b385760018101808211612b0b575b828110612a94575060010161298c565b612aa8612a48838787969997989598614ad9565b73ffffffffffffffffffffffffffffffffffffffff80612acc612a48858789614ad9565b16911614612ae35760010194919294939093612a84565b6004847f7804bc35000000000000000000000000000000000000000000000000000000008152fd5b6024867f4e487b710000000000000000000000000000000000000000000000000000000081526011600452fd5b6004857f7804bc35000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57612b98614890565b73ffffffffffffffffffffffffffffffffffffffff6008541633036104665773ffffffffffffffffffffffffffffffffffffffff168015612c2b576020817fcac43e3f2c27e1b165ed9d6100079705fcc1d17d86c9588a65b3b21af19efb55927fffffffffffffffffffffffff0000000000000000000000000000000000000000600d541617600d55604051908152a180f35b6004827fed2a1062000000000000000000000000000000000000000000000000000000008152fd5b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57612c8b614890565b612c93614fba565b73ffffffffffffffffffffffffffffffffffffffff600654163303612e4c57612cbb81614a3a565b15612e245773ffffffffffffffffffffffffffffffffffffffff8116604051917f2e1a7d4d000000000000000000000000000000000000000000000000000000008352602435600484015260208360248187865af19182156121f4578492612dd0575b808552601160205260408520547f77a629eef1a2b0e39a9b09a71ddafbded84fb873712d56f5b2f6b1e1706e266b945080841115612dc857905b8552601160205260408520612d6e8282546149d3565b90556005549081811115612db7575050836005555b6040805133815273ffffffffffffffffffffffffffffffffffffffff9092166020830152810191909152806060810161102a565b612dc0916149d3565b600555612d83565b508290612d58565b91506020833d602011612e1c575b81612deb6020938361493b565b810103126108be577f77a629eef1a2b0e39a9b09a71ddafbded84fb873712d56f5b2f6b1e1706e266b925191612d1e565b3d9150612dde565b6004827fe83f2cde000000000000000000000000000000000000000000000000000000008152fd5b6004827fbbab1213000000000000000000000000000000000000000000000000000000008152fd5b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b5773ffffffffffffffffffffffffffffffffffffffff600a541633036106f65773ffffffffffffffffffffffffffffffffffffffff601254168015612c2b57601354421061304757601054680100000000000000008110156116395790610dd3826001612f1294016010556148f6565b6008546012546040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301819052839290917f5196e6e427329801067f2d2174593bfbda5a246c506762f55fc401ee6084845e91a1803b15613044578180916024604051809581937f422570800000000000000000000000000000000000000000000000000000000083523060048401525af161302d575b601280547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560138190556008546040805173ffffffffffffffffffffffffffffffffffffffff928316815291831660208301527ffdcf3907978ffc608fc7f27e245c3d5d995700556bdc27685b2182a48b9b7e72919081908101610583565b6130369161493b565b805f1261031b575f81612fab565b50fd5b6004827fc2c1a34c000000000000000000000000000000000000000000000000000000008152fd5b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff600d5416604051908152f35b503461031b5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b576130f9614890565b602435613104614fba565b73ffffffffffffffffffffffffffffffffffffffff600654163303610ad85761312c82614a3a565b1561346d5773ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec716916040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481875afa8015613462578391869161342d575b501061340557604051927f095ea7b3000000000000000000000000000000000000000000000000000000005f5273ffffffffffffffffffffffffffffffffffffffff821693846004528360245260205f60448180865af19060015f51148216156133f6575b604052156132f6575b50823b156116e857836040517fb6b55f25000000000000000000000000000000000000000000000000000000008152836004820152818160248183895af180156108ca576132de575b50927fb03c53b28e78a88e31607a27e1fa48234dce28d5d9d9ec7b295aeb02e674a1e1935260116020526040842061329d838254614aa0565b90556132ab82600554614aa0565b6005556040805173ffffffffffffffffffffffffffffffffffffffff90921682526020820192909252908190810161102a565b906132e89161493b565b835f126116e857835f613264565b6040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52846004525f60245260205f60448180865af19060015f51148216156133de575b60405215613392576040517f095ea7b3000000000000000000000000000000000000000000000000000000005f52846004528360245260205f60448180865af19060015f51148216156133bd575b60405261321b575b7f5274afe7000000000000000000000000000000000000000000000000000000008552600452602484fd5b9060018115166133d557823b15153d1516169061338a565b503d5f823e3d90fd5b9060018115166133d557823b15153d1516169061333c565b90823b15153d15161690613212565b6004847f8dc3160f000000000000000000000000000000000000000000000000000000008152fd5b9150506020813d60201161345a575b816134496020938361493b565b810103126108be578290515f6131ad565b3d915061343c565b6040513d87823e3d90fd5b6004837fe83f2cde000000000000000000000000000000000000000000000000000000008152fd5b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff60125416604051908152f35b503461031b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261031b57602073ffffffffffffffffffffffffffffffffffffffff60085416604051908152f35b346108be5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57613570614890565b73ffffffffffffffffffffffffffffffffffffffff60085416908133036137375773ffffffffffffffffffffffffffffffffffffffff811690811561370f576135b890614a3a565b8015613665575b61363d57601280547fffffffffffffffffffffffff00000000000000000000000000000000000000001682179055426013556040805173ffffffffffffffffffffffffffffffffffffffff93841681529290911660208301527ffdcf3907978ffc608fc7f27e245c3d5d995700556bdc27685b2182a48b9b7e7291a1005b7fe83f2cde000000000000000000000000000000000000000000000000000000005f5260045ffd5b506040517ffc0c546a000000000000000000000000000000000000000000000000000000008152602081600481855afa908115613704575f916136e5575b5073ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec716911614156135bf565b6136fe915060203d602011611a4757611a39818361493b565b836136a3565b6040513d5f823e3d90fd5b7fed2a1062000000000000000000000000000000000000000000000000000000005f5260045ffd5b7f980bf844000000000000000000000000000000000000000000000000000000005f5260045ffd5b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be576040517f313ce56700000000000000000000000000000000000000000000000000000000815260208160048173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7165afa8015613704575f9061380d575b60209060ff60405191168152f35b506020813d602011613842575b816138276020938361493b565b810103126108be575160ff811681036108be576020906137ff565b3d915061381a565b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57602073ffffffffffffffffffffffffffffffffffffffff600c5416604051908152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be5773ffffffffffffffffffffffffffffffffffffffff6006541633141580613aa1575b613a79575f60105473ffffffffffffffffffffffffffffffffffffffff600a5416905f915b8183106139c35783801561399b576020907ff3055bc8d92d9c8d2f12b45d112dd345cd2cfd17292b8d65c5642ac6f912dfd760405180611da7847f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7338473ffffffffffffffffffffffffffffffffffffffff6040929594938160608401971683521660208201520152565b7f524b3c6c000000000000000000000000000000000000000000000000000000005f5260045ffd5b9091925f602073ffffffffffffffffffffffffffffffffffffffff6139e7876148f6565b90549060031b1c166024604051809481937f999927df0000000000000000000000000000000000000000000000000000000083528860048401525af1908115613704575f91613a47575b50613a3e90600192614aa0565b93019190613910565b90506020813d8211613a71575b81613a616020938361493b565b810103126108be57516001613a31565b3d9150613a54565b7f7158b7f3000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff600c54163314156138eb565b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57602073ffffffffffffffffffffffffffffffffffffffff600b5416604051908152f35b346108be5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be576020613b50612a6e614890565b6040519015158152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57613b90614b0a565b6002549081811115613ba85760209161095e916149d3565b505060205f61095e565b346108be5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57613be9614890565b613bf161486d565b6044359073ffffffffffffffffffffffffffffffffffffffff831692835f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f5260205260405f20547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110613c6d575b506113ad93506151c5565b838110613d12578415613ce6573315613cba576113ad945f52600160205260405f2073ffffffffffffffffffffffffffffffffffffffff33165f526020528360405f209103905584613c62565b7f94280d62000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b7fe602df05000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b83907ffb8f41b2000000000000000000000000000000000000000000000000000000005f523360045260245260445260645ffd5b346108be5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57613d7d614890565b613d85614fba565b73ffffffffffffffffffffffffffffffffffffffff600654163303613f2157613dad81614a3a565b1561363d5773ffffffffffffffffffffffffffffffffffffffff811690604051907fcdbb2fb400000000000000000000000000000000000000000000000000000000825260243560048301526020826024815f875af1918215613704575f92613eec575b50817f77a629eef1a2b0e39a9b09a71ddafbded84fb873712d56f5b2f6b1e1706e266b91846020955f526011865260405f20548084115f14613ee457905b5f526011865260405f20613e648282546149d3565b90556005549081811115613ed35750505f6005555b6040805133815273ffffffffffffffffffffffffffffffffffffffff929092166020830152810191909152606090a15f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d604051908152f35b613edc916149d3565b600555613e79565b508290613e4f565b9091506020813d602011613f19575b81613f086020938361493b565b810103126108be5751906020613e11565b3d9150613efb565b7fbbab1213000000000000000000000000000000000000000000000000000000005f5260045ffd5b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be576020600254604051908152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57602073ffffffffffffffffffffffffffffffffffffffff600f5416604051908152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be57602073ffffffffffffffffffffffffffffffffffffffff60095416604051908152f35b346108be5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be5761405d614890565b602435903315613ce65773ffffffffffffffffffffffffffffffffffffffff16908115613cba57335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be576020601054604051908152f35b346108be575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be576040515f6003548060011c9060018116801561424d575b602083108114614220578285529081156141de5750600114614180575b61157e83611eda8185038261493b565b91905060035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b915f905b8082106141c457509091508101602001611eda614170565b9192600181602092548385880101520191019092916141ac565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660208086019190915291151560051b84019091019150611eda9050614170565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b91607f1691614153565b346108be5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126108be5760043561429161486d565b9061429a614fba565b73ffffffffffffffffffffffffffffffffffffffff600d54163314158061484b575b6148235773ffffffffffffffffffffffffffffffffffffffff600f54168061479c575b50809173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec716906040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481865afa908115613704575f9161476a575b5080614743575b50601054925f5b8481108061473a575b15614669576024602073ffffffffffffffffffffffffffffffffffffffff61439b846148f6565b90549060031b1c16604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa5f9181614636575b506143f157506143ec90614a0d565b61436b565b80156144e757602073ffffffffffffffffffffffffffffffffffffffff614417846148f6565b90549060031b1c16916024604051809481937fafa9294500000000000000000000000000000000000000000000000000000000835260048301525afa5f9181614603575b5061446a57506143ec90614a0d565b80156144e757868111156145fa57505f6020875b602473ffffffffffffffffffffffffffffffffffffffff61449e866148f6565b90549060031b1c169160405194859384927f2e1a7d4d00000000000000000000000000000000000000000000000000000000845260048401525af15f91816145c7575b506144f1575b506143ec90614a0d565b80156144e757909573ffffffffffffffffffffffffffffffffffffffff614517886148f6565b90549060031b1c165f52601160205260405f20548083115f146145c0575b73ffffffffffffffffffffffffffffffffffffffff614553896148f6565b90549060031b1c165f52601160205260405f206145718282546149d3565b905560055490818111156145af5750505f6005555b8082111561459c5750506143ec5f955b906144e7565b6143ec916145a9916149d3565b95614596565b6145b8916149d3565b600555614586565b5081614535565b9091506020813d82116145f2575b816145e26020938361493b565b810103126108be575190886144e1565b3d91506145d5565b60205f9161447e565b9091506020813d821161462e575b8161461e6020938361493b565b810103126108be5751908861445b565b3d9150614611565b9091506020813d8211614661575b816146516020938361493b565b810103126108be575190886143dd565b3d9150614644565b506146758580926149d3565b90614712577f884edad9ce6fa2440d8a54cc123490eb96d2768479d49ff9c7366125a942436492816146ca9381151580614703575b6146f2575b50506040805133815260208101939093529192839283019150565b0390a15f7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d005b6146fb92615104565b8381816146af565b61470d833361502e565b6146aa565b7f8dc3160f000000000000000000000000000000000000000000000000000000005f5260045ffd5b50851515614374565b90935082811115614761575061475a825b836149d3565b9284614364565b61475a90614754565b90506020813d602011614794575b816147856020938361493b565b810103126108be57518561435d565b3d9150614778565b60406147ab5f92611b03614b0a565b03925af190815f915f93614800575b506147c6575b506142df565b156147d157806147c0565b907f1bbc0205000000000000000000000000000000000000000000000000000000005f5260045260245260445ffd5b90925061481c915060403d604011611c0457611bf5818361493b565b91856147ba565b7f52644c18000000000000000000000000000000000000000000000000000000005f5260045ffd5b5073ffffffffffffffffffffffffffffffffffffffff600e54163314156142bc565b6024359073ffffffffffffffffffffffffffffffffffffffff821682036108be57565b6004359073ffffffffffffffffffffffffffffffffffffffff821682036108be57565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f602080948051918291828752018686015e5f8582860101520116010190565b60105481101561490e5760105f5260205f2001905f90565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761497c57604052565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b519081151582036108be57565b91908260409103126108be5760206149cd836149a9565b92015190565b919082039182116149e057565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146149e05760010190565b601054905f5b828110614a4e575050505f90565b73ffffffffffffffffffffffffffffffffffffffff614a6c826148f6565b90549060031b1c1673ffffffffffffffffffffffffffffffffffffffff831614614a9857600101614a40565b505050600190565b919082018092116149e057565b908160209103126108be575173ffffffffffffffffffffffffffffffffffffffff811681036108be5790565b919081101561490e5760051b0190565b3573ffffffffffffffffffffffffffffffffffffffff811681036108be5790565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7165afa908115613704575f91614c43575b50906010545f905b808210614b96575050565b90926004602073ffffffffffffffffffffffffffffffffffffffff614bba876148f6565b90549060031b1c16604051928380927f89fe02cb0000000000000000000000000000000000000000000000000000000082525afa908115613704575f91614c11575b50614c0990600192614aa0565b930190614b8b565b90506020813d8211614c3b575b81614c2b6020938361493b565b810103126108be57516001614bfc565b3d9150614c1e565b90506020813d602011614c6d575b81614c5e6020938361493b565b810103126108be57515f614b83565b3d9150614c51565b614c7e81614a3a565b15614d945773ffffffffffffffffffffffffffffffffffffffff166040517f70a08231000000000000000000000000000000000000000000000000000000008152306004820152602081602481855afa5f9181614d60575b50614ce15750505f90565b6020906024604051809481937fafa9294500000000000000000000000000000000000000000000000000000000835260048301525afa5f9181614d2c575b50614d2957505f90565b90565b9091506020813d602011614d58575b81614d486020938361493b565b810103126108be5751905f614d1f565b3d9150614d3b565b9091506020813d602011614d8c575b81614d7c6020938361493b565b810103126108be5751905f614cd6565b3d9150614d6f565b505f90565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015260208160248173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7165afa908115613704575f91614f88575b50906010545f5b818110614e24575050565b6024602073ffffffffffffffffffffffffffffffffffffffff614e46846148f6565b90549060031b1c16604051928380927f70a082310000000000000000000000000000000000000000000000000000000082523060048301525afa5f9181614f55575b50614f5057505f5b80614e9f575b50600101614e19565b602073ffffffffffffffffffffffffffffffffffffffff614ebf846148f6565b90549060031b1c16916024604051809481937fafa9294500000000000000000000000000000000000000000000000000000000835260048301525afa5f9181614f1d575b5015614e9657614f169060019295614aa0565b9390614e96565b9091506020813d8211614f48575b81614f386020938361493b565b810103126108be5751905f614f03565b3d9150614f2b565b614e90565b9091506020813d8211614f80575b81614f706020938361493b565b810103126108be5751905f614e88565b3d9150614f63565b90506020813d602011614fb2575b81614fa36020938361493b565b810103126108be57515f614e12565b3d9150614f96565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005c6150065760017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f005d565b7f3ee5aeb5000000000000000000000000000000000000000000000000000000005f5260045ffd5b90919073ffffffffffffffffffffffffffffffffffffffff1680156150d857805f525f60205260405f20548381106150a5576020845f94957fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef938587528684520360408620558060025403600255604051908152a3565b91507fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7f96c6fd1e000000000000000000000000000000000000000000000000000000005f525f60045260245ffd5b9173ffffffffffffffffffffffffffffffffffffffff604051927fa9059cbb000000000000000000000000000000000000000000000000000000005f521660045260245260205f60448180865af19060015f51148216156151ad575b6040521561516b5750565b73ffffffffffffffffffffffffffffffffffffffff907f5274afe7000000000000000000000000000000000000000000000000000000005f521660045260245ffd5b9060018115166133d557823b15153d15161690615160565b73ffffffffffffffffffffffffffffffffffffffff169081156150d85773ffffffffffffffffffffffffffffffffffffffff1691821561528f57815f525f60205260405f205481811061525d57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b827fe450d38c000000000000000000000000000000000000000000000000000000005f5260045260245260445260645ffd5b7fec442f05000000000000000000000000000000000000000000000000000000005f525f60045260245ffdfea26469706673582212202b2f502bd8af25582f02c831c71eeffe0cd4319de27ac1eaf3ca6c7d2bf3857b64736f6c634300081e0033
Verified Source Code Full Match
Compiler: v0.8.30+commit.73712a01
EVM: cancun
Optimization: Yes (999999 runs)
ftYieldWrapper.sol 745 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {
IERC20Metadata,
IERC20
} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuardTransient} from "@openzeppelin/contracts/utils/ReentrancyGuardTransient.sol";
import {IStrategy, IStrategyWithQueue} from "./interfaces/IStrategy.sol";
import {IftYieldWrapper} from "./interfaces/IftYieldWrapper.sol";
import {ICircuitBreaker} from "./interfaces/ICircuitBreaker.sol";
// Single asset per chain wrapper
contract ftYieldWrapper is IftYieldWrapper, ERC20, ReentrancyGuardTransient {
using SafeERC20 for IERC20;
using SafeERC20 for IERC20Metadata;
uint256 public deployed; // default to 0
address public immutable token;
address public yieldClaimer;
address public pendingYieldClaimer;
address public strategyManager;
address public pendingStrategyManager;
address public treasury;
address public pendingTreasury;
address public subYieldClaimer;
address public putManager;
address public depositor;
address public circuitBreaker;
IStrategy[] public strategies;
mapping(address strategy => uint256 deployed) public deployedToStrategy;
// must be submitted by strategyManager
address public pendingStrategy;
uint256 public delayStrategy;
uint256 internal constant DELAY = 0; // 1 days in production
event Deployed(address strategy, uint256 allocation);
event YieldClaimed(address yieldClaimer, address token, uint256 amount);
event Deposit(address owner, uint256 amount);
event Withdraw(address owner, uint256 amount);
event WithdrawUnderlying(address owner, uint256 amount);
event QueuedToWrapper(address strategyManager, address strategy, uint256 amount);
event WithdrawToWrapper(address strategyManager, address strategy, uint256 amount);
event PendingYieldClaimer(address yieldClaimer, address pendingYieldClaimer);
event PendingStrategyManager(address strategyManager, address pendingStrategyManager);
event PendingTreasury(address treasury, address pendingTreasuy);
event PendingStrategy(address strategyManager, address pendingStrategy);
event UpdateYieldClaimer(address newYieldClaimer);
event UpdateStrategyManager(address newStrategyManager);
event UpdateTreasury(address newTreasury);
event UpdateSubYieldClaimer(address yieldClaimer, address subYieldClaimer);
event UpdatePutManager(address newPutManager);
event UpdateDepositor(address newDepositor);
event AddedStrategy(address strategyManager, address strategy);
event RemovedStrategy(address strategyManager, address strategy);
event StrategiesReordered(address[] newOrder);
event YieldSwept(address caller, address token, uint256 amount);
event CircuitBreakerUpdated(address indexed newCircuitBreaker);
error ftYieldWrapperInsufficientLiquidity();
error ftYieldWrapperNotYieldClaimer();
error ftYieldWrapperNotYieldClaimers();
error ftYieldWrapperDelayNotExpired();
error ftYieldWrapperNotStrategyManager();
error ftYieldWrapperZeroAddress();
error ftYieldWrapperNotSetter();
error ftYieldWrapperNotConfirmer();
error ftYieldWrapperNotYieldClaimConfirmer();
error ftYieldWrapperSettingUnchanged();
error ftYieldWrapperNotStrategy();
error ftYieldWrapperNoYield();
error ftYieldWrapperInvalidStrategyIndex();
error ftYieldWrapperInvalidStrategiesOrder();
error ftYieldWrapperNotPutManagerOrDepositor();
error ftYieldWrapperRateLimitExceeded(uint256 requested, uint256 available);
modifier onlyYieldClaimer() {
if (msg.sender != yieldClaimer) revert ftYieldWrapperNotYieldClaimer();
_;
}
modifier onlyStrategyManager() {
if (msg.sender != strategyManager) {
revert ftYieldWrapperNotStrategyManager();
}
_;
}
modifier onlyYieldClaimers() {
if (msg.sender != yieldClaimer && msg.sender != subYieldClaimer) {
revert ftYieldWrapperNotYieldClaimers();
}
_;
}
modifier onlyPutManagerOrDepositor() {
if (msg.sender != putManager && msg.sender != depositor) {
revert ftYieldWrapperNotPutManagerOrDepositor();
}
_;
}
constructor(
address _token,
address _yieldClaimer,
address _strategyManager,
address _treasury
)
ERC20(
string.concat("Flying Tulip ", IERC20Metadata(_token).name()),
string.concat("ft", IERC20Metadata(_token).symbol())
)
{
if (_token == address(0x0)) revert ftYieldWrapperZeroAddress();
if (_yieldClaimer == address(0x0)) revert ftYieldWrapperZeroAddress();
if (_strategyManager == address(0x0)) {
revert ftYieldWrapperZeroAddress();
}
if (_treasury == address(0x0)) revert ftYieldWrapperZeroAddress();
token = _token;
yieldClaimer = _yieldClaimer;
strategyManager = _strategyManager;
treasury = _treasury;
// putManager defaults to 0x0
// depositor defaults to 0x0
emit Transfer(address(0x0), address(this), 0);
}
function setYieldClaimer(address _yieldClaimer) external onlyYieldClaimer {
if (_yieldClaimer == address(0x0)) revert ftYieldWrapperZeroAddress();
pendingYieldClaimer = _yieldClaimer;
emit PendingYieldClaimer(yieldClaimer, pendingYieldClaimer);
}
function setSubYieldClaimer(address _subYieldClaimer) external onlyYieldClaimer {
if (_subYieldClaimer == address(0x0)) {
revert ftYieldWrapperZeroAddress();
}
subYieldClaimer = _subYieldClaimer;
emit UpdateSubYieldClaimer(yieldClaimer, subYieldClaimer);
}
function confirmYieldClaimer() external {
if (msg.sender != treasury && msg.sender != strategyManager) {
revert ftYieldWrapperNotYieldClaimConfirmer();
}
if (pendingYieldClaimer == address(0x0)) {
revert ftYieldWrapperZeroAddress();
}
if (yieldClaimer == pendingYieldClaimer) {
revert ftYieldWrapperSettingUnchanged();
}
yieldClaimer = pendingYieldClaimer;
pendingYieldClaimer = address(0x0);
emit UpdateYieldClaimer(yieldClaimer);
}
function setStrategyManager(address _strategyManager) external onlyStrategyManager {
if (_strategyManager == address(0x0)) {
revert ftYieldWrapperZeroAddress();
}
pendingStrategyManager = _strategyManager;
emit PendingStrategyManager(strategyManager, pendingStrategyManager);
}
function confirmStrategyManager() external {
if (msg.sender != treasury && msg.sender != yieldClaimer) {
revert ftYieldWrapperNotConfirmer();
}
if (pendingStrategyManager == address(0x0)) {
revert ftYieldWrapperZeroAddress();
}
if (strategyManager == pendingStrategyManager) {
revert ftYieldWrapperSettingUnchanged();
}
strategyManager = pendingStrategyManager;
pendingStrategyManager = address(0x0);
emit UpdateStrategyManager(strategyManager);
}
function setTreasury(address _treasury) external {
if (msg.sender != treasury) revert ftYieldWrapperNotSetter();
if (_treasury == address(0x0)) revert ftYieldWrapperZeroAddress();
pendingTreasury = _treasury;
emit PendingTreasury(treasury, pendingTreasury);
}
function confirmTreasury() external {
if (msg.sender != strategyManager && msg.sender != yieldClaimer) {
revert ftYieldWrapperNotConfirmer();
}
if (pendingTreasury == address(0x0)) revert ftYieldWrapperZeroAddress();
if (treasury == pendingTreasury) {
revert ftYieldWrapperSettingUnchanged();
}
treasury = pendingTreasury;
pendingTreasury = address(0x0);
emit UpdateTreasury(treasury);
}
function setPutManager(address _putManager) external onlyStrategyManager {
if (_putManager == address(0x0)) revert ftYieldWrapperZeroAddress();
putManager = _putManager;
emit UpdatePutManager(_putManager);
}
function setDepositor(address _depositor) external onlyStrategyManager {
depositor = _depositor;
emit UpdateDepositor(_depositor);
}
/// @notice Set or disable the circuit breaker
/// @dev Only callable by strategy manager. Set to address(0) to disable.
/// @param _circuitBreaker Address of circuit breaker, or address(0) to disable
function setCircuitBreaker(address _circuitBreaker) external onlyStrategyManager {
circuitBreaker = _circuitBreaker;
emit CircuitBreakerUpdated(_circuitBreaker);
}
function setStrategy(address _strategy) external onlyStrategyManager {
if (_strategy == address(0x0)) revert ftYieldWrapperZeroAddress();
if (isStrategy(_strategy) || IStrategy(_strategy).token() != token) {
revert ftYieldWrapperNotStrategy();
}
uint256 effectiveTime = block.timestamp + DELAY;
pendingStrategy = _strategy;
delayStrategy = effectiveTime;
emit PendingStrategy(strategyManager, pendingStrategy);
}
function confirmStrategy() external {
if (msg.sender != treasury) revert ftYieldWrapperNotConfirmer();
if (pendingStrategy == address(0x0)) revert ftYieldWrapperZeroAddress();
if (delayStrategy > block.timestamp) revert ftYieldWrapperDelayNotExpired();
strategies.push(IStrategy(pendingStrategy));
emit AddedStrategy(strategyManager, pendingStrategy);
// Ensure strategy wrapper pointer is set (no-op if already this wrapper)
try IStrategy(pendingStrategy).setftYieldWrapper(address(this)) {
// ok
}
catch {
// strategies are expected to support this; ignore to avoid bricking
}
pendingStrategy = address(0x0);
delayStrategy = 0;
emit PendingStrategy(strategyManager, pendingStrategy);
}
/// @notice Remove a strategy whose wrapper share balance is zero.
function removeStrategy(uint256 index) external onlyStrategyManager {
uint256 len = strategies.length;
if (index >= len) {
revert ftYieldWrapperInvalidStrategyIndex();
}
IStrategy s = strategies[index];
if (deployedToStrategy[address(s)] != 0) {
revert ftYieldWrapperNotStrategy();
}
address removed = address(s);
// swap & pop
if (index != len - 1) {
strategies[index] = strategies[len - 1];
}
strategies.pop();
emit RemovedStrategy(msg.sender, removed);
}
/**
* @dev Check if an address is a registered strategy
* @param _strategy The address to check
* @return bool True if the address is a registered strategy, false otherwise
*/
function isStrategy(address _strategy) public view returns (bool) {
uint256 strategiesLength = strategies.length;
for (uint256 i = 0; i < strategiesLength; i++) {
if (address(strategies[i]) == _strategy) return true;
}
return false;
}
/**
* @dev Reorder strategies for withdrawal priority
* @notice Can only be called by strategy manager
* @param _newOrder Array of strategy addresses in the desired order
*/
function setStrategiesOrder(address[] calldata _newOrder) external onlyStrategyManager {
uint256 currentLength = strategies.length;
// Check that array sizes match
if (_newOrder.length != currentLength) {
revert ftYieldWrapperInvalidStrategiesOrder();
}
// Verify all addresses are existing strategies and check for duplicates
for (uint256 i = 0; i < currentLength; i++) {
if (!isStrategy(_newOrder[i])) {
revert ftYieldWrapperInvalidStrategiesOrder();
}
// Check for duplicates
for (uint256 j = i + 1; j < currentLength; j++) {
if (_newOrder[i] == _newOrder[j]) {
revert ftYieldWrapperInvalidStrategiesOrder();
}
}
}
// Update strategies array with new order
for (uint256 i = 0; i < currentLength; i++) {
strategies[i] = IStrategy(_newOrder[i]);
}
emit StrategiesReordered(_newOrder);
}
/**
* @dev Claim yield from a specific strategy
* @notice Can only be called by registered strategies
* @param _strategy The strategy to claim yield from
* @return _yield The amount of yield claimed
*/
function claimYield(address _strategy) external onlyYieldClaimers returns (uint256 _yield) {
if (!isStrategy(_strategy)) revert ftYieldWrapperNotStrategy();
_yield = IStrategy(_strategy).claimYield(treasury);
if (_yield == 0) revert ftYieldWrapperNoYield();
emit YieldClaimed(msg.sender, address(token), _yield);
}
/**
* @dev Claim yield from all registered strategies
* @return _yield The total amount of yield claimed
*/
function claimYields() external onlyYieldClaimers returns (uint256 _yield) {
uint256 strategiesLength = strategies.length;
address _treasury = treasury;
for (uint256 i = 0; i < strategiesLength; i++) {
_yield += IStrategy(strategies[i]).claimYield(_treasury);
}
if (_yield == 0) revert ftYieldWrapperNoYield();
emit YieldClaimed(msg.sender, address(token), _yield);
}
function sweepIdleYield() external nonReentrant onlyYieldClaimers returns (uint256 amount) {
uint256 idleBalance = IERC20(token).balanceOf(address(this));
uint256 liabilities = totalSupply();
if (idleBalance <= liabilities) revert ftYieldWrapperNoYield();
amount = idleBalance - liabilities;
IERC20(token).safeTransfer(treasury, amount);
emit YieldSwept(msg.sender, address(token), amount);
}
function execute(
address _strategy,
address to,
uint256 value,
bytes calldata data
)
external
onlyYieldClaimers
returns (bool success, bytes memory result)
{
if (!isStrategy(_strategy)) revert ftYieldWrapperNotStrategy();
return IStrategy(_strategy).execute(to, value, data);
}
/**
* @dev Get the number of registered strategies
* @return uint The number of strategies
*/
function numberOfStrategies() external view returns (uint256) {
return strategies.length;
}
// simply a 1:1 mapping of capital provided
/**
* @dev Get the total capital managed by the wrapper
* @notice This is equal to totalSupply() of the wrapper token
* @return uint The total capital (in underlying token) managed by the wrapper
*/
function capital() external view returns (uint256) {
return totalSupply();
}
// capital + yield
function valueOfCapital() public view returns (uint256 _capital) {
_capital = IERC20(token).balanceOf(address(this));
uint256 strategiesLength = strategies.length;
for (uint256 i = 0; i < strategiesLength; i++) {
_capital += strategies[i].valueOfCapital();
}
}
function yield() public view returns (uint256) {
uint256 _capital = valueOfCapital();
uint256 _totalSupply = totalSupply();
return (_capital > _totalSupply) ? (_capital - _totalSupply) : 0;
}
// helper functions for strategy management
function availableToWithdraw(address strategy) public view returns (uint256 liquidity) {
// Only consider registered strategies; unrecognized addresses return zero
if (!isStrategy(strategy)) return 0;
// Defensive: treat failing strategies as having zero liquidity
uint256 shares;
try IStrategy(strategy).balanceOf(address(this)) returns (uint256 sb) {
shares = sb;
} catch {
return 0;
}
try IStrategy(strategy).maxAbleToWithdraw(shares) returns (uint256 m) {
liquidity = m;
} catch {
return 0;
}
}
// helper functions for put servicing
function availableToWithdraw() public view returns (uint256 liquidity) {
liquidity = IERC20(token).balanceOf(address(this));
uint256 strategiesLength = strategies.length;
for (uint256 i = 0; i < strategiesLength; i++) {
// Defensive view calls
uint256 shares;
try strategies[i].balanceOf(address(this)) returns (uint256 sb) {
shares = sb;
} catch {
shares = 0;
}
if (shares != 0) {
try strategies[i].maxAbleToWithdraw(shares) returns (uint256 m) {
liquidity += m;
} catch {
// treat as zero
}
}
}
}
function canWithdraw(uint256 amount) external view returns (bool) {
// NOTE: returns availability in underlying only (does not count position-token fallback)
return (availableToWithdraw() >= amount);
}
function maxAbleToWithdraw(uint256 amount) external view returns (uint256) {
uint256 _liquidity = availableToWithdraw();
return _liquidity > amount ? amount : _liquidity;
}
/**
* @dev Deposit underlying tokens into the wrapper and receive wrapper tokens
* @param amount The amount of underlying tokens to deposit
* @notice Mints wrapper tokens to the depositor based on the amount of underlying tokens deposited
* @notice we do not support fee on transfer tokens
* @notice this is simply a 1:1 mapping of capital provided, it does not provide a share
*/
function deposit(uint256 amount) external nonReentrant onlyPutManagerOrDepositor {
if (amount == 0) revert ftYieldWrapperInsufficientLiquidity();
// Circuit breaker: record inflow (fail-open)
address _cb = circuitBreaker;
if (_cb != address(0)) {
uint256 preTvl = valueOfCapital();
try ICircuitBreaker(_cb).recordInflow(token, amount, preTvl) {} catch {}
}
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
_mint(msg.sender, amount);
emit Deposit(msg.sender, amount);
}
function withdraw(uint256 amount, address to) external nonReentrant onlyPutManagerOrDepositor {
// Circuit breaker: check rate limit (fail-open)
address _cb = circuitBreaker;
if (_cb != address(0)) {
uint256 preTvl = valueOfCapital();
try ICircuitBreaker(_cb).checkAndRecordOutflow(token, amount, preTvl) returns (
bool allowed, uint256 available
) {
if (!allowed) {
revert ftYieldWrapperRateLimitExceeded(amount, available);
}
} catch {}
}
uint256 initialTarget = amount;
uint256 remaining = amount;
// 1) Use idle underlying on the wrapper first (accumulate, transfer at end)
uint256 idle = IERC20(token).balanceOf(address(this));
if (idle != 0) {
uint256 toTake = idle > remaining ? remaining : idle;
remaining -= toTake;
}
// 2) Drain strategies in order
uint256 _strategiesLength = strategies.length;
for (uint256 i = 0; i < _strategiesLength && remaining != 0; i++) {
// Check available liquidity for this strategy (defensive)
uint256 shareBal;
try strategies[i].balanceOf(address(this)) returns (uint256 sb) {
shareBal = sb;
} catch {
continue;
}
if (shareBal == 0) {
continue;
}
uint256 avail;
try strategies[i].maxAbleToWithdraw(shareBal) returns (uint256 m) {
avail = m;
} catch {
continue;
}
if (avail == 0) {
continue;
}
// Withdraw what we can from this strategy
uint256 toRequest = avail > remaining ? remaining : avail;
try strategies[i].withdraw(toRequest) returns (uint256 received) {
if (received != 0) {
// Protect against underflow if strategy returns more than deployed
uint256 currentDeployed = deployedToStrategy[address(strategies[i])];
uint256 toReduce = received > currentDeployed ? currentDeployed : received;
deployedToStrategy[address(strategies[i])] -= toReduce;
// Also cap the global deployed reduction
if (toReduce > deployed) {
deployed = 0;
} else {
deployed -= toReduce;
}
// Cap remaining reduction to avoid underflow
if (received > remaining) {
remaining = 0;
} else {
remaining -= received;
}
}
} catch {
// Skip failing strategies and continue
}
}
uint256 totalDelivered = initialTarget - remaining;
if (remaining != 0) {
revert ftYieldWrapperInsufficientLiquidity();
}
// Burn shares equal to what was actually delivered (no-op if zero)
if (totalDelivered != 0) {
_burn(msg.sender, totalDelivered);
}
// Single transfer at end (clamp to exact requested amount)
// Defensive: in case any strategy returned more than requested,
// only transfer exactly what was requested overall.
if (totalDelivered != 0) {
IERC20(token).safeTransfer(to, totalDelivered);
}
emit Withdraw(msg.sender, totalDelivered);
}
function withdrawUnderlying(
uint256 amount,
address to
)
external
nonReentrant
onlyPutManagerOrDepositor
{
// Circuit breaker: check rate limit (fail-open)
address _cb = circuitBreaker;
if (_cb != address(0)) {
uint256 preTvl = valueOfCapital();
try ICircuitBreaker(_cb).checkAndRecordOutflow(token, amount, preTvl) returns (
bool allowed, uint256 available
) {
if (!allowed) {
revert ftYieldWrapperRateLimitExceeded(amount, available);
}
} catch {}
}
uint256 initialTarget = amount;
uint256 remaining = amount;
uint256 _strategiesLength = strategies.length;
if (remaining != 0) {
for (uint256 i = 0; i < _strategiesLength && remaining != 0; ++i) {
uint256 shareBal = strategies[i].balanceOf(address(this));
if (shareBal == 0) continue;
uint256 toExit = shareBal > remaining ? remaining : shareBal;
// Try exit-in-kind via the lightweight extension
// (if strategy doesn't implement, call reverts and we skip)
try strategies[i].withdrawUnderlying(toExit) returns (uint256 got) {
if (got != 0) {
// Protect against underflow if more is withdrawn than deployed
uint256 currentDeployed = deployedToStrategy[address(strategies[i])];
uint256 toReduce = toExit > currentDeployed ? currentDeployed : toExit;
deployedToStrategy[address(strategies[i])] -= toReduce;
// Also cap the global deployed reduction
if (toReduce > deployed) {
deployed = 0;
} else {
deployed -= toReduce;
}
remaining -= toExit;
IERC20(strategies[i].positionToken()).safeTransfer(to, got);
}
} catch {
// strategy doesn't support exit-in-position-token or failed; skip
}
}
}
uint256 totalDelivered = initialTarget - remaining;
// If enforceExact, we must hit exact target (underlying + position tokens)
if (remaining != 0) {
revert ftYieldWrapperInsufficientLiquidity();
}
// Burn shares equal to what was actually delivered (no-op if zero)
if (totalDelivered != 0) {
_burn(msg.sender, totalDelivered);
}
emit WithdrawUnderlying(msg.sender, totalDelivered);
}
function availableToDeposit() external view returns (uint256) {
return IERC20(token).balanceOf(address(this));
}
/**
* @dev Deploy capital to registered strategy
* @param amount The total amount of underlying tokens to deploy
* @notice Can only be called by the yield claimer
*/
function deploy(address strategy, uint256 amount) external nonReentrant onlyYieldClaimer {
if (!isStrategy(strategy)) revert ftYieldWrapperNotStrategy();
if (IERC20(token).balanceOf(address(this)) < amount) {
revert ftYieldWrapperInsufficientLiquidity();
}
IERC20(token).forceApprove(address(strategy), amount);
IStrategy(strategy).deposit(amount);
deployedToStrategy[strategy] += amount;
deployed += amount;
emit Deployed(strategy, amount);
}
/**
* @dev Withdraw capital from registered strategy
* @param amount The total amount of underlying tokens to withdraw
* @notice Can only be called by the yield claimer
*/
function forceWithdrawToWrapper(
address strategy,
uint256 amount
)
external
nonReentrant
onlyYieldClaimer
{
if (!isStrategy(strategy)) revert ftYieldWrapperNotStrategy();
uint256 _withdrawn = IStrategy(strategy).withdraw(amount);
// Protect against underflow if strategy returns more than deployed
uint256 currentDeployed = deployedToStrategy[strategy];
uint256 toReduce = _withdrawn > currentDeployed ? currentDeployed : _withdrawn;
deployedToStrategy[strategy] -= toReduce;
// Also cap the global deployed reduction
if (toReduce > deployed) {
deployed = 0;
} else {
deployed -= toReduce;
}
emit WithdrawToWrapper(msg.sender, strategy, _withdrawn);
}
function withdrawQueued(
address strategy,
uint256 amount
)
external
nonReentrant
onlyYieldClaimer
returns (uint256 id)
{
if (!isStrategy(strategy)) revert ftYieldWrapperNotStrategy();
id = IStrategyWithQueue(strategy).withdrawQueued(amount);
emit QueuedToWrapper(msg.sender, strategy, amount);
}
function claimQueued(
address strategy,
uint256 id
)
external
nonReentrant
onlyYieldClaimer
returns (uint256 received)
{
if (!isStrategy(strategy)) revert ftYieldWrapperNotStrategy();
received = IStrategyWithQueue(strategy).claimQueued(id);
// Protect against underflow if more is claimed than deployed
uint256 currentDeployed = deployedToStrategy[strategy];
uint256 toReduce = received > currentDeployed ? currentDeployed : received;
deployedToStrategy[strategy] -= toReduce;
// Also cap the global deployed reduction
if (toReduce > deployed) {
deployed = 0;
} else {
deployed -= toReduce;
}
emit WithdrawToWrapper(msg.sender, strategy, received);
}
function decimals() public view override(ERC20, IERC20Metadata) returns (uint8) {
return IERC20Metadata(token).decimals();
}
}
ERC20.sol 305 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
*
* TIP: For a detailed writeup see our guide
* https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* The default value of {decimals} is 18. To change this, you should override
* this function so it returns a different value.
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC-20
* applications.
*/
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
mapping(address account => uint256) private _balances;
mapping(address account => mapping(address spender => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* Both values are immutable: they can only be set once during construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual returns (uint8) {
return 18;
}
/// @inheritdoc IERC20
function totalSupply() public view virtual returns (uint256) {
return _totalSupply;
}
/// @inheritdoc IERC20
function balanceOf(address account) public view virtual returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `value`.
*/
function transfer(address to, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_transfer(owner, to, value);
return true;
}
/// @inheritdoc IERC20
function allowance(address owner, address spender) public view virtual returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `value` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 value) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, value);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Skips emitting an {Approval} event indicating an allowance update. This is not
* required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `value`.
* - the caller must have allowance for ``from``'s tokens of at least
* `value`.
*/
function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, value);
_transfer(from, to, value);
return true;
}
/**
* @dev Moves a `value` amount of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _transfer(address from, address to, uint256 value) internal {
if (from == address(0)) {
revert ERC20InvalidSender(address(0));
}
if (to == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(from, to, value);
}
/**
* @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
* (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
* this function.
*
* Emits a {Transfer} event.
*/
function _update(address from, address to, uint256 value) internal virtual {
if (from == address(0)) {
// Overflow check required: The rest of the code assumes that totalSupply never overflows
_totalSupply += value;
} else {
uint256 fromBalance = _balances[from];
if (fromBalance < value) {
revert ERC20InsufficientBalance(from, fromBalance, value);
}
unchecked {
// Overflow not possible: value <= fromBalance <= totalSupply.
_balances[from] = fromBalance - value;
}
}
if (to == address(0)) {
unchecked {
// Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
_totalSupply -= value;
}
} else {
unchecked {
// Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
_balances[to] += value;
}
}
emit Transfer(from, to, value);
}
/**
* @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
* Relies on the `_update` mechanism
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead.
*/
function _mint(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidReceiver(address(0));
}
_update(address(0), account, value);
}
/**
* @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
* Relies on the `_update` mechanism.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* NOTE: This function is not virtual, {_update} should be overridden instead
*/
function _burn(address account, uint256 value) internal {
if (account == address(0)) {
revert ERC20InvalidSender(address(0));
}
_update(account, address(0), value);
}
/**
* @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/
function _approve(address owner, address spender, uint256 value) internal {
_approve(owner, spender, value, true);
}
/**
* @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
*
* By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
* `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
* `Approval` event during `transferFrom` operations.
*
* Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
* true using the following override:
*
* ```solidity
* function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
* super._approve(owner, spender, value, true);
* }
* ```
*
* Requirements are the same as {_approve}.
*/
function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
if (owner == address(0)) {
revert ERC20InvalidApprover(address(0));
}
if (spender == address(0)) {
revert ERC20InvalidSpender(address(0));
}
_allowances[owner][spender] = value;
if (emitEvent) {
emit Approval(owner, spender, value);
}
}
/**
* @dev Updates `owner`'s allowance for `spender` based on spent `value`.
*
* Does not update the allowance value in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Does not emit an {Approval} event.
*/
function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance < type(uint256).max) {
if (currentAllowance < value) {
revert ERC20InsufficientAllowance(spender, currentAllowance, value);
}
unchecked {
_approve(owner, spender, currentAllowance - value, false);
}
}
}
}
IERC20Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity >=0.6.2;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
SafeERC20.sol 280 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
import {IERC1363} from "../../../interfaces/IERC1363.sol";
/**
* @title SafeERC20
* @dev Wrappers around ERC-20 operations that throw on failure (when the token
* contract returns false). Tokens that return no value (and instead revert or
* throw on failure) are also supported, non-reverting calls are assumed to be
* successful.
* To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,
* which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
*/
library SafeERC20 {
/**
* @dev An operation with an ERC-20 token failed.
*/
error SafeERC20FailedOperation(address token);
/**
* @dev Indicates a failed `decreaseAllowance` request.
*/
error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease);
/**
* @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*/
function safeTransfer(IERC20 token, address to, uint256 value) internal {
if (!_safeTransfer(token, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the
* calling contract. If `token` returns no value, non-reverting calls are assumed to be successful.
*/
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
if (!_safeTransferFrom(token, from, to, value, true)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) {
return _safeTransfer(token, to, value, false);
}
/**
* @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful.
*/
function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) {
return _safeTransferFrom(token, from, to, value, false);
}
/**
* @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
uint256 oldAllowance = token.allowance(address(this), spender);
forceApprove(token, spender, oldAllowance + value);
}
/**
* @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no
* value, non-reverting calls are assumed to be successful.
*
* IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client"
* smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using
* this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract
* that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior.
*/
function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal {
unchecked {
uint256 currentAllowance = token.allowance(address(this), spender);
if (currentAllowance < requestedDecrease) {
revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease);
}
forceApprove(token, spender, currentAllowance - requestedDecrease);
}
}
/**
* @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value,
* non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval
* to be set to zero before setting it to a non-zero value, such as USDT.
*
* NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function
* only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being
* set here.
*/
function forceApprove(IERC20 token, address spender, uint256 value) internal {
if (!_safeApprove(token, spender, value, false)) {
if (!_safeApprove(token, spender, 0, true)) revert SafeERC20FailedOperation(address(token));
if (!_safeApprove(token, spender, value, true)) revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
safeTransfer(token, to, value);
} else if (!token.transferAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target
* has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* Reverts if the returned value is other than `true`.
*/
function transferFromAndCallRelaxed(
IERC1363 token,
address from,
address to,
uint256 value,
bytes memory data
) internal {
if (to.code.length == 0) {
safeTransferFrom(token, from, to, value);
} else if (!token.transferFromAndCall(from, to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no
* code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when
* targeting contracts.
*
* NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}.
* Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall}
* once without retrying, and relies on the returned value to be true.
*
* Reverts if the returned value is other than `true`.
*/
function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal {
if (to.code.length == 0) {
forceApprove(token, to, value);
} else if (!token.approveAndCall(to, value, data)) {
revert SafeERC20FailedOperation(address(token));
}
}
/**
* @dev Imitates a Solidity `token.transfer(to, value)` call, relaxing the requirement on the return value: the
* return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransfer(IERC20 token, address to, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.transfer.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(to, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
/**
* @dev Imitates a Solidity `token.transferFrom(from, to, value)` call, relaxing the requirement on the return
* value: the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param from The sender of the tokens
* @param to The recipient of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeTransferFrom(
IERC20 token,
address from,
address to,
uint256 value,
bool bubble
) private returns (bool success) {
bytes4 selector = IERC20.transferFrom.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(from, shr(96, not(0))))
mstore(0x24, and(to, shr(96, not(0))))
mstore(0x44, value)
success := call(gas(), token, 0, 0x00, 0x64, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
mstore(0x60, 0)
}
}
/**
* @dev Imitates a Solidity `token.approve(spender, value)` call, relaxing the requirement on the return value:
* the return value is optional (but if data is returned, it must not be false).
*
* @param token The token targeted by the call.
* @param spender The spender of the tokens
* @param value The amount of token to transfer
* @param bubble Behavior switch if the transfer call reverts: bubble the revert reason or return a false boolean.
*/
function _safeApprove(IERC20 token, address spender, uint256 value, bool bubble) private returns (bool success) {
bytes4 selector = IERC20.approve.selector;
assembly ("memory-safe") {
let fmp := mload(0x40)
mstore(0x00, selector)
mstore(0x04, and(spender, shr(96, not(0))))
mstore(0x24, value)
success := call(gas(), token, 0, 0x00, 0x44, 0x00, 0x20)
// if call success and return is true, all is good.
// otherwise (not success or return is not true), we need to perform further checks
if iszero(and(success, eq(mload(0x00), 1))) {
// if the call was a failure and bubble is enabled, bubble the error
if and(iszero(success), bubble) {
returndatacopy(fmp, 0x00, returndatasize())
revert(fmp, returndatasize())
}
// if the return value is not true, then the call is only successful if:
// - the token address has code
// - the returndata is empty
success := and(success, and(iszero(returndatasize()), gt(extcodesize(token), 0)))
}
mstore(0x40, fmp)
}
}
}
ReentrancyGuardTransient.sol 84 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/ReentrancyGuardTransient.sol)
pragma solidity ^0.8.24;
import {TransientSlot} from "./TransientSlot.sol";
/**
* @dev Variant of {ReentrancyGuard} that uses transient storage.
*
* NOTE: This variant only works on networks where EIP-1153 is available.
*
* _Available since v5.1._
*
* @custom:stateless
*/
abstract contract ReentrancyGuardTransient {
using TransientSlot for *;
// keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
bytes32 private constant REENTRANCY_GUARD_STORAGE =
0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
/**
* @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();
}
/**
* @dev A `view` only version of {nonReentrant}. Use to block view functions
* from being called, preventing reading from inconsistent contract state.
*
* CAUTION: This is a "view" modifier and does not change the reentrancy
* status. Use it only on view functions. For payable or non-payable functions,
* use the standard {nonReentrant} modifier instead.
*/
modifier nonReentrantView() {
_nonReentrantBeforeView();
_;
}
function _nonReentrantBeforeView() private view {
if (_reentrancyGuardEntered()) {
revert ReentrancyGuardReentrantCall();
}
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, REENTRANCY_GUARD_STORAGE.asBoolean().tload() will be false
_nonReentrantBeforeView();
// Any calls to nonReentrant after this point will fail
_reentrancyGuardStorageSlot().asBoolean().tstore(true);
}
function _nonReentrantAfter() private {
_reentrancyGuardStorageSlot().asBoolean().tstore(false);
}
/**
* @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) {
return _reentrancyGuardStorageSlot().asBoolean().tload();
}
function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
return REENTRANCY_GUARD_STORAGE;
}
}
IStrategy.sol 62 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IStrategy is IERC20Metadata {
event YieldClaimed(address yieldClaimer, address treasury, address token, uint256 amount);
event Deposit(address owner, uint256 amount);
event Withdraw(address owner, uint256 amount);
event WithdrawUnderlying(address owner, uint256 amount);
event UpdateftYieldWrapper(address newftYieldWrapper);
error StrategyNotYieldWrapper();
error StrategyZeroAddress();
error StrategyAmountZero();
error StrategyInsufficientLiquidity();
error StrategyCantInteractWithCoreAssets();
error StrategyCapitalMustNotChange();
function token() external view returns (address);
function valueOfCapital() external view returns (uint256);
function setftYieldWrapper(address _ftYieldWrapper) external;
function capital() external view returns (uint256);
function yield() external view returns (uint256);
function claimYield(address treasury) external returns (uint256);
function execute(
address to,
uint256 value,
bytes calldata data
)
external
returns (bool success, bytes memory result);
function availableToWithdraw() external view returns (uint256);
function maxAbleToWithdraw(uint256 amount) external view returns (uint256);
function withdraw(uint256 amount) external returns (uint256);
function deposit(uint256 amount) external;
/// @dev Address of the strategy's position token (e.g., aToken, stETH, etc)
function positionToken() external view returns (address);
/// @dev Burns wrapper's strategy shares and transfers `amount` of the position token to `to`.
/// Must return the actual amount sent (should be == amount for 1:1 strategies).
function withdrawUnderlying(uint256 amount) external returns (uint256 received);
}
interface IStrategyWithQueue is IStrategy {
event WithdrawQueued(address owner, uint256 amount, uint256 id);
event WithdrawClaimed(address owner, uint256 amount, uint256 id);
function withdrawQueued(uint256 amount) external returns (uint256 id);
function claimQueued(uint256 id) external returns (uint256 received);
}
IftYieldWrapper.sol 22 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
interface IftYieldWrapper is IERC20Metadata {
function token() external view returns (address);
function deposit(uint256 amount) external;
function canWithdraw(uint256 amount) external view returns (bool);
function maxAbleToWithdraw(uint256 amount) external view returns (uint256);
function withdraw(uint256 amount, address to) external;
function withdrawUnderlying(uint256 amount, address to) external;
function circuitBreaker() external view returns (address);
function setCircuitBreaker(address _circuitBreaker) external;
}
ICircuitBreaker.sol 177 lines
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;
/// @title ICircuitBreaker
/// @notice Interface for the optional circuit breaker module
/// @dev Designed for fail-open behavior - all calls should be wrapped in try/catch
interface ICircuitBreaker {
// ============ Events ============
/// @notice Emitted when an inflow (deposit) is recorded
/// @param asset The collateral token address
/// @param amount The amount deposited
/// @param newTvl The TVL after this deposit
event Inflow(address indexed asset, uint256 amount, uint256 newTvl);
/// @notice Emitted when an outflow (withdrawal) is recorded
/// @param asset The collateral token address
/// @param amount The amount withdrawn
/// @param newTvl The TVL after this withdrawal
event Outflow(address indexed asset, uint256 amount, uint256 newTvl);
/// @notice Emitted when a rate limit is triggered
/// @param asset The collateral token address
/// @param requested The amount requested to withdraw
/// @param available The maximum amount available to withdraw
event RateLimitTriggered(address indexed asset, uint256 requested, uint256 available);
/// @notice Emitted when the circuit breaker configuration is updated
/// @param maxDrawRateWad Maximum withdrawal rate as WAD (1e18 = 100%)
/// @param mainWindow Time for main buffer to fully replenish (in seconds)
/// @param elasticWindow Time for elastic buffer to decay (in seconds)
event ConfigUpdated(uint256 maxDrawRateWad, uint256 mainWindow, uint256 elasticWindow);
/// @notice Emitted when the circuit breaker is paused
/// @param by The address that paused the circuit breaker
event CircuitBreakerPaused(address indexed by);
/// @notice Emitted when the circuit breaker is unpaused
/// @param by The address that unpaused the circuit breaker
event CircuitBreakerUnpaused(address indexed by);
/// @notice Emitted when an emergency override is performed
/// @param asset The collateral token address
/// @param amount The amount added to withdrawal capacity
event EmergencyOverride(address indexed asset, uint256 amount);
// ============ Core Functions ============
/// @notice Record an asset inflow (deposit)
/// @dev Called after assets have been transferred in
/// @param asset The collateral token address
/// @param amount The amount deposited
/// @param preTvl The TVL before this deposit
function recordInflow(address asset, uint256 amount, uint256 preTvl) external;
/// @notice Check if outflow is allowed and record it
/// @dev Called before assets are transferred out
/// @param asset The collateral token address
/// @param amount The amount to withdraw
/// @param preTvl The TVL before this withdrawal
/// @return allowed Whether the withdrawal is within rate limits
/// @return available The maximum amount that could be withdrawn
function checkAndRecordOutflow(
address asset,
uint256 amount,
uint256 preTvl
)
external
returns (bool allowed, uint256 available);
// ============ View Functions ============
/// @notice Get the current withdrawal capacity for an asset
/// @param asset The collateral token address
/// @param currentTvl The current TVL
/// @return capacity The maximum amount that can be withdrawn
function withdrawalCapacity(
address asset,
uint256 currentTvl
)
external
view
returns (uint256 capacity);
/// @notice Check if the circuit breaker is currently active (not paused)
/// @return active True if the circuit breaker is active, false if paused
function isActive() external view returns (bool active);
// ============ Monitoring View Functions ============
/// @notice Get all protected contracts
/// @return contracts Array of protected contract addresses
function getProtectedContracts() external view returns (address[] memory contracts);
/// @notice Get count of protected contracts
/// @return count Number of protected contracts
function protectedContractCount() external view returns (uint256 count);
/// @notice Get all tracked assets
/// @return assets Array of tracked asset addresses
function getTrackedAssets() external view returns (address[] memory assets);
/// @notice Get count of tracked assets
/// @return count Number of tracked assets
function trackedAssetCount() external view returns (uint256 count);
/// @notice Get health metrics for an asset
/// @param asset The asset to query
/// @param currentTvl The current TVL
/// @return mainUtilizationBps Main buffer usage in basis points (0 = full, 10000 = depleted)
/// @return elasticBuffer Current elastic buffer amount
/// @return totalCapacity Total withdrawal capacity
/// @return maxCapacity Maximum possible capacity
/// @return secondsUntilFullReplenishment Seconds until main buffer fully replenishes
function getAssetHealth(
address asset,
uint256 currentTvl
)
external
view
returns (
uint256 mainUtilizationBps,
uint256 elasticBuffer,
uint256 totalCapacity,
uint256 maxCapacity,
uint256 secondsUntilFullReplenishment
);
/// @notice Get comprehensive system status
/// @return active Whether circuit breaker is active
/// @return adminAddr Current admin address
/// @return maxDrawRateBps Max draw rate in basis points
/// @return mainWindowSecs Main window in seconds
/// @return elasticWindowSecs Elastic window in seconds
/// @return numProtectedContracts Number of protected contracts
/// @return numTrackedAssets Number of tracked assets
function getSystemStatus()
external
view
returns (
bool active,
address adminAddr,
uint256 maxDrawRateBps,
uint256 mainWindowSecs,
uint256 elasticWindowSecs,
uint256 numProtectedContracts,
uint256 numTrackedAssets
);
// ============ Admin Functions ============
/// @notice Pause the circuit breaker (allows all transactions)
/// @dev Only callable by admin
function pause() external;
/// @notice Unpause the circuit breaker
/// @dev Only callable by admin
function unpause() external;
/// @notice Update rate limiting configuration
/// @dev Only callable by admin
/// @param maxDrawRateWad Maximum withdrawal rate as WAD (1e18 = 100%)
/// @param mainWindow Time for main buffer to fully replenish (in seconds)
/// @param elasticWindow Time for elastic buffer to decay (in seconds)
function updateConfig(
uint256 maxDrawRateWad,
uint256 mainWindow,
uint256 elasticWindow
)
external;
/// @notice Emergency override to allow a specific withdrawal
/// @dev Only callable by admin, for false positive resolution
/// @param asset The collateral token address
/// @param amount The amount to allow for withdrawal
function emergencyOverride(address asset, uint256 amount) external;
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
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);
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @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 Context {
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;
}
}
draft-IERC6093.sol 162 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;
/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/
interface IERC20Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/
error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/
error ERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/
interface IERC721Errors {
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/
error ERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/
error ERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/
error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/
error ERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/
interface IERC1155Errors {
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/
error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/
error ERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/
error ERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/
error ERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/
error ERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/
error ERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/
error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
IERC1363.sol 86 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC1363.sol)
pragma solidity >=0.6.2;
import {IERC20} from "./IERC20.sol";
import {IERC165} from "./IERC165.sol";
/**
* @title IERC1363
* @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363].
*
* Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract
* after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction.
*/
interface IERC1363 is IERC20, IERC165 {
/*
* Note: the ERC-165 identifier for this interface is 0xb0202a11.
* 0xb0202a11 ===
* bytes4(keccak256('transferAndCall(address,uint256)')) ^
* bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^
* bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^
* bytes4(keccak256('approveAndCall(address,uint256)')) ^
* bytes4(keccak256('approveAndCall(address,uint256,bytes)'))
*/
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism
* and then calls {IERC1363Receiver-onTransferReceived} on `to`.
* @param from The address which you want to send tokens from.
* @param to The address which you want to transfer to.
* @param value The amount of tokens to be transferred.
* @param data Additional data with no specified format, sent in call to `to`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value) external returns (bool);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`.
* @param spender The address which will spend the funds.
* @param value The amount of tokens to be spent.
* @param data Additional data with no specified format, sent in call to `spender`.
* @return A boolean value indicating whether the operation succeeded unless throwing.
*/
function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool);
}
TransientSlot.sol 183 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/TransientSlot.sol)
// This file was procedurally generated from scripts/generate/templates/TransientSlot.js.
pragma solidity ^0.8.24;
/**
* @dev Library for reading and writing value-types to specific transient storage slots.
*
* Transient slots are often used to store temporary values that are removed after the current transaction.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* * Example reading and writing values using transient storage:
* ```solidity
* contract Lock {
* using TransientSlot for *;
*
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
*
* modifier locked() {
* require(!_LOCK_SLOT.asBoolean().tload());
*
* _LOCK_SLOT.asBoolean().tstore(true);
* _;
* _LOCK_SLOT.asBoolean().tstore(false);
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library TransientSlot {
/**
* @dev UDVT that represents a slot holding an address.
*/
type AddressSlot is bytes32;
/**
* @dev Cast an arbitrary slot to a AddressSlot.
*/
function asAddress(bytes32 slot) internal pure returns (AddressSlot) {
return AddressSlot.wrap(slot);
}
/**
* @dev UDVT that represents a slot holding a bool.
*/
type BooleanSlot is bytes32;
/**
* @dev Cast an arbitrary slot to a BooleanSlot.
*/
function asBoolean(bytes32 slot) internal pure returns (BooleanSlot) {
return BooleanSlot.wrap(slot);
}
/**
* @dev UDVT that represents a slot holding a bytes32.
*/
type Bytes32Slot is bytes32;
/**
* @dev Cast an arbitrary slot to a Bytes32Slot.
*/
function asBytes32(bytes32 slot) internal pure returns (Bytes32Slot) {
return Bytes32Slot.wrap(slot);
}
/**
* @dev UDVT that represents a slot holding a uint256.
*/
type Uint256Slot is bytes32;
/**
* @dev Cast an arbitrary slot to a Uint256Slot.
*/
function asUint256(bytes32 slot) internal pure returns (Uint256Slot) {
return Uint256Slot.wrap(slot);
}
/**
* @dev UDVT that represents a slot holding a int256.
*/
type Int256Slot is bytes32;
/**
* @dev Cast an arbitrary slot to a Int256Slot.
*/
function asInt256(bytes32 slot) internal pure returns (Int256Slot) {
return Int256Slot.wrap(slot);
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(AddressSlot slot) internal view returns (address value) {
assembly ("memory-safe") {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(AddressSlot slot, address value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(BooleanSlot slot) internal view returns (bool value) {
assembly ("memory-safe") {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(BooleanSlot slot, bool value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Bytes32Slot slot) internal view returns (bytes32 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Bytes32Slot slot, bytes32 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Uint256Slot slot) internal view returns (uint256 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Uint256Slot slot, uint256 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/
function tload(Int256Slot slot) internal view returns (int256 value) {
assembly ("memory-safe") {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/
function tstore(Int256Slot slot, int256 value) internal {
assembly ("memory-safe") {
tstore(slot, value)
}
}
}
IERC20.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC20.sol)
pragma solidity >=0.4.16;
import {IERC20} from "../token/ERC20/IERC20.sol";
IERC165.sol 6 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/IERC165.sol)
pragma solidity >=0.4.16;
import {IERC165} from "../utils/introspection/IERC165.sol";
IERC165.sol 25 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (utils/introspection/IERC165.sol)
pragma solidity >=0.4.16;
/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* 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[ERC 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
allowance 0xdd62ed3e → uint256
availableToDeposit 0x7b9282b0 → uint256
availableToWithdraw 0xa25db8ce → uint256
availableToWithdraw 0xe322ad2b → uint256
balanceOf 0x70a08231 → uint256
canWithdraw 0xfbe85f06 → bool
capital 0xd211fd18 → uint256
circuitBreaker 0x16efd941 → address
decimals 0x313ce567 → uint8
delayStrategy 0x5d83f093 → uint256
deployed 0xf905c15a → uint256
deployedToStrategy 0x958da918 → uint256
depositor 0xc7c4ff46 → address
isStrategy 0x2e8ebaae → bool
maxAbleToWithdraw 0xafa92945 → uint256
name 0x06fdde03 → string
numberOfStrategies 0x0956e5a6 → uint256
pendingStrategy 0x465fc5d2 → address
pendingStrategyManager 0x0e845634 → address
pendingTreasury 0x2ed6b75d → address
pendingYieldClaimer 0x7a801f53 → address
putManager 0x4f5e8085 → address
strategies 0xd574ea3d → address
strategyManager 0x39b70e38 → address
subYieldClaimer 0x3066bb27 → address
symbol 0x95d89b41 → string
token 0xfc0c546a → address
totalSupply 0x18160ddd → uint256
treasury 0x61d027b3 → address
valueOfCapital 0x89fe02cb → uint256
yield 0x28593984 → uint256
yieldClaimer 0x78e808d5 → address
Write Contract 28 functions
These functions modify contract state and require a wallet transaction to execute.
approve 0x095ea7b3
address spender
uint256 value
returns: bool
claimQueued 0x1c30e682
address strategy
uint256 id
returns: uint256
claimYield 0x999927df
address _strategy
returns: uint256
claimYields 0x2f278fe8
No parameters
returns: uint256
confirmStrategy 0x4f908e7f
No parameters
confirmStrategyManager 0xaec48f50
No parameters
confirmTreasury 0xedf1d2b3
No parameters
confirmYieldClaimer 0x5e181655
No parameters
deploy 0x4956eaf0
address strategy
uint256 amount
deposit 0xb6b55f25
uint256 amount
execute 0x9aefaff8
address _strategy
address to
uint256 value
bytes data
returns: bool, bytes
forceWithdrawToWrapper 0x57c44f8e
address strategy
uint256 amount
removeStrategy 0xc0cbbca6
uint256 index
setCircuitBreaker 0x82beee89
address _circuitBreaker
setDepositor 0xf2c098b7
address _depositor
setPutManager 0x58e75440
address _putManager
setStrategiesOrder 0x59746aab
address[] _newOrder
setStrategy 0x33a100ca
address _strategy
setStrategyManager 0x5c966646
address _strategyManager
setSubYieldClaimer 0x75efcf77
address _subYieldClaimer
setTreasury 0xf0f44260
address _treasury
setYieldClaimer 0xd8b5138a
address _yieldClaimer
sweepIdleYield 0x8c05b472
No parameters
returns: uint256
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool
withdraw 0x00f714ce
uint256 amount
address to
withdrawQueued 0xe357e92e
address strategy
uint256 amount
returns: uint256
withdrawUnderlying 0x99f428cf
uint256 amount
address to
Token Balances (1)
View Transfers →Recent Transactions
No transactions found for this address