Skip to content

Commit

Permalink
CDAuctioneer: WIP getCurrentTick() tests
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJem committed Jan 6, 2025
1 parent 6cde285 commit f9e201d
Show file tree
Hide file tree
Showing 2 changed files with 185 additions and 20 deletions.
16 changes: 9 additions & 7 deletions src/policies/CDAuctioneer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
Day internal dayState;

/// @notice Scale of the OHM token
uint256 internal constant _ohmScale = 10 ** 9;
uint256 internal constant _ohmScale = 1e9;

/// @notice Address of the Convertible Deposit Facility
CDFacility public cdFacility;
Expand Down Expand Up @@ -195,7 +195,8 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
// If there is not enough capacity in the current tick, use the remaining capacity
if (currentTickCapacity < convertibleAmount) {
convertibleAmount = currentTickCapacity;
depositAmount = _getConvertedDeposit(convertibleAmount, currentTickPrice);
// Convertible = deposit * OHM scale / price, so this is the inverse
depositAmount = convertibleAmount.mulDiv(currentTickPrice, _ohmScale);

// The tick has also been depleted, so update the price
currentTickPrice = _getNewTickPrice(currentTickPrice, _tickStep);
Expand Down Expand Up @@ -265,19 +266,20 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
// TODO document approach
// find amount of time passed and new capacity to add
uint256 timePassed = block.timestamp - state.lastUpdate;
uint256 newCapacity = (state.target * timePassed) / 1 days;
uint256 capacityToAdd = (state.target * timePassed) / 1 days;

// Skip if the new capacity is 0
if (newCapacity == 0) return _previousTick;
if (capacityToAdd == 0) return _previousTick;

tick = _previousTick;
uint256 newCapacity = tick.capacity + capacityToAdd;


// Iterate over the ticks until the capacity is within the tick size
// This is the opposite of what happens in the bid function
while (tick.capacity + newCapacity > state.tickSize) {
// Adjust the new capacity so that the total is <= to the tick size
newCapacity -= newCapacity < state.tickSize ? newCapacity : state.tickSize;
while (newCapacity > state.tickSize) {
// Reduce the capacity by the tick size
newCapacity -= state.tickSize;

// Adjust the tick price by the tick step, in the opposite direction to the bid function
tick.price = tick.price.mulDivUp(ONE_HUNDRED_PERCENT, _tickStep);
Expand Down
189 changes: 176 additions & 13 deletions src/test/policies/ConvertibleDepositAuctioneer/getCurrentTick.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,21 @@ contract ConvertibleDepositAuctioneerCurrentTickTest is ConvertibleDepositAuctio
// [X] the tick price remains at the min price
// [X] the tick capacity remains at the tick size
// [X] the tick price remains at the min price
// when the total capacity (current tick capacity + new capacity) is equal to the tick size
// [ ] the tick price is unchanged
// [ ] the tick capacity is unchanged
// when the total capacity is less than the tick size
// [ ] the tick price is unchanged
// [ ] the tick capacity is unchanged
// when the total capacity is greater than the tick size
// when the new capacity (current tick capacity + added capacity) is equal to the tick size
// [X] the tick price is unchanged
// [X] the tick capacity is the tick size
// when the new capacity is less than the tick size
// [X] the tick price is unchanged
// [X] the tick capacity is the new capacity
// when the new capacity is greater than the tick size
// given the tick step is = 100e2
// [ ] the tick price is unchanged
// given the tick step is > 100e2
// when the new price is lower than the minimum price
// [ ] the tick price is set to the minimum price
// [ ] the capacity is set to the tick size
// [ ] it reduces the price by the tick step until the total capacity is less than the tick size
// [ ] the tick capacity is set to the remainder
// [X] the tick price is set to the minimum price
// [X] the capacity is set to the tick size
// [X] it reduces the price by the tick step until the total capacity is less than the tick size
// [X] the tick capacity is set to the remainder

function test_contractNotInitialized_reverts() public {
// Expect revert
Expand All @@ -47,7 +47,9 @@ contract ConvertibleDepositAuctioneerCurrentTickTest is ConvertibleDepositAuctio
auctioneer.getCurrentTick();
}

function test_minimumPrice_sameTime(uint48 secondsPassed_) public givenInitialized {
function test_fullCapacity_minimumPrice_sameTime(
uint48 secondsPassed_
) public givenInitialized {
uint48 secondsPassed = uint48(bound(secondsPassed_, 0, 86400 - 1));

// Warp to change the block timestamp
Expand All @@ -64,7 +66,7 @@ contract ConvertibleDepositAuctioneerCurrentTickTest is ConvertibleDepositAuctio
assertEq(tick.price, expectedTickPrice, "price");
}

function test_minimumPrice(uint48 secondsPassed_) public givenInitialized {
function test_fullCapacity_minimumPrice(uint48 secondsPassed_) public givenInitialized {
uint48 secondsPassed = uint48(bound(secondsPassed_, 1, 7 days));

// Warp to change the block timestamp
Expand Down Expand Up @@ -92,4 +94,165 @@ contract ConvertibleDepositAuctioneerCurrentTickTest is ConvertibleDepositAuctio
assertEq(tick.capacity, expectedTickCapacity, "capacity");
assertEq(tick.price, expectedTickPrice, "price");
}

function test_reducedCapacity_newCapacityEqualToTickSize()
public
givenInitialized
givenRecipientHasBid(75e18)
{
// Min price is 15e18
// We need a bid and time to pass so that remaining capacity + new capacity = tick size
// Given a tick size of 10e9
// We want to get to a remaining capacity of 5e9
// 5e9 = bid size * 1e9 / 15e18
// Bid size = 5e9 * 15e18 / 1e9 = 75e18
// If there is capacity of 5e9, we need new capacity of 5e9
// new capacity = 20e9 * time passed / 1 days
// time passed = 5e9 * 1 days / 20e9 = 21600 seconds

// Assert that the convertible amount is correct
uint256[] memory positionIds = convertibleDepositPositions.getUserPositionIds(recipient);
assertEq(
convertibleDepositPositions.previewConvert(positionIds[0], 75e18),
5e9,
"convertible amount"
);

// Assert tick capacity
assertEq(auctioneer.getCurrentTick().capacity, 5e9, "previous tick capacity");

// Assert that the time passed will result in the correct capacity
uint48 timePassed = 21600;
assertEq(
(auctioneer.getState().target * timePassed) / 1 days,
5e9,
"expected new capacity"
);

// Warp forward
vm.warp(block.timestamp + timePassed);

// Call function
IConvertibleDepositAuctioneer.Tick memory tick = auctioneer.getCurrentTick();

// Assert tick capacity
assertEq(tick.capacity, 10e9, "new tick capacity");
assertEq(tick.price, 15e18, "new tick price");
}

function test_reducedCapacity_newCapacityLessThanTickSize()
public
givenInitialized
givenRecipientHasBid(90e18)
{
// Bid size of 90e18 results in convertible amount of 6e9
// Remaining capacity is 4e9

// Added capacity will be 5e9
// New capacity will be 4e9 + 5e9 = 9e9

// Warp forward
uint48 timePassed = 21600;
vm.warp(block.timestamp + timePassed);

// Call function
IConvertibleDepositAuctioneer.Tick memory tick = auctioneer.getCurrentTick();

// Assert tick capacity
assertEq(tick.capacity, 9e9, "new tick capacity");
assertEq(tick.price, 15e18, "new tick price");
}

function test_reducedCapacity_newCapacityGreaterThanTickSize()
public
givenInitialized
givenRecipientHasBid(45e18)
{
// Bid size of 45e18 results in convertible amount of 3e9
// Remaining capacity is 7e9

// Added capacity will be 5e9
// New capacity will be 7e9 + 5e9 = 12e9
// Excess capacity = 12e9 - 10e9 = 2e9
// Because the minimum price is hit, capacity is set to the tick size
// Tick price = 15e18 * 100e2 / 110e2 = 13636363636363636364
// Will be set to the min price

// Warp forward
uint48 timePassed = 21600;
vm.warp(block.timestamp + timePassed);

// Call function
IConvertibleDepositAuctioneer.Tick memory tick = auctioneer.getCurrentTick();

// Assert tick capacity
assertEq(tick.capacity, 10e9, "new tick capacity");
assertEq(tick.price, 15e18, "new tick price");
}

function test_tickPriceAboveMinimum_newCapacityGreaterThanTickSize()
public
givenInitialized
givenRecipientHasBid(330e18)
{
// Bid size of 330e18 results in:
// 1. 330e18 * 1e9 / 15e18 = 22e9. Greater than tick size of 10e9. Bid amount becomes 150e18. New price is 15e18 * 110e2 / 100e2 = 165e17
// 2. (330e18 - 150e18) * 1e9 / 165e17 = 10,909,090,909. Greater than tick size of 10e9. Bid amount becomes 165e18. New price is 165e17 * 110e2 / 100e2 = 1815e16
// 3. (330e18 - 150e18 - 165e18) * 1e9 / 1815e16 = 826,446,280
// Remaining capacity is 10e9 - 826,446,280 = 9,173,553,720

// Added capacity will be 5e9
// New capacity will be 9,173,553,720 + 5e9 = 14,173,553,720

// Calculate the expected tick price
// Excess capacity = 14,173,553,720 - 10e9 = 4,173,553,720
// Tick price = 165e17

// Warp forward
uint48 timePassed = 21600;
vm.warp(block.timestamp + timePassed);

// Call function
IConvertibleDepositAuctioneer.Tick memory tick = auctioneer.getCurrentTick();

// Assert tick capacity
assertEq(tick.capacity, 4173553720, "new tick capacity");
assertEq(tick.price, 165e17, "new tick price");
}

function test_tickPriceAboveMinimum_newPriceBelowMinimum()
public
givenInitialized
givenRecipientHasBid(330e18)
{
// Bid size of 330e18 results in:
// 1. 330e18 * 1e9 / 15e18 = 22e9. Greater than tick size of 10e9. Bid amount becomes 150e18. New price is 15e18 * 110e2 / 100e2 = 165e17
// 2. (330e18 - 150e18) * 1e9 / 165e17 = 10,909,090,909. Greater than tick size of 10e9. Bid amount becomes 165e18. New price is 165e17 * 110e2 / 100e2 = 1815e16
// 3. (330e18 - 150e18 - 165e18) * 1e9 / 1815e16 = 826,446,280
// Remaining capacity is 10e9 - 826,446,280 = 9,173,553,720

// Added capacity will be 25e9
// New capacity will be 9,173,553,720 + 25e9 = 34,173,553,720

// Calculate the expected tick price
// 1. Excess capacity = 34,173,553,720 - 10e9 = 24,173,553,720
// Tick price = 165e17
// 2. Excess capacity = 24,173,553,720 - 10e9 = 14,173,553,720
// Tick price = 165e17 * 100e2 / 110e2 = 15e18
// 3. Excess capacity = 14,173,553,720 - 10e9 = 4,173,553,720
// Tick price = 15e18 * 100e2 / 110e2 = 13636363636363636364
// Tick price is below the minimum price, so it is set to the minimum price
// New capacity = tick size = 10e9

// Warp forward
uint48 timePassed = 5 * 21600;
vm.warp(block.timestamp + timePassed);

// Call function
IConvertibleDepositAuctioneer.Tick memory tick = auctioneer.getCurrentTick();

// Assert tick capacity
assertEq(tick.capacity, 10e9, "new tick capacity");
assertEq(tick.price, 15e18, "new tick price");
}
}

0 comments on commit f9e201d

Please sign in to comment.