added price oracle
This commit is contained in:
parent
5d209e5e19
commit
ec71bcd287
3 changed files with 83 additions and 7 deletions
|
|
@ -24,6 +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;
|
||||
// default fee of 1%
|
||||
uint24 constant FEE = uint24(10_000);
|
||||
// uint256 constant FLOOR = 0;
|
||||
|
|
@ -345,12 +346,27 @@ contract BaseLineLP {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
function _checkPriceStability(int24 currentTick) internal view returns (bool) {
|
||||
uint32 timeInterval = 300; // 5 minutes in seconds
|
||||
uint32[] memory secondsAgo = new uint32[](2);
|
||||
secondsAgo[0] = timeInterval; // 5 minutes ago
|
||||
secondsAgo[1] = 0; // current block timestamp
|
||||
|
||||
(int56[] memory tickCumulatives,) = pool.observe(secondsAgo);
|
||||
int56 tickCumulativeDiff = tickCumulatives[1] - tickCumulatives[0];
|
||||
int24 averageTick = int24(tickCumulativeDiff / int56(int32(timeInterval)));
|
||||
|
||||
return (currentTick >= averageTick - MAX_TICK_DEVIATION && currentTick <= averageTick + MAX_TICK_DEVIATION);
|
||||
}
|
||||
|
||||
// call this function when price has moved up 15%
|
||||
function shift() external {
|
||||
require(positions[Stage.ANCHOR].liquidity > 0, "Not initialized");
|
||||
// Fetch the current tick from the Uniswap V3 pool
|
||||
(uint160 sqrtPriceX96, int24 currentTick, , , , , ) = pool.slot0();
|
||||
// TODO: check slippage with oracle
|
||||
// check slippage with oracle
|
||||
_checkPriceStability(currentTick);
|
||||
|
||||
// ## check price moved up
|
||||
{
|
||||
|
|
@ -406,7 +422,8 @@ contract BaseLineLP {
|
|||
function slide() external {
|
||||
// Fetch the current tick from the Uniswap V3 pool
|
||||
(uint160 sqrtPriceX96, int24 currentTick, , , , , ) = pool.slot0();
|
||||
// TODO: check slippage with oracle
|
||||
// check slippage with oracle
|
||||
_checkPriceStability(currentTick);
|
||||
|
||||
// ## check price moved down
|
||||
if (positions[Stage.ANCHOR].liquidity > 0) {
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import "./interfaces/IStake.sol";
|
|||
import "./Harb.sol";
|
||||
|
||||
error ExceededAvailableStake(address receiver, uint256 stakeWanted, uint256 availableStake);
|
||||
error TooMuchSnatch(address receiver, uint256 stakeWanted, uint256 availableStake, uint256 smallestShare);
|
||||
|
||||
contract Stake is IStake {
|
||||
using Math for uint256;
|
||||
|
|
@ -32,6 +33,7 @@ contract Stake is IStake {
|
|||
event PositionCreated(uint256 indexed positionId, address indexed owner, uint256 share, uint32 creationTime, uint32 taxRate);
|
||||
event TaxPaid(uint256 indexed positionId, address indexed owner, uint256 taxAmount);
|
||||
event PositionRemoved(uint256 indexed positionId, uint256 share, uint32 lastTaxTime);
|
||||
event PositionShrunk(uint256 indexed positionId, uint256 share, uint32 lastTaxTime, uint256 sharesTaken);
|
||||
|
||||
struct StakingPosition {
|
||||
uint256 share;
|
||||
|
|
@ -93,6 +95,8 @@ contract Stake is IStake {
|
|||
return snatch(assets, receiver, taxRate, positionsToSnatch);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TODO: deal with metatransactions: While these are generally available
|
||||
* via msg.sender and msg.data, they should not be accessed in such a direct
|
||||
|
|
@ -111,8 +115,10 @@ contract Stake is IStake {
|
|||
}
|
||||
// TODO: check that position size is multiple of minStake
|
||||
|
||||
uint256 smallestPositionShare = totalSupply;
|
||||
|
||||
// run through all suggested positions to snatch
|
||||
for (uint256 i = 0; i < positionsToSnatch.length; i++) {
|
||||
for (uint256 i = 0; i < positionsToSnatch.length - 1; i++) {
|
||||
StakingPosition storage pos = positions[positionsToSnatch[i]];
|
||||
if (pos.creationTime == 0) {
|
||||
//TODO:
|
||||
|
|
@ -122,20 +128,48 @@ contract Stake is IStake {
|
|||
if (taxRate <= pos.taxRate) {
|
||||
revert TaxTooLow(receiver, taxRate, pos.taxRate, i);
|
||||
}
|
||||
if (pos.share < smallestPositionShare) {
|
||||
smallestPositionShare = pos.share;
|
||||
}
|
||||
// dissolve position
|
||||
// TODO: what if someone calls payTax and exitPosition in the same transaction?
|
||||
_payTax(positionsToSnatch[i], pos, 0);
|
||||
_exitPosition(positionsToSnatch[i], pos);
|
||||
// TODO: exit positions partially, if needed
|
||||
// TODO: avoid greeving where more positions are freed than needed.
|
||||
}
|
||||
|
||||
// try to make a new position in the free space and hope it is big enough
|
||||
uint256 availableStake = authorizedStake() - outstandingStake;
|
||||
|
||||
// handle last position
|
||||
if (positionsToSnatch.length > 0) {
|
||||
uint256 index = positionsToSnatch.length - 1;
|
||||
StakingPosition storage pos = positions[positionsToSnatch[index]];
|
||||
if (pos.creationTime == 0) {
|
||||
//TODO:
|
||||
revert PositionNotFound();
|
||||
}
|
||||
// check that tax lower
|
||||
if (taxRate <= pos.taxRate) {
|
||||
revert TaxTooLow(receiver, taxRate, pos.taxRate, index);
|
||||
}
|
||||
if (pos.share < smallestPositionShare) {
|
||||
smallestPositionShare = pos.share;
|
||||
}
|
||||
// dissolve position
|
||||
_payTax(positionsToSnatch[index], pos, 0);
|
||||
uint256 lastBitNeeded = sharesWanted - availableStake;
|
||||
_shrinkPosition(positionsToSnatch[index], pos, lastBitNeeded);
|
||||
availableStake += lastBitNeeded;
|
||||
}
|
||||
|
||||
if (sharesWanted > availableStake) {
|
||||
revert ExceededAvailableStake(receiver, sharesWanted, availableStake);
|
||||
}
|
||||
|
||||
// avoid greeving where more positions are freed than needed.
|
||||
if (availableStake - sharesWanted > smallestPositionShare) {
|
||||
revert TooMuchSnatch(receiver, sharesWanted, availableStake, smallestPositionShare);
|
||||
}
|
||||
|
||||
// transfer
|
||||
SafeERC20.safeTransferFrom(tokenContract, msg.sender, address(this), assets);
|
||||
|
||||
|
|
@ -210,7 +244,6 @@ contract Stake is IStake {
|
|||
pos.lastTaxTime = uint32(block.timestamp);
|
||||
} else {
|
||||
// if nothing left over, liquidate position
|
||||
// TODO: emit event
|
||||
outstandingStake -= pos.share;
|
||||
emit PositionRemoved(positionID, pos.share, pos.lastTaxTime);
|
||||
delete pos.owner;
|
||||
|
|
@ -227,4 +260,12 @@ contract Stake is IStake {
|
|||
delete pos.creationTime;
|
||||
SafeERC20.safeTransfer(tokenContract, owner, assets);
|
||||
}
|
||||
|
||||
function _shrinkPosition(uint256 positionId, StakingPosition storage pos, uint256 sharesToTake) private {
|
||||
require (sharesToTake > pos.share, "position too small");
|
||||
pos.share -= sharesToTake;
|
||||
uint256 assets = sharesToAssets(sharesToTake, Math.Rounding.Down);
|
||||
emit PositionShrunk(positionId, pos.share, pos.lastTaxTime, sharesToTake);
|
||||
SafeERC20.safeTransfer(tokenContract, pos.owner, assets);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue