Skip to content

Commit

Permalink
Fix reset of daily limits (#25)
Browse files Browse the repository at this point in the history
  • Loading branch information
k1rill-fedoseev authored Oct 29, 2022
1 parent 2bff025 commit a1ce123
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 4 deletions.
3 changes: 3 additions & 0 deletions script/scripts/Env.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ uint256 constant zkBobDailyWithdrawalCap = 100_000 ether;
uint256 constant zkBobDailyUserDepositCap = 10_000 ether;
uint256 constant zkBobDepositCap = 10_000 ether;

// new zkbob impl
address constant zkBobPool = 0x72e6B59D4a90ab232e55D4BB7ed2dD17494D62fB;

// vault
address constant vaultYieldAdmin = 0x0000000000000000000000000000000000000000;
address constant vaultInvestAdmin = 0x0000000000000000000000000000000000000000;
Expand Down
28 changes: 28 additions & 0 deletions script/scripts/NewZkBobPoolImpl.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: CC0-1.0

pragma solidity 0.8.15;

import "forge-std/Script.sol";
import "./Env.s.sol";
import "../../src/proxy/EIP1967Proxy.sol";
import "../../src/zkbob/ZkBobPool.sol";
import "../../src/zkbob/manager/MutableOperatorManager.sol";

contract DeployNewZkBobPoolImpl is Script {
function run() external {
vm.startBroadcast();

ZkBobPool pool = ZkBobPool(zkBobPool);

ZkBobPool impl = new ZkBobPool(
pool.pool_id(),
pool.token(),
pool.transfer_verifier(),
pool.tree_verifier()
);

vm.stopBroadcast();

console2.log("ZkBobPool implementation:", address(impl));
}
}
8 changes: 8 additions & 0 deletions src/zkbob/ZkBobPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,14 @@ contract ZkBobPool is EIP1967Admin, Ownable, Parameters, ZkBobAccounting {
);
}

/**
* @dev Resets daily limit usage for the current day.
* Callable only by the contract owner / proxy admin.
*/
function resetDailyLimits() external onlyOwner {
_resetDailyLimits();
}

