logo
bg_imgbg_imgbg_imgbg_img
exclamation mark iconReport an issue

If you notice some outdated information please let us know!

close icon
Name
Email
Your message
arrow-left

Yearn

93%

Previous versions

Process Quality Review (0.8)

Yearn

Final score:93%
Date:23 Feb 2022
Audit Process:version 0.8
Author:Nick
PQR Score:93%

PASS

Protocol Website:

Security Incidents

Date:04 Feb 2021
Details: $11m was lost to a flashloan attack.
Reference Linklink

Scoring Appendix

The final review score is indicated as a percentage. The percentage is calculated as Achieved Points due to MAX Possible Points. For each element the answer can be either Yes/No or a percentage. For a detailed breakdown of the individual weights of each question, please consult this document.

The blockchain used by this protocol
Arbitrum
Ethereum
Fantom
#QuestionAnswer
100%
1.100%
2.100%
3.Yes
4.100%
5.100
94%
6.Yes
7.Yes
8.100%
9.60%
90%
10.100%
11.100%
12.Yes
13.100%
14.No
15.Yes
96%
16.100%
17.70%
83%
18.100%
19.100%
20.100%
21.100%
22.30%
23.80%
24.100%
25.100%
100%
26.100
27.Yes
28.Yes
Total:93%

Very simply, the audit looks for the following declarations from the developer's site. With these declarations, it is reasonable to trust the smart contracts.

  • Here is my smart contract on the blockchain
  • You can see it matches a software repository used to develop the code
  • Here is the documentation that explains what my smart contract does
  • Here are the tests I ran to verify my smart contract
  • Here are the audit(s) performed to review my code by third party experts

This report is for informational purposes only and does not constitute investment advice of any kind, nor does it constitute an offer to provide investment advisory or other services. Nothing in this report shall be considered a solicitation or offer to buy or sell any security, token, future, option or other financial instrument or to offer or provide any investment advice or service to any person in any jurisdiction. Nothing contained in this report constitutes investment advice or offers any opinion with respect to the suitability of any security, and the views expressed in this report should not be taken as advice to buy, sell or hold any security. The information in this report should not be relied upon for the purpose of investing. In preparing the information contained in this report, we have not taken into account the investment needs, objectives and financial circumstances of any particular investor. This information has no regard to the specific investment objectives, financial situation and particular needs of any specific recipient of this information and investments discussed may not be suitable for all investors.

Any views expressed in this report by us were prepared based upon the information available to us at the time such views were written. The views expressed within this report are limited to DeFiSafety and the author and do not reflect those of any additional or third party and are strictly based upon DeFiSafety, its authors, interpretations and evaluation of relevant data. Changed or additional information could cause such views to change. All information is subject to possible correction. Information may quickly become unreliable for various reasons, including changes in market conditions or economic circumstances.

This completed report is copyright (c) DeFiSafety 2023. Permission is given to copy in whole, retaining this copyright label.

Smart Contracts & Team

100%

This section looks at the code deployed on the relevant chain that gets reviewed and its corresponding software repository. The document explaining these questions is here.

1. Are the smart contract addresses easy to find? (%)

Answer: 100%

They can be found at https://yearn.watch/network/ethereum, as indicated in the Appendix.

Percentage Score Guidance:
100%
Clearly labelled and on website, documents or repository, quick to find
70%
Clearly labelled and on website, docs or repo but takes a bit of looking
40%
Addresses in mainnet.json, in discord or sub graph, etc
20%
Address found but labeling not clear or easy to find
0%
Executing addresses could not be found

2. How active is the primary contract? (%)

Answer: 100%

Contract USDC Vault is used more than 10 times a day, as indicated in the Appendix.

Percentage Score Guidance:
100%
More than 10 transactions a day
70%
More than 10 transactions a week
40%
More than 10 transactions a month
10%
Less than 10 transactions a month
0%
No activity

3. Does the protocol have a public software repository? (Y/N)

Answer: Yes

Yes: https://github.com/iearn-finance

Score Guidance:
Yes
There is a public software repository with the code at a minimum, but also normally test and scripts. Even if the repository was created just to hold the files and has just 1 transaction.
No
For teams with private repositories.

4. Is there a development history visible? (%)

Answer: 100%

At 347 commits on their vault repo alone, it's clear that this DeFi monster has well documented its rise.

Percentage Score Guidance:
100%
Any one of 100+ commits, 10+branches
70%
Any one of 70+ commits, 7+branches
50%
Any one of 50+ commits, 5+branches
30%
Any one of 30+ commits, 3+branches
0%
Less than 2 branches or less than 30 commits

5. Is the team public (not anonymous)?

Answer: 100

Contributors are public and identify as Yearn employees on their LinkedIn employee page.

Score Guidance:
100%
At least two names can be easily found in the protocol's website, documentation or medium. These are then confirmed by the personal websites of the individuals / their linkedin / twitter.
50%
At least one public name can be found to be working on the protocol.
0%
No public team members could be found.

Documentation

94%

The difference between this and the old link is solely the link.    This section looks at the software documentation. The document explaining these questions is here.

6. Is there a whitepaper? (Y/N)

Answer: Yes

Location: https://docs.yearn.finance/

7. Is the protocol's software architecture documented? (Y/N)

Answer: Yes

This protocol's software architecture is documented in their docs.

Score Guidance:
Yes
The documents identify software architecture and contract interaction through any of the following: diagrams, arrows, specific reference to software functions or a written explanation on how smart contracts interact.
No
Protocols receive a "no" if none of these are included.

8. Does the software documentation fully cover the deployed contracts' source code? (%)

Answer: 100%

There is full coverage of deployed contracts by software function documentation.

Percentage Score Guidance:
100%
All contracts and functions documented
80%
Only the major functions documented
79 - 1%
Estimate of the level of software documentation
0%
No software documentation

9. Is it possible to trace the documented software to its implementation in the protocol's source code? (%)

Answer: 60%

There is clear but non-explicit traceability between software documentation and implemented code.

Percentage Score Guidance:
100%
Clear explicit traceability between code and documentation at a requirement level for all code
60%
Clear association between code and documents via non explicit traceability
40%
Documentation lists all the functions and describes their functions
0%
No connection between documentation and code

Testing

90%

10. Has the protocol tested their deployed code? (%)

Answer: 100%

Code examples are in the Appendix at the end of this report. As per the SLOC, there is 211% testing to code (TtC).    This score is guided by the Test to Code ratio (TtC). Generally a good test to code ratio is over 100%. However, the reviewer's best judgement is the final deciding factor.

Percentage Score Guidance:
100%
TtC > 120% Both unit and system test visible
80%
TtC > 80% Both unit and system test visible
40%
TtC < 80% Some tests visible
0%
No tests obvious

11. How covered is the protocol's code? (%)

Answer: 100%

Code coverage test instructions are provided, and there is a report for users to view.

Percentage Score Guidance:
100%
Documented full coverage
99 - 51%
Value of test coverage from documented results
50%
No indication of code coverage but clearly there is a complete set of tests
30%
Some tests evident but not complete
0%
No test for coverage seen

12. Does the protocol provide scripts and instructions to run their tests? (Y/N)

Answer: Yes

Scripts/Instructions location: https://github.com/yearn/yearn-vaults#tests

Score Guidance:
Yes
Scripts and/or instructions to run tests are available in the testing suite
No
Scripts and/or instructions to run tests are not available in the testing suite

13. Is there a detailed report of the protocol's test results?(%)

Answer: 100%

A full report is documented.

Percentage Score Guidance:
100%
Detailed test report as described below
70%
GitHub code coverage report visible
0%
No test report evident

14. Has the protocol undergone Formal Verification? (Y/N)

Answer: No

This protocol has not undergone formal verification. Yearn is exploring this, and this score will be updated as and when it goes live.

Score Guidance:
Yes
Formal Verification was performed and the report is readily available
No
Formal Verification was not performed and/or the report is not readily available.

