Skip to content

Commit

Permalink
Revert contracts/ changes added by #422
Browse files Browse the repository at this point in the history
These were unintentionally introduced by git merge conflicts.
  • Loading branch information
bpierre committed Sep 26, 2024
1 parent 235c05c commit ced551a
Show file tree
Hide file tree
Showing 27 changed files with 1,138 additions and 190 deletions.
2 changes: 2 additions & 0 deletions contracts/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ $ forge build
$ forge test
```

Run tests with `forge test -vvv` to see the console logs, which will show trove URI data.

### Format

```shell
Expand Down
50 changes: 26 additions & 24 deletions contracts/src/BorrowerOperations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
error BatchInterestRateChangePeriodNotPassed();
error TroveNotOpen();
error TroveNotActive();
error TroveNotUnredeemable();
error TroveNotZombie();
error TroveOpen();
error UpfrontFeeTooHigh();
error BelowCriticalThreshold();
Expand Down Expand Up @@ -470,7 +470,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
_adjustTrove(troveManagerCached, _troveId, troveChange, _maxUpfrontFee);
}

function adjustUnredeemableTrove(
function adjustZombieTrove(
uint256 _troveId,
uint256 _collChange,
bool _isCollIncrease,
Expand All @@ -481,7 +481,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
uint256 _maxUpfrontFee
) external override {
ITroveManager troveManagerCached = troveManager;
_requireTroveIsUnredeemable(troveManagerCached, _troveId);
_requireTroveIsZombie(troveManagerCached, _troveId);

TroveChange memory troveChange;
_initTroveChange(troveChange, _collChange, _isCollIncrease, _boldChange, _isDebtIncrease);
Expand Down Expand Up @@ -520,7 +520,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
_requireIsNotInBatch(_troveId);
address owner = troveNFT.ownerOf(_troveId);
_requireSenderIsOwnerOrInterestManager(_troveId, owner);
_requireInterestRateInDelegateRange(_troveId, _newAnnualInterestRate);
_requireInterestRateInDelegateRange(_troveId, _newAnnualInterestRate, owner);
_requireTroveIsActive(troveManagerCached, _troveId);

LatestTroveData memory trove = troveManagerCached.getLatestTroveData(_troveId);
Expand Down Expand Up @@ -650,8 +650,8 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
}
}

// Make sure the Trove doesn't end up unredeemable
// Now the max repayment is capped to stay above MIN_DEBT, so this only applies to adjustUnredeemableTrove
// Make sure the Trove doesn't end up zombie
// Now the max repayment is capped to stay above MIN_DEBT, so this only applies to adjustZombieTrove
_requireAtLeastMinDebt(vars.newDebt);

vars.newICR = LiquityMath._computeCR(vars.newColl, vars.newDebt, vars.price);
Expand Down Expand Up @@ -787,8 +787,8 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
);
activePool.mintAggInterestAndAccountForTroveChange(change, batchManager);

// If the trove was unredeemable, and now it’s not anymore, put it back in the list
if (_checkTroveIsUnredeemable(troveManagerCached, _troveId) && trove.entireDebt >= MIN_DEBT) {
// If the trove was zombie, and now it’s not anymore, put it back in the list
if (_checkTroveIsZombie(troveManagerCached, _troveId) && trove.entireDebt >= MIN_DEBT) {
troveManagerCached.setTroveStatusToActive(_troveId);
_reInsertIntoSortedTroves(
_troveId, trove.annualInterestRate, _upperHint, _lowerHint, batchManager, batch.annualInterestRate
Expand Down Expand Up @@ -1287,6 +1287,17 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
}
}

function _requireInterestRateInDelegateRange(uint256 _troveId, uint256 _annualInterestRate, address _owner) internal view {
InterestIndividualDelegate memory individualDelegate = interestIndividualDelegateOf[_troveId];
// We have previously checked that sender is either owner or delegate
// If it’s owner, this restriction doesn’t apply
if (individualDelegate.account == msg.sender) {
_requireInterestRateInRange(
_annualInterestRate, individualDelegate.minInterestRate, individualDelegate.maxInterestRate
);
}
}

function _requireIsNotInBatch(uint256 _troveId) internal view {
if (interestBatchManagerOf[_troveId] != address(0)) {
revert TroveInBatch();
Expand All @@ -1304,7 +1315,7 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio

function _requireTroveIsOpen(ITroveManager _troveManager, uint256 _troveId) internal view {
ITroveManager.Status status = _troveManager.getTroveStatus(_troveId);
if (status != ITroveManager.Status.active && status != ITroveManager.Status.unredeemable) {
if (status != ITroveManager.Status.active && status != ITroveManager.Status.zombie) {
revert TroveNotOpen();
}
}
Expand All @@ -1316,20 +1327,20 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
}
}

function _requireTroveIsUnredeemable(ITroveManager _troveManager, uint256 _troveId) internal view {
if (!_checkTroveIsUnredeemable(_troveManager, _troveId)) {
revert TroveNotUnredeemable();
function _requireTroveIsZombie(ITroveManager _troveManager, uint256 _troveId) internal view {
if (!_checkTroveIsZombie(_troveManager, _troveId)) {
revert TroveNotZombie();
}
}

function _checkTroveIsUnredeemable(ITroveManager _troveManager, uint256 _troveId) internal view returns (bool) {
function _checkTroveIsZombie(ITroveManager _troveManager, uint256 _troveId) internal view returns (bool) {
ITroveManager.Status status = _troveManager.getTroveStatus(_troveId);
return status == ITroveManager.Status.unredeemable;
return status == ITroveManager.Status.zombie;
}

function _requireTroveIsNotOpen(ITroveManager _troveManager, uint256 _troveId) internal view {
ITroveManager.Status status = _troveManager.getTroveStatus(_troveId);
if (status == ITroveManager.Status.active || status == ITroveManager.Status.unredeemable) {
if (status == ITroveManager.Status.active || status == ITroveManager.Status.zombie) {
revert TroveOpen();
}
}
Expand Down Expand Up @@ -1442,15 +1453,6 @@ contract BorrowerOperations is LiquityBase, AddRemoveManagers, IBorrowerOperatio
if (_minInterestRate >= _maxInterestRate) revert MinGeMax();
}

function _requireInterestRateInDelegateRange(uint256 _troveId, uint256 _annualInterestRate) internal view {
InterestIndividualDelegate memory individualDelegate = interestIndividualDelegateOf[_troveId];
if (individualDelegate.account != address(0)) {
_requireInterestRateInRange(
_annualInterestRate, individualDelegate.minInterestRate, individualDelegate.maxInterestRate
);
}
}

function _requireInterestRateInBatchManagerRange(address _interestBatchManagerAddress, uint256 _annualInterestRate)
internal
view
Expand Down
2 changes: 1 addition & 1 deletion contracts/src/Interfaces/IBorrowerOperations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ interface IBorrowerOperations is ILiquityBase, IAddRemoveManagers {
uint256 _maxUpfrontFee
) external;

function adjustUnredeemableTrove(
function adjustZombieTrove(
uint256 _troveId,
uint256 _collChange,
bool _isCollIncrease,
Expand Down
6 changes: 4 additions & 2 deletions contracts/src/Interfaces/ITroveManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface ITroveManager is ILiquityBase {
active,
closedByOwner,
closedByLiquidation,
unredeemable
zombie
}

function shutdownTime() external view returns (uint256);
Expand Down Expand Up @@ -53,6 +53,8 @@ interface ITroveManager is ILiquityBase {

function getCurrentICR(uint256 _troveId, uint256 _price) external view returns (uint256);

function lastZombieTroveId() external view returns (uint256);

function batchLiquidateTroves(uint256[] calldata _troveArray) external;

function redeemCollateral(
Expand Down Expand Up @@ -88,7 +90,7 @@ interface ITroveManager is ILiquityBase {
uint256 _batchDebt
) external;

// Called from `adjustUnredeemableTrove()`
// Called from `adjustZombieTrove()`
function setTroveStatusToActive(uint256 _troveId) external;

function onAdjustTroveInterestRate(
Expand Down
27 changes: 25 additions & 2 deletions contracts/src/NFTMetadata/MetadataNFT.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,16 @@ import "./utils/baseSVG.sol";
import "./utils/bauhaus.sol";

import "openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";

import {ITroveManager} from "src/Interfaces/ITroveManager.sol";

interface IMetadataNFT {
struct TroveData {
uint256 _tokenId;
address _owner;
address _collToken;
address _boldToken;
uint256 _collAmount;
uint256 _debtAmount;
uint256 _interestRate;
Expand All @@ -35,7 +38,8 @@ contract MetadataNFT is IMetadataNFT {
}

function uri(TroveData memory _troveData) public view returns (string memory) {
return json.formattedMetadata(name, description, renderSVGImage(_troveData));
string memory attr = attributes(_troveData);
return json.formattedMetadata(name, description, renderSVGImage(_troveData), attr);
}

function renderSVGImage(TroveData memory _troveData) internal view returns (string memory) {
Expand All @@ -45,6 +49,25 @@ contract MetadataNFT is IMetadataNFT {
);
}

function attributes(TroveData memory _troveData) public view returns (string memory) {
//include: collateral token address, collateral amount, debt token address, debt amount, interest rate, status
return string.concat(
'[{"trait_type": "Collateral Token", "value": "',
Strings.toHexString(_troveData._collToken),
'"}, {"trait_type": "Collateral Amount", "value": "',
Strings.toString(_troveData._collAmount),
'"}, {"trait_type": "Debt Token", "value": "',
Strings.toHexString(_troveData._boldToken),
'"}, {"trait_type": "Debt Amount", "value": "',
Strings.toString(_troveData._debtAmount),
'"}, {"trait_type": "Interest Rate", "value": "',
Strings.toString(_troveData._interestRate),
'"}, {"trait_type": "Status", "value": "',
_status2Str(_troveData._status),
'"} ]'
);
}

function dynamicTextComponents(TroveData memory _troveData) public view returns (string memory) {
string memory id = LibString.toHexString(_troveData._tokenId);
id = string.concat(LibString.slice(id, 0, 6), "...", LibString.slice(id, 38, 42));
Expand All @@ -62,7 +85,7 @@ contract MetadataNFT is IMetadataNFT {
if (status == ITroveManager.Status.active) return "Active";
if (status == ITroveManager.Status.closedByOwner) return "Closed";
if (status == ITroveManager.Status.closedByLiquidation) return "Liquidated";
if (status == ITroveManager.Status.unredeemable) return "Unredeemable";
if (status == ITroveManager.Status.zombie) return "Zombie";
return "";
}
}
21 changes: 15 additions & 6 deletions contracts/src/NFTMetadata/utils/JSON.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,25 @@ library json {

string constant DOUBLE_QUOTES = '\\"';

function formattedMetadata(string memory name, string memory description, string memory svgImg)
internal
pure
returns (string memory)
{
function formattedMetadata(
string memory name,
string memory description,
string memory svgImg,
string memory attributes
) internal pure returns (string memory) {
return string.concat(
"data:application/json;base64,",
encode(
bytes(
string.concat("{", _prop("name", name), _prop("description", description), _xmlImage(svgImg), "}")
string.concat(
"{",
_prop("name", name),
_prop("description", description),
_xmlImage(svgImg),
',"attributes":',
attributes,
"}"
)
)
)
);
Expand Down
Loading

0 comments on commit ced551a

Please sign in to comment.