Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

24.05.0-alpha; ERC4626StrategyBase, YearnStrategy, StrategyBase 1.1.0 #116

Merged
merged 20 commits into from
May 4, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion chains/PolygonLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ library PolygonLib {
address public constant POOL_UNISWAPV3_USDCe_WETH_500 = 0x45dDa9cb7c25131DF268515131f647d726f50608;
address public constant POOL_UNISWAPV3_PROFIT_WETH_100 = 0xE5e70cb76446BEE0053b1EdF22CaDa861c80D51F;
address public constant POOL_UNISWAPV3_WETH_COMP_3000 = 0x2260E0081A2A042DC55A07D379eb3c18bE28A1F2;
address public constant POOL_UNISWAPV3_WMATIC_COMP_3000 = 0x495b3576e2f67fa870e14d0996433FbdB4015794;
address public constant POOL_QUICKSWAPV3_USDCe_USDT = 0x7B925e617aefd7FB3a93Abe3a701135D7a1Ba710;
address public constant POOL_QUICKSWAPV3_USDCe_DAI = 0xe7E0eB9F6bCcCfe847fDf62a3628319a092F11a2;
address public constant POOL_QUICKSWAPV3_USDCe_WETH = 0x55CAaBB0d2b704FD0eF8192A7E35D8837e678207;
Expand Down Expand Up @@ -153,6 +154,13 @@ library PolygonLib {
address public constant CONVEX_REWARD_POOL_crvUSD_DAI = 0xaCb744c7e7C95586DB83Eda3209e6483Fb1FCbA4;
address public constant CONVEX_REWARD_POOL_crvUSD_USDC = 0x11F2217fa1D5c44Eae310b9b985E2964FC47D8f9;

// Yearn V3
address public constant YEARN_DAI = 0x90b2f54C6aDDAD41b8f6c4fCCd555197BC0F773B;
address public constant YEARN_USDT = 0xBb287E6017d3DEb0e2E65061e8684eab21060123;
address public constant YEARN_USDCe = 0xA013Fbd4b711f9ded6fB09C1c0d358E2FbC2EAA0;
address public constant YEARN_WMATIC = 0x28F53bA70E5c8ce8D03b1FaD41E9dF11Bb646c36;
address public constant YEARN_WETH = 0x305F25377d0a39091e99B975558b1bdfC3975654;

function runDeploy(bool showLog) internal returns (address platform) {
//region ----- DeployPlatform -----
uint[] memory buildingPrice = new uint[](3);
Expand Down Expand Up @@ -736,7 +744,10 @@ library PolygonLib {
_farms[i++] = _makeCurveConvexFarm(POOL_CURVE_crvUSD_USDC, CONVEX_REWARD_POOL_crvUSD_USDC);
}

function _makeCurveConvexFarm(address curvePool, address convexRewardPool) internal view returns (IFactory.Farm memory) {
function _makeCurveConvexFarm(
address curvePool,
address convexRewardPool
) internal view returns (IFactory.Farm memory) {
IFactory.Farm memory farm;
uint rewardTokensLength = IConvexRewardPool(convexRewardPool).rewardLength();
farm.status = 0;
Expand Down
5 changes: 4 additions & 1 deletion src/interfaces/IStrategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ interface IStrategy is IERC165 {
view
returns (string[] memory variants, address[] memory addresses, uint[] memory nums, int24[] memory ticks);

/// @notice How strategy earns money
/// @notice How does the strategy make money?
/// @return Description in free form
function description() external view returns (string memory);

Expand All @@ -147,6 +147,9 @@ interface IStrategy is IERC165 {
/// @notice Is HardWork can be executed
function isReadyForHardWork() external view returns (bool);

/// @notice Strategy not need to compound revenue on HardWorks
function autoCompoundingByUnderlyingProtocol() external view returns (bool);

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* WRITE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand Down
75 changes: 75 additions & 0 deletions src/strategies/YearnStrategy.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "./libs/StrategyIdLib.sol";
import "./base/ERC4626StrategyBase.sol";

/// @title Hodl Yearn V3 multi ERC4626 vault, emit revenue, collect fees and show underlying protocols
/// @author Alien Deployer (https://github.com/a17)
contract YearnStrategy is ERC4626StrategyBase {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @inheritdoc IControllable
string public constant VERSION = "1.0.0";

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INITIALIZATION */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @inheritdoc IStrategy
function initialize(address[] memory addresses, uint[] memory nums, int24[] memory ticks) public initializer {
if (addresses.length != 3 || nums.length != 0 || ticks.length != 0) {
revert IControllable.IncorrectInitParams();

Check warning on line 24 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L24

Added line #L24 was not covered by tests
}

__ERC4626StrategyBase_init(StrategyIdLib.YEARN, addresses[0], addresses[1], addresses[3]);

Check warning on line 27 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L27

Added line #L27 was not covered by tests
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VIEW FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @inheritdoc IStrategy
function description() external pure returns (string memory) {
// todo protocols
return "todo";

Check warning on line 37 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L37

Added line #L37 was not covered by tests
}

/// @inheritdoc IStrategy
function extra() external pure returns (bytes32) {
return CommonLib.bytesToBytes32(abi.encodePacked(bytes3(0xdc568a), bytes3(0x000000)));

Check warning on line 42 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L42

Added line #L42 was not covered by tests
}
Fixed Show fixed Hide fixed

/// @inheritdoc IStrategy
function getSpecificName() external pure override returns (string memory, bool) {
// todo concat protocols
return ("", false);

Check warning on line 48 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L48

Added line #L48 was not covered by tests
}

/// @inheritdoc IStrategy
function initVariants(address platform_)
public
view
returns (string[] memory variants, address[] memory addresses, uint[] memory nums, int24[] memory ticks)
{
// todo construct storage for allowed yaern v3 vaults
}

/// @inheritdoc IStrategy
function isHardWorkOnDepositAllowed() external pure returns (bool) {
return true;

Check warning on line 62 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L62

Added line #L62 was not covered by tests
}

/// @inheritdoc IStrategy
function isReadyForHardWork() external pure returns (bool isReady) {
// todo ready if share price of yaern vault increased
isReady = true;

Check warning on line 68 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L68

Added line #L68 was not covered by tests
}

/// @inheritdoc IStrategy
function strategyLogicId() public pure override returns (string memory) {
return StrategyIdLib.YEARN;

Check warning on line 73 in src/strategies/YearnStrategy.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/YearnStrategy.sol#L73

Added line #L73 was not covered by tests
}
}
159 changes: 159 additions & 0 deletions src/strategies/base/ERC4626StrategyBase.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "./StrategyBase.sol";

/// @notice Hold ERC4626 vault shares, emit APR and collect fees
/// @author Alien Deployer (https://github.com/a17)
abstract contract ERC4626StrategyBase is StrategyBase {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @dev Version of ERC4626StrategyBase implementation
string public constant VERSION_ERC4626_STRATEGY_BASE = "1.0.0";

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INITIALIZATION */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

//slither-disable-next-line naming-convention
function __ERC4626StrategyBase_init(
string memory id,
address platform,
Fixed Show fixed Hide fixed
address vault,
Fixed Show fixed Hide fixed
address underlying
Fixed Show fixed Hide fixed
) internal onlyInitializing {
address[] memory _assets = new address[](1);
_assets[0] = IERC4626(underlying).asset();

Check warning on line 29 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L28-L29

Added lines #L28 - L29 were not covered by tests
//slither-disable-next-line reentrancy-events
__StrategyBase_init(platform, id, vault, _assets, underlying, type(uint).max);

Check warning on line 31 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L31

Added line #L31 was not covered by tests
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* VIEW FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @inheritdoc IStrategy
function supportedVaultTypes() external view virtual override returns (string[] memory types) {
types = new string[](1);
types[0] = VaultTypeLib.COMPOUNDING;

Check warning on line 41 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L40-L41

Added lines #L40 - L41 were not covered by tests
}

/// @inheritdoc IStrategy
function total() public view override returns (uint) {
StrategyBaseStorage storage __$__ = _getStrategyBaseStorage();
return StrategyLib.balance(__$__._underlying);

Check warning on line 47 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L46-L47

Added lines #L46 - L47 were not covered by tests
}

/// @inheritdoc IStrategy
function getAssetsProportions() public pure returns (uint[] memory proportions) {
proportions = new uint[](1);
proportions[0] = 1e18;

Check warning on line 53 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L52-L53

Added lines #L52 - L53 were not covered by tests
}

/// @inheritdoc IStrategy
function getRevenue() external pure returns (address[] memory __assets, uint[] memory amounts) {
// todo
__assets = new address[](0);
amounts = new uint[](0);

Check warning on line 60 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L59-L60

Added lines #L59 - L60 were not covered by tests
}

/// @inheritdoc IStrategy
function autoCompoundingByUnderlyingProtocol() public view virtual override returns (bool) {
return true;

Check warning on line 65 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L65

Added line #L65 was not covered by tests
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STRATEGY BASE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @inheritdoc StrategyBase
function _depositAssets(uint[] memory amounts, bool) internal override returns (uint value) {
// StrategyBaseStorage storage $base = _getStrategyBaseStorage();
}

/// @inheritdoc StrategyBase
function _compound() internal override {
//
}

function _liquidateRewards(
address, /*exchangeAsset*/
address[] memory, /*rewardAssets_*/
uint[] memory /*rewardAmounts_*/
) internal pure override returns (uint earnedExchangeAsset) {
// do nothing
}

/// @inheritdoc StrategyBase
function _previewDepositAssets(uint[] memory amountsMax)
internal
view
override(StrategyBase)
returns (uint[] memory amountsConsumed, uint value)
{
amountsConsumed = new uint[](1);
amountsConsumed[0] = amountsMax[0];
StrategyBaseStorage storage __$__ = _getStrategyBaseStorage();
value = IERC4626(__$__._underlying).convertToShares(amountsMax[0]);

Check warning on line 100 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L97-L100

Added lines #L97 - L100 were not covered by tests
}

/// @inheritdoc StrategyBase
function _previewDepositAssets(
address[] memory, /*assets_*/
uint[] memory amountsMax
) internal view override(StrategyBase) returns (uint[] memory amountsConsumed, uint value) {
return _previewDepositAssets(amountsMax);

Check warning on line 108 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L108

Added line #L108 was not covered by tests
}

/// @inheritdoc StrategyBase
function _processRevenue(
address[] memory, /*assets_*/
uint[] memory /*amountsRemaining*/
) internal pure override returns (bool needCompound) {}

/// @inheritdoc StrategyBase
function _withdrawAssets(uint value, address receiver) internal override returns (uint[] memory amountsOut) {
StrategyBaseStorage storage _$_ = _getStrategyBaseStorage();
return _withdrawAssets(_$_._assets, value, receiver);

Check warning on line 120 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L119-L120

Added lines #L119 - L120 were not covered by tests
}

/// @inheritdoc StrategyBase
function _withdrawAssets(
address[] memory assets_,
uint value,
address receiver
) internal override returns (uint[] memory amountsOut) {
// amountsOut = new uint[](1);
// amountsOut[0] = value;
}

/// @inheritdoc StrategyBase
function _assetsAmounts() internal view override returns (address[] memory assets_, uint[] memory amounts_) {
StrategyBaseStorage storage __$__ = _getStrategyBaseStorage();
assets_ = __$__._assets;
address u = __$__._underlying;
amounts_ = new uint[](1);
amounts_[0] = IERC4626(u).convertToAssets(IERC20(u).balanceOf(address(this)));

Check warning on line 139 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L135-L139

Added lines #L135 - L139 were not covered by tests
}

/// @inheritdoc StrategyBase
function _claimRevenue()
internal
pure
override
returns (
address[] memory __assets,
uint[] memory __amounts,
address[] memory __rewardAssets,
uint[] memory __rewardAmounts
)
{
__assets = new address[](0);
__amounts = new uint[](0);
__rewardAssets = new address[](0);
__rewardAmounts = new uint[](0);

Check warning on line 157 in src/strategies/base/ERC4626StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/ERC4626StrategyBase.sol#L154-L157

Added lines #L154 - L157 were not covered by tests
}
}
33 changes: 22 additions & 11 deletions src/strategies/base/StrategyBase.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
import "../../interfaces/IVault.sol";

/// @dev Base universal strategy
/// Changelog:
/// 1.1.0: autoCompoundingByUnderlyingProtocol(), virtual total()
/// @author Alien Deployer (https://github.com/a17)
/// @author JodsMigel (https://github.com/JodsMigel)
abstract contract StrategyBase is Controllable, IStrategy {
Expand All @@ -18,7 +20,7 @@
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/

/// @dev Version of StrategyBase implementation
string public constant VERSION_STRATEGY_BASE = "1.0.0";
string public constant VERSION_STRATEGY_BASE = "1.1.0";

// keccak256(abi.encode(uint256(keccak256("erc7201:stability.StrategyBase")) - 1)) & ~bytes32(uint256(0xff));
bytes32 private constant STRATEGYBASE_STORAGE_LOCATION =
Expand Down Expand Up @@ -117,17 +119,22 @@
uint[] memory __rewardAmounts
) = _claimRevenue();

__amounts[exchangeAssetIndex] +=
_liquidateRewards(__assets[exchangeAssetIndex], __rewardAssets, __rewardAmounts);
uint totalBefore;
Fixed Show fixed Hide fixed
if (!autoCompoundingByUnderlyingProtocol()) {
__amounts[exchangeAssetIndex] +=
_liquidateRewards(__assets[exchangeAssetIndex], __rewardAssets, __rewardAmounts);

uint[] memory amountsRemaining = StrategyLib.extractFees(_platform, _vault, $._id, __assets, __amounts);
uint[] memory amountsRemaining = StrategyLib.extractFees(_platform, _vault, $._id, __assets, __amounts);

bool needCompound = _processRevenue(__assets, amountsRemaining);
bool needCompound = _processRevenue(__assets, amountsRemaining);

uint totalBefore = $.total;
totalBefore = $.total;

if (needCompound) {
_compound();
if (needCompound) {
_compound();
}
} else {
(, uint value) = _previewDepositAssets(__assets, __amounts);

Check warning on line 137 in src/strategies/base/StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/StrategyBase.sol#L137

Added line #L137 was not covered by tests
}

StrategyLib.emitApr($, _platform, __assets, __amounts, tvl, totalBefore);
Expand All @@ -136,9 +143,8 @@

/// @inheritdoc IStrategy
function emergencyStopInvesting() external onlyGovernanceOrMultisig {
StrategyBaseStorage storage $ = _getStrategyBaseStorage();
// slither-disable-next-line unused-return
_withdrawAssets($.total, address(this));
_withdrawAssets(total(), address(this));
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
Expand Down Expand Up @@ -168,7 +174,7 @@
}

/// @inheritdoc IStrategy
function total() public view override returns (uint) {
function total() public view virtual override returns (uint) {
return _getStrategyBaseStorage().total;
}

Expand Down Expand Up @@ -211,6 +217,11 @@
}
}

/// @inheritdoc IStrategy
function autoCompoundingByUnderlyingProtocol() public view virtual returns (bool) {
return false;

Check warning on line 222 in src/strategies/base/StrategyBase.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/base/StrategyBase.sol#L222

Added line #L222 was not covered by tests
}

/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* Default implementations */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
Expand Down
3 changes: 3 additions & 0 deletions src/strategies/libs/StrategyDeveloperLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
if (CommonLib.eq(strategyId, StrategyIdLib.CURVE_CONVEX_FARM)) {
return 0x88888887C3ebD4a33E34a15Db4254C74C75E5D4A;
}
if (CommonLib.eq(strategyId, StrategyIdLib.YEARN)) {
return 0x88888887C3ebD4a33E34a15Db4254C74C75E5D4A;

Check warning on line 36 in src/strategies/libs/StrategyDeveloperLib.sol

View check run for this annotation

Codecov / codecov/patch

src/strategies/libs/StrategyDeveloperLib.sol#L36

Added line #L36 was not covered by tests
}

return address(0);
}
Expand Down
1 change: 1 addition & 0 deletions src/strategies/libs/StrategyIdLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ library StrategyIdLib {
string internal constant QUICKSWAP_STATIC_MERKL_FARM = "QuickSwap Static Merkl Farm";
string internal constant GAMMA_RETRO_MERKL_FARM = "Gamma Retro Merkl Farm";
string internal constant CURVE_CONVEX_FARM = "Curve Convex Farm";
string internal constant YEARN = "Yearn";
}
3 changes: 2 additions & 1 deletion src/strategies/libs/StrategyLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,8 @@ library StrategyLib {
//slither-disable-next-line unused-return
(uint earned,, uint[] memory assetPrices,) = priceReader.getAssetsPrice(assets, amounts);
uint apr = computeApr(tvl, earned, duration);
uint aprCompound = computeApr(totalBefore, $.total - totalBefore, duration);
uint aprCompound = totalBefore != 0 ? computeApr(totalBefore, $.total - totalBefore, duration) : apr;

uint sharePrice = tvl * 1e18 / IERC20($.vault).totalSupply();
emit IStrategy.HardWork(apr, aprCompound, earned, tvl, duration, sharePrice, assetPrices);
$.lastApr = apr;
Expand Down
Loading