Skip to content

Commit

Permalink
CDAuctioneer: WIP getCurrentTick() tests and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
0xJem committed Jan 3, 2025
1 parent 3296f9e commit 6cde285
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 36 deletions.
11 changes: 7 additions & 4 deletions src/policies/CDAuctioneer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
uint256 price_
) internal view returns (uint256 convertibleAmount) {
// As price represents the number of bid tokens per OHM, we can convert the deposit to OHM by dividing by the price and adjusting for the decimal scale
convertibleAmount = deposit_.mulDiv(bidTokenScale, price_);
convertibleAmount = deposit_.mulDiv(_ohmScale, price_);
return convertibleAmount;
}

Expand All @@ -254,8 +254,7 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
uint256 currentPrice_,
uint256 tickStep_
) internal view returns (uint256 newPrice) {
// The tick step is a percentage increase (decrease) per tick, in terms of `decimals`, so we need to adjust for the decimal scale
newPrice = currentPrice_.mulDivUp(tickStep_, bidTokenScale);
newPrice = currentPrice_.mulDivUp(tickStep_, ONE_HUNDRED_PERCENT);
return newPrice;
}

Expand All @@ -268,13 +267,17 @@ contract CDAuctioneer is IConvertibleDepositAuctioneer, Policy, RolesConsumer, R
uint256 timePassed = block.timestamp - state.lastUpdate;
uint256 newCapacity = (state.target * timePassed) / 1 days;

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

tick = _previousTick;


// 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) {
newCapacity -= state.tickSize;
// Adjust the new capacity so that the total is <= to the tick size
newCapacity -= newCapacity < state.tickSize ? 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
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ contract ConvertibleDepositAuctioneerTest is Test {
address public emergency = address(0x5);

uint48 public constant INITIAL_BLOCK = 1_000_000;
uint256 public constant CONVERSION_PRICE = 2e18;
uint48 public constant EXPIRY = INITIAL_BLOCK + 1 days;
uint256 public constant RESERVE_TOKEN_AMOUNT = 10e18;

// @dev This should result in multiple ticks being filled
uint256 public constant BID_LARGE_AMOUNT = 3000e18;

uint256 public constant TICK_SIZE = 10e9;
uint24 public constant TICK_STEP = 110e2; // 110%
Expand Down Expand Up @@ -87,6 +87,7 @@ contract ConvertibleDepositAuctioneerTest is Test {
rolesAdmin.grantRole(bytes32("heart"), heart);
rolesAdmin.grantRole(bytes32("cd_admin"), admin);
rolesAdmin.grantRole(bytes32("emergency_shutdown"), emergency);
rolesAdmin.grantRole(bytes32("cd_auctioneer"), address(auctioneer));
}

// ========== HELPERS ========== //
Expand Down Expand Up @@ -214,7 +215,7 @@ contract ConvertibleDepositAuctioneerTest is Test {
_mintReserveToken(recipient, deposit_);

// Approve spending
_approveReserveTokenSpending(recipient, address(auctioneer), deposit_);
_approveReserveTokenSpending(recipient, address(convertibleDepository), deposit_);

// Bid
_bid(recipient, deposit_);
Expand Down
2 changes: 2 additions & 0 deletions src/test/policies/ConvertibleDepositAuctioneer/bid.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ contract ConvertibleDepositAuctioneerBidTest is ConvertibleDepositAuctioneerTest
// [ ] it reverts
// when the caller has not approved CDEPO to spend the bid token
// [ ] it reverts
// when the "cd_auctioneer" role is not granted to the auctioneer contract
// [ ] it reverts
// when the bid amount converted is 0
// [ ] it reverts
// when the tick price is below the minimum price
Expand Down
69 changes: 42 additions & 27 deletions src/test/policies/ConvertibleDepositAuctioneer/getCurrentTick.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,68 +6,83 @@ import {IConvertibleDepositAuctioneer} from "src/policies/interfaces/IConvertibl

contract ConvertibleDepositAuctioneerCurrentTickTest is ConvertibleDepositAuctioneerTest {
// given the contract has not been initialized
// [ ] it reverts
// [X] it reverts
// given the contract is inactive
// [X] it reverts
// given a bid has never been received
// [X] it calculates the new capacity based on the time since contract activation
// given less than 1 day has passed
// [ ] the tick capacity is unchanged
// [ ] the tick price is unchanged
// given a bid has never been received and the tick price is at the minimum price
// given no time has passed
// [X] the tick capacity remains at the tick size
// [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
// given the tick step is > 1e18
// [ ] the tick price increases
// given the tick step is = 1e18
// given the tick step is = 100e2
// [ ] the tick price is unchanged
// given the tick step is < 1e18
// 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

function test_contractInactive_reverts() public givenContractInactive {
function test_contractNotInitialized_reverts() public {
// Expect revert
vm.expectRevert(IConvertibleDepositAuctioneer.CDAuctioneer_NotActive.selector);

// Call function
auctioneer.getCurrentTick();
}

function test_contractInactive_reverts() public givenInitialized givenContractInactive {
// Expect revert
vm.expectRevert(IConvertibleDepositAuctioneer.CDAuctioneer_NotActive.selector);

// Call function
auctioneer.getCurrentTick();
}

function test_noBidReceived() public givenInitialized {
uint48 daysPassed = 2 days;
function test_minimumPrice_sameTime(uint48 secondsPassed_) public givenInitialized {
uint48 secondsPassed = uint48(bound(secondsPassed_, 0, 86400 - 1));

// Warp to change the block timestamp
vm.warp(block.timestamp + secondsPassed);

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

uint256 expectedTickPrice = 15e18;
uint256 expectedTickCapacity = 10e9;

// Assert current tick
assertEq(tick.capacity, expectedTickCapacity, "capacity");
assertEq(tick.price, expectedTickPrice, "price");
}

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

// Warp to change the block timestamp
vm.warp(block.timestamp + daysPassed);
vm.warp(block.timestamp + secondsPassed);

// Expected values
// Tick size = 10e9
// Tick step = 9e17
// Tick step = 110e2
// Current tick capacity = tick size = 10e9
// Current tick price = min price = 15e18
// New capacity added = target * days passed = 20e9 * 2 = 40e9
// New capacity = 10e9 + 40e9 = 50e9
// Iteration 1:
// New capacity = 50e9 - 10e9 = 40e9
// Tick price = 15e18 * 1e18 / 9e17 = 16666666666666666667 (rounded up)
// Iteration 2:
// New capacity = 40e9 - 10e9 = 30e9
// Tick price = 16666666666666666667 * 1e18 / 9e17 = 18518518518518518519 (rounded up)
// Iteration 3:
// New capacity = 30e9 - 10e9 = 20e9
// Tick price = 18518518518518518519 * 1e18 / 9e17 = 20576131687242798355 (rounded up)
// Iteration 4:
// New capacity = 20e9 - 10e9 = 10e9
// Tick price = 20576131687242798355 * 1e18 / 9e17 = 22862368541380887062
// Tick price = 15e18 * 100e2 / 110e2 = 13636363636363636364
//
// New capacity is not > tick size, so we stop
uint256 expectedTickPrice = 22862368541380887062;
// Updated tick price is < min price, so it is set to the min price
uint256 expectedTickPrice = 15e18;
uint256 expectedTickCapacity = 10e9;

// Call function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ contract ConvertibleDepositAuctioneerInitializeTest is ConvertibleDepositAuction
auctioneer.initialize(TARGET, TICK_SIZE, MIN_PRICE, TICK_STEP, TIME_TO_EXPIRY);

// Assert state
_assertState(TARGET, TICK_SIZE, MIN_PRICE, uint48(block.timestamp));
_assertState(TARGET, TICK_SIZE, MIN_PRICE, INITIAL_BLOCK);
assertEq(auctioneer.getTickStep(), TICK_STEP, "tick step");
assertEq(auctioneer.getTimeToExpiry(), TIME_TO_EXPIRY, "time to expiry");
assertEq(auctioneer.locallyActive(), true, "locally active");
Expand Down

0 comments on commit 6cde285

Please sign in to comment.