staking tests
This commit is contained in:
parent
39065a908e
commit
72abf097df
4 changed files with 192 additions and 16 deletions
|
|
@ -24,7 +24,7 @@ contract BaseLineLP {
|
|||
int24 constant TICK_SPACING = 200;
|
||||
int24 constant ANCHOR_SPACING = 5 * TICK_SPACING;
|
||||
int24 constant DISCOVERY_SPACING = 11000;
|
||||
int24 constant MAX_TICK_DEVIATION = 50;
|
||||
int24 constant MAX_TICK_DEVIATION = 50; // how much is that?
|
||||
// default fee of 1%
|
||||
uint24 constant FEE = uint24(10_000);
|
||||
// uint256 constant FLOOR = 0;
|
||||
|
|
|
|||
|
|
@ -138,6 +138,11 @@ contract Harb is ERC20, ERC20Permit {
|
|||
}
|
||||
twabController.mint(receiver, SafeCast.toUint96(amount));
|
||||
emit Transfer(address(0), receiver, amount);
|
||||
if (ubiTitles[receiver].time == 0 && amount > 0) {
|
||||
// new account, start UBI title
|
||||
ubiTitles[receiver].sumTaxCollected = sumTaxCollected;
|
||||
ubiTitles[receiver].time = block.timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ contract Stake is IStake {
|
|||
uint256 internal constant MAX_STAKE = 20; // 20% of HARB supply
|
||||
uint256 internal constant TAX_RATE_BASE = 100;
|
||||
uint256 internal constant TAX_FLOOR_DURATION = 60 * 60 * 24 * 3; //this duration is the minimum basis for fee calculation, regardless of actual holding time.
|
||||
uint256[] public TAX_RATES = [1, 3, 5, 8, 12, 18, 24, 30, 40, 50, 60, 80, 100, 130, 180, 250, 320, 420, 540, 700, 920, 1200, 1600];
|
||||
uint256[] public TAX_RATES = [1, 3, 5, 8, 12, 18, 24, 30, 40, 50, 60, 80, 100, 130, 180, 250, 320, 420, 540, 700, 920, 1200, 1600]; //TODO: increate until 3 days take all position
|
||||
/**
|
||||
* @dev Attempted to deposit more assets than the max amount for `receiver`.
|
||||
*/
|
||||
|
|
@ -48,7 +48,7 @@ contract Stake is IStake {
|
|||
address private immutable taxPool;
|
||||
uint256 public outstandingStake;
|
||||
uint256 public nextPositionId;
|
||||
uint256 public minStake;
|
||||
uint256 public minStake; // TODO: handle this
|
||||
mapping(uint256 => StakingPosition) public positions;
|
||||
|
||||
constructor(address _tokenContract) {
|
||||
|
|
@ -56,6 +56,7 @@ contract Stake is IStake {
|
|||
|
||||
totalSupply = 10 ** (tokenContract.decimals() + DECIMAL_OFFSET);
|
||||
taxPool = Harb(_tokenContract).TAX_POOL();
|
||||
nextPositionId = 654321;
|
||||
}
|
||||
|
||||
function dormantSupply() public view override returns (uint256) {
|
||||
|
|
@ -95,7 +96,7 @@ contract Stake is IStake {
|
|||
return snatch(assets, receiver, taxRate, positionsToSnatch);
|
||||
}
|
||||
|
||||
|
||||
event DEBUG(uint256 line);
|
||||
|
||||
/**
|
||||
* TODO: deal with metatransactions: While these are generally available
|
||||
|
|
@ -113,14 +114,18 @@ contract Stake is IStake {
|
|||
if (sharesWanted < minStake) {
|
||||
revert SharesTooLow(receiver, assets, sharesWanted, minStake);
|
||||
}
|
||||
emit DEBUG(authorizedStake());
|
||||
// TODO: check that position size is multiple of minStake
|
||||
// TODO: check that tax rate within limits of array
|
||||
|
||||
uint256 smallestPositionShare = totalSupply;
|
||||
emit DEBUG(outstandingStake);
|
||||
uint256 availableStake = authorizedStake() - outstandingStake;
|
||||
|
||||
if (positionsToSnatch.length > 0) {
|
||||
// run through all suggested positions to snatch
|
||||
emit DEBUG(2);
|
||||
|
||||
if (positionsToSnatch.length >= 2) {
|
||||
// run through all but last positions to snatch
|
||||
for (uint256 i = 0; i < positionsToSnatch.length - 1; i++) {
|
||||
StakingPosition storage pos = positions[positionsToSnatch[i]];
|
||||
if (pos.creationTime == 0) {
|
||||
|
|
@ -139,11 +144,11 @@ contract Stake is IStake {
|
|||
_payTax(positionsToSnatch[i], pos, 0);
|
||||
_exitPosition(positionsToSnatch[i], pos);
|
||||
}
|
||||
}
|
||||
availableStake = authorizedStake() - outstandingStake;
|
||||
|
||||
availableStake = authorizedStake() - outstandingStake;
|
||||
|
||||
// handle last position
|
||||
|
||||
if (positionsToSnatch.length > 0) {
|
||||
// handle last position, either shrink or snatch
|
||||
uint256 index = positionsToSnatch.length - 1;
|
||||
StakingPosition storage lastPos = positions[positionsToSnatch[index]];
|
||||
if (lastPos.creationTime == 0) {
|
||||
|
|
@ -159,10 +164,19 @@ contract Stake is IStake {
|
|||
}
|
||||
// dissolve position
|
||||
_payTax(positionsToSnatch[index], lastPos, 0);
|
||||
uint256 lastBitNeeded = sharesWanted - availableStake;
|
||||
_shrinkPosition(positionsToSnatch[index], lastPos, lastBitNeeded);
|
||||
availableStake += lastBitNeeded;
|
||||
emit DEBUG(sharesWanted);
|
||||
emit DEBUG(availableStake);
|
||||
if (availableStake > sharesWanted) {
|
||||
revert TooMuchSnatch(receiver, sharesWanted, availableStake, smallestPositionShare);
|
||||
}
|
||||
uint256 lastSharesNeeded = sharesWanted - availableStake;
|
||||
if (lastSharesNeeded > lastPos.share * 80 / 100) {
|
||||
_exitPosition(positionsToSnatch[index], lastPos);
|
||||
} else {
|
||||
_shrinkPosition(positionsToSnatch[index], lastPos, lastSharesNeeded);
|
||||
}
|
||||
}
|
||||
availableStake = authorizedStake() - outstandingStake;
|
||||
|
||||
if (sharesWanted > availableStake) {
|
||||
revert ExceededAvailableStake(receiver, sharesWanted, availableStake);
|
||||
|
|
@ -243,7 +257,9 @@ contract Stake is IStake {
|
|||
emit TaxPaid(positionID, pos.owner, taxAmountDue);
|
||||
if (assetsBefore - taxAmountDue > 0) {
|
||||
// if something left over, update storage
|
||||
pos.share = assetsToShares(assetsBefore - taxAmountDue, Math.Rounding.Down);
|
||||
uint256 shareAfterTax = assetsToShares(assetsBefore - taxAmountDue, Math.Rounding.Down);
|
||||
outstandingStake -= pos.share - shareAfterTax;
|
||||
pos.share = shareAfterTax;
|
||||
pos.lastTaxTime = uint32(block.timestamp);
|
||||
} else {
|
||||
// if nothing left over, liquidate position
|
||||
|
|
@ -265,9 +281,9 @@ contract Stake is IStake {
|
|||
}
|
||||
|
||||
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
||||
require (sharesToTake > pos.share, "position too small");
|
||||
pos.share -= sharesToTake;
|
||||
require (sharesToTake < pos.share, "position too small");
|
||||
uint256 assets = sharesToAssets(sharesToTake, Math.Rounding.Down);
|
||||
pos.share -= sharesToTake;
|
||||
emit PositionShrunk(positionId, pos.share, pos.lastTaxTime, sharesToTake);
|
||||
SafeERC20.safeTransfer(tokenContract, pos.owner, assets);
|
||||
}
|
||||
|
|
|
|||
155
onchain/test/Stake.t.sol
Normal file
155
onchain/test/Stake.t.sol
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Add a link
Reference in a new issue