add tax rate adjustment
This commit is contained in:
parent
4845129fe3
commit
3225be1084
4 changed files with 33 additions and 17 deletions
|
|
@ -30,6 +30,7 @@ contract Stake is IStake {
|
|||
error PositionNotFound();
|
||||
|
||||
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);
|
||||
|
||||
struct StakingPosition {
|
||||
|
|
@ -123,7 +124,7 @@ contract Stake is IStake {
|
|||
}
|
||||
// dissolve position
|
||||
// TODO: what if someone calls payTax and exitPosition in the same transaction?
|
||||
_payTax(pos, 0);
|
||||
_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.
|
||||
|
|
@ -151,20 +152,31 @@ contract Stake is IStake {
|
|||
emit PositionCreated(positionId, sp.owner, sp.share, sp.creationTime, sp.taxRate);
|
||||
}
|
||||
|
||||
function changeTax(uint256 positionID, uint32 taxRate) public {
|
||||
StakingPosition storage pos = positions[positionID];
|
||||
if (pos.owner != msg.sender) {
|
||||
revert NoPermission(msg.sender, pos.owner);
|
||||
}
|
||||
// to prevent snatch-and-change grieving attack, pay TAX_FLOOR_DURATION
|
||||
require(taxRate > pos.taxRate);
|
||||
_payTax(positionID, pos, TAX_FLOOR_DURATION);
|
||||
pos.taxRate = taxRate;
|
||||
}
|
||||
|
||||
function exitPosition(uint256 positionId) public {
|
||||
StakingPosition storage pos = positions[positionId];
|
||||
if (pos.owner != msg.sender) {
|
||||
revert NoPermission(msg.sender, pos.owner);
|
||||
}
|
||||
// to prevent snatch-and-exit grieving attack, pay TAX_FLOOR_DURATION
|
||||
_payTax(pos, TAX_FLOOR_DURATION);
|
||||
_payTax(positionId, pos, TAX_FLOOR_DURATION);
|
||||
_exitPosition(positionId, pos);
|
||||
}
|
||||
|
||||
function payTax(uint256 positionID) public {
|
||||
StakingPosition storage pos = positions[positionID];
|
||||
// TODO: what if someone calls payTax and exitPosition in the same transaction?
|
||||
_payTax(pos, 0);
|
||||
_payTax(positionID, pos, 0);
|
||||
}
|
||||
|
||||
function taxDue(uint256 positionID, uint256 taxFloorDuration) public view returns (uint256 amountDue) {
|
||||
|
|
@ -178,7 +190,7 @@ contract Stake is IStake {
|
|||
amountDue = assetsBefore * pos.taxRate * elapsedTime / (365 * 24 * 60 * 60) / TAX_RATE_BASE;
|
||||
}
|
||||
|
||||
function _payTax(StakingPosition storage pos, uint256 taxFloorDuration) private {
|
||||
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
|
||||
|
|
@ -191,6 +203,7 @@ contract Stake is IStake {
|
|||
taxAmountDue = assetsBefore;
|
||||
}
|
||||
SafeERC20.safeTransfer(tokenContract, taxPool, taxAmountDue);
|
||||
emit TaxPaid(positionID, pos.owner, taxAmountDue);
|
||||
if (assetsBefore - taxAmountDue > 0) {
|
||||
// if something left over, update storage
|
||||
pos.share = assetsToShares(assetsBefore - taxAmountDue, Math.Rounding.Down);
|
||||
|
|
@ -199,6 +212,7 @@ contract Stake is IStake {
|
|||
// if nothing left over, liquidate position
|
||||
// TODO: emit event
|
||||
outstandingStake -= pos.share;
|
||||
emit PositionRemoved(positionID, pos.share, pos.lastTaxTime);
|
||||
delete pos.owner;
|
||||
delete pos.creationTime;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -74,7 +74,10 @@ contract BaseLineLPTest is Test {
|
|||
harb.setLiquidityManager(address(liquidityManager));
|
||||
}
|
||||
|
||||
function testLP(address account, uint256 amount) public {
|
||||
function testLP(address account) public {
|
||||
vm.assume(account != address(0));
|
||||
vm.assume(account != address(1)); // TWAB sponsorship address
|
||||
vm.assume(account != address(2)); // tax pool address
|
||||
vm.deal(account, 10 ether);
|
||||
vm.prank(account);
|
||||
(bool sent, ) = address(liquidityManager).call{value: 10 ether}("");
|
||||
|
|
@ -83,7 +86,6 @@ contract BaseLineLPTest is Test {
|
|||
vm.expectRevert();
|
||||
liquidityManager.shift();
|
||||
|
||||
int24 startTick = (address(weth) < address(harb)) ? int24(128219) : int24(-128219); //initialize at 1 cent
|
||||
liquidityManager.slide();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
scalar Bytes
|
||||
scalar BigInt
|
||||
scalar BigDecimal
|
||||
# scalar Bytes
|
||||
# scalar BigInt
|
||||
# scalar BigDecimal
|
||||
|
||||
type Stats @entity {
|
||||
id: Bytes!
|
||||
|
|
@ -25,7 +25,7 @@ type Position @entity {
|
|||
status: PositionStatus!
|
||||
}
|
||||
|
||||
type Query {
|
||||
stats: [Stats]
|
||||
positions: [Position]
|
||||
}
|
||||
# type Query {
|
||||
# stats: [Stats!]
|
||||
# positions: [Position!]
|
||||
#}
|
||||
|
|
@ -8,9 +8,9 @@ dataSources:
|
|||
name: Harb
|
||||
network: sepolia
|
||||
source:
|
||||
address: "0xcd02666582a2057085edabc55c5120155ba4e93c"
|
||||
address: "0xcA85847c540a9706359E74155288Ab8e6b2475C7"
|
||||
abi: Harb
|
||||
startBlock: 5510934
|
||||
startBlock: 5677168
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.7
|
||||
|
|
@ -32,9 +32,9 @@ dataSources:
|
|||
name: Stake
|
||||
network: sepolia
|
||||
source:
|
||||
address: "0x4256777543814d66f9f66390f6bb33c55a24c331"
|
||||
address: "0x22c264Ecf8D4E49D1E3CabD8DD39b7C4Ab51C1B8"
|
||||
abi: Stake
|
||||
startBlock: 5510935
|
||||
startBlock: 5677168
|
||||
mapping:
|
||||
kind: ethereum/events
|
||||
apiVersion: 0.0.7
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue