Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ Below is an outline of all functions used in the library.
- `increaseIlkDebtCeiling(bytes32 _ilk, uint256 _amount, bool _global)`: Raise the debt ceiling of a particular ilk.
- `decreaseIlkDebtCeiling(bytes32 _ilk, uint256 _amount, bool _global)`: Lower the debt ceiling of a particular ilk.
- `setRWAIlkDebtCeiling(bytes32 _ilk, uint256 _ceiling, uint256 _price)`: Set the debt ceiling for a RWA collateral. This requires also a new oracle price.
- `setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap, uint256 _ttl)`: Configure the parameters for the Debt Ceiling auto line module for a particular ilk.
- `setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap)`: Configure the amount and gap parameters for the Debt Ceiling auto line module while keeping the existing TTL value.
- `setIlkAutoLineDebtCeiling(bytes32 _ilk, uint256 _amount)`: Adjust the debt ceiling in the auto line module.
- `removeIlkFromAutoLine(bytes32 _ilk)`: Remove the management of an ilk by the debt ceiling auto line module.
- `setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap, uint256 _ttl)`: Configure the Debt Ceiling auto line parameters, then call `DssAutoLine.exec(ilk)` to update the live Vat debt ceilings when AutoLine permits a change.
- `setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap)`: Configure the amount and gap while keeping the existing TTL, then call `DssAutoLine.exec(ilk)` to update the live Vat debt ceilings when AutoLine permits a change.
- `setIlkAutoLineDebtCeiling(bytes32 _ilk, uint256 _amount)`: Configure the maximum debt ceiling while keeping the existing gap and TTL, then call `DssAutoLine.exec(ilk)` to update the live Vat debt ceilings when AutoLine permits a change.
- `removeIlkFromAutoLine(bytes32 _ilk)`: Remove the AutoLine configuration for an ilk without updating the live Vat debt ceilings.
- `setIlkMinVaultAmount(bytes32 _ilk, uint256 _amount)`: Set a collateral minimum vault amount.
- `setIlkLiquidationPenalty(bytes32 _ilk, uint256 _pct_bps)`: Set a collateral liquidation penalty.
- `setIlkMaxLiquidationAmount(bytes32 _ilk, uint256 _amount)`: Set max DAI amount for liquidation per vault for a collateral type.
Expand Down
142 changes: 115 additions & 27 deletions src/DssAction.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -738,56 +738,144 @@ contract DssActionTest is Test {
}

function test_setIlkAutoLineParameters() public {
action.setIlkAutoLineParameters_test("gold", 150 * MILLION, 5 * MILLION, 10000); // Setup
(,,, uint256 initialIlkLine,) = vat.ilks("gold");
uint256 initialGlobalLine = vat.Line();

(,,, uint256 line,) = vat.ilks("gold");
assertEq(line, 1000 * RAD); // does not change line
action.setIlkAutoLineParameters_test("gold", 150 * MILLION, 5 * MILLION, 10000); // Increase, gap-bound

(uint256 maxLine, uint256 gap, uint48 ttl, uint48 last, uint48 lastInc) = autoLine.ilks("gold");
assertEq(maxLine, 150 * MILLION * RAD);
assertEq(gap, 5 * MILLION * RAD);
assertEq(uint256(ttl), 10000);
assertEq(uint256(last), block.number); // Records execution block
assertEq(uint256(lastInc), block.timestamp); // Records increase timestamp

(,,, uint256 ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 5 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // also increased

action.setIlkAutoLineParameters_test("gold", 2 * MILLION, 1 * MILLION, 10000); // Decrease, gap-bound

(maxLine, gap, ttl, last, lastInc) = autoLine.ilks("gold");
assertEq(maxLine, 2 * MILLION * RAD);
assertEq(gap, 1 * MILLION * RAD);
assertEq(uint256(ttl), 10000);
assertEq(uint256(last), block.number); // Records execution block
assertEq(uint256(lastInc), 0); // Decreases do not update lastInc

(,,, ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 1 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // also decreased

autoLine.exec("gold");
(,,, line,) = vat.ilks("gold");
assertEq(line, 5 * MILLION * RAD); // Change to match the gap
action.setIlkAutoLineParameters_test("gold", 2 * MILLION, 1 * MILLION, 10000); // Unchanged target

(maxLine, gap, ttl, last, lastInc) = autoLine.ilks("gold");
assertEq(maxLine, 2 * MILLION * RAD);
assertEq(gap, 1 * MILLION * RAD);
assertEq(uint256(ttl), 10000);
assertEq(uint256(last), 0); // Reset by setIlk before exec no-op
assertEq(uint256(lastInc), 0); // Reset by setIlk before exec no-op

(,,, ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 1 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // unchanged
}

function test_setIlkAutoLineParametersKeepTtl() public {
// First set up with initial values including ttl
action.setIlkAutoLineParameters_test("gold", 150 * MILLION, 5 * MILLION, 10000);
action.setIlkAutoLineParameters_test("gold", 150 * MILLION, 5 * MILLION, 10000); // Setup

// Get the initial ttl value
(,, uint48 initialTtl,,) = autoLine.ilks("gold");
assertEq(uint256(initialTtl), 10000);
(,,, uint256 initialIlkLine,) = vat.ilks("gold");
uint256 initialGlobalLine = vat.Line();

// Now use the overloaded function that should keep the ttl unchanged
action.setIlkAutoLineParameters_test("gold", 200 * MILLION, 10 * MILLION);
action.setIlkAutoLineParameters_test("gold", 200 * MILLION, 10 * MILLION); // Increase, keep ttl

// Verify line and gap were updated but ttl remains the same
(uint256 line, uint256 gap, uint48 ttl,,) = autoLine.ilks("gold");
assertEq(line, 200 * MILLION * RAD);
(uint256 maxLine, uint256 gap, uint48 ttl,,) = autoLine.ilks("gold");
assertEq(maxLine, 200 * MILLION * RAD);
assertEq(gap, 10 * MILLION * RAD);
assertEq(uint256(ttl), initialTtl); // ttl should remain unchanged
assertEq(uint256(ttl), initialTtl); // ttl unchanged

(,,, uint256 ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 10 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // also increased
}

function test_RevertSetIlkAutoLineParametersKeepTtl_WhenNotConfigured() public {
function test_revert_setIlkAutoLineParametersKeepTtl_WhenNotConfigured() public {
vm.expectRevert();
action.setIlkAutoLineParameters_test("gold", 200 * MILLION, 10 * MILLION);
action.setIlkAutoLineParameters_test("gold", 200 * MILLION, 10 * MILLION); // Fail if not configured
}

function test_setIlkAutoLineDebtCeiling() public {
action.setIlkAutoLineParameters_test("gold", 1, 5 * MILLION, 10000); // gap and ttl must be configured already
action.setIlkAutoLineDebtCeiling_test("gold", 150 * MILLION); // Setup
action.setIlkAutoLineParameters_test("gold", 2 * MILLION, 5 * MILLION, 10000); // Setup, maxLine-bound

(,,, uint256 line,) = vat.ilks("gold");
assertEq(line, 1000 * RAD); // does not change line
(,,, uint256 initialIlkLine,) = vat.ilks("gold");
uint256 initialGlobalLine = vat.Line();

action.setIlkAutoLineDebtCeiling_test("gold", 4 * MILLION); // Increase

autoLine.exec("gold");
(,,, line,) = vat.ilks("gold");
assertEq(line, 5 * MILLION * RAD); // Change to match the gap
(uint256 maxLine, uint256 gap, uint48 ttl,,) = autoLine.ilks("gold");
assertEq(maxLine, 4 * MILLION * RAD);
assertEq(gap, 5 * MILLION * RAD); // unchanged
assertEq(uint256(ttl), 10000); // unchanged

(,,, uint256 ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 4 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // also increased

action.setIlkAutoLineDebtCeiling_test("gold", 3 * MILLION); // Decrease

(maxLine, gap, ttl,,) = autoLine.ilks("gold");
assertEq(maxLine, 3 * MILLION * RAD);
assertEq(gap, 5 * MILLION * RAD); // unchanged
assertEq(uint256(ttl), 10000); // unchanged

(,,, ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, 3 * MILLION * RAD);
assertEq(vat.Line(), initialGlobalLine + ilkLine - initialIlkLine); // also decreased
}

function test_revert_setIlkAutoLineParameters_WhenAutoLineIsNotAuthorizedOnVat() public {
(uint256 initialMaxLine, uint256 initialGap, uint48 initialTtl, uint48 initialLast, uint48 initialLastInc) =
autoLine.ilks("gold");
(,,, uint256 initialIlkLine,) = vat.ilks("gold");
uint256 initialGlobalLine = vat.Line();

vat.deny(address(autoLine)); // Remove AutoLine authorization

vm.expectRevert("Vat/not-authorized");
action.setIlkAutoLineParameters_test("gold", 150 * MILLION, 5 * MILLION, 10000); // Fail on exec

(uint256 maxLine, uint256 gap, uint48 ttl, uint48 last, uint48 lastInc) = autoLine.ilks("gold");
assertEq(maxLine, initialMaxLine); // setIlk rolled back
assertEq(gap, initialGap);
assertEq(uint256(ttl), uint256(initialTtl));
assertEq(uint256(last), uint256(initialLast));
assertEq(uint256(lastInc), uint256(initialLastInc));

(,,, uint256 ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, initialIlkLine);
assertEq(vat.Line(), initialGlobalLine); // live ceilings unchanged
}

function test_setRemoveIlkFromAutoLine() public {
action.setIlkAutoLineParameters_test("gold", 100 * MILLION, 5 * MILLION, 10000); // gap and ttl must be configured already
action.removeIlkFromAutoLine_test("gold");
action.setIlkAutoLineParameters_test("gold", 100 * MILLION, 5 * MILLION, 10000); // Setup

(,,, uint256 initialIlkLine,) = vat.ilks("gold");
uint256 initialGlobalLine = vat.Line();

action.removeIlkFromAutoLine_test("gold"); // Remove configuration only

(uint256 maxLine, uint256 gap, uint48 ttl, uint48 last, uint48 lastInc) = autoLine.ilks("gold");
assertEq(maxLine, 0); // AutoLine configuration removed
assertEq(gap, 0);
assertEq(uint256(ttl), 0);
assertEq(uint256(last), 0);
assertEq(uint256(lastInc), 0);

assertEq(autoLine.exec("gold"), 1000 * RAD);
(,,, uint256 ilkLine,) = vat.ilks("gold");
assertEq(ilkLine, initialIlkLine);
assertEq(vat.Line(), initialGlobalLine); // live ceilings unchanged
}

function test_setIlkMinVaultAmountLt() public {
Expand Down
19 changes: 14 additions & 5 deletions src/DssExecLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ interface IAMLike {
function ilks(bytes32) external view returns (uint256, uint256, uint48, uint48, uint48);
function setIlk(bytes32, uint256, uint256, uint256) external;
function remIlk(bytes32) external;
function exec(bytes32) external returns (uint256);
}

interface LerpFactoryLike {
Expand Down Expand Up @@ -769,19 +770,23 @@ library DssExecLib {
updateCollateralPrice(_ilk);
}

/// @dev Set the parameters for an ilk in the "MCD_IAM_AUTO_LINE" auto-line
/// @dev Set the parameters for an ilk in the "MCD_IAM_AUTO_LINE" auto-line and call exec.
/// exec updates the live Vat debt ceilings when AutoLine permits a change.
/// @param _ilk The ilk to update (ex. bytes32("ETH-A"))
/// @param _amount The Maximum value (ex. 100m amount == 100000000)
/// @param _gap The amount per step (ex. 5m gap == 5000000)
/// @param _ttl The amount of time (in seconds)
function setIlkAutoLineParameters(bytes32 _ilk, uint256 _amount, uint256 _gap, uint256 _ttl) public {
require(_amount < WAD); // "LibDssExec/incorrect-auto-line-amount-precision"
require(_gap < WAD); // "LibDssExec/incorrect-auto-line-gap-precision"
IAMLike(autoLine()).setIlk(_ilk, _amount * RAD, _gap * RAD, _ttl);
address _autoLine = autoLine();
IAMLike(_autoLine).setIlk(_ilk, _amount * RAD, _gap * RAD, _ttl);
IAMLike(_autoLine).exec(_ilk);
}

/// @dev Set the parameters for an ilk in the "MCD_IAM_AUTO_LINE" auto-line. Keeps the ttl unchanged.
/// Requires the auto-line to be already configured for the ilk.
/// @dev Set the parameters for an ilk in the "MCD_IAM_AUTO_LINE" auto-line and call exec.
/// exec updates the live Vat debt ceilings when AutoLine permits a change.
/// Keeps the ttl unchanged. Requires the auto-line to be already configured for the ilk.
/// @param _ilk The ilk to update (ex. bytes32("ETH-A"))
/// @param _amount The Maximum value (ex. 100m amount == 100000000)
/// @param _gap The amount per step (ex. 5m gap == 5000000)
Expand All @@ -792,16 +797,20 @@ library DssExecLib {
(,, uint48 ttl,,) = IAMLike(_autoLine).ilks(_ilk);
require(ttl != 0); // "LibDssExec/auto-line-not-configured"
IAMLike(_autoLine).setIlk(_ilk, _amount * RAD, _gap * RAD, uint256(ttl));
IAMLike(_autoLine).exec(_ilk);
}

/// @dev Set the debt ceiling for an ilk in the "MCD_IAM_AUTO_LINE" auto-line without updating the time values
/// @dev Set the debt ceiling for an ilk in the "MCD_IAM_AUTO_LINE" auto-line and call exec.
/// exec updates the live Vat debt ceilings when AutoLine permits a change.
/// Keeps the gap and ttl unchanged. Requires the auto-line to be already configured for the ilk.
/// @param _ilk The ilk to update (ex. bytes32("ETH-A"))
/// @param _amount The Maximum value (ex. 100m amount == 100000000)
function setIlkAutoLineDebtCeiling(bytes32 _ilk, uint256 _amount) public {
address _autoLine = autoLine();
(, uint256 gap, uint48 ttl,,) = IAMLike(_autoLine).ilks(_ilk);
require(gap != 0 && ttl != 0); // "LibDssExec/auto-line-not-configured"
IAMLike(_autoLine).setIlk(_ilk, _amount * RAD, uint256(gap), uint256(ttl));
IAMLike(_autoLine).exec(_ilk);
}

/// @dev Remove an ilk in the "MCD_IAM_AUTO_LINE" auto-line
Expand Down
Loading