log the eth and lqty gains from stability pool operations. general tidy up

This commit is contained in:
Edward Mulraney 2021-06-09 21:02:06 +01:00
parent 7588733d98
commit 4ea58ba50d
6 changed files with 163 additions and 82 deletions

View File

@ -34,6 +34,8 @@ contract Events {
event LogStabilityDeposit( event LogStabilityDeposit(
address indexed borrower, address indexed borrower,
uint amount, uint amount,
uint ethGain,
uint lqtyGain,
address frontendTag, address frontendTag,
uint getDepositId, uint getDepositId,
uint setEthGainId, uint setEthGainId,
@ -41,6 +43,8 @@ contract Events {
); );
event LogStabilityWithdraw(address indexed borrower, event LogStabilityWithdraw(address indexed borrower,
uint amount, uint amount,
uint ethGain,
uint lqtyGain,
uint setWithdrawId, uint setWithdrawId,
uint setEthGainId, uint setEthGainId,
uint setLqtyGainId uint setLqtyGainId

View File

@ -66,3 +66,7 @@ interface StakingLike {
interface CollateralSurplusLike { interface CollateralSurplusLike {
function getCollateral(address _account) external view returns (uint); function getCollateral(address _account) external view returns (uint);
} }
interface LqtyTokenLike {
function balanceOf(address account) external view returns (uint256);
}

View File

@ -9,7 +9,8 @@ import {
TroveManagerLike, TroveManagerLike,
StabilityPoolLike, StabilityPoolLike,
StakingLike, StakingLike,
CollateralSurplusLike CollateralSurplusLike,
LqtyTokenLike
} from "./interface.sol"; } from "./interface.sol";
import { Stores } from "../../common/stores.sol"; import { Stores } from "../../common/stores.sol";
import { Helpers } from "./helpers.sol"; import { Helpers } from "./helpers.sol";
@ -26,6 +27,8 @@ abstract contract LiquityResolver is Events, Helpers {
StakingLike(0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d); StakingLike(0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d);
CollateralSurplusLike internal constant collateralSurplus = CollateralSurplusLike internal constant collateralSurplus =
CollateralSurplusLike(0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521); CollateralSurplusLike(0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521);
LqtyTokenLike internal constant lqtyToken =
LqtyTokenLike(0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D);
// Prevents stack-too-deep error // Prevents stack-too-deep error
struct AdjustTrove { struct AdjustTrove {
@ -45,8 +48,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @param depositAmount The amount of ETH to deposit * @param depositAmount The amount of ETH to deposit
* @param maxFeePercentage The maximum borrow fee that this transaction should permit * @param maxFeePercentage The maximum borrow fee that this transaction should permit
* @param borrowAmount The amount of LUSD to borrow * @param borrowAmount The amount of LUSD to borrow
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param getId Optional storage slot to retrieve ETH from * @param getId Optional storage slot to retrieve ETH from
* @param setId Optional storage slot to store the LUSD borrowed against * @param setId Optional storage slot to store the LUSD borrowed against
*/ */
@ -97,8 +100,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @dev Deposit ETH to Trove * @dev Deposit ETH to Trove
* @notice Increase Trove collateral (collateral Top up) * @notice Increase Trove collateral (collateral Top up)
* @param amount Amount of ETH to deposit into Trove * @param amount Amount of ETH to deposit into Trove
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param getId Optional storage slot to retrieve the ETH from * @param getId Optional storage slot to retrieve the ETH from
*/ */
function deposit( function deposit(
@ -120,8 +123,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @dev Withdraw ETH from Trove * @dev Withdraw ETH from Trove
* @notice Move Trove collateral from Trove to DSA * @notice Move Trove collateral from Trove to DSA
* @param amount Amount of ETH to move from Trove to DSA * @param amount Amount of ETH to move from Trove to DSA
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param setId Optional storage slot to store the withdrawn ETH in * @param setId Optional storage slot to store the withdrawn ETH in
*/ */
function withdraw( function withdraw(
@ -142,8 +145,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @notice Borrow LUSD via an existing Trove * @notice Borrow LUSD via an existing Trove
* @param maxFeePercentage The maximum borrow fee that this transaction should permit * @param maxFeePercentage The maximum borrow fee that this transaction should permit
* @param amount Amount of LUSD to borrow * @param amount Amount of LUSD to borrow
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param setId Optional storage slot to store the borrowed LUSD in * @param setId Optional storage slot to store the borrowed LUSD in
*/ */
function borrow( function borrow(
@ -155,7 +158,7 @@ abstract contract LiquityResolver is Events, Helpers {
) external payable returns (string memory _eventName, bytes memory _eventParam) { ) external payable returns (string memory _eventName, bytes memory _eventParam) {
borrowerOperations.withdrawLUSD(maxFeePercentage, amount, upperHint, lowerHint); borrowerOperations.withdrawLUSD(maxFeePercentage, amount, upperHint, lowerHint);
setUint(setId, amount); // TODO: apply fee / get exact amount borrowed (with the fee applied) setUint(setId, amount);
_eventName = "LogBorrow(address,uint256,uint256)"; _eventName = "LogBorrow(address,uint256,uint256)";
_eventParam = abi.encode(msg.sender, amount, setId); _eventParam = abi.encode(msg.sender, amount, setId);
} }
@ -164,8 +167,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @dev Send LUSD to repay debt * @dev Send LUSD to repay debt
* @notice Repay LUSD Trove debt * @notice Repay LUSD Trove debt
* @param amount Amount of LUSD to repay * @param amount Amount of LUSD to repay
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param getId Optional storage slot to retrieve the LUSD from * @param getId Optional storage slot to retrieve the LUSD from
*/ */
function repay( function repay(
@ -191,8 +194,8 @@ abstract contract LiquityResolver is Events, Helpers {
* @param depositAmount Amount of ETH to deposit * @param depositAmount Amount of ETH to deposit
* @param borrowAmount Amount of LUSD to borrow * @param borrowAmount Amount of LUSD to borrow
* @param repayAmount Amount of LUSD to repay * @param repayAmount Amount of LUSD to repay
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
* @param getDepositId Optional storage slot to retrieve the ETH to deposit * @param getDepositId Optional storage slot to retrieve the ETH to deposit
* @param setWithdrawId Optional storage slot to store the withdrawn ETH to * @param setWithdrawId Optional storage slot to store the withdrawn ETH to
* @param getRepayId Optional storage slot to retrieve the LUSD to repay * @param getRepayId Optional storage slot to retrieve the LUSD to repay
@ -269,7 +272,7 @@ abstract contract LiquityResolver is Events, Helpers {
* @param frontendTag Address of the frontend to make this deposit against (determines the kickback rate of rewards) * @param frontendTag Address of the frontend to make this deposit against (determines the kickback rate of rewards)
* @param getDepositId Optional storage slot to retrieve the LUSD from * @param getDepositId Optional storage slot to retrieve the LUSD from
* @param setEthGainId Optional storage slot to store any ETH gains in * @param setEthGainId Optional storage slot to store any ETH gains in
* @param setLqtyGainId Optional storage slot to store any ETH gains in * @param setLqtyGainId Optional storage slot to store any LQTY gains in
*/ */
function stabilityDeposit( function stabilityDeposit(
uint amount, uint amount,
@ -281,14 +284,18 @@ abstract contract LiquityResolver is Events, Helpers {
amount = getUint(getDepositId, amount); amount = getUint(getDepositId, amount);
uint ethGain = stabilityPool.getDepositorETHGain(address(this)); uint ethGain = stabilityPool.getDepositorETHGain(address(this));
uint lqtyGain = stabilityPool.getDepositorLQTYGain(address(this)); uint lqtyBalanceBefore = lqtyToken.balanceOf(address(this));
stabilityPool.provideToSP(amount, frontendTag); stabilityPool.provideToSP(amount, frontendTag);
uint lqtyBalanceAfter = lqtyToken.balanceOf(address(this));
uint lqtyGain = sub(lqtyBalanceAfter, lqtyBalanceBefore);
setUint(setEthGainId, ethGain); setUint(setEthGainId, ethGain);
setUint(setLqtyGainId, lqtyGain); setUint(setLqtyGainId, lqtyGain);
_eventName = "LogStabilityDeposit(address,uint256,address,uint256,uint256,uint256)"; _eventName = "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256)";
_eventParam = abi.encode(msg.sender, amount, frontendTag, getDepositId, setEthGainId, setLqtyGainId); _eventParam = abi.encode(msg.sender, amount, ethGain, lqtyGain, frontendTag, getDepositId, setEthGainId, setLqtyGainId);
} }
/** /**
@ -297,7 +304,7 @@ abstract contract LiquityResolver is Events, Helpers {
* @param amount Amount of LUSD to withdraw from Stability Pool * @param amount Amount of LUSD to withdraw from Stability Pool
* @param setWithdrawId Optional storage slot to store the withdrawn LUSD * @param setWithdrawId Optional storage slot to store the withdrawn LUSD
* @param setEthGainId Optional storage slot to store any ETH gains in * @param setEthGainId Optional storage slot to store any ETH gains in
* @param setLqtyGainId Optional storage slot to store any ETH gains in * @param setLqtyGainId Optional storage slot to store any LQTY gains in
*/ */
function stabilityWithdraw( function stabilityWithdraw(
uint amount, uint amount,
@ -305,23 +312,27 @@ abstract contract LiquityResolver is Events, Helpers {
uint setEthGainId, uint setEthGainId,
uint setLqtyGainId uint setLqtyGainId
) external returns (string memory _eventName, bytes memory _eventParam) { ) external returns (string memory _eventName, bytes memory _eventParam) {
stabilityPool.withdrawFromSP(amount);
uint ethGain = stabilityPool.getDepositorETHGain(address(this)); uint ethGain = stabilityPool.getDepositorETHGain(address(this));
uint lqtyGain = stabilityPool.getDepositorLQTYGain(address(this)); uint lqtyBalanceBefore = lqtyToken.balanceOf(address(this));
stabilityPool.withdrawFromSP(amount);
uint lqtyBalanceAfter = lqtyToken.balanceOf(address(this));
uint lqtyGain = sub(lqtyBalanceAfter, lqtyBalanceBefore);
setUint(setWithdrawId, amount); setUint(setWithdrawId, amount);
setUint(setEthGainId, ethGain); setUint(setEthGainId, ethGain);
setUint(setLqtyGainId, lqtyGain); setUint(setLqtyGainId, lqtyGain);
_eventName = "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256)"; _eventName = "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256,uint256)";
_eventParam = abi.encode(msg.sender, amount, setWithdrawId, setEthGainId, setLqtyGainId); _eventParam = abi.encode(msg.sender, amount, ethGain, lqtyGain, setWithdrawId, setEthGainId, setLqtyGainId);
} }
/** /**
* @dev Increase Trove collateral by sending Stability Pool ETH gain to user's Trove * @dev Increase Trove collateral by sending Stability Pool ETH gain to user's Trove
* @notice Moves user's ETH gain from the Stability Pool into their Trove * @notice Moves user's ETH gain from the Stability Pool into their Trove
* @param upperHint Address of the Trove near the upper bound of where the user's Trove will now sit in the ordered Trove list * @param upperHint Address of the Trove near the upper bound of where the user's Trove should now sit in the ordered Trove list
* @param lowerHint Address of the Trove near the lower bound of where the user's Trove will now sit in the ordered Trove list * @param lowerHint Address of the Trove near the lower bound of where the user's Trove should now sit in the ordered Trove list
*/ */
function stabilityMoveEthGainToTrove( function stabilityMoveEthGainToTrove(
address upperHint, address upperHint,

View File

@ -46,6 +46,7 @@ const STABILITY_POOL_ADDRESS = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb";
const STABILITY_POOL_ABI = [ const STABILITY_POOL_ABI = [
"function getCompoundedLUSDDeposit(address _depositor) external view returns (uint)", "function getCompoundedLUSDDeposit(address _depositor) external view returns (uint)",
"function getDepositorETHGain(address _depositor) external view returns (uint)", "function getDepositorETHGain(address _depositor) external view returns (uint)",
"function getDepositorLQTYGain(address _depositor) external view returns (uint)",
]; ];
const STAKING_ADDRESS = "0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d"; const STAKING_ADDRESS = "0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d";

View File

@ -121,7 +121,6 @@ const resetHardhatBlockNumber = async (blockNumber) => {
const deployAndConnect = async (contracts, isDebug = false) => { const deployAndConnect = async (contracts, isDebug = false) => {
// Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.) // Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.)
await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER); await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER);
const liquity = { const liquity = {
troveManager: null, troveManager: null,
borrowerOperations: null, borrowerOperations: null,
@ -163,93 +162,65 @@ const deployAndConnect = async (contracts, isDebug = false) => {
contracts.TROVE_MANAGER_ABI, contracts.TROVE_MANAGER_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("TroveManager contract address", liquity.troveManager.address);
liquity.borrowerOperations = new ethers.Contract( liquity.borrowerOperations = new ethers.Contract(
contracts.BORROWER_OPERATIONS_ADDRESS, contracts.BORROWER_OPERATIONS_ADDRESS,
contracts.BORROWER_OPERATIONS_ABI, contracts.BORROWER_OPERATIONS_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log(
"BorrowerOperations contract address",
liquity.borrowerOperations.address
);
liquity.stabilityPool = new ethers.Contract( liquity.stabilityPool = new ethers.Contract(
contracts.STABILITY_POOL_ADDRESS, contracts.STABILITY_POOL_ADDRESS,
contracts.STABILITY_POOL_ABI, contracts.STABILITY_POOL_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log(
"StabilityPool contract address",
liquity.stabilityPool.address
);
liquity.lusdToken = new ethers.Contract( liquity.lusdToken = new ethers.Contract(
contracts.LUSD_TOKEN_ADDRESS, contracts.LUSD_TOKEN_ADDRESS,
contracts.LUSD_TOKEN_ABI, contracts.LUSD_TOKEN_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("LusdToken contract address", liquity.lusdToken.address);
liquity.lqtyToken = new ethers.Contract( liquity.lqtyToken = new ethers.Contract(
contracts.LQTY_TOKEN_ADDRESS, contracts.LQTY_TOKEN_ADDRESS,
contracts.LQTY_TOKEN_ABI, contracts.LQTY_TOKEN_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("LqtyToken contract address", liquity.lqtyToken.address);
liquity.activePool = new ethers.Contract( liquity.activePool = new ethers.Contract(
contracts.ACTIVE_POOL_ADDRESS, contracts.ACTIVE_POOL_ADDRESS,
contracts.ACTIVE_POOL_ABI, contracts.ACTIVE_POOL_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("ActivePool contract address", liquity.activePool.address);
liquity.priceFeed = new ethers.Contract( liquity.priceFeed = new ethers.Contract(
contracts.PRICE_FEED_ADDRESS, contracts.PRICE_FEED_ADDRESS,
contracts.PRICE_FEED_ABI, contracts.PRICE_FEED_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("PriceFeed contract address", liquity.priceFeed.address);
liquity.hintHelpers = new ethers.Contract( liquity.hintHelpers = new ethers.Contract(
contracts.HINT_HELPERS_ADDRESS, contracts.HINT_HELPERS_ADDRESS,
contracts.HINT_HELPERS_ABI, contracts.HINT_HELPERS_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("HintHelpers contract address", liquity.hintHelpers.address);
liquity.sortedTroves = new ethers.Contract( liquity.sortedTroves = new ethers.Contract(
contracts.SORTED_TROVES_ADDRESS, contracts.SORTED_TROVES_ADDRESS,
contracts.SORTED_TROVES_ABI, contracts.SORTED_TROVES_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("SortedTroves contract address", liquity.sortedTroves.address);
liquity.staking = new ethers.Contract( liquity.staking = new ethers.Contract(
contracts.STAKING_ADDRESS, contracts.STAKING_ADDRESS,
contracts.STAKING_ABI, contracts.STAKING_ABI,
ethers.provider ethers.provider
); );
isDebug && console.log("Staking contract address", liquity.staking.address);
liquity.collSurplus = new ethers.Contract( liquity.collSurplus = new ethers.Contract(
contracts.COLL_SURPLUS_ADDRESS, contracts.COLL_SURPLUS_ADDRESS,
contracts.COLL_SURPLUS_ABI, contracts.COLL_SURPLUS_ABI,
ethers.provider ethers.provider
); );
isDebug &&
console.log("CollSurplus contract address", liquity.collSurplus.address);
return liquity; return liquity;
}; };

View File

@ -11,7 +11,7 @@ const contracts = require("./liquity.contracts");
// Liquity helpers // Liquity helpers
const helpers = require("./liquity.helpers"); const helpers = require("./liquity.helpers");
describe.only("Liquity", () => { describe("Liquity", () => {
const { waffle, ethers } = hre; const { waffle, ethers } = hre;
const { provider } = waffle; const { provider } = waffle;
@ -1732,6 +1732,7 @@ describe.only("Liquity", () => {
it("returns Instadapp event name and data", async () => { it("returns Instadapp event name and data", async () => {
const amount = ethers.utils.parseUnits("100", 18); const amount = ethers.utils.parseUnits("100", 18);
const halfAmount = amount.div(2);
const frontendTag = ethers.constants.AddressZero; const frontendTag = ethers.constants.AddressZero;
const getDepositId = 0; const getDepositId = 0;
const setEthGainId = 0; const setEthGainId = 0;
@ -1747,21 +1748,67 @@ describe.only("Liquity", () => {
const stabilityDepositSpell = { const stabilityDepositSpell = {
connector: helpers.LIQUITY_CONNECTOR, connector: helpers.LIQUITY_CONNECTOR,
method: "stabilityDeposit", method: "stabilityDeposit",
args: [amount, frontendTag, getDepositId, 0, 0], args: [halfAmount, frontendTag, getDepositId, 0, 0],
}; };
const depositTx = await dsa // Create a Stability deposit for this DSA
await dsa
.connect(userWallet) .connect(userWallet)
.cast(...encodeSpells([stabilityDepositSpell]), userWallet.address); .cast(...encodeSpells([stabilityDepositSpell]), userWallet.address);
const receipt = await depositTx.wait(); // Liquidate a Trove to cause an ETH gain
await liquity.troveManager.connect(userWallet).liquidateTroves(1, {
gasLimit: helpers.MAX_GAS,
});
// Fast forward in time so we have an LQTY gain
await provider.send("evm_increaseTime", [600]);
await provider.send("evm_mine");
// Create a Stability Pool deposit with a differen DSA so that LQTY gains can be calculated
// See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts
const tempDsa = await buildDSAv2(userWallet.address);
await helpers.sendToken(
liquity.lusdToken,
amount,
contracts.STABILITY_POOL_ADDRESS,
tempDsa.address
);
await tempDsa
.connect(userWallet)
.cast(...encodeSpells([stabilityDepositSpell]), userWallet.address);
const ethGain = await liquity.stabilityPool.getDepositorETHGain(
dsa.address
);
const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain(
dsa.address
);
// Top up the user's deposit so that we can track their ETH and LQTY gain
const depositAgainTx = await dsa
.connect(userWallet)
.cast(...encodeSpells([stabilityDepositSpell]), userWallet.address);
const receipt = await depositAgainTx.wait();
const castLogEvent = receipt.events.find((e) => e.event === "LogCast") const castLogEvent = receipt.events.find((e) => e.event === "LogCast")
.args; .args;
const expectedEventParams = ethers.utils.defaultAbiCoder.encode( const expectedEventParams = ethers.utils.defaultAbiCoder.encode(
["address", "uint256", "address", "uint256", "uint256", "uint256"], [
"address",
"uint256",
"uint256",
"uint256",
"address",
"uint256",
"uint256",
"uint256",
],
[ [
userWallet.address, userWallet.address,
amount, halfAmount,
ethGain,
lqtyGain,
frontendTag, frontendTag,
getDepositId, getDepositId,
setEthGainId, setEthGainId,
@ -1769,7 +1816,7 @@ describe.only("Liquity", () => {
] ]
); );
expect(castLogEvent.eventNames[0]).eq( expect(castLogEvent.eventNames[0]).eq(
"LogStabilityDeposit(address,uint256,address,uint256,uint256,uint256)" "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256)"
); );
expect(castLogEvent.eventParams[0]).eq(expectedEventParams); expect(castLogEvent.eventParams[0]).eq(expectedEventParams);
}); });
@ -1777,7 +1824,7 @@ describe.only("Liquity", () => {
describe("stabilityWithdraw()", () => { describe("stabilityWithdraw()", () => {
it("withdraws from Stability Pool", async () => { it("withdraws from Stability Pool", async () => {
// Start this test from scratch since we don't want to rely on test order for this to pass. // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool
[liquity, dsa] = await helpers.resetInitialState( [liquity, dsa] = await helpers.resetInitialState(
userWallet.address, userWallet.address,
contracts contracts
@ -1788,6 +1835,7 @@ describe.only("Liquity", () => {
await liquity.troveManager.connect(userWallet).liquidateTroves(90, { await liquity.troveManager.connect(userWallet).liquidateTroves(90, {
gasLimit: helpers.MAX_GAS, gasLimit: helpers.MAX_GAS,
}); });
const amount = ethers.utils.parseUnits("100", 18); const amount = ethers.utils.parseUnits("100", 18);
const frontendTag = ethers.constants.AddressZero; const frontendTag = ethers.constants.AddressZero;
@ -1805,12 +1853,12 @@ describe.only("Liquity", () => {
}; };
// Withdraw half of the deposit // Withdraw half of the deposit
const stabilitWithdrawSpell = { const stabilityWithdrawSpell = {
connector: helpers.LIQUITY_CONNECTOR, connector: helpers.LIQUITY_CONNECTOR,
method: "stabilityWithdraw", method: "stabilityWithdraw",
args: [amount.div(2), 0, 0, 0], args: [amount.div(2), 0, 0, 0],
}; };
const spells = [stabilityDepositSpell, stabilitWithdrawSpell]; const spells = [stabilityDepositSpell, stabilityWithdrawSpell];
await dsa await dsa
.connect(userWallet) .connect(userWallet)
@ -1826,7 +1874,7 @@ describe.only("Liquity", () => {
}); });
it("withdraws from Stability Pool and stores the LUSD for other spells", async () => { it("withdraws from Stability Pool and stores the LUSD for other spells", async () => {
// Start this test from scratch since we don't want to rely on test order for this to pass. // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool
[liquity, dsa] = await helpers.resetInitialState( [liquity, dsa] = await helpers.resetInitialState(
userWallet.address, userWallet.address,
contracts contracts
@ -1855,7 +1903,7 @@ describe.only("Liquity", () => {
}; };
// Withdraw half of the deposit // Withdraw half of the deposit
const stabilitWithdrawSpell = { const stabilityWithdrawSpell = {
connector: helpers.LIQUITY_CONNECTOR, connector: helpers.LIQUITY_CONNECTOR,
method: "stabilityWithdraw", method: "stabilityWithdraw",
args: [amount.div(2), 0, 0, withdrawId], args: [amount.div(2), 0, 0, withdrawId],
@ -1875,7 +1923,7 @@ describe.only("Liquity", () => {
const spells = [ const spells = [
stabilityDepositSpell, stabilityDepositSpell,
stabilitWithdrawSpell, stabilityWithdrawSpell,
withdrawLusdSpell, withdrawLusdSpell,
]; ];
@ -1895,17 +1943,12 @@ describe.only("Liquity", () => {
}); });
it("returns Instadapp event name and data", async () => { it("returns Instadapp event name and data", async () => {
// Start this test from scratch since we don't want to rely on test order for this to pass. // Start this test from scratch since we need to remove any liquidatable Troves withdrawing from Stability Pool
[liquity, dsa] = await helpers.resetInitialState( [liquity, dsa] = await helpers.resetInitialState(
userWallet.address, userWallet.address,
contracts contracts
); );
// The current block number has liquidatable Troves.
// Remove them otherwise Stability Pool withdrawals are disabled
await liquity.troveManager.connect(userWallet).liquidateTroves(90, {
gasLimit: helpers.MAX_GAS,
});
const amount = ethers.utils.parseUnits("100", 18); const amount = ethers.utils.parseUnits("100", 18);
const frontendTag = ethers.constants.AddressZero; const frontendTag = ethers.constants.AddressZero;
@ -1928,34 +1971,81 @@ describe.only("Liquity", () => {
const setEthGainId = 0; const setEthGainId = 0;
const setLqtyGainId = 0; const setLqtyGainId = 0;
const stabilitWithdrawSpell = { // Create a Stability Pool deposit
await dsa
.connect(userWallet)
.cast(...encodeSpells([stabilityDepositSpell]), userWallet.address);
// The current block number has liquidatable Troves.
// Remove them otherwise Stability Pool withdrawals are disabled
await liquity.troveManager.connect(userWallet).liquidateTroves(90, {
gasLimit: helpers.MAX_GAS,
});
// Fast forward in time so we have an LQTY gain
await provider.send("evm_increaseTime", [600]);
await provider.send("evm_mine");
// Create another Stability Pool deposit so that LQTY gains are realized
// See: https://github.com/liquity/dev/#lqty-reward-events-and-payouts
const tempDsa = await buildDSAv2(userWallet.address);
await helpers.sendToken(
liquity.lusdToken,
amount,
contracts.STABILITY_POOL_ADDRESS,
tempDsa.address
);
await tempDsa
.connect(userWallet)
.cast(...encodeSpells([stabilityDepositSpell]), userWallet.address);
const ethGain = await liquity.stabilityPool.getDepositorETHGain(
dsa.address
);
const lqtyGain = await liquity.stabilityPool.getDepositorLQTYGain(
dsa.address
);
const stabilityWithdrawSpell = {
connector: helpers.LIQUITY_CONNECTOR, connector: helpers.LIQUITY_CONNECTOR,
method: "stabilityWithdraw", method: "stabilityWithdraw",
args: [withdrawAmount, setWithdrawId, setEthGainId, setLqtyGainId], args: [withdrawAmount, setWithdrawId, setEthGainId, setLqtyGainId],
}; };
const spells = [stabilityDepositSpell, stabilitWithdrawSpell];
const castTx = await dsa const withdrawTx = await dsa
.connect(userWallet) .connect(userWallet)
.cast(...encodeSpells(spells), userWallet.address); .cast(
...encodeSpells([stabilityWithdrawSpell]),
userWallet.address
);
const receipt = await castTx.wait(); const receipt = await withdrawTx.wait();
const castLogEvent = receipt.events.find((e) => e.event === "LogCast") const castLogEvent = receipt.events.find((e) => e.event === "LogCast")
.args; .args;
const expectedEventParams = ethers.utils.defaultAbiCoder.encode( const expectedEventParams = ethers.utils.defaultAbiCoder.encode(
["address", "uint256", "uint256", "uint256", "uint256"], [
"address",
"uint256",
"uint256",
"uint256",
"uint256",
"uint256",
"uint256",
],
[ [
userWallet.address, userWallet.address,
withdrawAmount, withdrawAmount,
ethGain,
lqtyGain,
setWithdrawId, setWithdrawId,
setEthGainId, setEthGainId,
setLqtyGainId, setLqtyGainId,
] ]
); );
expect(castLogEvent.eventNames[1]).eq( expect(castLogEvent.eventNames[0]).eq(
"LogStabilityWithdraw(address,uint256,uint256,uint256,uint256)" "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256,uint256)"
); );
expect(castLogEvent.eventParams[1]).eq(expectedEventParams); expect(castLogEvent.eventParams[0]).eq(expectedEventParams);
}); });
}); });