Skip to content

Commit

Permalink
tmp
Browse files Browse the repository at this point in the history
  • Loading branch information
Szymx95 committed Apr 24, 2024
1 parent 72b4f20 commit dc134d7
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 11 deletions.
44 changes: 43 additions & 1 deletion contracts/StabilityPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./Dependencies/SafetyTransfer.sol";
import "./Interfaces/IStabilityPool.sol";
import "./Interfaces/IDebtToken.sol";
import "./Interfaces/IVesselManager.sol";

import "../lib/forge-std/src/console.sol";
/**
* @title The Stability Pool holds debt tokens deposited by Stability Pool depositors.
* @dev When a vessel is liquidated, then depending on system conditions, some of its debt tokens debt gets offset with
Expand Down Expand Up @@ -328,6 +328,9 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
*/
function offset(uint256 _debtToOffset, address _asset, uint256 _amountAdded) external onlyVesselManager {
uint256 cachedTotalDebtTokenDeposits = totalDebtTokenDeposits; // cached to save an SLOAD
console.log("totalDebtTokenDeposits: ", totalDebtTokenDeposits);
console.log("_amountAdded: ", _amountAdded);

if (cachedTotalDebtTokenDeposits == 0 || _debtToOffset == 0) {
return;
}
Expand All @@ -338,6 +341,9 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
_debtToOffset,
cachedTotalDebtTokenDeposits
);
console.log("collGainPerUnitStaked: ", collGainPerUnitStaked);
console.log("debtLossPerUnitStaked: ", debtLossPerUnitStaked);


_updateRewardSumAndProduct(_asset, collGainPerUnitStaked, debtLossPerUnitStaked); // updates S and P
_moveOffsetCollAndDebt(_asset, _amountAdded, _debtToOffset);
Expand Down Expand Up @@ -367,6 +373,7 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
uint256 _totalDeposits
) internal returns (uint256 collGainPerUnitStaked, uint256 debtLossPerUnitStaked) {
uint256 assetIndex = IAdminContract(adminContract).getIndex(_asset);

uint256 collateralNumerator = (_amountAdded * DECIMAL_PRECISION) + lastAssetError_Offset[assetIndex];
require(_debtToOffset <= _totalDeposits, "StabilityPool: Debt is larger than totalDeposits");
if (_debtToOffset == _totalDeposits) {
Expand All @@ -381,6 +388,8 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
debtLossPerUnitStaked = (lossNumerator / _totalDeposits) + 1;
lastDebtTokenLossError_Offset = (debtLossPerUnitStaked * _totalDeposits) - lossNumerator;
}
console.log("collateralNumerator", collateralNumerator);
console.log("_totalDeposits", _totalDeposits);
collGainPerUnitStaked = collateralNumerator / _totalDeposits;
lastAssetError_Offset[assetIndex] = collateralNumerator - (collGainPerUnitStaked * _totalDeposits);
}
Expand Down Expand Up @@ -410,11 +419,21 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
*
* Since S corresponds to asset gain, and P to deposit loss, we update S first.
*/

console.log("currentS: ", currentS);
console.log("currentP: ", currentP);
uint256 marginalAssetGain = _collGainPerUnitStaked * currentP;
console.log("marginalAssetGain: ", marginalAssetGain);

uint256 newS = currentS + marginalAssetGain;

console.log("new S: ", newS);

epochToScaleToSum[_asset][currentEpochCached][currentScaleCached] = newS;
emit S_Updated(_asset, newS, currentEpochCached, currentScaleCached);



// If the Stability Pool was emptied, increment the epoch, and reset the scale and product P
if (newProductFactor == 0) {
currentEpochCached += 1;
Expand All @@ -427,20 +446,28 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
// If multiplying P by a non-zero product factor would reduce P below the scale boundary, increment the scale
} else {
uint256 mulCached = currentP * newProductFactor;
console.log("mulCached: ", mulCached);

uint256 mulDivCached = mulCached / DECIMAL_PRECISION;

if (mulDivCached < SCALE_FACTOR) {

newP = (mulCached * SCALE_FACTOR) / DECIMAL_PRECISION;
currentScaleCached += 1;
currentScale = currentScaleCached;
emit ScaleUpdated(currentScaleCached);
console.log("adjust scale factor: ", currentScaleCached);
} else {
newP = mulDivCached;
console.log("set scale factor: ", newP);

}
}

require(newP != 0, "StabilityPool: P = 0");
P = newP;
console.log("new P: ", newP);

emit P_Updated(newP);
}

Expand Down Expand Up @@ -538,6 +565,7 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
Snapshots storage snapshots,
address asset
) internal view returns (uint256) {
console.log("______ RUNNING _getGainFromSnapshots _____");
/*
* Grab the sum 'S' from the epoch at which the stake was made. The Collateral amount gain may span up to one scale change.
* If it does, the second portion of the Collateral amount gain is scaled by 1e9.
Expand All @@ -546,12 +574,26 @@ contract StabilityPool is ReentrancyGuardUpgradeable, UUPSUpgradeable, TrinityBa
uint256 S_Snapshot = snapshots.S[asset];
uint256 P_Snapshot = snapshots.P;

console.log("S_Snapshot: ", S_Snapshot);

mapping(uint128 => uint256) storage scaleToSum = epochToScaleToSum[asset][snapshots.epoch];

console.log("S: ", scaleToSum[snapshots.scale], scaleToSum[snapshots.scale + 1]);


uint256 firstPortion = scaleToSum[snapshots.scale] - S_Snapshot;
uint256 secondPortion = scaleToSum[snapshots.scale + 1] / SCALE_FACTOR;

uint256 assetGain = (initialDeposit * (firstPortion + secondPortion)) / P_Snapshot / DECIMAL_PRECISION;

console.log("assetGain: ", assetGain);
console.log("initialDeposit: ", initialDeposit);
console.log("firstPortion: ", firstPortion);
console.log("secondPortion: ", secondPortion);
console.log("P_Snapshot: ", P_Snapshot);
console.log("DECIMAL_PRECISION: ", DECIMAL_PRECISION);


return assetGain;
}

Expand Down
7 changes: 7 additions & 0 deletions contracts/VesselManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.

import "./Dependencies/TrinityBase.sol";
import "./Interfaces/IVesselManager.sol";
import "../lib/forge-std/src/console.sol";

contract VesselManager is IVesselManager, UUPSUpgradeable, ReentrancyGuardUpgradeable, TrinityBase {
// Constants ------------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -350,6 +351,12 @@ contract VesselManager is IVesselManager, UUPSUpgradeable, ReentrancyGuardUpgrad
uint256 _debtToOffset,
uint256 _collToSendToStabilityPool
) external override nonReentrant onlyVesselManagerOperations {
console.log("asset", _asset);
console.log("debt", _debt);
console.log("coll", _coll);
console.log("debtToOffset", _debtToOffset);
console.log("collToSendToStabilityPool", _collToSendToStabilityPool);

IStabilityPool(stabilityPool).offset(_debtToOffset, _asset, _collToSendToStabilityPool);

if (_debt == 0) {
Expand Down
15 changes: 14 additions & 1 deletion contracts/VesselManagerOperations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.

import "./Dependencies/TrinityBase.sol";
import "./Interfaces/IVesselManagerOperations.sol";
import "../lib/forge-std/src/console.sol";

contract VesselManagerOperations is IVesselManagerOperations, UUPSUpgradeable, ReentrancyGuardUpgradeable, TrinityBase {
string public constant NAME = "VesselManagerOperations";
Expand Down Expand Up @@ -123,8 +124,10 @@ contract VesselManagerOperations is IVesselManagerOperations, UUPSUpgradeable, R

// Perform the appropriate liquidation sequence - tally values and obtain their totals.
if (vars.recoveryModeAtStart) {
console.log("Recovery mode at start");
totals = _getTotalFromBatchLiquidate_RecoveryMode(_asset, vars.price, vars.debtTokenInStabPool, _vesselArray);
} else {
console.log("Normal mode at start");
totals = _getTotalsFromBatchLiquidate_NormalMode(_asset, vars.price, vars.debtTokenInStabPool, _vesselArray);
}

Expand Down Expand Up @@ -485,11 +488,12 @@ contract VesselManagerOperations is IVesselManagerOperations, UUPSUpgradeable, R
LiquidationValues memory singleLiquidation;

vars.remainingDebtTokenInStabPool = _debtTokenInStabPool;
console.log("Remaining debt token in stab pool: ", vars.remainingDebtTokenInStabPool);

for (uint i = 0; i < _vesselArray.length; ) {
vars.user = _vesselArray[i];
vars.ICR = IVesselManager(vesselManager).getCurrentICR(_asset, vars.user, _price);

if (vars.ICR < IAdminContract(adminContract).getMcr(_asset)) {
singleLiquidation = _liquidateNormalMode(_asset, vars.user, vars.remainingDebtTokenInStabPool);
vars.remainingDebtTokenInStabPool = vars.remainingDebtTokenInStabPool - singleLiquidation.debtToOffset;
Expand Down Expand Up @@ -563,6 +567,10 @@ contract VesselManagerOperations is IVesselManagerOperations, UUPSUpgradeable, R
vars.pendingDebtReward,
vars.pendingCollReward
) = IVesselManager(vesselManager).getEntireDebtAndColl(_asset, _borrower);
console.log("Entire vessel debt: ", singleLiquidation.entireVesselDebt);
console.log("Entire vessel coll: ", singleLiquidation.entireVesselColl);
console.log("Pending debt reward: ", vars.pendingDebtReward);
console.log("Pending coll reward: ", vars.pendingCollReward);

IVesselManager(vesselManager).movePendingVesselRewardsToActivePool(
_asset,
Expand All @@ -572,13 +580,18 @@ contract VesselManagerOperations is IVesselManagerOperations, UUPSUpgradeable, R
IVesselManager(vesselManager).removeStake(_asset, _borrower);

uint256 collToLiquidate = singleLiquidation.entireVesselColl;
console.log("Collateral to liquidate: ", collToLiquidate);

(
singleLiquidation.debtToOffset,
singleLiquidation.collToSendToSP,
singleLiquidation.debtToRedistribute,
singleLiquidation.collToRedistribute
) = _getOffsetAndRedistributionVals(singleLiquidation.entireVesselDebt, collToLiquidate, _debtTokenInStabPool);
console.log("Debt to offset: ", singleLiquidation.debtToOffset);
console.log("Coll to send to SP: ", singleLiquidation.collToSendToSP);
console.log("Debt to redistribute: ", singleLiquidation.debtToRedistribute);
console.log("Coll to redistribute: ", singleLiquidation.collToRedistribute);

IVesselManager(vesselManager).closeVesselLiquidation(_asset, _borrower);
emit VesselLiquidated(
Expand Down
42 changes: 33 additions & 9 deletions test/trinity/StabilityPoolTest.js
Original file line number Diff line number Diff line change
Expand Up @@ -1085,10 +1085,9 @@ contract("StabilityPool", async accounts => {
assert.isAtMost(th.getDifference(stability_col_DifferenceERC20, aliceGainERC20), 10000)
})

it("withdrawFromSP(): withdraw from SP forfeiting gains", async () => {
it.only("withdrawFromSP(): withdraw from SP forfeiting gains", async () => {
await openWhaleVessel(erc20, (icr = 10), (extraDebtTokenAmt = 1_000_000))
await stabilityPool.provideToSP(dec(199_000, 18), validCollateral, { from: whale })

// 2 defaulter opens
await openVessel({
asset: erc20.address,
Expand All @@ -1113,38 +1112,63 @@ contract("StabilityPool", async accounts => {

// price drops: defaulter's Vessel falls below MCR, alice and whale Vessel remain active
await priceFeed.setPrice(erc20.address, dec("100", 18))


console.log("____ FIRST LIQUIDATE ____")
// defaulter's Vessel is closed.
const liquidationTx_1ERC20 = await vesselManagerOperations.liquidate(erc20.address, defaulter_1, {
from: owner,
}) // 180 TRI closed
const [, liquidatedCollERC20] = th.getEmittedLiquidationValues(liquidationTx_1ERC20)
console.log("____ AFTER FIRST LIQUIDATE ____")



const idx = validCollateral.indexOf(erc20.address)

const [, liquidatedCollERC20] = th.getEmittedLiquidationValues(liquidationTx_1ERC20)

// Get ActivePool and StabilityPool collateral before retrieval:
const active_col_BeforeERC20 = await activePool.getAssetBalance(erc20.address)
const stability_col_BeforeERC20 = await stabilityPool.getCollateral(erc20.address)

// Expect alice to be entitled to 1000/200000 of the liquidated coll

const aliceExpectedGainERC20 = liquidatedCollERC20.mul(toBN(dec(1000, 18))).div(toBN(dec(200_000, 18)))
const idx = validCollateral.indexOf(erc20.address)
const aliceGainERC20 = (await stabilityPool.getDepositorGains(alice, validCollateral))[1][idx]
assert.isTrue(aliceExpectedGainERC20.eq(aliceGainERC20))


console.log("____ ALICE WITHDRAWS ____")
// Alice withdraws from SP, chooses not to receive gains to avoid transfer/swap costs
await stabilityPool.withdrawFromSP(dec(1000, 18), [], { from: alice })
console.log("____ AFTER ALICE WITHDRAWS ____")


const active_col_AfterERC20 = await activePool.getAssetBalance(erc20.address)
const stability_col_AfterERC20 = await stabilityPool.getCollateral(erc20.address)

assert.isTrue(active_col_AfterERC20.eq(active_col_BeforeERC20))
assert.isTrue(stability_col_AfterERC20.eq(stability_col_BeforeERC20))

console.log("____ SECOND LIQUIDATE ____")
const liquidationTx_2ERC20 = await vesselManagerOperations.liquidate(erc20.address, defaulter_2, {
from: owner,
}) // 180 TRI closed
console.log("____ AFTER SECOND LIQUIDATE ____")


console.log("____ BEFORE WHALE WITHDRAW ____")
await stabilityPool.withdrawFromSP(dec(199_000, 18), validCollateral, { from: whale })
console.log("____ AFTER WHALE WITHDRAW ____")

console.log("stability pool balance after whale withdraw", (await stabilityPool.getTotalDebtTokenDeposits()).toString())

const stability_col_AfterWhaleERC20 = await stabilityPool.getCollateral(erc20.address)
assert.isAtMost(stability_col_AfterWhaleERC20.sub(aliceExpectedGainERC20), 10000)

console.log((await stabilityPool.getCollateral(erc20.address)).toString())

const lastAssetError_Offset= (await stabilityPool.lastAssetError_Offset(idx)).div(toBN(10).pow(toBN(18)))
console.log((await stabilityPool.lastAssetError_Offset(idx)).div(toBN(10).pow(toBN(18))).toString())

assert.equal(stability_col_AfterWhaleERC20.sub(aliceExpectedGainERC20), lastAssetError_Offset)
})

it("withdrawFromSP(): withdraw from SP, passing same asset twice will revert", async () => {
Expand Down

0 comments on commit dc134d7

Please sign in to comment.