cleanup
This commit is contained in:
parent
694afbe9fe
commit
9f03bd9f5d
3 changed files with 89 additions and 108 deletions
|
|
@ -143,24 +143,16 @@ open features:
|
|||
- coverage
|
||||
- overflows
|
||||
- reentry
|
||||
- definition of severity and rewards
|
||||
- Minor: Results in some unexpected or undesired behavior or disrupts a system function, causing at least minor loss of funds for user or Liquidity Manager. - reward 0.5% share of fees
|
||||
- Major: Bug capable of creating a severe loss of funds for HARB holders or collapsing large parts of the system - reward: 2% share of fees
|
||||
- Critical: Bug capable of triggering severe loss of funds for LiquidityManager contract or complete shutdown in Harb/Stake/LiquidityManager contracts - reward: 5%
|
||||
- limitations: max 10% share of fees, no seat in multisig
|
||||
- HARB
|
||||
- mint - limit supply to 2^96?
|
||||
- Stake
|
||||
- sharesToAssets - should the average total supply be used for this calculation?
|
||||
- what if someone calls payTax and exitPosition in the same transaction?
|
||||
-
|
||||
- LiquidityManager
|
||||
- add events
|
||||
- what to do with stuck funds if slide/shift become inoperable?
|
||||
- _isPriceStable - // Handle try catch, possibly by trying with a different time interval or providing a default response
|
||||
- make slide and shift one function
|
||||
|
||||
|
||||
|
||||
- find a way to account harb/eth for attacker
|
||||
- NFT support of etherscan
|
||||
https://etherscan.io/nft/0xe12edaab53023c75473a5a011bdb729ee73545e8/4218
|
||||
|
|
@ -211,7 +211,7 @@ contract LiquidityManager {
|
|||
/// @dev Recalculates and realigns all liquidity positions according to the latest market data and strategic requirements.
|
||||
function _set(int24 currentTick) internal {
|
||||
|
||||
// ### set Floor position
|
||||
// set Floor position
|
||||
int24 vwapTick;
|
||||
{
|
||||
uint256 outstandingSupply = harb.outstandingSupply();
|
||||
|
|
@ -257,7 +257,6 @@ contract LiquidityManager {
|
|||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(vwapTick);
|
||||
int24 floorTick = token0isWeth ? vwapTick + TICK_SPACING: vwapTick - TICK_SPACING;
|
||||
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(floorTick);
|
||||
|
||||
uint128 liquidity;
|
||||
if (token0isWeth) {
|
||||
liquidity = LiquidityAmounts.getLiquidityForAmount0(
|
||||
|
|
@ -268,20 +267,10 @@ contract LiquidityManager {
|
|||
sqrtRatioAX96, sqrtRatioBX96, requiredEthForBuyback
|
||||
);
|
||||
}
|
||||
|
||||
// uint128 liquidity = LiquidityAmounts.getLiquidityForAmounts(
|
||||
// sqrtPriceX96,
|
||||
// sqrtRatioAX96,
|
||||
// sqrtRatioBX96,
|
||||
// token0isWeth ? requiredEthForBuyback : 0,
|
||||
// token0isWeth ? 0 : requiredEthForBuyback
|
||||
// );
|
||||
|
||||
// mint
|
||||
_mint(Stage.FLOOR, token0isWeth ? vwapTick : floorTick, token0isWeth ? floorTick : vwapTick, liquidity);
|
||||
}
|
||||
|
||||
// ### set Anchor position
|
||||
// set Anchor position
|
||||
uint128 anchorLiquidity;
|
||||
uint24 anchorWidth;
|
||||
{
|
||||
|
|
@ -310,7 +299,7 @@ contract LiquidityManager {
|
|||
}
|
||||
currentTick = currentTick / TICK_SPACING * TICK_SPACING;
|
||||
|
||||
// ## set Discovery position
|
||||
// set Discovery position
|
||||
{
|
||||
int24 tickLower = token0isWeth ? currentTick - DISCOVERY_SPACING - ANCHOR_SPACING : currentTick + ANCHOR_SPACING;
|
||||
int24 tickUpper = token0isWeth ? currentTick - ANCHOR_SPACING : currentTick + DISCOVERY_SPACING + ANCHOR_SPACING;
|
||||
|
|
|
|||
|
|
@ -86,6 +86,61 @@ contract Stake {
|
|||
return totalSupply * MAX_STAKE / 100;
|
||||
}
|
||||
|
||||
/// @dev Internal function to calculate and pay taxes for a position, adjusting shares and handling position liquidation if necessary.
|
||||
function _payTax(uint256 positionId, StakingPosition storage pos, uint256 taxFloorDuration) private {
|
||||
// ihet = Implied Holding Expiry Timestamp
|
||||
uint256 ihet = (block.timestamp - pos.creationTime < taxFloorDuration)
|
||||
? pos.creationTime + taxFloorDuration
|
||||
: block.timestamp;
|
||||
uint256 elapsedTime = ihet - pos.lastTaxTime;
|
||||
uint256 assetsBefore = sharesToAssets(pos.share);
|
||||
uint256 taxAmountDue = assetsBefore * TAX_RATES[pos.taxRate] * elapsedTime / (365 * 24 * 60 * 60) / TAX_RATE_BASE;
|
||||
if (taxAmountDue >= assetsBefore) {
|
||||
// can not pay more tax than value of position
|
||||
taxAmountDue = assetsBefore;
|
||||
}
|
||||
SafeERC20.safeTransfer(harb, taxPool, taxAmountDue);
|
||||
|
||||
if (assetsBefore - taxAmountDue > 0) {
|
||||
// if something left over, update storage
|
||||
uint256 shareAfterTax = assetsToShares(assetsBefore - taxAmountDue);
|
||||
outstandingStake -= pos.share - shareAfterTax;
|
||||
pos.share = shareAfterTax;
|
||||
pos.lastTaxTime = uint32(block.timestamp);
|
||||
emit PositionTaxPaid(positionId, pos.owner, taxAmountDue, shareAfterTax, pos.taxRate);
|
||||
} else {
|
||||
// if nothing left over, liquidate position
|
||||
outstandingStake -= pos.share;
|
||||
emit PositionTaxPaid(positionId, pos.owner, taxAmountDue, 0, pos.taxRate);
|
||||
emit PositionRemoved(positionId, pos.owner, 0);
|
||||
delete pos.owner;
|
||||
delete pos.creationTime;
|
||||
delete pos.share;
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Internal function to close a staking position, transferring the remaining Harb tokens back to the owner after tax payment.
|
||||
function _exitPosition(uint256 positionId, StakingPosition storage pos) private {
|
||||
outstandingStake -= pos.share;
|
||||
address owner = pos.owner;
|
||||
uint256 assets = sharesToAssets(pos.share);
|
||||
emit PositionRemoved(positionId, owner, assets);
|
||||
delete pos.owner;
|
||||
delete pos.creationTime;
|
||||
delete pos.share;
|
||||
SafeERC20.safeTransfer(harb, owner, assets);
|
||||
}
|
||||
|
||||
/// @dev Internal function to reduce the size of a staking position by a specified number of shares, transferring the corresponding Harb tokens to the owner.
|
||||
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
||||
require (sharesToTake < pos.share, "position too small");
|
||||
uint256 assets = sharesToAssets(sharesToTake);
|
||||
pos.share -= sharesToTake;
|
||||
outstandingStake -= sharesToTake;
|
||||
emit PositionShrunk(positionId, pos.owner, pos.share, assets);
|
||||
SafeERC20.safeTransfer(harb, pos.owner, assets);
|
||||
}
|
||||
|
||||
/// @notice Converts Harb token assets to shares of the total staking pool.
|
||||
/// @param assets Number of Harb tokens to convert.
|
||||
/// @return Number of shares corresponding to the input assets based on the current total supply of Harb tokens.
|
||||
|
|
@ -100,33 +155,6 @@ contract Stake {
|
|||
return shares.mulDiv(harb.totalSupply(), totalSupply, Math.Rounding.Down);
|
||||
}
|
||||
|
||||
/// @notice Combines an ERC20 permit operation with the snatch function, allowing a staking position creation in one transaction.
|
||||
/// @param assets Number of Harb tokens to stake.
|
||||
/// @param receiver Address that will own the new staking position.
|
||||
/// @param taxRate The initial tax rate for the new staking position.
|
||||
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
||||
/// @param deadline Time until which the permit is valid.
|
||||
/// @param v, r, s Components of the signature for the permit.
|
||||
/// @return positionId The ID of the newly created staking position.
|
||||
function permitAndSnatch(
|
||||
uint256 assets,
|
||||
address receiver,
|
||||
uint32 taxRate,
|
||||
uint256[] calldata positionsToSnatch,
|
||||
// address owner,
|
||||
// address spender,
|
||||
// uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external
|
||||
returns (uint256 positionId)
|
||||
{
|
||||
ERC20Permit(address(harb)).permit(receiver, address(this), assets, deadline, v, r, s);
|
||||
return snatch(assets, receiver, taxRate, positionsToSnatch);
|
||||
}
|
||||
|
||||
/// @notice Creates a new staking position by potentially snatching shares from existing positions.
|
||||
/// @param assets Amount of Harb tokens to convert into a staking position.
|
||||
/// @param receiver Address that will own the new staking position.
|
||||
|
|
@ -227,11 +255,38 @@ contract Stake {
|
|||
emit PositionCreated(positionId, sp.owner, assets, sp.share, sp.taxRate);
|
||||
}
|
||||
|
||||
/// @notice Combines an ERC20 permit operation with the snatch function, allowing a staking position creation in one transaction.
|
||||
/// @param assets Number of Harb tokens to stake.
|
||||
/// @param receiver Address that will own the new staking position.
|
||||
/// @param taxRate The initial tax rate for the new staking position.
|
||||
/// @param positionsToSnatch Array of position IDs that the new position will replace by snatching.
|
||||
/// @param deadline Time until which the permit is valid.
|
||||
/// @param v, r, s Components of the signature for the permit.
|
||||
/// @return positionId The ID of the newly created staking position.
|
||||
function permitAndSnatch(
|
||||
uint256 assets,
|
||||
address receiver,
|
||||
uint32 taxRate,
|
||||
uint256[] calldata positionsToSnatch,
|
||||
// address owner,
|
||||
// address spender,
|
||||
// uint256 value,
|
||||
uint256 deadline,
|
||||
uint8 v,
|
||||
bytes32 r,
|
||||
bytes32 s
|
||||
) external
|
||||
returns (uint256 positionId)
|
||||
{
|
||||
ERC20Permit(address(harb)).permit(receiver, address(this), assets, deadline, v, r, s);
|
||||
return snatch(assets, receiver, taxRate, positionsToSnatch);
|
||||
}
|
||||
|
||||
/// @notice Changes the tax rate of an existing staking position.
|
||||
/// @param positionId The ID of the staking position to update.
|
||||
/// @param taxRate The new tax rate to apply to the position.
|
||||
/// @dev Ensures that the tax rate change is valid and applies the minimum tax based on the TAX_FLOOR_DURATION.
|
||||
function changeTax(uint256 positionId, uint32 taxRate) public {
|
||||
function changeTax(uint256 positionId, uint32 taxRate) external {
|
||||
require(taxRate < TAX_RATES.length, "tax rate out of bounds");
|
||||
StakingPosition storage pos = positions[positionId];
|
||||
if (pos.creationTime == 0) {
|
||||
|
|
@ -250,7 +305,7 @@ contract Stake {
|
|||
/// @notice Allows the owner of a staking position to exit, returning the staked assets.
|
||||
/// @param positionId The ID of the staking position to exit.
|
||||
/// @dev Pays the due taxes based on the TAX_FLOOR_DURATION and returns the remaining assets to the position owner.
|
||||
function exitPosition(uint256 positionId) public {
|
||||
function exitPosition(uint256 positionId) external {
|
||||
StakingPosition storage pos = positions[positionId];
|
||||
if (pos.creationTime == 0) {
|
||||
revert PositionNotFound(positionId, msg.sender);
|
||||
|
|
@ -266,7 +321,7 @@ contract Stake {
|
|||
/// @notice Manually triggers the tax payment for a specified staking position.
|
||||
/// @param positionId The ID of the staking position for which to pay taxes.
|
||||
/// @dev Calculates and pays the tax due, possibly adjusting the position's share count.
|
||||
function payTax(uint256 positionId) public {
|
||||
function payTax(uint256 positionId) external {
|
||||
StakingPosition storage pos = positions[positionId];
|
||||
_payTax(positionId, pos, 0);
|
||||
}
|
||||
|
|
@ -285,59 +340,4 @@ contract Stake {
|
|||
uint256 assetsBefore = sharesToAssets(pos.share);
|
||||
amountDue = assetsBefore * TAX_RATES[pos.taxRate] * elapsedTime / (365 * 24 * 60 * 60) / TAX_RATE_BASE;
|
||||
}
|
||||
|
||||
/// @dev Internal function to calculate and pay taxes for a position, adjusting shares and handling position liquidation if necessary.
|
||||
function _payTax(uint256 positionId, StakingPosition storage pos, uint256 taxFloorDuration) private {
|
||||
// ihet = Implied Holding Expiry Timestamp
|
||||
uint256 ihet = (block.timestamp - pos.creationTime < taxFloorDuration)
|
||||
? pos.creationTime + taxFloorDuration
|
||||
: block.timestamp;
|
||||
uint256 elapsedTime = ihet - pos.lastTaxTime;
|
||||
uint256 assetsBefore = sharesToAssets(pos.share);
|
||||
uint256 taxAmountDue = assetsBefore * TAX_RATES[pos.taxRate] * elapsedTime / (365 * 24 * 60 * 60) / TAX_RATE_BASE;
|
||||
if (taxAmountDue >= assetsBefore) {
|
||||
// can not pay more tax than value of position
|
||||
taxAmountDue = assetsBefore;
|
||||
}
|
||||
SafeERC20.safeTransfer(harb, taxPool, taxAmountDue);
|
||||
|
||||
if (assetsBefore - taxAmountDue > 0) {
|
||||
// if something left over, update storage
|
||||
uint256 shareAfterTax = assetsToShares(assetsBefore - taxAmountDue);
|
||||
outstandingStake -= pos.share - shareAfterTax;
|
||||
pos.share = shareAfterTax;
|
||||
pos.lastTaxTime = uint32(block.timestamp);
|
||||
emit PositionTaxPaid(positionId, pos.owner, taxAmountDue, shareAfterTax, pos.taxRate);
|
||||
} else {
|
||||
// if nothing left over, liquidate position
|
||||
outstandingStake -= pos.share;
|
||||
emit PositionTaxPaid(positionId, pos.owner, taxAmountDue, 0, pos.taxRate);
|
||||
emit PositionRemoved(positionId, pos.owner, 0);
|
||||
delete pos.owner;
|
||||
delete pos.creationTime;
|
||||
delete pos.share;
|
||||
}
|
||||
}
|
||||
|
||||
/// @dev Internal function to close a staking position, transferring the remaining Harb tokens back to the owner after tax payment.
|
||||
function _exitPosition(uint256 positionId, StakingPosition storage pos) private {
|
||||
outstandingStake -= pos.share;
|
||||
address owner = pos.owner;
|
||||
uint256 assets = sharesToAssets(pos.share);
|
||||
emit PositionRemoved(positionId, owner, assets);
|
||||
delete pos.owner;
|
||||
delete pos.creationTime;
|
||||
delete pos.share;
|
||||
SafeERC20.safeTransfer(harb, owner, assets);
|
||||
}
|
||||
|
||||
/// @dev Internal function to reduce the size of a staking position by a specified number of shares, transferring the corresponding Harb tokens to the owner.
|
||||
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
||||
require (sharesToTake < pos.share, "position too small");
|
||||
uint256 assets = sharesToAssets(sharesToTake);
|
||||
pos.share -= sharesToTake;
|
||||
outstandingStake -= sharesToTake;
|
||||
emit PositionShrunk(positionId, pos.owner, pos.share, assets);
|
||||
SafeERC20.safeTransfer(harb, pos.owner, assets);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue