debugging UBI
This commit is contained in:
parent
582a47c689
commit
047d1967e1
5 changed files with 302 additions and 27 deletions
|
|
@ -124,3 +124,260 @@ address: 0xeEa613dB62D5F0e914FfE7Ac85a1AdcFEddb8063
|
|||
- limit discovery position growth to max_issuance / day
|
||||
|
||||
|
||||
## old lp
|
||||
|
||||
```
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
pragma solidity ^0.8.20;
|
||||
|
||||
import "@uniswap-v3-periphery/libraries/PositionKey.sol";
|
||||
import "@uniswap-v3-core/libraries/FixedPoint128.sol";
|
||||
import "@uniswap-v3-core/interfaces/IUniswapV3Pool.sol";
|
||||
import "@aperture/uni-v3-lib/TickMath.sol";
|
||||
import "@aperture/uni-v3-lib/LiquidityAmounts.sol";
|
||||
import "@aperture/uni-v3-lib/PoolAddress.sol";
|
||||
import "@aperture/uni-v3-lib/CallbackValidation.sol";
|
||||
import "@openzeppelin/token/ERC20/IERC20.sol";
|
||||
|
||||
/**
|
||||
* @title LiquidityManager - A contract that supports the harb ecosystem. It
|
||||
* protects the communities liquidity while allowing a manager role to
|
||||
* take strategic liqudity positions.
|
||||
*/
|
||||
contract LiquidityManager {
|
||||
// default fee of 1%
|
||||
uint24 constant FEE = uint24(10_000);
|
||||
|
||||
// the address of the Uniswap V3 factory
|
||||
address immutable factory;
|
||||
IWETH9 immutable weth;
|
||||
Harb immutable harb;
|
||||
IUniswapV3Pool immutable pool;
|
||||
PoolKey immutable poolKey;
|
||||
bool immutable token0isWeth;
|
||||
|
||||
|
||||
struct TokenPosition {
|
||||
// the liquidity of the position
|
||||
uint128 liquidity;
|
||||
uint128 ethOwed;
|
||||
// the fee growth of the aggregate position as of the last action on the individual position
|
||||
uint256 feeGrowthInside0LastX128;
|
||||
uint256 feeGrowthInside1LastX128;
|
||||
}
|
||||
|
||||
/// @dev The token ID position data
|
||||
mapping(bytes26 => TokenPosition) private _positions;
|
||||
|
||||
modifier checkDeadline(uint256 deadline) {
|
||||
require(block.timestamp <= deadline, "Transaction too old");
|
||||
_;
|
||||
}
|
||||
|
||||
/// @notice Emitted when liquidity is increased for a position
|
||||
/// @param liquidity The amount by which liquidity for the NFT position was increased
|
||||
/// @param amount0 The amount of token0 that was paid for the increase in liquidity
|
||||
/// @param amount1 The amount of token1 that was paid for the increase in liquidity
|
||||
event IncreaseLiquidity(int24 indexed tickLower, int24 indexed tickUpper, uint128 liquidity, uint256 amount0, uint256 amount1);
|
||||
/// @notice Emitted when liquidity is decreased for a position
|
||||
/// @param liquidity The amount by which liquidity for the NFT position was decreased
|
||||
/// @param ethReceived The amount of WETH that was accounted for the decrease in liquidity
|
||||
event PositionLiquidated(int24 indexed tickLower, int24 indexed tickUpper, uint128 liquidity, uint256 ethReceived);
|
||||
|
||||
constructor(address _factory, address _WETH9, address _harb) {
|
||||
factory = _factory;
|
||||
weth = IWETH9(_WETH9);
|
||||
poolKey = PoolAddress.getPoolKey(_WETH9, _harb, FEE);
|
||||
pool = IUniswapV3Pool(PoolAddress.computeAddress(factory, poolKey));
|
||||
harb = Harb(_harb);
|
||||
token0isWeth = _WETH9 < _harb;
|
||||
}
|
||||
|
||||
function posKey(int24 tickLower, int24 tickUpper) internal pure returns (bytes6 _posKey) {
|
||||
bytes memory _posKeyBytes = abi.encodePacked(tickLower, tickUpper);
|
||||
assembly {
|
||||
_posKey := mload(add(_posKeyBytes, 6))
|
||||
}
|
||||
}
|
||||
|
||||
function positions(int24 tickLower, int24 tickUpper)
|
||||
external
|
||||
view
|
||||
returns (uint128 liquidity, uint128 ethOwed, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128)
|
||||
{
|
||||
TokenPosition memory position = _positions[posKey(tickLower, tickUpper)];
|
||||
return (position.liquidity, position.ethOwed, position.feeGrowthInside0LastX128, position.feeGrowthInside1LastX128);
|
||||
}
|
||||
|
||||
function uniswapV3MintCallback(uint256 amount0Owed, uint256 amount1Owed, bytes calldata data) external {
|
||||
CallbackValidation.verifyCallback(factory, poolKey);
|
||||
|
||||
if (amount0Owed > 0) IERC20(poolKey.token0).transfer(msg.sender, amount0Owed);
|
||||
if (amount1Owed > 0) IERC20(poolKey.token1).transfer(msg.sender, amount1Owed);
|
||||
}
|
||||
|
||||
|
||||
/// @notice Add liquidity to an initialized pool
|
||||
// TODO: use uint256 amount0Min; uint256 amount1Min; if addLiquidity is called directly
|
||||
function addLiquidity(int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 deadline) internal checkDeadline(deadline) {
|
||||
|
||||
|
||||
(uint256 amount0, uint256 amount1) = pool.mint(address(this), tickLower, tickUpper, liquidity, abi.encode(poolKey));
|
||||
// If addLiquidity is only called after other pool operations that have checked slippage, this here is not needed
|
||||
//require(amount0 >= params.amount0Min && amount1 >= params.amount1Min, "Price slippage check");
|
||||
|
||||
|
||||
// read position and start tracking in storage
|
||||
bytes32 positionKey = PositionKey.compute(address(this), tickLower, tickUpper);
|
||||
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128,,) = pool.positions(positionKey);
|
||||
TokenPosition storage position = _positions[posKey(token, tickLower, tickUpper)];
|
||||
if (liquidity == 0) {
|
||||
// create entry
|
||||
position = TokenPosition({
|
||||
liquidity: liquidity,
|
||||
ethOwed: 0,
|
||||
feeGrowthInside0LastX128: feeGrowthInside0LastX128,
|
||||
feeGrowthInside1LastX128: feeGrowthInside1LastX128
|
||||
});
|
||||
} else {
|
||||
position.ethOwed += FullMath.mulDiv(
|
||||
(token0isWeth) ? feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128 : feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
|
||||
position.liquidity,
|
||||
FixedPoint128.Q128
|
||||
);
|
||||
position.feeGrowthInside0LastX128 = feeGrowthInside0LastX128;
|
||||
position.feeGrowthInside1LastX128 = feeGrowthInside1LastX128;
|
||||
position.liquidity += liquidity;
|
||||
}
|
||||
emit IncreaseLiquidity(tickLower, tickUpper, liquidity, amount0, amount1);
|
||||
}
|
||||
|
||||
function liquidatePosition(int24 tickLower, int24 tickUpper, uint256 amount0Min, uint256 amount1Min)
|
||||
internal
|
||||
returns (uint256 ethReceived, uint256 liquidity)
|
||||
{
|
||||
// load position
|
||||
TokenPosition storage position = _positions[posKey(tickLower, tickUpper)];
|
||||
|
||||
// burn and check slippage
|
||||
uint256 liquidity = position.liquidity;
|
||||
(uint256 amount0, uint256 amount1) = pool.burn(tickLower, tickUpper, liquidity);
|
||||
require(amount0 >= amount0Min && amount1 >= amount1Min, "Price slippage check");
|
||||
// TODO: send harb fees or burn?
|
||||
//harb.burn(token0isWeth ? amount1 : amount0);
|
||||
|
||||
// calculate and transfer fees
|
||||
bytes32 positionKey = PositionKey.compute(address(this), tickLower, tickUpper);
|
||||
(, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128,,) = pool.positions(positionKey);
|
||||
uint256 ethOwed = position.ethOwed;
|
||||
ethOwed +=
|
||||
FullMath.mulDiv(
|
||||
(token0isWeth) ? feeGrowthInside0LastX128 - position.feeGrowthInside0LastX128 : feeGrowthInside1LastX128 - position.feeGrowthInside1LastX128,
|
||||
liquidity,
|
||||
FixedPoint128.Q128
|
||||
);
|
||||
weth.withdraw(ethOwed);
|
||||
(bool sent, ) = feeRecipient.call{value: ethOwed}("");
|
||||
require(sent, "Failed to send Ether");
|
||||
|
||||
// event, cleanup and return
|
||||
ethReceived = token0isWeth ? amount0 - ethOwed : amount1 - ethOwed;
|
||||
emit PositionLiquidated(tickLower, tickUpper, liquidity, ethReceived);
|
||||
delete position.liquidity;
|
||||
delete position.ethOwed;
|
||||
delete position.feeGrowthInside0LastX128;
|
||||
delete position.feeGrowthInside1LastX128;
|
||||
}
|
||||
|
||||
// function compareTokenToEthBalance(uint256 ethAmountInPosition, uint256 tokenAmountInPosition) external view returns (bool hasMoreToken) {
|
||||
// // Fetch the current sqrtPriceX96 from the pool
|
||||
// (uint160 sqrtPriceX96,,,) = uniswapV3Pool.slot0();
|
||||
|
||||
// // Convert sqrtPriceX96 to a conventional price format
|
||||
// // Note: The price is calculated as (sqrtPriceX96^2 / 2^192), simplified here as (price / 2^96) for the sake of example
|
||||
// uint256 price = uint256(sqrtPriceX96) * uint256(sqrtPriceX96) / (1 << 96);
|
||||
|
||||
// // Calculate the equivalent token amount for the ETH in the position at the current price
|
||||
// // Assuming price is expressed as the amount of token per ETH
|
||||
// uint256 equivalentTokenAmountForEth = ethAmountInPosition * price;
|
||||
|
||||
// // Compare to the actual token amount in the position
|
||||
// hasMoreToken = tokenAmountInPosition > equivalentTokenAmountForEth;
|
||||
|
||||
// return hasMoreToken;
|
||||
// }
|
||||
|
||||
////////
|
||||
// - check if tick in range, otherwise revert
|
||||
// - check if the position has more Token or more ETH, at current price
|
||||
// - if more ETH,
|
||||
// - calculate the amount of Token needed to be minted to bring the position to 50/50
|
||||
// - mint
|
||||
// - deposit Token into pool
|
||||
// - if more TOKEN
|
||||
// - calculate the amount of token needed to be withdrawn from the position, to bring the position to 50/50
|
||||
// - withdraw
|
||||
// - burn tokens
|
||||
|
||||
|
||||
|
||||
function stretch(int24 tickLower, int24 tickUpper, uint256 deadline, uint256 amount0Min, uint256 amount1Min) external checkDeadline(deadline) {
|
||||
|
||||
// Fetch the current tick from the Uniswap V3 pool
|
||||
(, int24 currentTick, , , , , ) = pool.slot0();
|
||||
|
||||
// Check if current tick is within the specified range
|
||||
int24 centerTick = tickLower + ((tickUpper - tickLower) / 2);
|
||||
// TODO: add hysteresis
|
||||
if (token0isWeth) {
|
||||
require(currentTick > centerTick && currentTick <= tickUpper, "Current tick out of range for stretch");
|
||||
} else {
|
||||
require(currentTick >= tickLower && currentTick < centerTick, "Current tick out of range for stretch");
|
||||
}
|
||||
|
||||
(uint256 ethReceived, uint256 oldliquidity) = liquidatePosition(tickLower, tickUpper, amount0Min, amount1Min);
|
||||
|
||||
uint256 liquidity;
|
||||
int24 newTickLower;
|
||||
int24 newTickUpper;
|
||||
if (token0isWeth) {
|
||||
newTickLower = tickLower;
|
||||
newTickUpper = currentTick + (currentTick - tickLower);
|
||||
// extend the range up
|
||||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
||||
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(newTickUpper);
|
||||
liquidity = LiquidityAmounts.getLiquidityForAmount0(
|
||||
sqrtRatioAX96, sqrtRatioBX96, ethReceived
|
||||
);
|
||||
// calculate amount for new liquidity
|
||||
uint256 newAmount1 = LiquidityAmounts.getAmount1ForLiquidity(
|
||||
sqrtRatioAX96, sqrtRatioBX96, liquidity
|
||||
);
|
||||
uint256 currentBal = harb.balanceOf(address(this));
|
||||
if (currentBal < newAmount1) {
|
||||
harb.mint(address(this), newAmount1 - currentBal);
|
||||
}
|
||||
|
||||
} else {
|
||||
newTickUpper = tickUpper;
|
||||
// extend the range down
|
||||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
||||
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(currentTick - (tickUpper - currentTick));
|
||||
liquidity = LiquidityAmounts.getLiquidityForAmount1(
|
||||
sqrtRatioAX96, sqrtRatioBX96, ethReceived
|
||||
);
|
||||
// calculate amount for new liquidity
|
||||
uint256 newAmount0 = LiquidityAmounts.getAmount0ForLiquidity(
|
||||
sqrtRatioAX96, sqrtRatioBX96, liquidity
|
||||
);
|
||||
uint256 currentBal = harb.balanceOf(address(this));
|
||||
if (currentBal < newAmount0) {
|
||||
harb.mint(address(this), newAmount0 - currentBal);
|
||||
}
|
||||
newTickLower = ...
|
||||
}
|
||||
addLiquidity(newTickLower, newTickUpper, liquidity, deadline);
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
|
@ -21,6 +21,7 @@ import {Harb} from "./Harb.sol";
|
|||
*/
|
||||
contract BaseLineLP {
|
||||
int24 constant TICK_SPACING = 200;
|
||||
int24 constant ANCHOR_SPACING = 5 * TICK_SPACING;
|
||||
// default fee of 1%
|
||||
uint24 constant FEE = uint24(10_000);
|
||||
// uint256 constant FLOOR = 0;
|
||||
|
|
@ -88,7 +89,7 @@ contract BaseLineLP {
|
|||
harb.mint(token0isWeth ? amount1Owed : amount0Owed);
|
||||
// pack ETH
|
||||
weth.deposit{value: token0isWeth ? amount0Owed : amount1Owed}();
|
||||
// ## mint harb if needed
|
||||
// do transfers
|
||||
if (amount0Owed > 0) IERC20(poolKey.token0).transfer(msg.sender, amount0Owed);
|
||||
if (amount1Owed > 0) IERC20(poolKey.token1).transfer(msg.sender, amount1Owed);
|
||||
}
|
||||
|
|
@ -208,31 +209,33 @@ contract BaseLineLP {
|
|||
return amount;
|
||||
}
|
||||
|
||||
event DEBUG(uint256 indexed eth, uint256 indexed outstanding, int24 indexed floorTick, int24 startTick);
|
||||
event DEBUG(uint256 indexed eth, uint256 indexed outstanding, int24 indexed floorTick, int24 startTick, bool ethIs0);
|
||||
|
||||
function _set(uint160 sqrtPriceX96, int24 currentTick, uint256 ethInNewAnchor) internal {
|
||||
// ### set Anchor position
|
||||
uint128 anchorLiquidity;
|
||||
{
|
||||
int24 tickLower = currentTick - 400;
|
||||
int24 tickUpper = currentTick + 400;
|
||||
int24 tickLower = currentTick - ANCHOR_SPACING;
|
||||
int24 tickUpper = currentTick + ANCHOR_SPACING;
|
||||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
||||
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
||||
if (token0isWeth) {
|
||||
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount1(
|
||||
sqrtRatioAX96, sqrtRatioBX96, ethInNewAnchor
|
||||
);
|
||||
} else {
|
||||
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount0(
|
||||
sqrtRatioAX96, sqrtRatioBX96, ethInNewAnchor
|
||||
);
|
||||
} else {
|
||||
anchorLiquidity = LiquidityAmounts.getLiquidityForAmount1(
|
||||
sqrtRatioAX96, sqrtRatioBX96, ethInNewAnchor
|
||||
);
|
||||
}
|
||||
_mint(tickLower, tickUpper, anchorLiquidity);
|
||||
// TODO: calculate liquidity correctly
|
||||
// or make sure that we don't have to pay more than we have
|
||||
_mint(tickLower, tickUpper, anchorLiquidity * 2);
|
||||
}
|
||||
|
||||
// ### set Floor position
|
||||
{
|
||||
int24 startTick = token0isWeth ? currentTick - 400 : currentTick + 400;
|
||||
int24 startTick = token0isWeth ? currentTick + ANCHOR_SPACING : currentTick - ANCHOR_SPACING;
|
||||
|
||||
// all remaining eth will be put into this position
|
||||
uint256 ethInFloor = address(this).balance;
|
||||
|
|
@ -241,10 +244,12 @@ contract BaseLineLP {
|
|||
uint256 _outstanding = outstanding();
|
||||
if (_outstanding > 0) {
|
||||
floorTick = tickAtPrice(_outstanding, ethInFloor);
|
||||
emit DEBUG(ethInFloor,0,floorTick,startTick,token0isWeth);
|
||||
|
||||
// put a position symetrically around the price, startTick being edge on one side
|
||||
floorTick = token0isWeth ? startTick + (floorTick - startTick) : floorTick - (startTick - floorTick);
|
||||
} else {
|
||||
floorTick = startTick + ((token0isWeth ? int24(1) : int24(-1)) * 200);
|
||||
floorTick = startTick + ((token0isWeth ? int24(1) : int24(-1)) * 400);
|
||||
}
|
||||
// calculate liquidity
|
||||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(floorTick);
|
||||
|
|
@ -253,17 +258,18 @@ contract BaseLineLP {
|
|||
sqrtPriceX96,
|
||||
sqrtRatioAX96,
|
||||
sqrtRatioBX96,
|
||||
token0isWeth ? 0 : ethInFloor,
|
||||
token0isWeth ? ethInFloor : 0
|
||||
token0isWeth ? ethInFloor : 0,
|
||||
token0isWeth ? 0 : ethInFloor
|
||||
);
|
||||
emit DEBUG(ethInFloor,uint256(liquidity),floorTick,startTick,token0isWeth);
|
||||
// mint
|
||||
_mint(floorTick, startTick, liquidity);
|
||||
_mint(startTick, floorTick, liquidity);
|
||||
}
|
||||
|
||||
// ## set Discovery position
|
||||
{
|
||||
int24 tickLower = token0isWeth ? currentTick + 400 : currentTick - 11400;
|
||||
int24 tickUpper = token0isWeth ? currentTick + 11400 : currentTick - 400;
|
||||
int24 tickLower = token0isWeth ? currentTick + ANCHOR_SPACING : currentTick - 11400;
|
||||
int24 tickUpper = token0isWeth ? currentTick + 11400 : currentTick - ANCHOR_SPACING;
|
||||
uint160 sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
||||
uint160 sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
||||
// discovery with 1.5 times as much liquidity per tick as anchor
|
||||
|
|
@ -294,19 +300,17 @@ contract BaseLineLP {
|
|||
harb.mint(amount);
|
||||
mintedToday += amount;
|
||||
amount = harb.balanceOf(address(this));
|
||||
emit DEBUG(amount, harbInDiscovery, 0, 0);
|
||||
if(amount < harbInDiscovery) {
|
||||
// calculate new ticks so that discovery liquidity is still
|
||||
// deeper than anchor, but less wide
|
||||
int24 tickWidth = int24(int256(11000 * amount / harbInDiscovery)) + 400;
|
||||
int24 tickWidth = int24(int256(11000 * amount / harbInDiscovery)) + ANCHOR_SPACING;
|
||||
|
||||
tickWidth = tickWidth / TICK_SPACING * TICK_SPACING;
|
||||
tickWidth = (tickWidth <= 400) ? tickWidth + TICK_SPACING : tickWidth;
|
||||
tickLower = token0isWeth ? currentTick - tickWidth : currentTick + 400;
|
||||
tickUpper = token0isWeth ? currentTick - 400 : currentTick + tickWidth;
|
||||
tickWidth = (tickWidth <= ANCHOR_SPACING) ? tickWidth + TICK_SPACING : tickWidth;
|
||||
tickLower = token0isWeth ? currentTick - tickWidth : currentTick + ANCHOR_SPACING;
|
||||
tickUpper = token0isWeth ? currentTick - ANCHOR_SPACING : currentTick + tickWidth;
|
||||
sqrtRatioAX96 = TickMath.getSqrtRatioAtTick(tickLower);
|
||||
sqrtRatioBX96 = TickMath.getSqrtRatioAtTick(tickUpper);
|
||||
emit DEBUG(uint256(sqrtRatioAX96), uint256(sqrtRatioBX96), tickLower, tickWidth);
|
||||
liquidity = LiquidityAmounts.getLiquidityForAmounts(
|
||||
sqrtPriceX96,
|
||||
sqrtRatioAX96,
|
||||
|
|
@ -417,6 +421,7 @@ contract BaseLineLP {
|
|||
// but cap anchor size at 10 % of total ETH
|
||||
ethInNewAnchor = (ethInNewAnchor > ethBalance / 10) ? ethBalance / 10 : ethInNewAnchor;
|
||||
|
||||
emit DEBUG(0, 0, currentTick, currentTick / TICK_SPACING * TICK_SPACING, token0isWeth);
|
||||
currentTick = currentTick / TICK_SPACING * TICK_SPACING;
|
||||
_set(sqrtPriceX96, currentTick, ethInNewAnchor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -178,6 +178,9 @@ contract Harb is ERC20, ERC20Permit {
|
|||
}
|
||||
|
||||
function ubiDue(address _account, uint256 lastTaxClaimed, uint256 _sumTaxCollected) internal view returns (uint256) {
|
||||
if (lastTaxClaimed == 0 || block.timestamp - lastTaxClaimed < 60) {
|
||||
return 0;
|
||||
}
|
||||
uint256 accountTwab = twabController.getTwabBetween(address(this), _account, lastTaxClaimed, block.timestamp);
|
||||
uint256 stakeTwab = twabController.getTwabBetween(address(this), stakingPool, lastTaxClaimed, block.timestamp);
|
||||
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ contract BaseLineLPTest is Test {
|
|||
uint256 price;
|
||||
if (isEthToken0) {
|
||||
// ETH as token0, so we are setting the price of 1 ETH in terms of token1 (USD cent)
|
||||
price = 3700 * 10**20; // 1 ETH = 3700 USD, scaled by 10^18 for precision
|
||||
price = 3000 * 10**20; // 1 ETH = 3700 USD, scaled by 10^18 for precision
|
||||
} else {
|
||||
// Token (valued at 1 USD cent) as token0, ETH as token1
|
||||
// We invert the logic to represent the price of 1 token in terms of ETH
|
||||
price = uint256(10**16) / 3700; // Adjust for 18 decimal places
|
||||
}
|
||||
|
||||
uint160 sqrtPriceX96 = uint160(sqrt(price) * 2**96 / 10**18); // Adjust sqrt value to 96-bit precision
|
||||
uint160 sqrtPriceX96 = uint160(sqrt(price) * 2**96 / 10**9); // Adjust sqrt value to 96-bit precision
|
||||
|
||||
// Initialize pool with the calculated sqrtPriceX96
|
||||
IUniswapV3Pool(pool).initialize(sqrtPriceX96);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,7 @@ contract HarbTest is Test {
|
|||
vm.assume(account != address(2)); // tax pool address
|
||||
vm.assume(account != address(harb));
|
||||
vm.assume(account != address(stake));
|
||||
address alice = makeAddr("alice");
|
||||
|
||||
// test mint
|
||||
uint256 totalSupplyBefore = harb.totalSupply();
|
||||
|
|
@ -75,7 +76,6 @@ contract HarbTest is Test {
|
|||
// prepare UBI title
|
||||
vm.prank(account);
|
||||
harb.mint(amount * 4);
|
||||
address alice = makeAddr("alice");
|
||||
vm.prank(account);
|
||||
harb.transfer(alice, amount);
|
||||
vm.prank(alice);
|
||||
|
|
@ -116,11 +116,12 @@ contract HarbTest is Test {
|
|||
stake.snatch(amount, account, 2, empty);
|
||||
}
|
||||
|
||||
|
||||
// test unstake
|
||||
{
|
||||
// advance the time
|
||||
uint256 timeBefore = block.timestamp;
|
||||
vm.warp(timeBefore + 60 * 60 * 24 * 4);
|
||||
vm.warp(timeBefore + (60 * 60 * 24 * 4));
|
||||
uint256 taxDue = stake.taxDue(0, 60 * 60 * 24 * 3);
|
||||
|
||||
uint256 sumTaxCollectedBefore = harb.sumTaxCollected();
|
||||
|
|
@ -137,8 +138,17 @@ contract HarbTest is Test {
|
|||
uint256 ubiDue = harb.getUbiDue(account);
|
||||
vm.prank(account);
|
||||
harb.claimUbi(account);
|
||||
assertFalse(ubiDue == 0, "Not UBI paid");
|
||||
assertFalse(ubiDue == 0, "No UBI paid");
|
||||
assertEq(balanceBefore + ubiDue, harb.balanceOf(account), "ubi should match");
|
||||
}
|
||||
|
||||
|
||||
// test UBIdue
|
||||
{
|
||||
uint256 timeBefore = block.timestamp;
|
||||
vm.warp(timeBefore + (60 * 60 * 24 * 7));
|
||||
harb.getUbiDue(account);
|
||||
harb.getUbiDue(alice);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue