Forkchoice Ethereum Mainnet

Address Contract Partially Verified

Address 0x3280499298ACe3FD3cd9C2558e9e8746ACE3E52d
Balance 0 ETH
Nonce 12
Code Size 21992 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

21992 bytes
0x608060405234801561001057600080fd5b50600436106103995760003560e01c806376ee75d8116101e9578063af306e161161010f578063ec38a862116100ad578063f8c8765e1161007c578063f8c8765e146106c3578063fbfa77cf146106d6578063fcc5f59a146106de578063fcf2d0ad146106f357610399565b8063ec38a86214610682578063ed882c2b14610695578063efbb5cb0146106a8578063f017c92f146106b057610399565b8063c7b9d530116100e9578063c7b9d53014610631578063ce5494bb14610644578063d051184214610657578063d6c382711461066a57610399565b8063af306e1614610619578063b252720b14610621578063bb927c461461062957610399565b80638e6350e21161018757806395e80c501161015657806395e80c50146105ee5780639ec5a894146105f6578063ac00ff26146105fe578063aced16611461061157610399565b80638e6350e2146105ad57806391397ab4146105b5578063929eea21146105c857806393084b34146105db57610399565b80637a4b1c14116101c35780637a4b1c141461056c5780638124b78e1461057f5780638baf2957146105925780638cdfe166146105a557610399565b806376ee75d81461053e578063780022a0146105515780637985fd511461056457610399565b8063397dc149116102ce578063530e784f1161026c5780636718835f1161023b5780636718835f14610508578063735de9f714610510578063748747e614610518578063750521f51461052b57610399565b8063530e784f146104d25780635641ec03146104e55780635a5cd45e146104ed578063650d1880146104f557610399565b8063440368a3116102a8578063440368a3146104a75780634641257d146104af57806346d8cf3f146104b75780634786b0cb146104bf57610399565b8063397dc1491461047957806339a172a81461048c5780633fc8cef31461049f57610399565b80631f1fcd511161033b5780632582941011610315578063258294101461044e57806328b7ccf7146104565780632a5dc8c11461045e5780632e1a7d4d1461046657610399565b80631f1fcd511461041c5780631fe4a6861461043157806322f3e2d41461043957610399565b80630e6e15f0116103775780630e6e15f0146103d95780630f969b87146103ee57806311bc8245146104015780631d12f28b1461041457610399565b806301681a621461039e57806303ee438c146103b357806306fdde03146103d1575b600080fd5b6103b16103ac366004614bef565b6106fb565b005b6103bb61089a565b6040516103c8919061511a565b60405180910390f35b6103bb610928565b6103e1610960565b6040516103c89190615469565b6103b16103fc366004614f64565b610a17565b6103b161040f366004614bef565b610aa4565b6103e1610ba5565b610424610bab565b6040516103c89190614fe9565b610424610bba565b610441610bc9565b6040516103c891906150e0565b6103bb610c6b565b6103e1610c8a565b610424610c90565b6103e1610474366004614f64565b610ca4565b6103e1610487366004614f64565b610cff565b6103b161049a366004614f64565b610dbd565b610424610e3f565b6103b1610e57565b6103b1611080565b610441611559565b6103b16104cd366004614f64565b611562565b6103b16104e0366004614bef565b6115b4565b610441611629565b6103e1611632565b610441610503366004614f64565b6116d1565b61044161181e565b610424611827565b6103b1610526366004614bef565b61183f565b6103b1610539366004614ded565b6118ea565b6103b161054c366004614bef565b611981565b6103e161055f366004614f64565b6119dc565b6103e1611b1a565b6103b161057a366004614c82565b611b20565b61042461058d366004614bef565b611e68565b6103b16105a0366004614bef565b611eec565b6103e1611f44565b6103e1611f4a565b6103b16105c3366004614f64565b611f4f565b6104246105d6366004614f64565b611fd1565b6103b16105e9366004614bef565b611ff8565b6103e1612183565b610424612189565b6103b161060c366004614db5565b612198565b610424612284565b6103e1612293565b61042461229b565b6103e16122af565b6103b161063f366004614bef565b6122b5565b6103b1610652366004614bef565b612360565b610424610665366004614c27565b6124ab565b610672612598565b6040516103c894939291906154de565b6103b1610690366004614bef565b61297e565b6104416106a3366004614f64565b612b11565b6103e1612d9b565b6103b16106be366004614f64565b612e3a565b6103b16106d1366004614c27565b612ebc565b610424612ece565b6106e6612edd565b6040516103c8919061505b565b6103b1613153565b610703613489565b6001600160a01b0316336001600160a01b03161461073c5760405162461bcd60e51b815260040161073390615357565b60405180910390fd5b6006546001600160a01b038281169116141561076a5760405162461bcd60e51b81526004016107339061517b565b6002546001600160a01b03828116911614156107985760405162461bcd60e51b8152600401610733906152d8565b60606107a2613506565b905060005b81518110156107fd578181815181106107bc57fe5b60200260200101516001600160a01b0316836001600160a01b031614156107f55760405162461bcd60e51b8152600401610733906153c6565b6001016107a7565b50610896610809613489565b6040516370a0823160e01b81526001600160a01b038516906370a0823190610835903090600401614fe9565b60206040518083038186803b15801561084d57600080fd5b505afa158015610861573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108859190614f7c565b6001600160a01b0385169190613562565b5050565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156109205780601f106108f557610100808354040283529160200191610920565b820191906000526020600020905b81548152906001019060200180831161090357829003601f168201915b505050505081565b60408051808201909152601c81527f53747261746567794c656e6465725969656c644f7074696d697365720000000060208201525b90565b600080805b600d54811015610a1157610a07600d828154811061097f57fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b1580156109c857600080fd5b505afa1580156109dc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a009190614f7c565b8390613581565b9150600101610965565b50905090565b6003546001600160a01b0316331480610a485750610a33613489565b6001600160a01b0316336001600160a01b0316145b610a645760405162461bcd60e51b815260040161073390615357565b600a8190556040517fa68ba126373d04c004c5748c300c9fca12bd444b3d4332e261f3bd2bac4a860090610a99908390615469565b60405180910390a150565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610af257600080fd5b505afa158015610b06573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2a9190614c0b565b6001600160a01b0316336001600160a01b03161480610b615750610b4c613489565b6001600160a01b0316336001600160a01b0316145b610b7d5760405162461bcd60e51b815260040161073390615357565b600180546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600a5481565b6006546001600160a01b031681565b6003546001600160a01b031681565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610bfe903090600401614fe9565b6101206040518083038186803b158015610c1757600080fd5b505afa158015610c2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c4f9190614ee6565b604001511180610c6657506000610c64612d9b565b115b905090565b604080518082019091526005815264302e342e3360d81b602082015290565b60085481565b600e5461010090046001600160a01b031681565b6002546000906001600160a01b03163314610cd15760405162461bcd60e51b8152600401610733906152b8565b6000610cdc836135ad565b600654909350909150610cf9906001600160a01b03163383613562565b50919050565b6002546040516339ebf82360e01b815260009182916001600160a01b03909116906339ebf82390610d34903090600401614fe9565b6101206040518083038186803b158015610d4d57600080fd5b505afa158015610d61573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d859190614ee6565b60c001519050600083821015610dab5750808303610da281613688565b92505050610db8565b50828103610da281613849565b919050565b6003546001600160a01b0316331480610dee5750610dd9613489565b6001600160a01b0316336001600160a01b0316145b610e0a5760405162461bcd60e51b815260040161073390615357565b60078190556040517fbb2c369a0355a34b02ab5fce0643150c87e1c8dfe7c918d465591879f57948b190610a99908390615469565b73c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281565b6005546001600160a01b0316331480610e7a57506003546001600160a01b031633145b80610e9d5750610e88613489565b6001600160a01b0316336001600160a01b0316145b80610f3e5750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b158015610ef157600080fd5b505afa158015610f05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f299190614c0b565b6001600160a01b0316336001600160a01b0316145b80610fdf5750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b158015610f9257600080fd5b505afa158015610fa6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fca9190614c0b565b6001600160a01b0316336001600160a01b0316145b610ffb5760405162461bcd60e51b815260040161073390615357565b6002546040805163bf3759b560e01b8152905161107e926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b15801561104157600080fd5b505afa158015611055573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110799190614f7c565b613a1d565b565b6005546001600160a01b03163314806110a357506003546001600160a01b031633145b806110c657506110b1613489565b6001600160a01b0316336001600160a01b0316145b806111675750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b15801561111a57600080fd5b505afa15801561112e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111529190614c0b565b6001600160a01b0316336001600160a01b0316145b806112085750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156111bb57600080fd5b505afa1580156111cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111f39190614c0b565b6001600160a01b0316336001600160a01b0316145b6112245760405162461bcd60e51b815260040161073390615357565b6000806000600260009054906101000a90046001600160a01b03166001600160a01b031663bf3759b56040518163ffffffff1660e01b815260040160206040518083038186803b15801561127757600080fd5b505afa15801561128b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112af9190614f7c565b600b5490915060009060ff161561130c5760006112ca613c27565b9050828110156112e5576112de8382613c39565b93506112fa565b828111156112fa576112f78184613c39565b94505b6113048385613c39565b91505061131d565b61131582613c7b565b919550935090505b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf8239061134e903090600401614fe9565b6101206040518083038186803b15801561136757600080fd5b505afa15801561137b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061139f9190614ee6565b60c001516002546040516328766ebf60e21b81529192506001600160a01b03169063a1d9bafc906113d8908890889087906004016154c8565b602060405180830381600087803b1580156113f257600080fd5b505af1158015611406573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061142a9190614f7c565b925061143583613a1d565b60015460ff168015611456575060015461010090046001600160a01b031615155b156115085760015460405163c70fa00b60e01b81526101009091046001600160a01b03169063c70fa00b9061149790889088908790899088906004016154f9565b60206040518083038186803b1580156114af57600080fd5b505afa1580156114c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114e79190614dd1565b6115035760405162461bcd60e51b81526004016107339061521a565b611515565b6001805460ff1916811790555b7f4c0f499ffe6befa0ca7c826b0916cf87bea98de658013e76938489368d60d5098585848660405161154a94939291906154de565b60405180910390a15050505050565b600e5460ff1681565b6003546001600160a01b0316331480611593575061157e613489565b6001600160a01b0316336001600160a01b0316145b6115af5760405162461bcd60e51b815260040161073390615357565b600c55565b6003546001600160a01b03163314806115e557506115d0613489565b6001600160a01b0316336001600160a01b0316145b6116015760405162461bcd60e51b815260040161073390615357565b600e80546001600160a01b0390921661010002610100600160a81b0319909216919091179055565b600b5460ff1681565b60008061163d612d9b565b90508061164e57600091505061095d565b6000805b600d548110156116bf576116b5600d828154811061166c57fe5b600091825260209182902001546040805163116ac4a360e01b815290516001600160a01b039092169263116ac4a392600480840193829003018186803b1580156109c857600080fd5b9150600101611652565b506116ca8183613fa5565b9250505090565b60006116dc82612b11565b156116e957506000610db8565b60008060006116f6612598565b9350509250925081811115611816576000600d848154811061171457fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b15801561175d57600080fd5b505afa158015611771573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117959190614f7c565b905060006117e36301e185586117dd6008546117d7670de0b6b3a76400006117c68a89613fe790919063ffffffff16565b6117d0898b613fe7565b0390613fa5565b90613fe7565b90613fa5565b905060006117f088614021565b90508161180860095483613fe790919063ffffffff16565b109650505050505050610db8565b505050919050565b60015460ff1681565b737a250d5630b4cf539739df2c5dacb4c659f2488d81565b6003546001600160a01b0316331480611870575061185b613489565b6001600160a01b0316336001600160a01b0316145b61188c5760405162461bcd60e51b815260040161073390615357565b6001600160a01b03811661189f57600080fd5b600580546001600160a01b0319166001600160a01b0383161790556040517f2f202ddb4a2e345f6323ed90f8fc8559d770a7abbbeee84dde8aca3351fe715490610a99908390614fe9565b6003546001600160a01b031633148061191b5750611906613489565b6001600160a01b0316336001600160a01b0316145b6119375760405162461bcd60e51b815260040161073390615357565b61194360008383614a95565b507f300e67d5a415b6d015a471d9c7b95dd58f3e8290af965e84e0f845de2996dda682826040516119759291906150eb565b60405180910390a15050565b6003546001600160a01b03163314806119b2575061199d613489565b6001600160a01b0316336001600160a01b0316145b6119ce5760405162461bcd60e51b815260040161073390615357565b6119d98160016140fd565b50565b604080516002808252606080830184526000939092919060208301908036833701905050905073c02aaa39b223fe8d0a0e5c4f27ead9083c756cc281600081518110611a2457fe5b6001600160a01b039283166020918202929092010152600654825191169082906001908110611a4f57fe5b6001600160a01b039092166020928302919091019091015260405163d06ca61f60e01b8152606090737a250d5630b4cf539739df2c5dacb4c659f2488d9063d06ca61f90611aa39087908690600401615472565b60006040518083038186803b158015611abb57600080fd5b505afa158015611acf573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052611af79190810190614d25565b905080600182510381518110611b0957fe5b602002602001015192505050919050565b600c5481565b6003546001600160a01b0316331480611b515750611b3c613489565b6001600160a01b0316336001600160a01b0316145b611b6d5760405162461bcd60e51b815260040161073390615357565b6000805b600d54811015611c2157600d8181548110611b8857fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b8152600401602060405180830381600087803b158015611be057600080fd5b505af1158015611bf4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c189190614dd1565b50600101611b71565b506006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190611c53903090600401614fe9565b60206040518083038186803b158015611c6b57600080fd5b505afa158015611c7f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ca39190614f7c565b905060005b8351811015611e41576000805b600d54811015611d1557858381518110611ccb57fe5b6020026020010151600001516001600160a01b0316600d8281548110611ced57fe5b6000918252602090912001546001600160a01b03161415611d0d57600191505b600101611cb5565b5080611d335760405162461bcd60e51b8152600401610733906151f6565b611d61858381518110611d4257fe5b60200260200101516020015161ffff168561358190919063ffffffff16565b93506000611d996103e86117dd888681518110611d7a57fe5b60200260200101516020015161ffff1687613fe790919063ffffffff16565b9050611dc9868481518110611daa57fe5b6020908102919091010151516006546001600160a01b03169083613562565b858381518110611dd557fe5b6020026020010151600001516001600160a01b031663d0e30db06040518163ffffffff1660e01b8152600401600060405180830381600087803b158015611e1b57600080fd5b505af1158015611e2f573d6000803e3d6000fd5b505060019094019350611ca892505050565b50816103e814611e635760405162461bcd60e51b81526004016107339061519a565b505050565b6040516368288c2160e11b8152600090309063d051184290611e94908590339081908190600401615017565b602060405180830381600087803b158015611eae57600080fd5b505af1158015611ec2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611ee69190614c0b565b92915050565b6003546001600160a01b0316331480611f1d5750611f08613489565b6001600160a01b0316336001600160a01b0316145b611f395760405162461bcd60e51b815260040161073390615357565b6119d98160006140fd565b60095481565b600090565b6003546001600160a01b0316331480611f805750611f6b613489565b6001600160a01b0316336001600160a01b0316145b611f9c5760405162461bcd60e51b815260040161073390615357565b60098190556040517fd94596337df4c2f0f44d30a7fc5db1c7bb60d9aca4185ed77c6fd96eb45ec29890610a99908390615469565b600d8181548110611fde57fe5b6000918252602090912001546001600160a01b0316905081565b612000613489565b6001600160a01b0316336001600160a01b0316146120305760405162461bcd60e51b815260040161073390615357565b6000819050306001600160a01b0316816001600160a01b031663a8c62e766040518163ffffffff1660e01b815260040160206040518083038186803b15801561207857600080fd5b505afa15801561208c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120b09190614c0b565b6001600160a01b0316146120d65760405162461bcd60e51b815260040161073390615152565b60005b600d5481101561212f57600d81815481106120f057fe5b6000918252602090912001546001600160a01b03848116911614156121275760405162461bcd60e51b8152600401610733906152f9565b6001016120d9565b50600d80546001810182556000919091527fd7b6990105719101dabeb77144f2a3385c8033acd3af97e9423a695e81ad1eb50180546001600160a01b0319166001600160a01b039290921691909117905550565b60075481565b6004546001600160a01b031681565b600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b1580156121e657600080fd5b505afa1580156121fa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061221e9190614c0b565b6001600160a01b0316336001600160a01b031614806122555750612240613489565b6001600160a01b0316336001600160a01b0316145b6122715760405162461bcd60e51b815260040161073390615357565b6001805460ff1916911515919091179055565b6005546001600160a01b031681565b6301e1855881565b60015461010090046001600160a01b031681565b600d5490565b6003546001600160a01b03163314806122e657506122d1613489565b6001600160a01b0316336001600160a01b0316145b6123025760405162461bcd60e51b815260040161073390615357565b6001600160a01b03811661231557600080fd5b600380546001600160a01b0319166001600160a01b0383161790556040517f352ececae6d7d1e6d26bcf2c549dfd55be1637e9b22dc0cf3b71ddb36097a6b490610a99908390614fe9565b6002546001600160a01b0316331461237757600080fd5b6002546040805163fbfa77cf60e01b815290516001600160a01b039283169284169163fbfa77cf916004808301926020929190829003018186803b1580156123be57600080fd5b505afa1580156123d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123f69190614c0b565b6001600160a01b03161461240957600080fd5b61241281614355565b6006546040516370a0823160e01b81526119d99183916001600160a01b03909116906370a0823190612448903090600401614fe9565b60206040518083038186803b15801561246057600080fd5b505afa158015612474573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906124989190614f7c565b6006546001600160a01b03169190613562565b604051733d602d80600a3d3981f3363d3d373d3d3d363d7360601b81523060601b601482018190526e5af43d82803e903d91602b57fd5bf360881b602883015260009160378184f0604051637c643b2f60e11b81529093506001600160a01b038416915063f8c8765e90612529908990899089908990600401615017565b600060405180830381600087803b15801561254357600080fd5b505af1158015612557573d6000803e3d6000fd5b50506040516001600160a01b03851692507f783540fb4221a3238720dc7038937d0d79982bcf895274aa6ad179f82cf0d53c9150600090a250949350505050565b6006546040516370a0823160e01b815260009182918291829182916001600160a01b0316906370a08231906125d1903090600401614fe9565b60206040518083038186803b1580156125e957600080fd5b505afa1580156125fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126219190614f7c565b90506000199350600094506000805b600d5481101561280857600d818154811061264757fe5b6000918252602091829020015460408051635be9b2d360e01b815290516001600160a01b0390921692635be9b2d392600480840193829003018186803b15801561269057600080fd5b505afa1580156126a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126c89190614dd1565b15612800576000600d82815481106126dc57fe5b60009182526020918290200154604080516357ded9c960e01b815290516001600160a01b03909216926357ded9c992600480840193829003018186803b15801561272557600080fd5b505afa158015612739573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061275d9190614f7c565b9050868110156127fe57809650819750600d828154811061277a57fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b1580156127c357600080fd5b505afa1580156127d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906127fb9190614f7c565b92505b505b600101612630565b5060006128158284613581565b9050600080955060005b600d548110156128db576000600d828154811061283857fe5b60009182526020909120015460405163052692b960e21b81526001600160a01b039091169063149a4ae490612871908990600401615469565b60206040518083038186803b15801561288957600080fd5b505afa15801561289d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128c19190614f7c565b9050828111156128d2578092508197505b5060010161281f565b50600d86815481106128e957fe5b60009182526020909120015460405163052692b960e21b81526001600160a01b039091169063149a4ae490612922908590600401615469565b60206040518083038186803b15801561293a57600080fd5b505afa15801561294e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129729190614f7c565b94505050505090919293565b6003546001600160a01b031633146129a85760405162461bcd60e51b81526004016107339061512d565b6001600160a01b0381166129bb57600080fd5b6002546004805460405163095ea7b360e01b81526001600160a01b039384169363095ea7b3936129f2939091169160009101615042565b602060405180830381600087803b158015612a0c57600080fd5b505af1158015612a20573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612a449190614dd1565b50600480546001600160a01b0319166001600160a01b038381169190911780835560025460405163095ea7b360e01b81529083169363095ea7b393612a8f9316916000199101615042565b602060405180830381600087803b158015612aa957600080fd5b505af1158015612abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae19190614dd1565b507fafbb66abf8f3b719799940473a4052a3717cdd8e40fb6c8a3faadab316b1a06981604051610a999190614fe9565b600080612b1d836119dc565b9050612b27614b13565b6002546040516339ebf82360e01b81526001600160a01b03909116906339ebf82390612b57903090600401614fe9565b6101206040518083038186803b158015612b7057600080fd5b505afa158015612b84573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ba89190614ee6565b9050806020015160001415612bc257600092505050610db8565b60075460a0820151612bd5904290613c39565b1015612be657600092505050610db8565b60085460a0820151612bf9904290613c39565b10612c0957600192505050610db8565b6002546040805163bf3759b560e01b815290516000926001600160a01b03169163bf3759b5916004808301926020929190829003018186803b158015612c4e57600080fd5b505afa158015612c62573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612c869190614f7c565b9050600a54811115612c9e5760019350505050610db8565b6000612ca8612d9b565b90508260c00151612cc4600a548361358190919063ffffffff16565b1015612cd7576001945050505050610db8565b60008360c00151821115612cf85760c0840151612cf5908390613c39565b90505b6002546040805163112c1f9b60e01b815290516000926001600160a01b03169163112c1f9b916004808301926020929190829003018186803b158015612d3d57600080fd5b505afa158015612d51573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d759190614f7c565b9050612d818183613581565b600954612d8e9088613fe7565b1098975050505050505050565b600080612da6610960565b6006546040516370a0823160e01b8152919250612e34916001600160a01b03909116906370a0823190612ddd903090600401614fe9565b60206040518083038186803b158015612df557600080fd5b505afa158015612e09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e2d9190614f7c565b8290613581565b91505090565b6003546001600160a01b0316331480612e6b5750612e56613489565b6001600160a01b0316336001600160a01b0316145b612e875760405162461bcd60e51b815260040161073390615357565b60088190556040517f5430e11864ad7aa9775b07d12657fe52df9aa2ba734355bd8ef8747be2c800c590610a99908390615469565b612ec8848484846143f2565b50505050565b6002546001600160a01b031681565b600d54606090819067ffffffffffffffff81118015612efb57600080fd5b50604051908082528060200260200182016040528015612f3557816020015b612f22614b5f565b815260200190600190039081612f1a5790505b50905060005b600d54811015610a1157612f4d614b5f565b600d8281548110612f5a57fe5b60009182526020822001546040805163459010bb60e11b815290516001600160a01b0390921692638b20217692600480840193829003018186803b158015612fa157600080fd5b505afa158015612fb5573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052612fdd9190810190614e5a565b8152600d805483908110612fed57fe5b6000918252602090912001546001600160a01b03166060820152600d80548390811061301557fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b15801561305e57600080fd5b505afa158015613072573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906130969190614f7c565b6020820152600d8054839081106130a957fe5b60009182526020918290200154604080516357ded9c960e01b815290516001600160a01b03909216926357ded9c992600480840193829003018186803b1580156130f257600080fd5b505afa158015613106573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061312a9190614f7c565b60408201528251819084908490811061313f57fe5b602090810291909101015250600101612f3b565b6003546001600160a01b0316331480613184575061316f613489565b6001600160a01b0316336001600160a01b0316145b806132255750600260009054906101000a90046001600160a01b03166001600160a01b031663452a93206040518163ffffffff1660e01b815260040160206040518083038186803b1580156131d857600080fd5b505afa1580156131ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132109190614c0b565b6001600160a01b0316336001600160a01b0316145b806132c65750600260009054906101000a90046001600160a01b03166001600160a01b03166388a8d6026040518163ffffffff1660e01b815260040160206040518083038186803b15801561327957600080fd5b505afa15801561328d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906132b19190614c0b565b6001600160a01b0316336001600160a01b0316145b6132e25760405162461bcd60e51b815260040161073390615357565b600b805460ff191660011790556002546040805163507257cd60e11b815290516001600160a01b039092169163a0e4af9a9160048082019260009290919082900301818387803b15801561333557600080fd5b505af1158015613349573d6000803e3d6000fd5b50506040517f97e963041e952738788b9d4871d854d282065b8f90a464928d6528f2e9a4fd0b925060009150a1565b8015806134005750604051636eb1769f60e11b81526001600160a01b0384169063dd62ed3e906133ae9030908690600401614ffd565b60206040518083038186803b1580156133c657600080fd5b505afa1580156133da573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906133fe9190614f7c565b155b61341c5760405162461bcd60e51b815260040161073390615413565b611e638363095ea7b360e01b848460405160240161343b929190615042565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526145b2565b60606134818484600085614641565b949350505050565b60025460408051635aa6e67560e01b815290516000926001600160a01b031691635aa6e675916004808301926020929190829003018186803b1580156134ce57600080fd5b505afa1580156134e2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c669190614c0b565b60408051600180825281830190925260609182919060208083019080368337505060065482519293506001600160a01b03169183915060009061354557fe5b6001600160a01b0390921660209283029190910190910152905090565b611e638363a9059cbb60e01b848460405160240161343b929190615042565b6000828201838110156135a65760405162461bcd60e51b8152600401610733906151bf565b9392505050565b6006546040516370a0823160e01b8152600091829182916001600160a01b0316906370a08231906135e2903090600401614fe9565b60206040518083038186803b1580156135fa57600080fd5b505afa15801561360e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906136329190614f7c565b9050838110613648578360009250925050613683565b600061365f82613659848803614705565b90613581565b905084811061367657846000935093505050613683565b9250600091506136839050565b915091565b6000808080805b600d548110156137db576000600d82815481106136a857fe5b60009182526020909120015460405163052692b960e21b81526001600160a01b039091169063149a4ae4906136e1908a90600401615469565b60206040518083038186803b1580156136f957600080fd5b505afa15801561370d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137319190614f7c565b9050848111156137d257819350809450600d828154811061374e57fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b15801561379757600080fd5b505afa1580156137ab573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906137cf9190614f7c565b92505b5060010161368f565b5060006137f26137eb8388613581565b8590613fe7565b905060005b600d548110156138235783811461381b57613818600d828154811061166c57fe5b91505b6001016137f7565b50600061383287613659612d9b565b905061383e8282613fa5565b979650505050505050565b600060001981805b600d5481101561390d576000600d828154811061386a57fe5b60009182526020909120015460405163052692b960e21b81526001600160a01b039091169063149a4ae4906138a3908990600401615469565b60206040518083038186803b1580156138bb57600080fd5b505afa1580156138cf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906138f39190614f7c565b905083811015613904578192508093505b50600101613851565b506000805b600d548110156139f85782811461393a57613933600d828154811061166c57fe5b91506139f0565b6000600d828154811061394957fe5b600091825260209182902001546040805163c1590cd760e01b815290516001600160a01b039092169263c1590cd792600480840193829003018186803b15801561399257600080fd5b505afa1580156139a6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906139ca9190614f7c565b9050868110156139d8578096505b6139ec6139e58689613fe7565b8490613581565b9250505b600101613912565b506000613a0786613659612d9b565b9050613a138282613fa5565b9695505050505050565b600b5460ff1615613a2d576119d9565b600d54613a39576119d9565b600080600080613a47612598565b935093509350935082811115613af657600d8481548110613a6457fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b8152600401602060405180830381600087803b158015613abc57600080fd5b505af1158015613ad0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613af49190614dd1565b505b6006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613b27903090600401614fe9565b60206040518083038186803b158015613b3f57600080fd5b505afa158015613b53573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613b779190614f7c565b90508015613c1f57613bb1600d8481548110613b8f57fe5b6000918252602090912001546006546001600160a01b03908116911683613562565b600d8381548110613bbe57fe5b600091825260208220015460408051630d0e30db60e41b815290516001600160a01b039092169263d0e30db09260048084019382900301818387803b158015613c0657600080fd5b505af1158015613c1a573d6000803e3d6000fd5b505050505b505050505050565b6000610c66613c34610960565b614705565b60006135a683836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506149e3565b6000808281613c88610960565b6006546040516370a0823160e01b81529192506000916001600160a01b03909116906370a0823190613cbe903090600401614fe9565b60206040518083038186803b158015613cd657600080fd5b505afa158015613cea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613d0e9190614f7c565b90506000613d1c8284613581565b905082613d375781841115613d2f578193505b505050613f9e565b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf82390613d68903090600401614fe9565b6101206040518083038186803b158015613d8157600080fd5b505afa158015613d95573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613db99190614ee6565b60c00151905080821115613eb25780820396506000613dd88887613581565b9050600081118015613de957508084105b15613eac57613dfb613c348286613c39565b506006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613e2d903090600401614fe9565b60206040518083038186803b158015613e4557600080fd5b505afa158015613e59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613e7d9190614f7c565b905081811015613eaa5780891115613e9b5780985060009650613eaa565b613ea789820388614a0f565b96505b505b50613f99565b81810395506000613ec38787613581565b9050600081118015613ed457508084105b15613f9757613ee6613c348286613c39565b506006546040516370a0823160e01b81526000916001600160a01b0316906370a0823190613f18903090600401614fe9565b60206040518083038186803b158015613f3057600080fd5b505afa158015613f44573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613f689190614f7c565b905081811015613f955780881115613f865780975060009650613f95565b613f9288820388614a0f565b96505b505b505b505050505b9193909250565b60006135a683836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f000000000000815250614a25565b600082613ff657506000611ee6565b8282028284828161400357fe5b04146135a65760405162461bcd60e51b815260040161073390615277565b60065460009081906001600160a01b031673c02aaa39b223fe8d0a0e5c4f27ead9083c756cc21415614054575081611ee6565b600e5461010090046001600160a01b031661407957614072836119dc565b9050611ee6565b600e546040516303c0011560e51b81526101009091046001600160a01b03169063780022a0906140ad908690600401615469565b60206040518083038186803b1580156140c557600080fd5b505afa1580156140d9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135a69190614f7c565b60005b600d5481101561433c57600d818154811061411757fe5b6000918252602090912001546001600160a01b0384811691161415614334576000600d828154811061414557fe5b9060005260206000200160009054906101000a90046001600160a01b03166001600160a01b031663853828b66040518163ffffffff1660e01b8152600401602060405180830381600087803b15801561419d57600080fd5b505af11580156141b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906141d59190614dd1565b9050826141f957806141f95760405162461bcd60e51b8152600401610733906153ea565b600d5460001901821461426d57600d8054600019810190811061421857fe5b600091825260209091200154600d80546001600160a01b03909216918490811061423e57fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b031602179055505b600d80548061427857fe5b600082815260208120600019908301810180546001600160a01b03191690559091019091556006546040516370a0823160e01b81526001600160a01b03909116906370a08231906142cd903090600401614fe9565b60206040518083038186803b1580156142e557600080fd5b505afa1580156142f9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061431d9190614f7c565b111561432d5761432d6000613a1d565b5050610896565b600101614100565b5060405162461bcd60e51b8152600401610733906151f6565b6002546040516339ebf82360e01b81526000916001600160a01b0316906339ebf82390614386903090600401614fe9565b6101206040518083038186803b15801561439f57600080fd5b505afa1580156143b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906143d79190614ee6565b60c0015190506000806143e983613c7b565b50505050505050565b6006546001600160a01b03161561441b5760405162461bcd60e51b815260040161073390615240565b600280546001600160a01b0319166001600160a01b03868116919091179182905560408051637e062a3560e11b81529051929091169163fc0c546a91600480820192602092909190829003018186803b15801561447757600080fd5b505afa15801561448b573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906144af9190614c0b565b600680546001600160a01b0319166001600160a01b0392831617908190556144db911685600019613378565b600380546001600160a01b038086166001600160a01b03199283161790925560048054858416908316178082556005805486861694169390931790925560006007819055620151806008556064600955600a5560025460405163095ea7b360e01b81529084169363095ea7b393614559939116916000199101615042565b602060405180830381600087803b15801561457357600080fd5b505af1158015614587573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906145ab9190614dd1565b5050505050565b6060614607826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166134729092919063ffffffff16565b805190915015611e6357808060200190518101906146259190614dd1565b611e635760405162461bcd60e51b81526004016107339061537c565b606061464c85614a5c565b6146685760405162461bcd60e51b815260040161073390615320565b60006060866001600160a01b031685876040516146859190614fcd565b60006040518083038185875af1925050503d80600081146146c2576040519150601f19603f3d011682016040523d82523d6000602084013e6146c7565b606091505b509150915081156146db5791506134819050565b8051156146eb5780518082602001fd5b8360405162461bcd60e51b8152600401610733919061511a565b600d5460009061471757506000610db8565b600c5482101561472957506000610db8565b506000805b82821015610cf9576000196000805b600d5481101561488557600d818154811061475457fe5b6000918252602091829020015460408051635be9b2d360e01b815290516001600160a01b0390921692635be9b2d392600480840193829003018186803b15801561479d57600080fd5b505afa1580156147b1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906147d59190614dd1565b1561487d576000600d82815481106147e957fe5b60009182526020918290200154604080516357ded9c960e01b815290516001600160a01b03909216926357ded9c992600480840193829003018186803b15801561483257600080fd5b505afa158015614846573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061486a9190614f7c565b90508381101561487b578093508192505b505b60010161473d565b50600d818154811061489357fe5b6000918252602091829020015460408051635be9b2d360e01b815290516001600160a01b0390921692635be9b2d392600480840193829003018186803b1580156148dc57600080fd5b505afa1580156148f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149149190614dd1565b61492057505050610db8565b6149c4600d828154811061493057fe5b600091825260209091200154604051632e1a7d4d60e01b81526001600160a01b0390911690632e1a7d4d9061496b90888a0390600401615469565b602060405180830381600087803b15801561498557600080fd5b505af1158015614999573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906149bd9190614f7c565b8590613581565b9350600190920191600683106149dc57505050610db8565b505061472e565b60008184841115614a075760405162461bcd60e51b8152600401610733919061511a565b505050900390565b6000818310614a1e57816135a6565b5090919050565b60008183614a465760405162461bcd60e51b8152600401610733919061511a565b506000838581614a5257fe5b0495945050505050565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590613481575050151592915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10614ad65782800160ff19823516178555614b03565b82800160010185558215614b03579182015b82811115614b03578235825591602001919060010190614ae8565b50614b0f929150614b90565b5090565b6040518061012001604052806000815260200160008152602001600081526020016000815260200160008152602001600081526020016000815260200160008152602001600081525090565b604051806080016040528060608152602001600081526020016000815260200160006001600160a01b031681525090565b5b80821115614b0f5760008155600101614b91565b600060408284031215614bb6578081fd5b614bc0604061551c565b90508135614bcd8161558f565b8152602082013561ffff81168114614be457600080fd5b602082015292915050565b600060208284031215614c00578081fd5b81356135a68161558f565b600060208284031215614c1c578081fd5b81516135a68161558f565b60008060008060808587031215614c3c578283fd5b8435614c478161558f565b93506020850135614c578161558f565b92506040850135614c678161558f565b91506060850135614c778161558f565b939692955090935050565b60006020808385031215614c94578182fd5b823567ffffffffffffffff811115614caa578283fd5b8301601f81018513614cba578283fd5b8035614ccd614cc882615543565b61551c565b818152838101908385016040808502860187018a1015614ceb578788fd5b8795505b84861015614d1757614d018a83614ba5565b8452600195909501949286019290810190614cef565b509098975050505050505050565b60006020808385031215614d37578182fd5b825167ffffffffffffffff811115614d4d578283fd5b8301601f81018513614d5d578283fd5b8051614d6b614cc882615543565b8181528381019083850185840285018601891015614d87578687fd5b8694505b83851015614da9578051835260019490940193918501918501614d8b565b50979650505050505050565b600060208284031215614dc6578081fd5b81356135a6816155a4565b600060208284031215614de2578081fd5b81516135a6816155a4565b60008060208385031215614dff578182fd5b823567ffffffffffffffff80821115614e16578384fd5b818501915085601f830112614e29578384fd5b813581811115614e37578485fd5b866020828501011115614e48578485fd5b60209290920196919550909350505050565b600060208284031215614e6b578081fd5b815167ffffffffffffffff80821115614e82578283fd5b818401915084601f830112614e95578283fd5b815181811115614ea3578384fd5b614eb6601f8201601f191660200161551c565b9150808252856020828501011115614ecc578384fd5b614edd816020840160208601615563565b50949350505050565b6000610120808385031215614ef9578182fd5b614f028161551c565b9050825181526020830151602082015260408301516040820152606083015160608201526080830151608082015260a083015160a082015260c083015160c082015260e083015160e08201526101008084015181830152508091505092915050565b600060208284031215614f75578081fd5b5035919050565b600060208284031215614f8d578081fd5b5051919050565b6001600160a01b03169052565b60008151808452614fb9816020860160208601615563565b601f01601f19169290920160200192915050565b60008251614fdf818460208701615563565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03948516815292841660208401529083166040830152909116606082015260800190565b6001600160a01b03929092168252602082015260400190565b60208082528251828201819052600091906040908185019080840286018301878501865b83811015614d1757603f198984030185528151608081518186526150a582870182614fa1565b9150508882015189860152878201518886015260608083015192506150cc81870184614f94565b50958801959350509086019060010161507f565b901515815260200190565b60006020825282602083015282846040840137818301604090810191909152601f909201601f19160101919050565b6000602082526135a66020830184614fa1565b6020808252600b908201526a085cdd1c985d1959da5cdd60aa1b604082015260600190565b6020808252600f908201526e2ab73237b1b5b2b2102632b73232b960891b604082015260600190565b602080825260059082015264085dd85b9d60da1b604082015260600190565b6020808252600b908201526a05348415245213d313030360ac1b604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252600a90820152692727aa102622a72222a960b11b604082015260600190565b6020808252600c908201526b216865616c7468636865636b60a01b604082015260600190565b6020808252601c908201527f537472617465677920616c726561647920696e697469616c697a656400000000604082015260600190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b602080825260069082015265085d985d5b1d60d21b604082015260600190565b6020808252600790820152662173686172657360c81b604082015260600190565b6020808252600d908201526c105b1c9958591e481059191959609a1b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252600b908201526a08585d5d1a1bdc9a5e995960aa1b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b6020808252600a9082015269085c1c9bdd1958dd195960b21b604082015260600190565b6020808252600f908201526e15d2551211149055c8119052531151608a1b604082015260600190565b60208082526036908201527f5361666545524332303a20617070726f76652066726f6d206e6f6e2d7a65726f60408201527520746f206e6f6e2d7a65726f20616c6c6f77616e636560501b606082015260800190565b90815260200190565b60006040820184835260206040818501528185518084526060860191508287019350845b818110156154bb5784516001600160a01b031683529383019391830191600101615496565b5090979650505050505050565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b948552602085019390935260408401919091526060830152608082015260a00190565b60405181810167ffffffffffffffff8111828210171561553b57600080fd5b604052919050565b600067ffffffffffffffff821115615559578081fd5b5060209081020190565b60005b8381101561557e578181015183820152602001615566565b83811115612ec85750506000910152565b6001600160a01b03811681146119d957600080fd5b80151581146119d957600080fdfea26469706673582212207a224399c14c11ec8e7f566fabefc939a638034f3ad5dd97286939b9860a8e5f64736f6c634300060c0033

Verified Source Code Partial Match

Compiler: v0.6.12+commit.27d51765 EVM: istanbul Optimization: Yes (200 runs)
Strategy.sol 1985 lines
// SPDX-License-Identifier: GPL-3.0

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

// Global Enums and Structs



struct StrategyParams {
    uint256 performanceFee;
    uint256 activation;
    uint256 debtRatio;
    uint256 minDebtPerHarvest;
    uint256 maxDebtPerHarvest;
    uint256 lastReport;
    uint256 totalDebt;
    uint256 totalGain;
    uint256 totalLoss;
}

// Part: IGenericLender

interface IGenericLender {
    function lenderName() external view returns (string memory);

    function nav() external view returns (uint256);

    function strategy() external view returns (address);

    function apr() external view returns (uint256);

    function weightedApr() external view returns (uint256);

    function withdraw(uint256 amount) external returns (uint256);

    function emergencyWithdraw(uint256 amount) external;

    function deposit() external;

    function withdrawAll() external returns (bool);

    function hasAssets() external view returns (bool);

    function aprAfterDeposit(uint256 amount) external view returns (uint256);

    function setDust(uint256 _dust) external;

    function sweep(address _token) external;
}

// Part: IUni

interface IUni {
    function getAmountsOut(uint256 amountIn, address[] calldata path) external view returns (uint256[] memory amounts);
}

// Part: IWantToEth

interface IWantToEth {
    function wantToEth(uint256 input) external view returns (uint256);

    function ethToWant(uint256 input) external view returns (uint256);
}

// Part: OpenZeppelin/[email protected]/Address

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // According to EIP-1052, 0x0 is the value returned for not-yet created accounts
        // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned
        // for accounts without code, i.e. `keccak256('')`
        bytes32 codehash;
        bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;
        // solhint-disable-next-line no-inline-assembly
        assembly { codehash := extcodehash(account) }
        return (codehash != accountHash && codehash != 0x0);
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return _functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        return _functionCallWithValue(target, data, value, errorMessage);
    }

    function _functionCallWithValue(address target, bytes memory data, uint256 weiValue, string memory errorMessage) private returns (bytes memory) {
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: weiValue }(data);
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// Part: OpenZeppelin/[email protected]/IERC20

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

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

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

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @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);
}

// Part: OpenZeppelin/[email protected]/Math

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

// Part: OpenZeppelin/[email protected]/SafeMath

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");

        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        return sub(a, b, "SafeMath: subtraction overflow");
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        uint256 c = a - b;

        return c;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        return div(a, b, "SafeMath: division by zero");
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        return mod(a, b, "SafeMath: modulo by zero");
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts with custom message when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b != 0, errorMessage);
        return a % b;
    }
}

// Part: iearn-finance/[email protected]/HealthCheck

interface HealthCheck {
    function check(
        uint256 profit,
        uint256 loss,
        uint256 debtPayment,
        uint256 debtOutstanding,
        uint256 totalDebt
    ) external view returns (bool);
}

// Part: OpenZeppelin/[email protected]/SafeERC20

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 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 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value, "SafeERC20: decreased allowance below zero");
        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), 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 data The call data (encoded using abi.encode or one of its variants).
     */
    function _callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "SafeERC20: low-level call failed");
        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

// Part: iearn-finance/[email protected]/VaultAPI

interface VaultAPI is IERC20 {
    function name() external view returns (string calldata);

    function symbol() external view returns (string calldata);

    function decimals() external view returns (uint256);

    function apiVersion() external pure returns (string memory);

    function permit(
        address owner,
        address spender,
        uint256 amount,
        uint256 expiry,
        bytes calldata signature
    ) external returns (bool);

    // NOTE: Vyper produces multiple signatures for a given function with "default" args
    function deposit() external returns (uint256);

    function deposit(uint256 amount) external returns (uint256);

    function deposit(uint256 amount, address recipient) external returns (uint256);

    // NOTE: Vyper produces multiple signatures for a given function with "default" args
    function withdraw() external returns (uint256);

    function withdraw(uint256 maxShares) external returns (uint256);

    function withdraw(uint256 maxShares, address recipient) external returns (uint256);

    function token() external view returns (address);

    function strategies(address _strategy) external view returns (StrategyParams memory);

    function pricePerShare() external view returns (uint256);

    function totalAssets() external view returns (uint256);

    function depositLimit() external view returns (uint256);

    function maxAvailableShares() external view returns (uint256);

    /**
     * View how much the Vault would increase this Strategy's borrow limit,
     * based on its present performance (since its last report). Can be used to
     * determine expectedReturn in your Strategy.
     */
    function creditAvailable() external view returns (uint256);

    /**
     * View how much the Vault would like to pull back from the Strategy,
     * based on its present performance (since its last report). Can be used to
     * determine expectedReturn in your Strategy.
     */
    function debtOutstanding() external view returns (uint256);

    /**
     * View how much the Vault expect this Strategy to return at the current
     * block, based on its present performance (since its last report). Can be
     * used to determine expectedReturn in your Strategy.
     */
    function expectedReturn() external view returns (uint256);

    /**
     * This is the main contact point where the Strategy interacts with the
     * Vault. It is critical that this call is handled as intended by the
     * Strategy. Therefore, this function will be called by BaseStrategy to
     * make sure the integration is correct.
     */
    function report(
        uint256 _gain,
        uint256 _loss,
        uint256 _debtPayment
    ) external returns (uint256);