/**
* @dev Updates users limit tiers.
* Callable only by the contract owner / proxy admin.
Expand Down
20 changes: 16 additions & 4 deletions src/zkbob/utils/ZkBobAccounting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,21 @@ contract ZkBobAccounting {
}

function _processTVLChange(Slot0 memory s0, Slot1 memory s1, address _user, int256 _txAmount) internal {
uint16 curDay = uint16(block.timestamp / SLOT_DURATION / DAY_SLOTS);

bool isDayTransition = curDay > s0.headSlot / DAY_SLOTS;

if (_txAmount == 0) {
if (isDayTransition) {
(s1.dailyDeposit, s1.dailyWithdrawal) = (0, 0);
slot1 = s1;
}
return;
}

UserStats memory us = userStats[_user];
PoolLimits memory pl = poolLimits[us.tier];

uint16 curDay = uint16(block.timestamp / SLOT_DURATION / DAY_SLOTS);

if (_txAmount > 0) {
uint256 depositAmount = uint256(_txAmount);
s1.tvl += uint72(depositAmount);
Expand All @@ -201,9 +207,10 @@ contract ZkBobAccounting {
userStats[_user] = us;
}

if (curDay > s0.headSlot / DAY_SLOTS) {
if (isDayTransition) {
// latest deposit was on an earlier day, reset daily deposit sum
s1.dailyDeposit = uint32(depositAmount / PRECISION);
s1.dailyWithdrawal = 0;
} else {
s1.dailyDeposit += uint32(depositAmount / PRECISION);
require(s1.dailyDeposit <= pl.dailyDepositCap, "ZkBobAccounting: daily deposit cap exceeded");
Expand All @@ -212,7 +219,8 @@ contract ZkBobAccounting {
uint256 withdrawAmount = uint256(-_txAmount);
s1.tvl -= uint72(withdrawAmount);

if (curDay > s0.headSlot / DAY_SLOTS) {
if (isDayTransition) {
s1.dailyDeposit = 0;
// latest withdrawal was on an earlier day, reset daily deposit sum
s1.dailyWithdrawal = uint32(withdrawAmount / PRECISION);
} else {
Expand All @@ -224,6 +232,10 @@ contract ZkBobAccounting {
slot1 = s1;
}

function _resetDailyLimits() internal {
(slot1.dailyDeposit, slot1.dailyWithdrawal) = (0, 0);
}

function _setLimits(
uint8 _tier,
uint256 _tvlCap,
Expand Down
87 changes: 87 additions & 0 deletions test/zkbob/utils/ZkBobAccounting.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,93 @@ contract ZkBobAccountingTest is Test {
assertEq(limits2.depositCap, 150 gwei);
}

function testPoolDailyLimitsReset() public {
pool.setLimits(0, 10000 ether, 500 ether, 400 ether, 300 ether, 150 ether);

ZkBobAccounting.Limits memory limits1;

vm.startPrank(user1);
pool.transact(70 ether);
pool.transact(-50 ether);
vm.stopPrank();

limits1 = pool.getLimitsFor(user1);
assertEq(limits1.tvlCap, 10000 gwei);
assertEq(limits1.tvl, 20 gwei);
assertEq(limits1.dailyDepositCap, 500 gwei);
assertEq(limits1.dailyDepositCapUsage, 70 gwei);
assertEq(limits1.dailyWithdrawalCap, 400 gwei);
assertEq(limits1.dailyWithdrawalCapUsage, 50 gwei);
assertEq(limits1.dailyUserDepositCap, 300 gwei);
assertEq(limits1.dailyUserDepositCapUsage, 70 gwei);
assertEq(limits1.depositCap, 150 gwei);

vm.warp(block.timestamp + 1 days);

limits1 = pool.getLimitsFor(user1);
assertEq(limits1.tvlCap, 10000 gwei);
assertEq(limits1.tvl, 20 gwei);
assertEq(limits1.dailyDepositCap, 500 gwei);
assertEq(limits1.dailyDepositCapUsage, 0 gwei);
assertEq(limits1.dailyWithdrawalCap, 400 gwei);
assertEq(limits1.dailyWithdrawalCapUsage, 0 gwei);
assertEq(limits1.dailyUserDepositCap, 300 gwei);
assertEq(limits1.dailyUserDepositCapUsage, 0 gwei);
assertEq(limits1.depositCap, 150 gwei);

uint256 sid1 = vm.snapshot();
uint256 sid2 = vm.snapshot();

// deposit on a new day should reset daily deposit and withdrawal limits
vm.prank(user1);
pool.transact(100 ether);

limits1 = pool.getLimitsFor(user1);
assertEq(limits1.tvlCap, 10000 gwei);
assertEq(limits1.tvl, 120 gwei);
assertEq(limits1.dailyDepositCap, 500 gwei);
assertEq(limits1.dailyDepositCapUsage, 100 gwei);
assertEq(limits1.dailyWithdrawalCap, 400 gwei);
assertEq(limits1.dailyWithdrawalCapUsage, 0 gwei);
assertEq(limits1.dailyUserDepositCap, 300 gwei);
assertEq(limits1.dailyUserDepositCapUsage, 100 gwei);
assertEq(limits1.depositCap, 150 gwei);

vm.revertTo(sid2);

// withdrawal on a new day should reset daily deposit and withdrawal limits
vm.prank(user1);
pool.transact(-10 ether);

limits1 = pool.getLimitsFor(user1);
assertEq(limits1.tvlCap, 10000 gwei);
assertEq(limits1.tvl, 10 gwei);
assertEq(limits1.dailyDepositCap, 500 gwei);
assertEq(limits1.dailyDepositCapUsage, 0 gwei);
assertEq(limits1.dailyWithdrawalCap, 400 gwei);
assertEq(limits1.dailyWithdrawalCapUsage, 10 gwei);
assertEq(limits1.dailyUserDepositCap, 300 gwei);
assertEq(limits1.dailyUserDepositCapUsage, 0 gwei);
assertEq(limits1.depositCap, 150 gwei);

vm.revertTo(sid1);

// private transfer on a new day should reset daily deposit and withdrawal limits
vm.prank(user1);
pool.transact(0 ether);

limits1 = pool.getLimitsFor(user1);
assertEq(limits1.tvlCap, 10000 gwei);
assertEq(limits1.tvl, 20 gwei);
assertEq(limits1.dailyDepositCap, 500 gwei);
assertEq(limits1.dailyDepositCapUsage, 0 gwei);
assertEq(limits1.dailyWithdrawalCap, 400 gwei);
assertEq(limits1.dailyWithdrawalCapUsage, 0 gwei);
assertEq(limits1.dailyUserDepositCap, 300 gwei);
assertEq(limits1.dailyUserDepositCapUsage, 0 gwei);
assertEq(limits1.depositCap, 150 gwei);
}

function testPoolLimitsTiers() public {
pool.setLimits(0, 600 ether, 500 ether, 400 ether, 300 ether, 150 ether);
pool.setLimits(1, 10000 ether, 1000 ether, 800 ether, 600 ether, 300 ether);
Expand Down

0 comments on commit a1ce123

Please sign in to comment.