Skip to content

Commit

Permalink
added events and further management functions
Browse files Browse the repository at this point in the history
  • Loading branch information
RedVeil committed Jun 13, 2024
1 parent 1cb9fe2 commit c874421
Show file tree
Hide file tree
Showing 2 changed files with 246 additions and 60 deletions.
190 changes: 170 additions & 20 deletions src/strategies/AnyConverter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ abstract contract AnyConverter is BaseStrategy {

IPriceOracle public oracle;

uint256 public slippage;
uint256 public floatRatio;

/*//////////////////////////////////////////////////////////////
INITIALIZATION
//////////////////////////////////////////////////////////////*/
Expand Down Expand Up @@ -61,12 +58,29 @@ abstract contract AnyConverter is BaseStrategy {
ACCOUNTING LOGIC
//////////////////////////////////////////////////////////////*/

/**
* @notice Total amount of underlying `asset` token managed by adapter.
* @dev Return assets held by adapter if paused.
*/
function totalAssets() public view virtual override returns (uint256) {
uint256 bal = IERC20(asset()).balanceOf(address(this));
uint256 _totalReservedAssets = totalReservedAssets;
uint256 yieldAssetBal = _totalAssets();

if (bal <= _totalReservedAssets) return yieldAssetBal;
return (bal - totalReservedAssets) + yieldAssetBal;
}

/// @notice Calculates the total amount of underlying tokens the Vault holds.
/// @return The total amount of underlying tokens the Vault holds.
function _totalAssets() internal view override returns (uint256) {
uint256 yieldBal = IERC20(yieldAsset).balanceOf(address(this));
uint256 _totalReservedYieldAssets = totalReservedYieldAssets;

if (yieldBal <= _totalReservedYieldAssets) return 0;
return
oracle.getQuote(
IERC20(yieldAsset).balanceOf(address(this)),
yieldBal - _totalReservedYieldAssets,
yieldAsset,
asset()
);
Expand Down Expand Up @@ -98,24 +112,28 @@ abstract contract AnyConverter is BaseStrategy {
PUSH/PULL LOGIC
//////////////////////////////////////////////////////////////*/

event PushedFunds(uint256 yieldAssetsIn, uint256 assetsOut);
event PulledFunds(uint256 assetsIn, uint256 yieldAssetsOut);

error SlippageTooHigh();
error NotEnoughFloat();

function pushFunds(
uint256 assets,
bytes memory data
bytes memory
) external override onlyKeeperOrOwner {
// caching
IERC20 _asset = IERC20(asset());
address _asset = asset();
address _yieldAsset = yieldAsset;

uint256 ta = this.totalAssets();
uint256 bal = _asset.balanceOf(address(this));
uint256 bal = IERC20(_asset).balanceOf(address(this));

IERC20(yieldAsset).transferFrom(msg.sender, address(this), assets);
IERC20(_yieldAsset).transferFrom(msg.sender, address(this), assets);

uint256 postTa = this.totalAssets();

uint256 withdrawable = oracle.getQuote(assets, yieldAsset, asset());
uint256 withdrawable = oracle.getQuote(assets, _yieldAsset, _asset);

if (floatRatio > 0) {
uint256 float = ta.mulDiv(
Expand All @@ -134,42 +152,174 @@ abstract contract AnyConverter is BaseStrategy {
ta.mulDiv(10_000 - slippage, 10_000, Math.Rounding.Floor)
) revert SlippageTooHigh();

_asset.transfer(msg.sender, withdrawable);
_reserveToken(assets, withdrawable, _asset, false);

emit PushedFunds(assets, withdrawable);
}

function pullFunds(
uint256 assets,
bytes memory data
bytes memory
) external override onlyKeeperOrOwner {
// caching
IERC20 _asset = IERC20(asset());
address _asset = asset();
address _yieldAsset = yieldAsset;

uint256 ta = this.totalAssets();
uint256 bal = IERC20(yieldAsset).balanceOf(address(this));

_asset.transferFrom(msg.sender, address(this), assets);
IERC20(_asset).transferFrom(msg.sender, address(this), assets);

uint256 postTa = this.totalAssets();

uint256 withdrawable = oracle.getQuote(assets, yieldAsset, asset());
uint256 withdrawable = oracle.getQuote(assets, _yieldAsset, _asset);

if (
postTa - withdrawable <
ta.mulDiv(10_000 - slippage, 10_000, Math.Rounding.Floor)
) revert SlippageTooHigh();

_asset.transfer(msg.sender, withdrawable);
_reserveToken(assets, withdrawable, _yieldAsset, true);

emit PulledFunds(assets, withdrawable);
}

/*//////////////////////////////////////////////////////////////
ADMIN LOGIC
//////////////////////////////////////////////////////////////*/
error Misconfigured();

event SlippageProposed(uint256 slippage);
event SlippageChanged(uint256 oldSlippage, uint256 newSlippage);
event FloatRatioProposed(uint256 ratio);
event FloatRatioChanged(uint256 oldRatio, uint256 newRatio);

struct ProposedChange {
uint256 value;
uint256 changeTime;
}

ProposedChange public proposedSlippage;
uint256 public slippage;

ProposedChange public proposedFloatRatio;
uint256 public floatRatio;

function proposeSlippage(uint256 slippage_) external onlyOwner {
if (slippage_ > 10_000) revert Misconfigured();

proposedSlippage = ProposedChange({
value: slippage_,
changeTime: block.timestamp + 3 days
});

emit SlippageProposed(slippage_);
}

function changeSlippage() external onlyOwner {
ProposedChange memory _proposedSlippage = proposedSlippage;

if (_proposedSlippage.changeTime == 0) revert Misconfigured();

emit SlippageChanged(slippage, _proposedSlippage.value);

function setSlippage(uint256 slippage_) external onlyOwner {
slippage = slippage_;
slippage = _proposedSlippage.value;

delete proposedSlippage;
}

function setFloatRatio(uint256 floatRatio_) external onlyOwner {
floatRatio = floatRatio_;
function proposeFloatRatio(uint256 ratio_) external onlyOwner {
if (ratio_ > 10_000) revert Misconfigured();

proposedFloatRatio = ProposedChange({
value: ratio_,
changeTime: block.timestamp + 3 days
});

emit FloatRatioProposed(ratio_);
}

function changeFloatRatio() external onlyOwner {
ProposedChange memory _proposedFloatRatio = proposedFloatRatio;

if (_proposedFloatRatio.changeTime == 0) revert Misconfigured();

emit FloatRatioChanged(slippage, _proposedFloatRatio.value);

floatRatio = _proposedFloatRatio.value;

delete proposedFloatRatio;
}

/*//////////////////////////////////////////////////////////////
ADMIN LOGIC
//////////////////////////////////////////////////////////////*/

struct Reserved {
uint256 unlockTime;
uint256 deposited;
uint256 withdrawable;
}

event ReserveClaimed(address user, address token, uint256 withdrawn);

uint256 public totalReservedAssets;
uint256 public totalReservedYieldAssets;

mapping(address => mapping(address => Reserved)) public reserved;

function claimReserved() external {
address _asset = asset();
address _yieldAsset = yieldAsset;

_claimReserved(_asset, _yieldAsset, false);
_claimReserved(_yieldAsset, _asset, true);
}

function _claimReserved(
address base,
address quote,
bool isYieldAsset
) internal {
Reserved memory _reserved = reserved[msg.sender][base];
if (_reserved.unlockTime < block.timestamp) {
uint256 withdrawable = Math.min(
oracle.getQuote(_reserved.deposited, base, quote),
_reserved.withdrawable
);

if (withdrawable > 0) {
delete reserved[msg.sender][base];

if (isYieldAsset) {
totalReservedYieldAssets -= withdrawable;
} else {
totalReservedAssets -= withdrawable;
}

IERC20(base).transfer(msg.sender, withdrawable);
}
emit ReserveClaimed(msg.sender, base, _reserved.withdrawable);
}
}

function _reserveToken(
uint256 amount,
uint256 withdrawable,
address token,
bool isYieldAsset
) internal {
Reserved memory _reserved = reserved[msg.sender][token];

_reserved.deposited += amount;
_reserved.withdrawable += withdrawable;
_reserved.unlockTime = block.timestamp + 1 days;

reserved[msg.sender][token] = _reserved;

if (isYieldAsset) {
totalReservedYieldAssets += amount;
} else {
totalReservedAssets += amount;
}
}
}
Loading

0 comments on commit c874421

Please sign in to comment.