15. Were the smart contracts deployed to a testnet? (Y/N)

Answer: Yes

This protocol deploys to ganache.

Score Guidance:
Yes
Protocol has proved their tesnet usage by providing the addresses
No
Protocol has not proved their testnet usage by providing the addresses

Security

96%

This section looks at the 3rd party software audits done. It is explained in this document.

16. Is the protocol sufficiently audited? (%)

Answer: 100%

Yearn and its respective strapiucts have been audited countless times, both before and after launch. Yearn should be commended for this commitment to security - DeFiSafety has not seen this many audits conducted on a protocol before.

Percentage Score Guidance:
100%
Multiple Audits performed before deployment and the audit findings are public and implemented or not required
90%
Single audit performed before deployment and audit findings are public and implemented or not required
70%
Audit(s) performed after deployment and no changes required. The Audit report is public.
65%
Code is forked from an already audited protocol and a changelog is provided explaining why forked code was used and what changes were made. This changelog must justify why the changes made do not affect the audit.
50%
Audit(s) performed after deployment and changes are needed but not implemented.
30%
Audit(s) performed are low-quality and do not indicate proper due diligence.
20%
No audit performed
0%
Audit Performed after deployment, existence is public, report is not public OR smart contract address' not found.
Deduct 25% if the audited code is not available for comparison.

17. Is the bounty value acceptably high (%)

Answer: 70%

This protocol offers an active bug bounty of $200K.

Percentage Score Guidance:
100%
Bounty is 10% TVL or at least $1M AND active program (see below)
90%
Bounty is 5% TVL or at least 500k AND active program
80%
Bounty is 5% TVL or at least 500k
70%
Bounty is 100k or over AND active program
60%
Bounty is 100k or over
50%
Bounty is 50k or over AND active program
40%
Bounty is 50k or over
20%
Bug bounty program bounty is less than 50k
0%
No bug bounty program offered / the bug bounty program is dead
An active program means that a third party (such as Immunefi) is actively driving hackers to the site. An inactive program would be static mentions on the docs.

Admin Controls

83%

This section covers the documentation of special access controls for a DeFi protocol. The admin access controls are the contracts that allow updating contracts or coefficients in the protocol. Since these contracts can allow the protocol admins to "change the rules", complete disclosure of capabilities is vital for user's transparency. It is explained in this document.

18. Is the protocol's admin control information easy to find?

Answer: 100%

Admin control information was documented at this location. This was quick to find.

Percentage Score Guidance:
100%
Admin Controls are clearly labelled and on website, docs or repo, quick to find
70%
Admin Controls are clearly labelled and on website, docs or repo but takes a bit of looking
40%
Admin Control docs are in multiple places and not well labelled
20%
Admin Control docs are in multiple places and not labelled
0%
Admin Control information could not be found

19. Are relevant contracts clearly labelled as upgradeable or immutable? (%)

Answer: 100%

The relevant contracts are identified as upgradeable/callable/governable within their respective technical documentations, although this is certainly more implicit than explicit. However, this is more explicitly implied in their governance documentation.

Percentage Score Guidance:
100%
Both the contract documentation and the smart contract code state that the code is not upgradeable or immutable.
80%
All Contracts are clearly labelled as upgradeable (or not)
50%
Code is immutable but not mentioned anywhere in the documentation
0%
Admin control information could not be found

20. Is the type of smart contract ownership clearly indicated? (%)

Answer: 100%

Ownership is clearly indicated in this location.

Percentage Score Guidance:
100%
The type of ownership is clearly indicated in their documentation. (OnlyOwner / MultiSig / etc)
50%
The type of ownership is indicated, but only in the code. (OnlyOwner / MultiSig / etc)
0%
Admin Control information could not be found

21. Are the protocol's smart contract change capabilities described? (%)

Answer: 100%

Smart contract change capabilities are identified.

Percentage Score Guidance:
100%
The documentation covers the capabilities for change for all smart contracts
50%
The documentation covers the capabilities for change in some, but not all contracts
0%
The documentation does not cover the capabilities for change in any contract

22. Is the protocol's admin control information easy to understand? (%)

Answer: 30%

This information is in software specific language.

Percentage Score Guidance:
100%
All the contracts are immutable
90%
Description relates to investments safety in clear non-software language
30%
Description all in software-specific language
0%
No admin control information could be found

23. Is there sufficient Pause Control documentation? (%)

Answer: 80%

This protocol's pause control (setEmergencyShutdown) is documented here.

Percentage Score Guidance:
100%
If immutable and no changes possible
100%
If admin control is fully via governance
80%
Robust transaction signing process (7 or more elements)
70%
Adequate transaction signing process (5 or more elements)
60%
Weak transaction signing process (3 or more elements)
0%
No transaction signing process evident
Evidence of audits of signers following the process add 20%

24. Is there sufficient Timelock documentation? (%)

Answer: 100%

This protocol has no timelock and this is explained.

Percentage Score Guidance:
100%
Documentation identifies and explains why the protocol does not need a Timelock OR Timelock documentation identifies its duration, which contracts it applies to and justifies this time period.
60%
A Timelock is identified and its duration is specified
30%
A Timelock is identified
0%
No Timelock information was documented

25. Is the Timelock of an adequate length? (Y/N)

Answer: 100%

Timelock is not needed, as identified by the development team.

Percentage Score Guidance:
100%
Timelock is between 48 hours to 1 week OR justification as to why no Timelock is needed / is outside this length.
50%
Timelock is less than 48 hours or greater than 1 week.
0%
No Timelock information was documented OR no timelock length was identified.

Oracles

100%

This section goes over the documentation that a protocol may or may not supply about their Oracle usage. Oracles are a fundamental part of DeFi as they are responsible for relaying tons of price data information to thousands of protocols using blockchain technology. Not only are they important for price feeds, but they are also an essential component of transaction verification and security. This is explained in this document.

26. Is the protocol's Oracle sufficiently documented? (%)

Answer: 100

Yearn doesn't use oracles, as explained here.

Score Guidance:
100%
If it uses one, the Oracle is specified. The contracts dependent on the oracle are identified. Basic software functions are identified (if the protocol provides its own price feed data). Timeframe of price feeds are identified. OR The reason as to why the protocol does not use an Oracle is identified and explained.
75%
The Oracle documentation identifies both source and timeframe, but does not provide additional context regarding smart contracts.
50%
Only the Oracle source is identified.
0%
No oracle is named / no oracle information is documented.

27. Is front running mitigated by this protocol? (Y/N)

Answer: Yes

This protocol documents sandwich attack mitigation techniques.

Score Guidance:
Yes
The protocol cannot be front run and there is an explanation as to why OR documented front running countermeasures are implemented.
No
The Oracle documentation identifies both source and timeframe, but does not provide additional context regarding smart contracts.

28. Can flashloan attacks be applied to the protocol, and if so, are those flashloan attack risks mitigated? (Y/N)

Answer: Yes

This protocol documents flashloan countermeasures at this location.

Score Guidance:
Yes
The protocol's documentation includes information on how they mitigate the possibilities and extents of flash loan attacks.
No
The protocol's documentation does not include any information regarding the mitigation of flash loan attacks.

Appendices

1pragma solidity >=0.6.0 <0.7.0;
2pragma experimental ABIEncoderV2;
3
4import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
6import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol";
7import {StrategyLib} from "./StrategyLib.sol";
8
9struct StrategyParams {
10    uint256 performanceFee;
11    uint256 activation;
12    uint256 debtRatio;
13    uint256 minDebtPerHarvest;
14    uint256 maxDebtPerHarvest;
15    uint256 lastReport;
16    uint256 totalDebt;
17    uint256 totalGain;
18    uint256 totalLoss;
19}
20
21interface VaultAPI is IERC20 {
22    function name() external view returns (string calldata);
23
24    function symbol() external view returns (string calldata);
25
26    function decimals() external view returns (uint256);
27
28    function apiVersion() external pure returns (string memory);
29
30    function permit(
31        address owner,
32        address spender,
33        uint256 amount,
34        uint256 expiry,
35        bytes calldata signature
36    ) external returns (bool);
37
38    // NOTE: Vyper strapiuces multiple signatures for a given function with "default" args
39    function deposit() external returns (uint256);
40
41    function deposit(uint256 amount) external returns (uint256);
42
43    function deposit(uint256 amount, address recipient) external returns (uint256);
44
45    // NOTE: Vyper strapiuces multiple signatures for a given function with "default" args
46    function withdraw() external returns (uint256);
47
48    function withdraw(uint256 maxShares) external returns (uint256);
49
50    function withdraw(uint256 maxShares, address recipient) external returns (uint256);
51
52    function token() external view returns (address);
53
54    function strategies(address _strategy) external view returns (StrategyParams memory);
55
56    function pricePerShare() external view returns (uint256);
57
58    function totalAssets() external view returns (uint256);
59
60    function depositLimit() external view returns (uint256);
61
62    function maxAvailableShares() external view returns (uint256);
63
64    /**
65     * View how much the Vault would increase this Strategy's borrow limit,
66     * based on its present performance (since its last report). Can be used to
67     * determine expectedReturn in your Strategy.
68     */
69    function creditAvailable() external view returns (uint256);
70
71    /**
72     * View how much the Vault would like to pull back from the Strategy,
73     * based on its present performance (since its last report). Can be used to
74     * determine expectedReturn in your Strategy.
75     */
76    function debtOutstanding() external view returns (uint256);
77
78    /**
79     * View how much the Vault expect this Strategy to return at the current
80     * block, based on its present performance (since its last report). Can be
81     * used to determine expectedReturn in your Strategy.
82     */
83    function expectedReturn() external view returns (uint256);
84
85    /**
86     * This is the main contact point where the Strategy interacts with the
87     * Vault. It is critical that this call is handled as intended by the
88     * Strategy. Therefore, this function will be called by BaseStrategy to
89     * make sure the integration is correct.
90     */
91    function report(
92        uint256 _gain,
93        uint256 _loss,
94        uint256 _debtPayment
95    ) external returns (uint256);
96
97    /**
98     * This function should only be used in the scenario where the Strategy is
99     * being retired but no migration of the positions are possible, or in the
100     * extreme scenario that the Strategy needs to be put into "Emergency Exit"
101     * mode in order for it to exit as quickly as possible. The latter scenario
102     * could be for any reason that is considered "critical" that the Strategy
103     * exits its position as fast as possible, such as a sudden change in
104     * market conditions leading to losses, or an imminent failure in an
105     * external dependency.
106     */
107    function revokeStrategy() external;
108
109    /**
110     * View the governance address of the Vault to assert privileged functions
111     * can only be called by governance. The Strategy serves the Vault, so it
112     * is subject to governance defined by the Vault.
113     */
114    function governance() external view returns (address);
115
116    /**
117     * View the management address of the Vault to assert privileged functions
118     * can only be called by management. The Strategy serves the Vault, so it
119     * is subject to management defined by the Vault.
120     */
121    function management() external view returns (address);
122
123    /**
124     * View the guardian address of the Vault to assert privileged functions
125     * can only be called by guardian. The Strategy serves the Vault, so it
126     * is subject to guardian defined by the Vault.
127     */
128    function guardian() external view returns (address);
129}
130
131/**
132 * This interface is here for the keeper bot to use.
133 */
134interface StrategyAPI {
135    function name() external view returns (string memory);
136
137    function vault() external view returns (address);
138
139    function want() external view returns (address);
140
141    function apiVersion() external pure returns (string memory);
142
143    function keeper() external view returns (address);
144
145    function isActive() external view returns (bool);
146
147    function delegatedAssets() external view returns (uint256);
148
149    function estimatedTotalAssets() external view returns (uint256);
150
151    function tendTrigger(uint256 callCost) external view returns (bool);
152
153    function tend() external;
154
155    function harvestTrigger(uint256 callCost) external view returns (bool);
156
157    function harvest() external;
158
159    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);
160}
161
162/**
163 * @title Yearn Base Strategy
164 * @author yearn.finance
165 * @notice
166 *  BaseStrategy implements all of the required functionality to interoperate
167 *  closely with the Vault contract. This contract should be inherited and the
168 *  abstract methods implemented to adapt the Strategy to the particular needs
169 *  it has to create a return.
170 *
171 *  Of special interest is the relationship between `harvest()` and
172 *  `vault.report()'. `harvest()` may be called simply because enough time has
173 *  elapsed since the last report, and not because any funds need to be moved
174 *  or positions adjusted. This is critical so that the Vault may maintain an
175 *  accurate picture of the Strategy's performance. See  `vault.report()`,
176 *  `harvest()`, and `harvestTrigger()` for further details.
177 */
178
179abstract contract BaseStrategy {
180    using SafeMath for uint256;
181    string public metadataURI;
182
183    /**
184     * @notice
185     *  Used to track which version of `StrategyAPI` this Strategy
186     *  implements.
187     * @dev The Strategy's version must match the Vault's `API_VERSION`.
188     * @return A string which holds the current API version of this contract.
189     */
190    function apiVersion() public pure returns (string memory) {
191        return "0.4.3";
192    }
193
194    /**
195     * @notice This Strategy's name.
196     * @dev
197     *  You can use this field to manage the "version" of this Strategy, e.g.
198     *  `StrategySomethingOrOtherV1`. However, "API Version" is managed by
199     *  `apiVersion()` function above.
200     * @return This Strategy's name.
201     */
202    function name() external view virtual returns (string memory);
203
204    /**
205     * @notice
206     *  The amount (priced in want) of the total assets managed by this strategy should not count
207     *  towards Yearn's TVL calculations.
208     * @dev
209     *  You can override this field to set it to a non-zero value if some of the assets of this
210     *  Strategy is somehow delegated inside another part of of Yearn's ecosystem e.g. another Vault.
211     *  Note that this value must be strictly less than or equal to the amount provided by
212     *  `estimatedTotalAssets()` below, as the TVL calc will be total assets minus delegated assets.
213     *  Also note that this value is used to determine the total assets under management by this
214     *  strategy, for the purposes of computing the management fee in `Vault`
215     * @return
216     *  The amount of assets this strategy manages that should not be included in Yearn's Total Value
217     *  Locked (TVL) calculation across it's ecosystem.
218     */
219    function delegatedAssets() external view virtual returns (uint256) {
220        return 0;
221    }
222
223    VaultAPI public vault;
224    address public strategist;
225    address public rewards;
226    address public keeper;
227
228    IERC20 public want;
229
230    // So indexers can keep track of this
231    event Harvested(uint256 profit, uint256 loss, uint256 debtPayment, uint256 debtOutstanding);
232
233    event UpdatedStrategist(address newStrategist);
234
235    event UpdatedKeeper(address newKeeper);
236
237    event UpdatedRewards(address rewards);
238
239    event UpdatedMinReportDelay(uint256 delay);
240
241    event UpdatedMaxReportDelay(uint256 delay);
242
243    event UpdatedProfitFactor(uint256 profitFactor);
244
245    event UpdatedDebtThreshold(uint256 debtThreshold);
246
247    event EmergencyExitEnabled();
248
249    event UpdatedMetadataURI(string metadataURI);
250
251    // The minimum number of seconds between harvest calls. See
252    // `setMinReportDelay()` for more details.
253    uint256 public minReportDelay;
254
255    // The maximum number of seconds between harvest calls. See
256    // `setMaxReportDelay()` for more details.
257    uint256 public maxReportDelay;
258
259    // The minimum multiple that `callCost` must be above the credit/profit to
260    // be "justifiable". See `setProfitFactor()` for more details.
261    uint256 public profitFactor;
262
263    // Use this to adjust the threshold at which running a debt causes a
264    // harvest trigger. See `setDebtThreshold()` for more details.
265    uint256 public debtThreshold;
266
267    // See note on `setEmergencyExit()`.
268    bool public emergencyExit;
269
270    // modifiers
271    modifier onlyAuthorized() {
272        _onlyAuthorized();
273        _;
274    }
275
276    modifier onlyEmergencyAuthorized() {
277        _onlyEmergencyAuthorized();
278        _;
279    }
280
281    modifier onlyStrategist() {
282        _onlyStrategist();
283        _;
284    }
285
286    modifier onlyGovernance() {
287        _onlyGovernance();
288        _;
289    }
290
291    modifier onlyRewarder() {
292        _onlyRewarder();
293        _;
294    }
295
296    modifier onlyKeepers() {
297        _onlyKeepers();
298        _;
299    }
300
301    function _onlyAuthorized() internal {
302        require(msg.sender == strategist || msg.sender == governance());
303    }
304
305    function _onlyEmergencyAuthorized() internal {
306        require(msg.sender == strategist || msg.sender == governance() || msg.sender == vault.guardian() || msg.sender == vault.management());
307    }
308
309    function _onlyStrategist() internal {
310        require(msg.sender == strategist);
311    }
312
313    function _onlyGovernance() internal {
314        require(msg.sender == governance());
315    }
316
317    function _onlyRewarder() internal {
318        require(msg.sender == governance() || msg.sender == strategist);
319    }
320
321    function _onlyKeepers() internal {
322        require(
323            msg.sender == keeper ||
324                msg.sender == strategist ||
325                msg.sender == governance() ||
326                msg.sender == vault.guardian() ||
327                msg.sender == vault.management()
328        );
329    }
330
331    constructor(address _vault) public {
332        _initialize(_vault, msg.sender, msg.sender, msg.sender);
333    }
334
335    /**
336     * @notice
337     *  Initializes the Strategy, this is called only once, when the
338     *  contract is deployed.
339     * @dev `_vault` should implement `VaultAPI`.
340     * @param _vault The address of the Vault responsible for this Strategy.
341     * @param _strategist The address to assign as `strategist`.
342     * The strategist is able to change the reward address
343     * @param _rewards  The address to use for pulling rewards.
344     * @param _keeper The adddress of the _keeper. _keeper
345     * can harvest and tend a strategy.
346     */
347    function _initialize(
348        address _vault,
349        address _strategist,
350        address _rewards,
351        address _keeper
352    ) internal {
353        require(address(want) == address(0), "Strategy already initialized");
354
355        vault = VaultAPI(_vault);
356        want = IERC20(vault.token());
357        SafeERC20.safeApprove(want, _vault, type(uint256).max); // Give Vault unlimited access (might save gas)
358        strategist = _strategist;
359        rewards = _rewards;
360        keeper = _keeper;
361
362        // initialize variables
363        minReportDelay = 0;
364        maxReportDelay = 86400;
365        profitFactor = 100;
366        debtThreshold = 0;
367
368        vault.approve(rewards, type(uint256).max); // Allow rewards to be pulled
369    }
370
371    /**
372     * @notice
373     *  Used to change `strategist`.
374     *
375     *  This may only be called by governance or the existing strategist.
376     * @param _strategist The new address to assign as `strategist`.
377     */
378    function setStrategist(address _strategist) external onlyAuthorized {
379        require(_strategist != address(0));
380        strategist = _strategist;
381        emit UpdatedStrategist(_strategist);
382    }
383
384    /**
385     * @notice
386     *  Used to change `keeper`.
387     *
388     *  `keeper` is the only address that may call `tend()` or `harvest()`,
389     *  other than `governance()` or `strategist`. However, unlike
390     *  `governance()` or `strategist`, `keeper` may *only* call `tend()`
391     *  and `harvest()`, and no other authorized functions, following the
392     *  principle of least privilege.
393     *
394     *  This may only be called by governance or the strategist.
395     * @param _keeper The new address to assign as `keeper`.
396     */
397    function setKeeper(address _keeper) external onlyAuthorized {
398        require(_keeper != address(0));
399        keeper = _keeper;
400        emit UpdatedKeeper(_keeper);
401    }
402
403    /**
404     * @notice
405     *  Used to change `rewards`. EOA or smart contract which has the permission
406     *  to pull rewards from the vault.
407     *
408     *  This may only be called by the strategist.
409     * @param _rewards The address to use for pulling rewards.
410     */
411    function setRewards(address _rewards) external onlyRewarder {
412        address oldRewards = rewards;
413        rewards = _rewards;
414        StrategyLib.internalSetRewards(oldRewards, _rewards, address(vault));
415        emit UpdatedRewards(_rewards);
416    }
417
418    /**
419     * @notice
420     *  Used to change `minReportDelay`. `minReportDelay` is the minimum number
421     *  of blocks that should pass for `harvest()` to be called.
422     *
423     *  For external keepers (such as the Keep3r network), this is the minimum
424     *  time between jobs to wait. (see `harvestTrigger()`
425     *  for more details.)
426     *
427     *  This may only be called by governance or the strategist.
428     * @param _delay The minimum number of seconds to wait between harvests.
429     */
430    function setMinReportDelay(uint256 _delay) external onlyAuthorized {
431        minReportDelay = _delay;
432        emit UpdatedMinReportDelay(_delay);
433    }
434
435    /**
436     * @notice
437     *  Used to change `maxReportDelay`. `maxReportDelay` is the maximum number
438     *  of blocks that should pass for `harvest()` to be called.
439     *
440     *  For external keepers (such as the Keep3r network), this is the maximum
441     *  time between jobs to wait. (see `harvestTrigger()`
442     *  for more details.)
443     *
444     *  This may only be called by governance or the strategist.
445     * @param _delay The maximum number of seconds to wait between harvests.
446     */
447    function setMaxReportDelay(uint256 _delay) external onlyAuthorized {
448        maxReportDelay = _delay;
449        emit UpdatedMaxReportDelay(_delay);
450    }
451
452    /**
453     * @notice
454     *  Used to change `profitFactor`. `profitFactor` is used to determine
455     *  if it's worthwhile to harvest, given gas costs. (See `harvestTrigger()`
456     *  for more details.)
457     *
458     *  This may only be called by governance or the strategist.
459     * @param _profitFactor A ratio to multiply anticipated
460     * `harvest()` gas cost against.
461     */
462    function setProfitFactor(uint256 _profitFactor) external onlyAuthorized {
463        profitFactor = _profitFactor;
464        emit UpdatedProfitFactor(_profitFactor);
465    }
466
467    /**
468     * @notice
469     *  Sets how far the Strategy can go into loss without a harvest and report
470     *  being required.
471     *
472     *  By default this is 0, meaning any losses would cause a harvest which
473     *  will subsequently report the loss to the Vault for tracking. (See
474     *  `harvestTrigger()` for more details.)
475     *
476     *  This may only be called by governance or the strategist.
477     * @param _debtThreshold How big of a loss this Strategy may carry without
478     * being required to report to the Vault.
479     */
480    function setDebtThreshold(uint256 _debtThreshold) external onlyAuthorized {
481        debtThreshold = _debtThreshold;
482        emit UpdatedDebtThreshold(_debtThreshold);
483    }
484
485    /**
486     * @notice
487     *  Used to change `metadataURI`. `metadataURI` is used to store the URI
488     * of the file describing the strategy.
489     *
490     *  This may only be called by governance or the strategist.
491     * @param _metadataURI The URI that describe the strategy.
492     */
493    function setMetadataURI(string calldata _metadataURI) external onlyAuthorized {
494        metadataURI = _metadataURI;
495        emit UpdatedMetadataURI(_metadataURI);
496    }
497

JavaScript Tests

Language
Files
Lines
Blanks
Comments
Testing Code
Deployed Code
Complexity
Python
19
2666
538
291
1837
868
73

Tests to Code: 1837 / 868 = 212 %