Skip to content

Commit

Permalink
Adding deposit and redeem functionality
Browse files Browse the repository at this point in the history
Renamed AcreRouter to Dispatcher and introduced an abstract contract
called Router that will handle moving funds between Acre and Vaults.

In order to deposit / redeem assets, Acre contract should approve assets
for Dispatcher to spend and call depositToVault or redeemFromVault
functions. These Acre's functions can be also called by a bot for
rebalancing purposes.
  • Loading branch information
dimpar committed Dec 12, 2023
1 parent e94c5fc commit dfec9bf
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 0 deletions.
26 changes: 26 additions & 0 deletions core/contracts/Dispatcher.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
pragma solidity ^0.8.21;

import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.sol";
import "./Router.sol";

/// @title Dispatcher
/// @notice Dispatcher is a contract that routes TBTC from stBTC (Acre) to
Expand Down Expand Up @@ -66,4 +68,28 @@ contract Dispatcher is Ownable {
function getVaults() external view returns (address[] memory) {
return vaults;
}

// TODO: add documentation
function depositToVault(
address vault,
uint256 amount,
uint256 minSharesOut
) public {
require(msg.sender == address(stBTC), "stBTC only");
require(vaultsInfo[vault].authorized, "Vault is not approved");

deposit(IERC4626(vault), address(stBTC), amount, minSharesOut);
}

// TODO: add documentation
function redeemFromVault(
address vault,
uint256 shares,
uint256 minAssetsOut
) public {
require(msg.sender == address(stBTC), "stBTC only");
require(vaultsInfo[vault].authorized, "Vault is not approved");

redeem(IERC4626(vault), address(stBTC), shares, minAssetsOut);
}
}
57 changes: 57 additions & 0 deletions core/contracts/Router.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.21;

import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC20.sol";
import "@openzeppelin/contracts/interfaces/IERC4626.sol";

/// TODO: Add documentation
abstract contract Router {
using SafeERC20 for IERC20;

/// @notice Routes funds from stBTC (Acre) to a vault. The amount of tBTC to
/// Shares of deposited tBTC are minted to the stBTC contract.
/// @param vault Address of the vault to route the funds to.
/// @param to Address of the receiver of the shares.
/// @param amount Amount of tBTC to deposit.
/// @param minSharesOut Minimum amount of shares to receive.
function deposit(
IERC4626 vault,
address to,
uint256 amount,
uint256 minSharesOut
) public returns (uint256 sharesOut) {
IERC20(vault.asset()).safeTransferFrom(
msg.sender,
address(this),
amount
);
IERC20(vault.asset()).safeIncreaseAllowance(address(vault), amount);
if ((sharesOut = vault.deposit(amount, to)) < minSharesOut) {
revert("Not enough shares received");
}
}

/// @notice Redeem tBTC from a vault and approve tokens to be transferred
/// by stBTC (Acre)
/// @param vault Address of the vault to collect the assets from.
/// @param to Address of the receiver of the assets.
/// @param shares Amount of shares to collect. Shares are the internal representation
/// of the underlying asset in the vault. Concrete amount of the
/// underlying asset is calculated by calling `convertToAssets` on
/// the vault and the shares are burned.
/// @param minAssetsOut Minimum amount of TBTC to receive.
function redeem(
IERC4626 vault,
address to,
uint256 shares,
uint256 minAssetsOut
) public returns (uint256 assetsOut) {
if (
(assetsOut = vault.redeem(shares, address(this), to)) < minAssetsOut
) {
revert("Not enough assets received");
}
IERC20(vault.asset()).safeIncreaseAllowance(to, assetsOut);
}
}

0 comments on commit dfec9bf

Please sign in to comment.