mirror of
https://github.com/Instadapp/fluid-contracts-public.git
synced 2024-07-29 21:57:37 +00:00
1226 lines
47 KiB
Solidity
1226 lines
47 KiB
Solidity
|
//SPDX-License-Identifier: MIT
|
||
|
pragma solidity 0.8.21;
|
||
|
|
||
|
import { LibraryLiquidityCalcsBaseTest } from "./liquidityCalcsBaseTest.t.sol";
|
||
|
import { BigMathMinified } from "../../../../contracts/libraries/bigMathMinified.sol";
|
||
|
|
||
|
import "forge-std/console2.sol";
|
||
|
|
||
|
contract LibraryLiquidityCalcsWithdrawalLimitsBaseTest is LibraryLiquidityCalcsBaseTest {
|
||
|
uint256 constant DEFAULT_EXPAND_PERCENTAGE = 20 * 1e2; // 20%
|
||
|
uint256 constant DEFAULT_BASE_LIMIT = 5 ether;
|
||
|
uint256 constant DEFAULT_EXPAND_DURATION = 200 seconds;
|
||
|
|
||
|
uint256 immutable DEFAULT_BASE_LIMIT_AFTER_BIG_MATH;
|
||
|
|
||
|
constructor() {
|
||
|
DEFAULT_BASE_LIMIT_AFTER_BIG_MATH = BigMathMinified.fromBigNumber(
|
||
|
BigMathMinified.toBigNumber(DEFAULT_BASE_LIMIT, 10, _DEFAULT_EXPONENT_SIZE, BigMathMinified.ROUND_DOWN),
|
||
|
8,
|
||
|
0xff
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function setUp() public virtual override {
|
||
|
super.setUp();
|
||
|
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
}
|
||
|
|
||
|
function _getUserSupplyDataForBeforeOperate(
|
||
|
uint256 userSupply,
|
||
|
uint256 previousLimit,
|
||
|
uint256 lastUpdateTimestamp,
|
||
|
uint256 expandPercentage,
|
||
|
uint256 expandDuration,
|
||
|
uint256 baseLimit
|
||
|
) internal pure returns (uint256) {
|
||
|
return
|
||
|
_simulateUserSupplyDataFull(
|
||
|
1, // interest mode irrelevant for withdrawal limit calculation
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false // user pause status irrelevant for withdrawal limit calculation
|
||
|
);
|
||
|
}
|
||
|
|
||
|
function _getUserSupplyDataForAfterOperate(
|
||
|
uint256 userSupply,
|
||
|
uint256 expandPercentage,
|
||
|
uint256 expandDuration,
|
||
|
uint256 baseLimit
|
||
|
) internal pure returns (uint256) {
|
||
|
return
|
||
|
_simulateUserSupplyDataFull(
|
||
|
1, // interest mode irrelevant for withdrawal limit calculation
|
||
|
userSupply,
|
||
|
0, // previous limit in storage should never matter for after operate limit
|
||
|
0, // last update timestamp in storage should never matter for after operate limit
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false // user pause status irrelevant for withdrawal limit calculation
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
contract LibraryLiquidityCalcsWithdrawalLimitBeforeOperateTests is LibraryLiquidityCalcsWithdrawalLimitsBaseTest {
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenLastWithdrawalLimitZero() public {
|
||
|
uint256 userSupply = 0;
|
||
|
uint256 previousLimit = 0;
|
||
|
uint256 lastUpdateTimestamp = 0;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenUserSupply0() public {
|
||
|
uint256 userSupply = 0;
|
||
|
uint256 previousLimit = 0; // can only be 0 as afterOperate withdrawal limit method always goes into base limit is >
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION / 10; // 10 percent passed
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_When10PercentOf30PercentExpanded() public {
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 1 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION / 10; // 10 percent passed
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
// 30% would be at 0.7 ether, but only 10% is expanded so 3% -> 0.97
|
||
|
assertEq(limit, 0.97 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_When10PercentOf30PercentExpandedFromPreviousLimit() public {
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.9 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION / 10; // 10 percent passed
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
// 30% would be at 0.7 ether, but only 10% is expanded so 3% but from last limit 0.9 ether -> so 0.87 ether
|
||
|
assertEq(limit, 0.87 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_When50PercentOf20PercentExpanded() public {
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 1 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION / 2; // 50 percent passed
|
||
|
uint256 expandPercentage = 20 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
// 20% would be at 0.8 ether, but only 50% is expanded so 10% -> 0.9
|
||
|
assertEq(limit, 0.9 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_When50PercentOf20PercentExpandedFromPreviousLimit() public {
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.9 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION / 2; // 50 percent passed
|
||
|
uint256 expandPercentage = 20 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
// 20% would be at 0.8 ether, but only 50% is expanded so 10%, but starting from 0.9 -> so 0.8
|
||
|
assertEq(limit, 0.8 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenBeyondMaxExpansion() public {
|
||
|
// e.g. because > 100% of expand duration passed
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.9 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION * 2; // > 100 percent passed
|
||
|
uint256 expandPercentage = 20 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
// limit should be fully expanded -> 1 ether - 20% -> 0.8 ether
|
||
|
assertEq(limit, 0.8 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenExpandPercent100() public {
|
||
|
// withdrawable is full user supply (meaning limit is 0)
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 1; // should not matter
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION; // fully expanded
|
||
|
uint256 expandPercentage = 100 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0);
|
||
|
|
||
|
previousLimit = userSupply + 1; // verify last limit should not matter when fully expanded
|
||
|
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenExpandPercent0() public {
|
||
|
// withdrawable should be 0 (limit = userSupply).
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 1 ether; // should not matter
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION; // fully expanded
|
||
|
uint256 expandPercentage = 0;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, userSupply);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenExpandPercent0FromPreviousLimit() public {
|
||
|
// withdrawable should be 0 (limit = userSupply).
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.9 ether; // should not matter, limit should still be userSupply
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION; // fully expanded
|
||
|
uint256 expandPercentage = 0;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, userSupply);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenLastUpdateTimestampIsBlockTimestamp() public {
|
||
|
// no expansion happened yet so limit should be previous Limit
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 1 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, previousLimit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenLastUpdateTimestampIsBlockTimestampFromPreviousLimit() public {
|
||
|
// no expansion happened yet so limit should be previous Limit
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.9 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, previousLimit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenPreviousLimitBelowMaxExpansion() public {
|
||
|
// limit should be max expansion
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.7 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0.8 ether); // 0.8 ether is max expansion
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitBeforeOperate_WhenLastWithdrawalLimitSmallerThanExpansionAmount() public {
|
||
|
// limit should be max expansion
|
||
|
uint256 userSupply = 1 ether;
|
||
|
uint256 previousLimit = 0.1 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - DEFAULT_EXPAND_DURATION; // fully expanded
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
// expansion amount is 0.2 ether. last limit only 0.1 ether.
|
||
|
// limit should still be max expansion limit of 0.8 ether.
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 0.8 ether); // 0.8 ether is max expansion
|
||
|
}
|
||
|
}
|
||
|
|
||
|
contract LibraryLiquidityCalcsWithdrawalLimitAfterOperateTests is LibraryLiquidityCalcsWithdrawalLimitsBaseTest {
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupply0() public {
|
||
|
// limit should be 0
|
||
|
uint256 userSupply = 0;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 0; // irrelevant for this test
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyBelowBaseLimit() public {
|
||
|
// limit should be 0
|
||
|
uint256 userSupply = DEFAULT_BASE_LIMIT_AFTER_BIG_MATH - 1;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 0; // irrelevant for this test
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyExactlyBaseLimit() public {
|
||
|
uint256 userSupply = DEFAULT_BASE_LIMIT_AFTER_BIG_MATH;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
DEFAULT_EXPAND_PERCENTAGE,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 0;
|
||
|
|
||
|
// limit will be full expansion from userSupply (~5ether * 0.8 = ~4 ether)
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, (DEFAULT_BASE_LIMIT_AFTER_BIG_MATH * 8) / 10);
|
||
|
assertApproxEqAbs(limit, 4 ether, 1e16);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyExactlyBaseLimitWithLimitBeforeBigger() public {
|
||
|
uint256 userSupply = DEFAULT_BASE_LIMIT_AFTER_BIG_MATH;
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 4.9 ether; // e.g. deposit was 7 ether and limit was fully expanded to 4.9 ether.
|
||
|
|
||
|
// limit will be 4.9 ether as that is > fully expanded limit
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 4.9 ether);
|
||
|
|
||
|
// cross check new limit beforeOperate
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 4.9 ether
|
||
|
block.timestamp - DEFAULT_EXPAND_DURATION / 5, // last update timestamp 20% of expand duration
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 4.9 ether - ((((DEFAULT_BASE_LIMIT_AFTER_BIG_MATH * 3) / 10) * 2) / 10));
|
||
|
assertApproxEqAbs(limit, 4.6 ether, 1e16); // should be 20% of ~1.5 ether expansion expanded, starting from 4.9 ether. so ~4.6 ether
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyAboveBaseLimitButExpansionGoesBelow() public {
|
||
|
// big deposit case
|
||
|
uint256 userSupply = 6 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2; // so going to 4.2 ether
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 2 ether; // limit will be instantly fully expanded (deposit case)
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 4.2 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyAboveBaseLimitButExpansionGoesBelowWithLimitBefore()
|
||
|
public
|
||
|
{
|
||
|
// small deposit case
|
||
|
uint256 userSupply = 5.2 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 4.8 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, limitFromBeforeOperate); // should be previous limit
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenUserSupplyAboveBaseLimitButExpansionGoesBelowWithLimitBeforeWithdrawalCase()
|
||
|
public
|
||
|
{
|
||
|
// withdrawal case
|
||
|
uint256 userSupply = 5.2 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 6 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, limitFromBeforeOperate); // should be previous limit
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenExpandPercent0() public {
|
||
|
// withdrawal case
|
||
|
uint256 userSupply = 5.2 ether;
|
||
|
uint256 expandPercentage = 0;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 1 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, userSupply); // should be user supply exactly as no expansion happens
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenExpandPercent100() public {
|
||
|
uint256 userSupply = 5.2 ether;
|
||
|
uint256 expandPercentage = 100 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 5 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 5 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenExpandPercent100To0() public {
|
||
|
uint256 userSupply = 5.2 ether;
|
||
|
uint256 expandPercentage = 100 * 1e2;
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
// expansion starts from last limit, but limit would be instantly max expansion.
|
||
|
// so with last limit being 0 we know expansion goes to 0
|
||
|
uint256 limitFromBeforeOperate = 0;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 0);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenSimulateBigDepositToInstantExpansion() public {
|
||
|
// e.g. after big enough deposit withdrawal limit is instantly fully expanded
|
||
|
uint256 userSupply = 8 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2; // so going to 5.6 ether
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 5 ether; // limit will be instantly fully expanded (deposit case)
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 5.6 ether);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenSimulateSmallDeposit() public {
|
||
|
// e.g. after big enough deposit withdrawal limit is instantly fully expanded
|
||
|
// e.g. user supply was 7.5 ether, 0.5 ether is deposited. limit before was 7 ether.
|
||
|
uint256 userSupply = 8 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2; // so going to 5.6 ether
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 7 ether; // was only partially expanded
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, 7 ether); // new limit starts from 7 ether.
|
||
|
|
||
|
// cross check new limit beforeOperate
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 7 ether
|
||
|
block.timestamp - DEFAULT_EXPAND_DURATION / 5, // last update timestamp 20% of expand duration
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
|
||
|
assertEq(limit, 6.52 ether); // should be 20% of 2.4 ether expansion expanded, starting from 7 ether. so 6.52 ether
|
||
|
|
||
|
// cross check new limit beforeOperate fully expansion after only 60% of time because starting from 7
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 7 ether
|
||
|
block.timestamp - (DEFAULT_EXPAND_DURATION * 6) / 10, // last update timestamp 60% of expand duration
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
|
||
|
assertEq(limit, 5.6 ether); // should be 60% of 2.4 ether expansion expanded, starting from 7 ether. so 5.56 ether
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenSimulateSmallWithdrawal() public {
|
||
|
// withdrawal case
|
||
|
// e.g. user supply was 8 ether, 0.5 ether is withdrawn. limit before was 7 ether.
|
||
|
uint256 userSupply = 7.5 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2; // so going to 5.25 ether
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 7 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, limitFromBeforeOperate); // should start from previous limit
|
||
|
|
||
|
// cross check new limit beforeOperate
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 7 ether
|
||
|
block.timestamp - DEFAULT_EXPAND_DURATION / 2, // last update timestamp 50% of expand duration
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 5.875 ether); // should be 50% of 2.4 ether expansion expanded, starting from 7 ether. so 5.875 ether
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimitAfterOperate_WhenSimulateBigWithdrawalToLimit() public {
|
||
|
// withdrawal case
|
||
|
// e.g. user supply was 8 ether, 0.5 ether is withdrawn. limit before was 7.5 ether.
|
||
|
uint256 userSupply = 7.5 ether;
|
||
|
uint256 expandPercentage = 30 * 1e2; // so going to 5.25 ether
|
||
|
|
||
|
uint256 userSupplyData = _getUserSupplyDataForAfterOperate(
|
||
|
userSupply,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
uint256 limitFromBeforeOperate = 7.5 ether;
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, limitFromBeforeOperate);
|
||
|
assertEq(limit, limitFromBeforeOperate); // should start from previous limit
|
||
|
|
||
|
// cross check new limit beforeOperate right after
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 7.5 ether
|
||
|
block.timestamp,
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 7.5 ether); // should be no withdrawal possible anymore
|
||
|
|
||
|
// cross check new limit beforeOperate after some expansion
|
||
|
userSupplyData = _getUserSupplyDataForBeforeOperate(
|
||
|
userSupply,
|
||
|
limit, // previous limit is 7.5 ether
|
||
|
block.timestamp - (DEFAULT_EXPAND_DURATION * 8) / 10, // last update timestamp 80% of expand duration
|
||
|
expandPercentage,
|
||
|
DEFAULT_EXPAND_DURATION,
|
||
|
DEFAULT_BASE_LIMIT
|
||
|
);
|
||
|
|
||
|
limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
assertEq(limit, 5.7 ether); // should be 80% of 2.25 ether expansion expanded, starting from 7.5 ether. so 5.7 ether
|
||
|
}
|
||
|
}
|
||
|
|
||
|
contract LibraryLiquidityCalcsWithdrawalLimitTests is LibraryLiquidityCalcsBaseTest {
|
||
|
function test_calcWithdrawalLimit_CombinationSequence() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 expandPercentage = 20 * 1e2; // 20%
|
||
|
uint256 baseLimit = 5 ether;
|
||
|
uint256 expandDuration = 200 seconds;
|
||
|
|
||
|
console2.log("-------------------------------");
|
||
|
console2.log("Config expandPercentage 20%", expandPercentage);
|
||
|
console2.log("Config baseLimit 5 ether", baseLimit);
|
||
|
console2.log("Config expandDuration 200 seconds", expandDuration);
|
||
|
|
||
|
uint256 previousLimit = 0;
|
||
|
uint256 lastUpdateTimestamp = 0;
|
||
|
|
||
|
console2.log("\n--------- Simulate 1. action: deposit of 1 ether ---------");
|
||
|
uint256 userSupply = 0;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0);
|
||
|
|
||
|
userSupply = 1 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0);
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 100);
|
||
|
console2.log("--------- TIME WARP 100 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 2. action: deposit of 4.5 ether to 5.5 ether total ---------");
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0);
|
||
|
|
||
|
userSupply += 4.5 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.4 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 1);
|
||
|
console2.log("--------- TIME WARP 1 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 3. action: deposit of 0.5 ether to 6 ether total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.4 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
userSupply += 0.5 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.8 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 1);
|
||
|
console2.log("--------- TIME WARP 1 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 4. action: withdraw 0.01 ether to total 5.99 ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.8 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
userSupply -= 0.01 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.8 ether); // triggered expansion from 4.8 down
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 200);
|
||
|
console2.log("--------- TIME WARP 200 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 5. action: deposit of 1.01 ether to 7 ether total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.792 ether); // fully expanded from 5.99
|
||
|
|
||
|
userSupply += 1.01 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.6 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 1);
|
||
|
console2.log("--------- TIME WARP 1 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 6. action: withdraw 1.4 ether down to 5.6 total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.6 ether); // fully expanded immediately because of deposits only
|
||
|
|
||
|
userSupply -= 1.4 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.6 ether); // last withdrawal limit used as point to expand from
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 40);
|
||
|
console2.log("--------- TIME WARP 40 seconds (20% of 20% epanded, 0.224 down to 5.376) ---------\n");
|
||
|
|
||
|
console2.log("\n--------- Simulate 7. action: withdraw 0.1 ether down to 5.5 total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.376 ether); // last withdrawal limit 5.6 20% of 20% epanded, 0.224 down to 5.376
|
||
|
|
||
|
userSupply -= 0.1 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.376 ether); // last withdrawal limit used as point to expand from
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 200);
|
||
|
console2.log("--------- TIME WARP 200 seconds (full expansion to 4.4) ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 8. action: withdraw 0.51 ether down to 4.99 total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 4.4 ether); // fully expanded from 5.5
|
||
|
|
||
|
userSupply -= 0.51 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0); // below base limit so 0
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 1);
|
||
|
console2.log("--------- TIME WARP 1 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 9. action: withdraw 4.99 ether down to 0 total ---------");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0); // below base limit so 0
|
||
|
|
||
|
userSupply -= 4.99 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0); // below base limit so 0
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimit_CalcWithdrawalLimitAfterOperate() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 previousLimit = 0; // not used in calcWithdrawalLimitAfterOperate
|
||
|
uint256 lastUpdateTimestamp = block.timestamp; // not used in calcWithdrawalLimitAfterOperate
|
||
|
uint256 expandDuration = 200 seconds; // not used in calcWithdrawalLimitAfterOperate
|
||
|
|
||
|
uint256 userSupply = 5.5 ether;
|
||
|
uint256 expandPercentage = 20 * 1e2; // 20%
|
||
|
uint256 baseLimit = 2 ether;
|
||
|
uint256 beforeOperateWithdrawalLimit = 0;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitAfterOperate(
|
||
|
userSupplyData,
|
||
|
userSupply,
|
||
|
beforeOperateWithdrawalLimit
|
||
|
);
|
||
|
|
||
|
console2.log("limit", limit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimit_CalcWithdrawalLimitBeforeOperate() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 userSupply = 10 ether;
|
||
|
uint256 previousLimit = 9.5 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - 100;
|
||
|
uint256 expandPercentage = 20 * 1e2; // 20%
|
||
|
uint256 expandDuration = 200 seconds;
|
||
|
uint256 baseLimit = 2 ether;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
|
||
|
console2.log("limit", limit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimit_CalcWithdrawalLimitBeforeOperate1() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 userSupply = 5.5 ether;
|
||
|
uint256 previousLimit = 0;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp;
|
||
|
uint256 expandPercentage = 20 * 1e2; // 20% -> down to 4,4
|
||
|
uint256 expandDuration = 200 seconds;
|
||
|
uint256 baseLimit = 5 ether;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
|
||
|
console2.log("limit", limit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimit_CalcWithdrawalLimitBeforeOperate2() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 userSupply = 5.5 ether;
|
||
|
uint256 previousLimit = 4.4 ether;
|
||
|
uint256 lastUpdateTimestamp = block.timestamp - 100; // half time passed
|
||
|
uint256 expandPercentage = 20 * 1e2; // 20% -> down to 4,4
|
||
|
uint256 expandDuration = 200 seconds;
|
||
|
uint256 baseLimit = 5 ether;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
uint256 limit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
|
||
|
console2.log("limit", limit);
|
||
|
}
|
||
|
|
||
|
function test_calcWithdrawalLimit_CalcWithdrawalLimit_FirstTimeAboveBaseLimit() public {
|
||
|
vm.warp(block.timestamp + 10_000); // skip ahead to not cause an underflow for last update timestamp
|
||
|
|
||
|
uint256 expandPercentage = 10 * 1e2; // 10%
|
||
|
uint256 expandDuration = 200 seconds;
|
||
|
uint256 baseLimit = 5 ether;
|
||
|
|
||
|
console2.log("-------------------------------");
|
||
|
console2.log("Config expandPercentage 10%", expandPercentage);
|
||
|
console2.log("Config baseLimit 5 ether", baseLimit);
|
||
|
console2.log("Config expandDuration 200 seconds", expandDuration);
|
||
|
|
||
|
uint256 previousLimit = 0;
|
||
|
uint256 lastUpdateTimestamp = 0;
|
||
|
|
||
|
console2.log("\n--------- Simulate 1. action: deposit of 6 ether ---------");
|
||
|
uint256 userSupply = 0;
|
||
|
|
||
|
uint256 userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 0);
|
||
|
|
||
|
userSupply = 6 ether;
|
||
|
console2.log("userSupply", userSupply);
|
||
|
assertEq(userSupply >= previousLimit, true, "USER SUPPLY IS < LIMIT");
|
||
|
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitAfterOperate(userSupplyData, userSupply, previousLimit);
|
||
|
console2.log("AFTER operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.4 ether);
|
||
|
|
||
|
lastUpdateTimestamp = block.timestamp;
|
||
|
vm.warp(block.timestamp + 100);
|
||
|
console2.log("--------- TIME WARP 100 seconds ---------");
|
||
|
|
||
|
console2.log("\n--------- Simulate 2. action: check before operate limit ---------");
|
||
|
userSupplyData = _simulateUserSupplyDataFull(
|
||
|
1,
|
||
|
userSupply,
|
||
|
previousLimit,
|
||
|
lastUpdateTimestamp,
|
||
|
expandPercentage,
|
||
|
expandDuration,
|
||
|
baseLimit,
|
||
|
false
|
||
|
);
|
||
|
previousLimit = testHelper.calcWithdrawalLimitBeforeOperate(userSupplyData, userSupply);
|
||
|
console2.log("BEFORE operate limit", previousLimit);
|
||
|
assertEq(previousLimit, 5.4 ether);
|
||
|
}
|
||
|
}
|