    /**
     * This function should only be used in the scenario where the Strategy is
     * being retired but no migration of the positions are possible, or in the
     * extreme scenario that the Strategy needs to be put into "Emergency Exit"
     * mode in order for it to exit as quickly as possible. The latter scenario
     * could be for any reason that is considered "critical" that the Strategy
     * exits its position as fast as possible, such as a sudden change in
     * market conditions leading to losses, or an imminent failure in an
     * external dependency.
     */
    function revokeStrategy() external;

    /**
     * View the governance address of the Vault to assert privileged functions
     * can only be called by governance. The Strategy serves the Vault, so it
     * is subject to governance defined by the Vault.
     */
    function governance() external view returns (address);

    /**
     * View the management address of the Vault to assert privileged functions
     * can only be called by management. The Strategy serves the Vault, so it
     * is subject to management defined by the Vault.
     */
    function management() external view returns (address);

    /**
     * View the guardian address of the Vault to assert privileged functions
     * can only be called by guardian. The Strategy serves the Vault, so it
     * is subject to guardian defined by the Vault.
     */
    function guardian() external view returns (address);
}

// Part: iearn-finance/[email protected]/BaseStrategy

/**
 * @title Yearn Base Strategy
 * @author yearn.finance
 * @notice
 *  BaseStrategy implements all of the required functionality to interoperate
 *  closely with the Vault contract. This contract should be inherited and the
 *  abstract methods implemented to adapt the Strategy to the particular needs
 *  it has to create a return.
 *
 *  Of special interest is the relationship between `harvest()` and
 *  `vault.report()'. `harvest()` may be called simply because enough time has
 *  elapsed since the last report, and not because any funds need to be moved
 *  or positions adjusted. This is critical so that the Vault may maintain an
 *  accurate picture of the Strategy's performance. See  `vault.report()`,
 *  `harvest()`, and `harvestTrigger()` for further details.
 */

abstract contract BaseStrategy {
    using SafeMath for uint256;
    using SafeERC20 for IERC20;
    string public metadataURI;

    // health checks
    bool public doHealthCheck;
    address public healthCheck;

    /**
     * @notice
     *  Used to track which version of `StrategyAPI` this Strategy
     *  implements.
     * @dev The Strategy's version must match the Vault's `API_VERSION`.
     * @return A string which holds the current API version of this contract.
     */
    function apiVersion() public pure returns (string memory) {
        return "0.4.3";
    }

    /**
     * @notice This Strategy's name.
     * @dev
     *  You can use this field to manage the "version" of this Strategy, e.g.
     *  `StrategySomethingOrOtherV1`. However, "API Version" is managed by
     *  `apiVersion()` function above.
     * @return This Strategy's name.
     */
    function name() external view virtual returns (string memory);

    /**
     * @notice
     *  The amount (priced in want) of the total assets managed by this strategy should not count
     *  towards Yearn's TVL calculations.
     * @dev
     *  You can override this field to set it to a non-zero value if some of the assets of this
     *  Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault.
     *  Note that this value must be strictly less than or equal to the amount provided by
     *  `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets.
     *  Also note that this value is used to determine the total assets under management by this
     *  strategy, for the purposes of computing the management fee in `Vault`
     * @return
     *  The amount of assets this strategy manages that should not be included in Yearn's Total Value
     *  Locked (TVL) calculation across it's ecosystem.
     */
    function delegatedAssets() external view virtual returns (uint256) {
        return 0;
    }

    VaultAPI public vault;
    address public strategist;
    address public rewards;
    address public keeper;

    IERC20 public want;

    // So indexers can keep track of this
    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);

    event UpdatedStrategist(address newStrategist);

    event UpdatedKeeper(address newKeeper);

    event UpdatedRewards(address rewards);

    event UpdatedMinReportDelay(uint256 delay);

    event UpdatedMaxReportDelay(uint256 delay);

    event UpdatedProfitFactor(uint256 profitFactor);

    event UpdatedDebtThreshold(uint256 debtThreshold);

    event EmergencyExitEnabled();

    event UpdatedMetadataURI(string metadataURI);

    // The minimum number of seconds between harvest calls. See
    // `setMinReportDelay()` for more details.
    uint256 public minReportDelay;

    // The maximum number of seconds between harvest calls. See
    // `setMaxReportDelay()` for more details.
    uint256 public maxReportDelay;

    // The minimum multiple that `callCost` must be above the credit/profit to
    // be "justifiable". See `setProfitFactor()` for more details.
    uint256 public profitFactor;

    // Use this to adjust the threshold at which running a debt causes a
    // harvest trigger. See `setDebtThreshold()` for more details.
    uint256 public debtThreshold;

    // See note on `setEmergencyExit()`.
    bool public emergencyExit;

    // modifiers
    modifier onlyAuthorized() {
        require(msg.sender == strategist || msg.sender == governance(), "!authorized");
        _;
    }

    modifier onlyEmergencyAuthorized() {
        require(
            msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management(),
            "!authorized"
        );
        _;
    }

    modifier onlyStrategist() {
        require(msg.sender == strategist, "!strategist");
        _;
    }

    modifier onlyGovernance() {
        require(msg.sender == governance(), "!authorized");
        _;
    }

    modifier onlyKeepers() {
        require(
            msg.sender == keeper ||
                msg.sender == strategist ||
                msg.sender == governance() ||
                msg.sender == vault.guardian() ||
                msg.sender == vault.management(),
            "!authorized"
        );
        _;
    }

    modifier onlyVaultManagers() {
        require(msg.sender == vault.management() || msg.sender == governance(), "!authorized");
        _;
    }

    constructor(address _vault) public {
        _initialize(_vault, msg.sender, msg.sender, msg.sender);
    }

    /**
     * @notice
     *  Initializes the Strategy, this is called only once, when the
     *  contract is deployed.
     * @dev `_vault` should implement `VaultAPI`.
     * @param _vault The address of the Vault responsible for this Strategy.
     * @param _strategist The address to assign as `strategist`.
     * The strategist is able to change the reward address
     * @param _rewards  The address to use for pulling rewards.
     * @param _keeper The adddress of the _keeper. _keeper
     * can harvest and tend a strategy.
     */
    function _initialize(
        address _vault,
        address _strategist,
        address _rewards,
        address _keeper
    ) internal {
        require(address(want) == address(0), "Strategy already initialized");

        vault = VaultAPI(_vault);
        want = IERC20(vault.token());
        want.safeApprove(_vault, uint256(-1)); // Give Vault unlimited access (might save gas)
        strategist = _strategist;
        rewards = _rewards;
        keeper = _keeper;

        // initialize variables
        minReportDelay = 0;
        maxReportDelay = 86400;
        profitFactor = 100;
        debtThreshold = 0;

        vault.approve(rewards, uint256(-1)); // Allow rewards to be pulled
    }

    function setHealthCheck(address _healthCheck) external onlyVaultManagers {
        healthCheck = _healthCheck;
    }

    function setDoHealthCheck(bool _doHealthCheck) external onlyVaultManagers {
        doHealthCheck = _doHealthCheck;
    }

    /**
     * @notice
     *  Used to change `strategist`.
     *
     *  This may only be called by governance or the existing strategist.
     * @param _strategist The new address to assign as `strategist`.
     */
    function setStrategist(address _strategist) external onlyAuthorized {
        require(_strategist != address(0));
        strategist = _strategist;
        emit UpdatedStrategist(_strategist);
    }

    /**
     * @notice
     *  Used to change `keeper`.
     *
     *  `keeper` is the only address that may call `tend()` or `harvest()`,
     *  other than `governance()` or `strategist`. However, unlike
     *  `governance()` or `strategist`, `keeper` may *only* call `tend()`
     *  and `harvest()`, and no other authorized functions, following the
     *  principle of least privilege.
     *
     *  This may only be called by governance or the strategist.
     * @param _keeper The new address to assign as `keeper`.
     */
    function setKeeper(address _keeper) external onlyAuthorized {
        require(_keeper != address(0));
        keeper = _keeper;
        emit UpdatedKeeper(_keeper);
    }

    /**
     * @notice
     *  Used to change `rewards`. EOA or smart contract which has the permission
     *  to pull rewards from the vault.
     *
     *  This may only be called by the strategist.
     * @param _rewards The address to use for pulling rewards.
     */
    function setRewards(address _rewards) external onlyStrategist {
        require(_rewards != address(0));
        vault.approve(rewards, 0);
        rewards = _rewards;
        vault.approve(rewards, uint256(-1));
        emit UpdatedRewards(_rewards);
    }

    /**
     * @notice
     *  Used to change `minReportDelay`. `minReportDelay` is the minimum number
     *  of blocks that should pass for `harvest()` to be called.
     *
     *  For external keepers (such as the Keep3r network), this is the minimum
     *  time between jobs to wait. (see `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _delay The minimum number of seconds to wait between harvests.
     */
    function setMinReportDelay(uint256 _delay) external onlyAuthorized {
        minReportDelay = _delay;
        emit UpdatedMinReportDelay(_delay);
    }

    /**
     * @notice
     *  Used to change `maxReportDelay`. `maxReportDelay` is the maximum number
     *  of blocks that should pass for `harvest()` to be called.
     *
     *  For external keepers (such as the Keep3r network), this is the maximum
     *  time between jobs to wait. (see `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _delay The maximum number of seconds to wait between harvests.
     */
    function setMaxReportDelay(uint256 _delay) external onlyAuthorized {
        maxReportDelay = _delay;
        emit UpdatedMaxReportDelay(_delay);
    }

    /**
     * @notice
     *  Used to change `profitFactor`. `profitFactor` is used to determine
     *  if it's worthwhile to harvest, given gas costs. (See `harvestTrigger()`
     *  for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _profitFactor A ratio to multiply anticipated
     * `harvest()` gas cost against.
     */
    function setProfitFactor(uint256 _profitFactor) external onlyAuthorized {
        profitFactor = _profitFactor;
        emit UpdatedProfitFactor(_profitFactor);
    }

    /**
     * @notice
     *  Sets how far the Strategy can go into loss without a harvest and report
     *  being required.
     *
     *  By default this is 0, meaning any losses would cause a harvest which
     *  will subsequently report the loss to the Vault for tracking. (See
     *  `harvestTrigger()` for more details.)
     *
     *  This may only be called by governance or the strategist.
     * @param _debtThreshold How big of a loss this Strategy may carry without
     * being required to report to the Vault.
     */
    function setDebtThreshold(uint256 _debtThreshold) external onlyAuthorized {
        debtThreshold = _debtThreshold;
        emit UpdatedDebtThreshold(_debtThreshold);
    }

    /**
     * @notice
     *  Used to change `metadataURI`. `metadataURI` is used to store the URI
     * of the file describing the strategy.
     *
     *  This may only be called by governance or the strategist.
     * @param _metadataURI The URI that describe the strategy.
     */
    function setMetadataURI(string calldata _metadataURI) external onlyAuthorized {
        metadataURI = _metadataURI;
        emit UpdatedMetadataURI(_metadataURI);
    }

    /**
     * Resolve governance address from Vault contract, used to make assertions
     * on protected functions in the Strategy.
     */
    function governance() internal view returns (address) {
        return vault.governance();
    }

    /**
     * @notice
     *  Provide an accurate conversion from `_amtInWei` (denominated in wei)
     *  to `want` (using the native decimal characteristics of `want`).
     * @dev
     *  Care must be taken when working with decimals to assure that the conversion
     *  is compatible. As an example:
     *
     *      given 1e17 wei (0.1 ETH) as input, and want is USDC (6 decimals),
     *      with USDC/ETH = 1800, this should give back 1800000000 (180 USDC)
     *
     * @param _amtInWei The amount (in wei/1e-18 ETH) to convert to `want`
     * @return The amount in `want` of `_amtInEth` converted to `want`
     **/
    function ethToWant(uint256 _amtInWei) public view virtual returns (uint256);

    /**
     * @notice
     *  Provide an accurate estimate for the total amount of assets
     *  (principle + return) that this Strategy is currently managing,
     *  denominated in terms of `want` tokens.
     *
     *  This total should be "realizable" e.g. the total value that could
     *  *actually* be obtained from this Strategy if it were to divest its
     *  entire position based on current on-chain conditions.
     * @dev
     *  Care must be taken in using this function, since it relies on external
     *  systems, which could be manipulated by the attacker to give an inflated
     *  (or reduced) value produced by this function, based on current on-chain
     *  conditions (e.g. this function is possible to influence through
     *  flashloan attacks, oracle manipulations, or other DeFi attack
     *  mechanisms).
     *
     *  It is up to governance to use this function to correctly order this
     *  Strategy relative to its peers in the withdrawal queue to minimize
     *  losses for the Vault based on sudden withdrawals. This value should be
     *  higher than the total debt of the Strategy and higher than its expected
     *  value to be "safe".
     * @return The estimated total assets in this Strategy.
     */
    function estimatedTotalAssets() public view virtual returns (uint256);

    /*
     * @notice
     *  Provide an indication of whether this strategy is currently "active"
     *  in that it is managing an active position, or will manage a position in
     *  the future. This should correlate to `harvest()` activity, so that Harvest
     *  events can be tracked externally by indexing agents.
     * @return True if the strategy is actively managing a position.
     */
    function isActive() public view returns (bool) {
        return vault.strategies(address(this)).debtRatio > 0 || estimatedTotalAssets() > 0;
    }

    /**
     * Perform any Strategy unwinding or other calls necessary to capture the
     * "free return" this Strategy has generated since the last time its core
     * position(s) were adjusted. Examples include unwrapping extra rewards.
     * This call is only used during "normal operation" of a Strategy, and
     * should be optimized to minimize losses as much as possible.
     *
     * This method returns any realized profits and/or realized losses
     * incurred, and should return the total amounts of profits/losses/debt
     * payments (in `want` tokens) for the Vault's accounting (e.g.
     * `want.balanceOf(this) >= _debtPayment + _profit`).
     *
     * `_debtOutstanding` will be 0 if the Strategy is not past the configured
     * debt limit, otherwise its value will be how far past the debt limit
     * the Strategy is. The Strategy's debt limit is configured in the Vault.
     *
     * NOTE: `_debtPayment` should be less than or equal to `_debtOutstanding`.
     *       It is okay for it to be less than `_debtOutstanding`, as that
     *       should only used as a guide for how much is left to pay back.
     *       Payments should be made to minimize loss from slippage, debt,
     *       withdrawal fees, etc.
     *
     * See `vault.debtOutstanding()`.
     */
    function prepareReturn(uint256 _debtOutstanding)
        internal
        virtual
        returns (
            uint256 _profit,
            uint256 _loss,
            uint256 _debtPayment
        );

    /**
     * Perform any adjustments to the core position(s) of this Strategy given
     * what change the Vault made in the "investable capital" available to the
     * Strategy. Note that all "free capital" in the Strategy after the report
     * was made is available for reinvestment. Also note that this number
     * could be 0, and you should handle that scenario accordingly.
     *
     * See comments regarding `_debtOutstanding` on `prepareReturn()`.
     */
    function adjustPosition(uint256 _debtOutstanding) internal virtual;

    /**
     * Liquidate up to `_amountNeeded` of `want` of this strategy's positions,
     * irregardless of slippage. Any excess will be re-invested with `adjustPosition()`.
     * This function should return the amount of `want` tokens made available by the
     * liquidation. If there is a difference between them, `_loss` indicates whether the
     * difference is due to a realized loss, or if there is some other sitution at play
     * (e.g. locked funds) where the amount made available is less than what is needed.
     *
     * NOTE: The invariant `_liquidatedAmount + _loss <= _amountNeeded` should always be maintained
     */
    function liquidatePosition(uint256 _amountNeeded) internal virtual returns (uint256 _liquidatedAmount, uint256 _loss);

    /**
     * Liquidate everything and returns the amount that got freed.
     * This function is used during emergency exit instead of `prepareReturn()` to
     * liquidate all of the Strategy's positions back to the Vault.
     */

    function liquidateAllPositions() internal virtual returns (uint256 _amountFreed);

    /**
     * @notice
     *  Provide a signal to the keeper that `tend()` should be called. The
     *  keeper will provide the estimated gas cost that they would pay to call
     *  `tend()`, and this function should use that estimate to make a
     *  determination if calling it is "worth it" for the keeper. This is not
     *  the only consideration into issuing this trigger, for example if the
     *  position would be negatively affected if `tend()` is not called
     *  shortly, then this can return `true` even if the keeper might be
     *  "at a loss" (keepers are always reimbursed by Yearn).
     * @dev
     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
     *
     *  This call and `harvestTrigger()` should never return `true` at the same
     *  time.
     * @param callCostInWei The keeper's estimated gas cost to call `tend()` (in wei).
     * @return `true` if `tend()` should be called, `false` otherwise.
     */
    function tendTrigger(uint256 callCostInWei) public view virtual returns (bool) {
        // We usually don't need tend, but if there are positions that need
        // active maintainence, overriding this function is how you would
        // signal for that.
        // If your implementation uses the cost of the call in want, you can
        // use uint256 callCost = ethToWant(callCostInWei);

        return false;
    }

    /**
     * @notice
     *  Adjust the Strategy's position. The purpose of tending isn't to
     *  realize gains, but to maximize yield by reinvesting any returns.
     *
     *  See comments on `adjustPosition()`.
     *
     *  This may only be called by governance, the strategist, or the keeper.
     */
    function tend() external onlyKeepers {
        // Don't take profits with this call, but adjust for better gains
        adjustPosition(vault.debtOutstanding());
    }

    /**
     * @notice
     *  Provide a signal to the keeper that `harvest()` should be called. The
     *  keeper will provide the estimated gas cost that they would pay to call
     *  `harvest()`, and this function should use that estimate to make a
     *  determination if calling it is "worth it" for the keeper. This is not
     *  the only consideration into issuing this trigger, for example if the
     *  position would be negatively affected if `harvest()` is not called
     *  shortly, then this can return `true` even if the keeper might be "at a
     *  loss" (keepers are always reimbursed by Yearn).
     * @dev
     *  `callCostInWei` must be priced in terms of `wei` (1e-18 ETH).
     *
     *  This call and `tendTrigger` should never return `true` at the
     *  same time.
     *
     *  See `min/maxReportDelay`, `profitFactor`, `debtThreshold` to adjust the
     *  strategist-controlled parameters that will influence whether this call
     *  returns `true` or not. These parameters will be used in conjunction
     *  with the parameters reported to the Vault (see `params`) to determine
     *  if calling `harvest()` is merited.
     *
     *  It is expected that an external system will check `harvestTrigger()`.
     *  This could be a script run off a desktop or cloud bot (e.g.
     *  https://github.com/iearn-finance/yearn-vaults/blob/main/scripts/keep.py),
     *  or via an integration with the Keep3r network (e.g.
     *  https://github.com/Macarse/GenericKeep3rV2/blob/master/contracts/keep3r/GenericKeep3rV2.sol).
     * @param callCostInWei The keeper's estimated gas cost to call `harvest()` (in wei).
     * @return `true` if `harvest()` should be called, `false` otherwise.
     */
    function harvestTrigger(uint256 callCostInWei) public view virtual returns (bool) {
        uint256 callCost = ethToWant(callCostInWei);
        StrategyParams memory params = vault.strategies(address(this));

        // Should not trigger if Strategy is not activated
        if (params.activation == 0) return false;

        // Should not trigger if we haven't waited long enough since previous harvest
        if (block.timestamp.sub(params.lastReport) < minReportDelay) return false;

        // Should trigger if hasn't been called in a while
        if (block.timestamp.sub(params.lastReport) >= maxReportDelay) return true;

        // If some amount is owed, pay it back
        // NOTE: Since debt is based on deposits, it makes sense to guard against large
        //       changes to the value from triggering a harvest directly through user
        //       behavior. This should ensure reasonable resistance to manipulation
        //       from user-initiated withdrawals as the outstanding debt fluctuates.
        uint256 outstanding = vault.debtOutstanding();
        if (outstanding > debtThreshold) return true;

        // Check for profits and losses
        uint256 total = estimatedTotalAssets();
        // Trigger if we have a loss to report
        if (total.add(debtThreshold) < params.totalDebt) return true;

        uint256 profit = 0;
        if (total > params.totalDebt) profit = total.sub(params.totalDebt); // We've earned a profit!

        // Otherwise, only trigger if it "makes sense" economically (gas cost
        // is <N% of value moved)
        uint256 credit = vault.creditAvailable();
        return (profitFactor.mul(callCost) < credit.add(profit));
    }

    /**
     * @notice
     *  Harvests the Strategy, recognizing any profits or losses and adjusting
     *  the Strategy's position.
     *
     *  In the rare case the Strategy is in emergency shutdown, this will exit
     *  the Strategy's position.
     *
     *  This may only be called by governance, the strategist, or the keeper.
     * @dev
     *  When `harvest()` is called, the Strategy reports to the Vault (via
     *  `vault.report()`), so in some cases `harvest()` must be called in order
     *  to take in profits, to borrow newly available funds from the Vault, or
     *  otherwise adjust its position. In other cases `harvest()` must be
     *  called to report to the Vault on the Strategy's position, especially if
     *  any losses have occurred.
     */
    function harvest() external onlyKeepers {
        uint256 profit = 0;
        uint256 loss = 0;
        uint256 debtOutstanding = vault.debtOutstanding();
        uint256 debtPayment = 0;
        if (emergencyExit) {
            // Free up as much capital as possible
            uint256 amountFreed = liquidateAllPositions();
            if (amountFreed < debtOutstanding) {
                loss = debtOutstanding.sub(amountFreed);
            } else if (amountFreed > debtOutstanding) {
                profit = amountFreed.sub(debtOutst...

// [truncated — 76371 bytes total]

Read Contract

SECONDSPERYEAR 0xaf306e16 → uint256
apiVersion 0x25829410 → string
debtThreshold 0x1d12f28b → uint256
delegatedAssets 0x8e6350e2 → uint256
doHealthCheck 0x6718835f → bool
emergencyExit 0x5641ec03 → bool
estimateAdjustPosition 0xd6c38271 → uint256, uint256, uint256, uint256
estimatedAPR 0x5a5cd45e → uint256
estimatedFutureAPR 0x397dc149 → uint256
estimatedTotalAssets 0xefbb5cb0 → uint256
ethToWant 0x780022a0 → uint256
externalOracle 0x46d8cf3f → bool
harvestTrigger 0xed882c2b → bool
healthCheck 0xb252720b → address
isActive 0x22f3e2d4 → bool
keeper 0xaced1661 → address
lendStatuses 0xfcc5f59a → tuple[]
lenders 0x929eea21 → address
lentTotalAssets 0x0e6e15f0 → uint256
maxReportDelay 0x28b7ccf7 → uint256
metadataURI 0x03ee438c → string
minReportDelay 0x95e80c50 → uint256
name 0x06fdde03 → string
numLenders 0xbb927c46 → uint256
profitFactor 0x8cdfe166 → uint256
rewards 0x9ec5a894 → address
strategist 0x1fe4a686 → address
tendTrigger 0x650d1880 → bool
uniswapRouter 0x735de9f7 → address
vault 0xfbfa77cf → address
want 0x1f1fcd51 → address
wantToEthOracle 0x2a5dc8c1 → address
weth 0x3fc8cef3 → address
withdrawalThreshold 0x7985fd51 → uint256

Write Contract 25 functions

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

addLender 0x93084b34
address a
clone 0x8124b78e
address _vault
returns: address
clone 0xd0511842
address _vault
address _strategist
address _rewards
address _keeper
returns: address
forceRemoveLender 0x76ee75d8
address a
harvest 0x4641257d
No parameters
initialize 0xf8c8765e
address _vault
address _strategist
address _rewards
address _keeper
manualAllocation 0x6e96b8d6
tuple[] _newPositions
migrate 0xce5494bb
address _newStrategy
safeRemoveLender 0x8baf2957
address a
setDebtThreshold 0x0f969b87
uint256 _debtThreshold
setDoHealthCheck 0xac00ff26
bool _doHealthCheck
setEmergencyExit 0xfcf2d0ad
No parameters
setHealthCheck 0x11bc8245
address _healthCheck
setKeeper 0x748747e6
address _keeper
setMaxReportDelay 0xf017c92f
uint256 _delay
setMetadataURI 0x750521f5
string _metadataURI
setMinReportDelay 0x39a172a8
uint256 _delay
setPriceOracle 0x530e784f
address _oracle
setProfitFactor 0x91397ab4
uint256 _profitFactor
setRewards 0xec38a862
address _rewards
setStrategist 0xc7b9d530
address _strategist
setWithdrawalThreshold 0x4786b0cb
uint256 _threshold
sweep 0x01681a62
address _token
tend 0x440368a3
No parameters
withdraw 0x2e1a7d4d
uint256 _amountNeeded
returns: uint256

Recent Transactions

No transactions found for this address