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

Staking limits #68

Merged
merged 50 commits into from
Dec 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2bdc9b5
Create `StakingParameters` struct
r-czajkowski Dec 7, 2023
5679d87
Set default staking parameters in constructor
r-czajkowski Dec 7, 2023
ae7b3fb
Implement min amount limit for a single deposit
r-czajkowski Dec 7, 2023
1765b6d
Fix typo
r-czajkowski Dec 7, 2023
5494c44
Simplify test
r-czajkowski Dec 7, 2023
15ff38d
Override `maxDeposit` fn
r-czajkowski Dec 7, 2023
0efc202
Implement staking limits in `mint` fn
r-czajkowski Dec 7, 2023
2fda404
Add fn that allows owner to update staking params
r-czajkowski Dec 8, 2023
7ae23cb
Add unit test for `updateStakingParameters` fn
r-czajkowski Dec 8, 2023
a5d022c
Fix unit tests
r-czajkowski Dec 8, 2023
4a1de54
Fix slither errors
r-czajkowski Dec 8, 2023
afc2323
Fix deployment scripts
r-czajkowski Dec 8, 2023
7b907fe
Simplify overridden `deposit` fn
r-czajkowski Dec 8, 2023
2ecd47f
Simplify the Acre constructor
r-czajkowski Dec 12, 2023
425a06f
Update `maxDeposit` fn
r-czajkowski Dec 12, 2023
8535cfe
Move the require check before `super.mint`
r-czajkowski Dec 12, 2023
ec6f06e
Update `updateStakingParameters` fn
r-czajkowski Dec 12, 2023
7516de4
Leave TODO in `updateStakingParameters`
r-czajkowski Dec 12, 2023
331c1d3
Define custom errors for the checks
r-czajkowski Dec 12, 2023
17dc55a
Merge branch 'main' into staking-limits
r-czajkowski Dec 13, 2023
f23a8e7
Merge branch 'main' into staking-limits
r-czajkowski Dec 19, 2023
bff9665
Update `mint` function
r-czajkowski Dec 19, 2023
9ed875d
Update `updateStakingParameters` function
r-czajkowski Dec 19, 2023
f9f230a
Rename error
r-czajkowski Dec 19, 2023
b2c4a80
Simplify `maxDeposit` function
r-czajkowski Dec 19, 2023
ea67712
Add unit test for `mint` function
r-czajkowski Dec 19, 2023
43f583d
Fix typo
r-czajkowski Dec 20, 2023
becb46e
Add unit tests for `maxMint` function
r-czajkowski Dec 20, 2023
1c42a37
Update validation of staking parameters
r-czajkowski Dec 20, 2023
a5903e3
Update `maxMint` function
r-czajkowski Dec 20, 2023
a13b09f
Get rid of `StakingParameter` struct
r-czajkowski Dec 20, 2023
31f74f2
Update `Acre` constructor
r-czajkowski Dec 21, 2023
5ec1b80
Rename error
r-czajkowski Dec 21, 2023
1f14cde
Update Acre docs
r-czajkowski Dec 21, 2023
e8f7aa1
Remove unnecessary test
r-czajkowski Dec 21, 2023
ab8d89c
Add `.withArgs` for all errors that have args
r-czajkowski Dec 21, 2023
0e33e4b
Celean up Acre unit tests
r-czajkowski Dec 21, 2023
3266007
Merge branch 'main' into staking-limits
r-czajkowski Dec 21, 2023
edd69cf
Add missing `await` in `before` test hook
r-czajkowski Dec 27, 2023
a373b59
Use `convertToShares` instead of `previewDeposit`
r-czajkowski Dec 27, 2023
f5a4429
Update `mint` test case
r-czajkowski Dec 27, 2023
fc5f585
Update `updateDepositParameters` fn
r-czajkowski Dec 27, 2023
1356fb0
Allow to remove the limit for deposits
r-czajkowski Dec 27, 2023
54bcf17
Update `maxMint` function
r-czajkowski Dec 28, 2023
0f8b830
Add unit tests for `deposit` function
r-czajkowski Dec 28, 2023
53ca7fc
Merge branch 'main' into staking-limits
r-czajkowski Dec 28, 2023
771553b
Fix slither error
r-czajkowski Dec 29, 2023
cc05de6
Fix typo
r-czajkowski Dec 29, 2023
d2fcf4a
Add new test case for staking
r-czajkowski Dec 29, 2023
1140bcb
Merge branch 'main' into staking-limits
r-czajkowski Dec 29, 2023
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
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(
nkuba marked this conversation as resolved.
Show resolved Hide resolved
uint256 assets,
address receiver
) public override returns (uint256) {
if (assets < minimumDepositAmount) {
revert DepositAmountLessThanMin(assets, minimumDepositAmount);
nkuba marked this conversation as resolved.
Show resolved Hide resolved
}

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(
dimpar marked this conversation as resolved.
Show resolved Hide resolved
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) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It says that

// Maximum total amount of tBTC token held by Acre.
maximumTotalAssets

tBTC is pegged to BTC. As of now, max total supply of BTC is capped to 21M. No way BTC will reach max of uint256, unless something really ground breaking will happen to the whole crypto space. I don't think this check is necessary.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The max uint256 value is used to disable the limit. If the maximumTotalAssets is set to the maxuint256, the function won't bother with further calculations and immediately returns the max uint256 value.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, but this is a view function that doesn't cost anything even if we do the calculation. I think it's a bit confusing and I know that uint256 is a big number, but logically it's not 100% correct, because if there are already assets in Acre, then maxDeposit should return maxuint256 - totalAssets, not just maxuint256. I don't think it can bite us though. Up to you guys.

return type(uint256).max;
}

uint256 _totalAssets = totalAssets();
nkuba marked this conversation as resolved.
Show resolved Hide resolved

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);
dimpar marked this conversation as resolved.
Show resolved Hide resolved

// 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
Loading