Skip to content

Commit

Permalink
Staking limits (#68)
Browse files Browse the repository at this point in the history
Closes: #59 

This PR implements staking limits. Here we add staking parameters that
define the maximum total assets(tBTC) that the Acre contract can hold
and the minimum deposit amount for a single deposit operation. Each
staking parameter can be updated by the owner.
  • Loading branch information
nkuba authored Dec 29, 2023
2 parents 8f1c189 + 1140bcb commit 8cd6745
Show file tree
Hide file tree
Showing 3 changed files with 785 additions and 90 deletions.
118 changes: 116 additions & 2 deletions core/contracts/Acre.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
pragma solidity ^0.8.21;

import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/// @title Acre
/// @notice This contract implements the ERC-4626 tokenized vault standard. By
Expand All @@ -14,12 +15,86 @@ import "@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol";
/// of yield-bearing vaults. This contract facilitates the minting and
/// burning of shares (stBTC), which are represented as standard ERC20
/// tokens, providing a seamless exchange with tBTC tokens.
contract Acre is ERC4626 {
contract Acre is ERC4626, Ownable {
// Minimum amount for a single deposit operation.
uint256 public minimumDepositAmount;
// Maximum total amount of tBTC token held by Acre.
uint256 public maximumTotalAssets;

event StakeReferral(bytes32 indexed referral, uint256 assets);
event DepositParametersUpdated(
uint256 minimumDepositAmount,
uint256 maximumTotalAssets
);

error DepositAmountLessThanMin(uint256 amount, uint256 min);

constructor(
IERC20 tbtc
) ERC4626(tbtc) ERC20("Acre Staked Bitcoin", "stBTC") {}
) ERC4626(tbtc) ERC20("Acre Staked Bitcoin", "stBTC") Ownable(msg.sender) {
// TODO: Revisit the exact values closer to the launch.
minimumDepositAmount = 0.01 * 1e18; // 0.01 tBTC
maximumTotalAssets = 25 * 1e18; // 25 tBTC
}

/// @notice Updates deposit parameters.
/// @dev To disable the limit for deposits, set the maximum total assets to
/// maximum (`type(uint256).max`).
/// @param _minimumDepositAmount New value of the minimum deposit amount. It
/// is the minimum amount for a single deposit operation.
/// @param _maximumTotalAssets New value of the maximum total assets amount.
/// It is the maximum amount of the tBTC token that the Acre can
/// hold.
function updateDepositParameters(
uint256 _minimumDepositAmount,
uint256 _maximumTotalAssets
) external onlyOwner {
// TODO: Introduce a parameters update process.
minimumDepositAmount = _minimumDepositAmount;
maximumTotalAssets = _maximumTotalAssets;

emit DepositParametersUpdated(
_minimumDepositAmount,
_maximumTotalAssets
);
}

/// @notice Mints shares to receiver by depositing exactly amount of
/// tBTC tokens.
/// @dev Takes into account a deposit parameter, minimum deposit amount,
/// which determines the minimum amount for a single deposit operation.
/// The amount of the assets has to be pre-approved in the tBTC
/// contract.
/// @param assets Approved amount of tBTC tokens to deposit.
/// @param receiver The address to which the shares will be minted.
/// @return Minted shares.
function deposit(
uint256 assets,
address receiver
) public override returns (uint256) {
if (assets < minimumDepositAmount) {
revert DepositAmountLessThanMin(assets, minimumDepositAmount);
}

return super.deposit(assets, receiver);
}

/// @notice Mints shares to receiver by depositing tBTC tokens.
/// @dev Takes into account a deposit parameter, minimum deposit amount,
/// which determines the minimum amount for a single deposit operation.
/// The amount of the assets has to be pre-approved in the tBTC
/// contract.
/// @param shares Amount of shares to mint. To get the amount of share use
/// `previewMint`.
/// @param receiver The address to which the shares will be minted.
function mint(
uint256 shares,
address receiver
) public override returns (uint256 assets) {
if ((assets = super.mint(shares, receiver)) < minimumDepositAmount) {
revert DepositAmountLessThanMin(assets, minimumDepositAmount);
}
}

/// @notice Stakes a given amount of tBTC token and mints shares to a
/// receiver.
Expand All @@ -43,4 +118,43 @@ contract Acre is ERC4626 {

return shares;
}

/// @notice Returns the maximum amount of the tBTC token that can be
/// deposited into the vault for the receiver, through a deposit
/// call. It takes into account the deposit parameter, maximum total
/// assets, which determines the total amount of tBTC token held by
/// Acre.
/// @return The maximum amount of the tBTC token.
function maxDeposit(address) public view override returns (uint256) {
if (maximumTotalAssets == type(uint256).max) {
return type(uint256).max;
}

uint256 _totalAssets = totalAssets();

return
_totalAssets >= maximumTotalAssets
? 0
: maximumTotalAssets - _totalAssets;
}

/// @notice Returns the maximum amount of the vault shares that can be
/// minted for the receiver, through a mint call.
/// @dev Since the Acre contract limits the maximum total tBTC tokens this
/// function converts the maximum deposit amount to shares.
/// @return The maximum amount of the vault shares.
function maxMint(address receiver) public view override returns (uint256) {
uint256 _maxDeposit = maxDeposit(receiver);

// slither-disable-next-line incorrect-equality
return
_maxDeposit == type(uint256).max
? type(uint256).max
: convertToShares(_maxDeposit);
}

/// @return Returns deposit parameters.
function depositParameters() public view returns (uint256, uint256) {
return (minimumDepositAmount, maximumTotalAssets);
}
}
2 changes: 0 additions & 2 deletions core/deploy/21_transfer_ownership_acre.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,5 +19,3 @@ const func: DeployFunction = async (hre: HardhatRuntimeEnvironment) => {
export default func

func.tags = ["TransferOwnershipAcre"]
// TODO: Enable once Acre extends Ownable
func.skip = async () => true
Loading

0 comments on commit 8cd6745

Please sign in to comment.