-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
56d7476
commit efda155
Showing
4 changed files
with
195 additions
and
4 deletions.
There are no files selected for viewing
92 changes: 92 additions & 0 deletions
92
contracts/strategies/crosschain/lamapay/LamaPayStrategyBase.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.13; | ||
|
||
import "./../../BaseStrategy.sol"; | ||
|
||
import "./../../../interfaces/ILamaPay.sol"; | ||
|
||
abstract contract LamaPayStrategyBase is BaseStrategy { | ||
using SafeERC20 for IERC20; | ||
|
||
struct Stream { | ||
address lamaPayInstance; | ||
address payer; | ||
uint216 amountPerSec; | ||
address token; | ||
} | ||
|
||
Stream[] public streams; | ||
|
||
event AddStream(address lamaPayInstance, address payer, uint216 amountPerSec, address token); | ||
event RemoveStream(address lamaPayInstance, address payer, uint216 amountPerSec, address token); | ||
event BorkedStream(address lamaPayInstance, address payer, uint216 amountPerSec, address token); | ||
|
||
constructor(BaseStrategySettings memory _baseStrategySettings, StrategySettings memory _strategySettings) | ||
BaseStrategy(_baseStrategySettings, _strategySettings) | ||
{} | ||
|
||
function addStream(address _lamaPayInstance, address _payer, uint216 _amountPerSec) external onlyDev { | ||
if (_lamaPayInstance > address(0) && _payer > address(0) && _amountPerSec > 0) { | ||
(, bool found) = findStream(_lamaPayInstance, _payer, _amountPerSec); | ||
require(!found, "MemeRushStrategy::Stream already configured!"); | ||
address token = ILamaPay(_lamaPayInstance).token(); | ||
streams.push( | ||
Stream({lamaPayInstance: _lamaPayInstance, payer: _payer, amountPerSec: _amountPerSec, token: token}) | ||
); | ||
emit AddStream(_lamaPayInstance, _payer, _amountPerSec, token); | ||
} | ||
} | ||
|
||
function removeStream(address _lamaPayInstance, address _payer, uint216 _amountPerSec) external onlyDev { | ||
(uint256 index, bool found) = findStream(_lamaPayInstance, _payer, _amountPerSec); | ||
require(found, "MemeRushStrategy::Stream not configured!"); | ||
streams[index] = streams[streams.length - 1]; | ||
streams.pop(); | ||
emit RemoveStream(_lamaPayInstance, _payer, _amountPerSec, ILamaPay(_lamaPayInstance).token()); | ||
} | ||
|
||
function findStream(address _lamaPayInstance, address _payer, uint216 _amountPerSec) | ||
internal | ||
view | ||
returns (uint256 index, bool found) | ||
{ | ||
for (uint256 i = 0; i < streams.length; i++) { | ||
if ( | ||
_lamaPayInstance == streams[i].lamaPayInstance && _payer == streams[i].payer | ||
&& _amountPerSec == streams[i].amountPerSec | ||
) { | ||
found = true; | ||
index = i; | ||
} | ||
} | ||
} | ||
|
||
function _readStream(Stream memory _stream) internal view returns (Reward memory) { | ||
try ILamaPay(_stream.lamaPayInstance).withdrawable(_stream.payer, address(this), _stream.amountPerSec) returns ( | ||
uint256 withdrawableAmount, uint256, uint256 | ||
) { | ||
return Reward({reward: _stream.token, amount: withdrawableAmount}); | ||
} catch { | ||
return Reward({reward: _stream.token, amount: 0}); | ||
} | ||
} | ||
|
||
function _pendingRewards() internal view virtual override returns (Reward[] memory) { | ||
Reward[] memory rewards = new Reward[](streams.length); | ||
for (uint256 i = 0; i < streams.length; i++) { | ||
rewards[i] = _readStream(streams[i]); | ||
} | ||
return rewards; | ||
} | ||
|
||
function _getRewards() internal virtual override { | ||
for (uint256 i = 0; i < streams.length; i++) { | ||
try ILamaPay(streams[i].lamaPayInstance).withdraw(streams[i].payer, address(this), streams[i].amountPerSec) | ||
{} catch { | ||
emit BorkedStream( | ||
streams[i].lamaPayInstance, streams[i].payer, streams[i].amountPerSec, streams[i].token | ||
); | ||
} | ||
} | ||
} | ||
} |
99 changes: 99 additions & 0 deletions
99
contracts/strategies/crosschain/pendle/BoostedPendleStrategy.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.13; | ||
|
||
import "./../lamapay/LamaPayStrategyBase.sol"; | ||
|
||
import "./interfaces/IPendleProxy.sol"; | ||
import "./interfaces/IPendleRouter.sol"; | ||
import "./interfaces/IPendleMarketLP.sol"; | ||
import "./interfaces/ISy.sol"; | ||
|
||
contract BoostedPendleStrategy is LamaPayStrategyBase { | ||
using SafeERC20 for IERC20; | ||
|
||
IPendleProxy public proxy; | ||
|
||
address public immutable lpTokenIn; | ||
IPendleRouter public immutable pendleRouter; | ||
|
||
// EmptySwap means no swap aggregator is involved | ||
IPendleRouter.SwapData private emptySwap; | ||
// EmptyLimit means no limit order is involved | ||
IPendleRouter.LimitOrderData private emptyLimit; | ||
// DefaultApprox means no off-chain preparation is involved, more gas consuming (~ 180k gas) | ||
IPendleRouter.ApproxParams private defaultApprox = IPendleRouter.ApproxParams(0, type(uint256).max, 0, 256, 1e14); | ||
|
||
constructor( | ||
address _proxy, | ||
address _pendleRouter, | ||
BaseStrategySettings memory baseStrategySettings, | ||
StrategySettings memory _strategySettings | ||
) LamaPayStrategyBase(baseStrategySettings, _strategySettings) { | ||
proxy = IPendleProxy(_proxy); | ||
pendleRouter = IPendleRouter(_pendleRouter); | ||
(address sy,,) = IPendleMarketLP(address(depositToken)).readTokens(); | ||
lpTokenIn = ISy(sy).yieldToken(); | ||
} | ||
|
||
function setProxy(address _proxy) external onlyDev { | ||
proxy = IPendleProxy(_proxy); | ||
} | ||
|
||
function _depositToStakingContract(uint256 _amount, uint256) internal override { | ||
depositToken.transfer(proxy.voter(), _amount); | ||
} | ||
|
||
function _withdrawFromStakingContract(uint256 _amount) internal override returns (uint256 _withdrawAmount) { | ||
proxy.withdrawFromStakingContract(address(depositToken), _amount); | ||
return _amount; | ||
} | ||
|
||
function _pendingRewards() internal view override returns (Reward[] memory) { | ||
Reward[] memory rewardsProxy = proxy.pendingRewards(address(depositToken)); | ||
|
||
uint256 length = rewardsProxy.length + streams.length; | ||
|
||
Reward[] memory rewards = new Reward[](length); | ||
uint256 i; | ||
for (i; i < streams.length; i++) { | ||
rewards[i] = _readStream(streams[i]); | ||
} | ||
for (uint256 j; j < rewardsProxy.length; j++) { | ||
rewards[i + j] = rewardsProxy[j]; | ||
} | ||
return rewards; | ||
} | ||
|
||
function _getRewards() internal override { | ||
super._getRewards(); | ||
proxy.getRewards(address(depositToken)); | ||
} | ||
|
||
function _convertRewardTokenToDepositToken(uint256 _fromAmount) internal override returns (uint256 out) { | ||
if (address(rewardToken) != lpTokenIn) { | ||
FormattedOffer memory offer = simpleRouter.query(_fromAmount, address(rewardToken), lpTokenIn); | ||
_fromAmount = _swap(offer); | ||
} | ||
if (_fromAmount > 0) { | ||
IERC20(lpTokenIn).approve(address(pendleRouter), _fromAmount); | ||
IPendleRouter.TokenInput memory tokenInput = IPendleRouter.TokenInput({ | ||
tokenIn: lpTokenIn, | ||
netTokenIn: _fromAmount, | ||
tokenMintSy: lpTokenIn, | ||
pendleSwap: address(0), | ||
swapData: emptySwap | ||
}); | ||
(out,,) = pendleRouter.addLiquiditySingleToken( | ||
address(this), address(depositToken), 0, defaultApprox, tokenInput, emptyLimit | ||
); | ||
} | ||
} | ||
|
||
function totalDeposits() public view override returns (uint256) { | ||
return proxy.totalDeposits(address(depositToken)); | ||
} | ||
|
||
function _emergencyWithdraw() internal override { | ||
proxy.emergencyWithdraw(address(depositToken)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters