Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add multicollateral registry and weakest collateral redemption #127

Merged
merged 9 commits into from
May 1, 2024

Conversation

bingen
Copy link
Collaborator

@bingen bingen commented Apr 23, 2024

Closes #90

@bingen bingen self-assigned this Apr 23, 2024
@bingen bingen force-pushed the multicollateral_1_registry branch 3 times, most recently from 2843b68 to bd3224b Compare April 23, 2024 17:43
@bingen bingen marked this pull request as ready for review April 23, 2024 17:49
@bingen bingen force-pushed the multicollateral_1_registry branch from bd3224b to 4ac8dc3 Compare April 24, 2024 09:13
mapping(address => bool) troveManagerAddresses;
mapping(address => bool) stabilityPoolAddresses;
mapping(address => bool) borrowerOperationsAddresses;
mapping(address => bool) activePoolAddresses;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

address public immutable troveManagerAddress0;
address public immutable troveManagerAddress1;
// ...
address public immutable troveManagerAddress7;

address public immutable stabilityPoolAddress0;
address public immutable stabilityPoolAddress1;
// ...
address public immutable stabilityPoolAddress7;

// ...

?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we get around to that, maybe we could put that (along with all the _requireXXXs) in a base contract to keep that pollution tucked away? 😄

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the idea was to do something like your suggestion above (and like CollateralRegistry), I’ll change it when the rest of the PR is done.


// Decay the baseRate due to time passed, and then increase it according to the size of this redemption.
// Use the saved total Bold supply value, from before it was reduced by the redemption.
// TODO: what if the final redeemed amount is less than the requested amount?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, as it stands, a griefer could just flashloan a huge wad of BOLD (in addition to a relatively small amount of their own funds), set _maxIterations to 1, create minimal non-zombies at the start of each SortedTroves list, and cause a huge spike in base rate by redeeming that wad of BOLD. Economically, this doesn't seem to make sense, but the cost of it is way too low (< the capital required to open the minimal Troves, as the overcollateral part and the ETH not eaten up by redemption fees is recovered).

We need to move the calculation of the fee and payout of ETH out of TroveManager::redeemCollateral() and perform the redemption in 2 stages:

  • redeem from each branch
  • (in the registry, tally the amount redeemed, calculate fee)
  • payout ETH from each branch, deducting the fee

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, I guess a whale could even use this to make redemptions against their huge Trove unprofitable, while paying minimal interest.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon discussing this with @cvalkan on Slack, my proposal is not feasible, because we want to keep the redemption fee inside the redeemed Troves. So unless we want to go back and iterate over the Troves again (let's not do that), we have to commit to a fee percentage at the start.

To avoid attacks like the one outlined above, we should make sure that the post-redemption spike of the base rate is based on the actual redeemed amount instead of the attempted amount though.

Copy link
Collaborator

@RickGriff RickGriff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thanks!

contracts/src/BoldToken.sol Show resolved Hide resolved
contracts/src/CollateralRegistry.sol Outdated Show resolved Hide resolved
contracts/src/CollateralRegistry.sol Outdated Show resolved Hide resolved
contracts/src/CollateralRegistry.sol Outdated Show resolved Hide resolved
if (redeemAmount > 0) {
ITroveManager troveManager = getTroveManager(index);
uint256 feePercentage = troveManager.redeemCollateral(msg.sender, redeemAmount, _maxIterations);
totalFeePercentage += feePercentage * redeemAmount;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just reading this line as-is I initially thought it was a mistake, but the final calculation is correct.

Perhaps we could use an intermediate variable here, since (as you show below), the totalFeePercentage must be calculated using the totalRedeemedAmount.

(This intermediate var could be feeWeightedRedeemAmount or something)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this should be now changed, after discussion on Slack. The fee is now common, based in total Bold supply. Can you refresh in your browser?

contracts/src/TroveManager.sol Outdated Show resolved Hide resolved
const dumbContract = await GasPool.new();
const params = Array(numberOfAddresses).fill(dumbContract.address);

// Attempt call from alice
await th.assertRevert(contract.setAddresses(...params, { from: alice }));
await th.assertRevert(contract[method](...params, { from: alice }));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the reason for this change?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That now I’m using it also for other methods, like setCollateralRegistry or setBranchAddresses. I’ll change the function name so it’s clearer.

contracts/src/TroveManager.sol Outdated Show resolved Hide resolved
}

// Updates the `baseRate` state with math from `_getUpdatedBaseRateFromRedemption`
function _updateBaseRateAndGetRedemptionRate(IBoldToken _boldToken, uint256 _boldAmount, uint256 _totalBoldSupplyAtStart)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

_boldToken is unused now.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, thanks! It would be nice to be able to see warnings only from current changes.

Copy link
Collaborator

@danielattilasimon danielattilasimon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me! 👍 👍
I would just remove the unused variable.

@bingen bingen force-pushed the multicollateral_1_registry branch from 42f2bed to 6036ad7 Compare May 1, 2024 09:19
@bingen bingen merged commit d183913 into main May 1, 2024
7 checks passed
@danielattilasimon danielattilasimon deleted the multicollateral_1_registry branch May 6, 2024 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Multicollateral: Registry and weakest collateral redemptions
3 participants