mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Merge pull request #1 from edmulraney/liquity-connector
Instadapp integration: add Liquity connector
This commit is contained in:
commit
03a1f64398
58
contracts/mainnet/connectors/liquity/events.sol
Normal file
58
contracts/mainnet/connectors/liquity/events.sol
Normal file
|
@ -0,0 +1,58 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
contract Events {
|
||||
|
||||
/* Trove */
|
||||
event LogOpen(
|
||||
address indexed borrower,
|
||||
uint maxFeePercentage,
|
||||
uint depositAmount,
|
||||
uint borrowAmount,
|
||||
uint getId,
|
||||
uint setId
|
||||
);
|
||||
event LogClose(address indexed borrower, uint setId);
|
||||
event LogDeposit(address indexed borrower, uint amount, uint getId);
|
||||
event LogWithdraw(address indexed borrower, uint amount, uint setId);
|
||||
event LogBorrow(address indexed borrower, uint amount, uint setId);
|
||||
event LogRepay(address indexed borrower, uint amount, uint getId);
|
||||
event LogAdjust(
|
||||
address indexed borrower,
|
||||
uint maxFeePercentage,
|
||||
uint depositAmount,
|
||||
uint withdrawAmount,
|
||||
uint borrowAmount,
|
||||
uint repayAmount,
|
||||
uint getDepositId,
|
||||
uint setWithdrawId,
|
||||
uint getRepayId,
|
||||
uint setBorrowId
|
||||
);
|
||||
event LogClaimCollateralFromRedemption(address indexed borrower, uint amount, uint setId);
|
||||
|
||||
/* Stability Pool */
|
||||
event LogStabilityDeposit(
|
||||
address indexed borrower,
|
||||
uint amount,
|
||||
uint ethGain,
|
||||
uint lqtyGain,
|
||||
address frontendTag,
|
||||
uint getDepositId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
);
|
||||
event LogStabilityWithdraw(address indexed borrower,
|
||||
uint amount,
|
||||
uint ethGain,
|
||||
uint lqtyGain,
|
||||
uint setWithdrawId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
);
|
||||
event LogStabilityMoveEthGainToTrove(address indexed borrower, uint amount);
|
||||
|
||||
/* Staking */
|
||||
event LogStake(address indexed borrower, uint amount, uint getStakeId, uint setEthGainId, uint setLusdGainId);
|
||||
event LogUnstake(address indexed borrower, uint amount, uint setUnstakeId, uint setEthGainId, uint setLusdGainId);
|
||||
event LogClaimStakingGains(address indexed borrower, uint ethGain, uint lusdGain, uint setEthGainId, uint setLusdGainId);
|
||||
}
|
6
contracts/mainnet/connectors/liquity/helpers.sol
Normal file
6
contracts/mainnet/connectors/liquity/helpers.sol
Normal file
|
@ -0,0 +1,6 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {}
|
72
contracts/mainnet/connectors/liquity/interface.sol
Normal file
72
contracts/mainnet/connectors/liquity/interface.sol
Normal file
|
@ -0,0 +1,72 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
interface BorrowerOperationsLike {
|
||||
function openTrove(
|
||||
uint256 _maxFee,
|
||||
uint256 _LUSDAmount,
|
||||
address _upperHint,
|
||||
address _lowerHint
|
||||
) external payable;
|
||||
|
||||
function addColl(address _upperHint, address _lowerHint) external payable;
|
||||
|
||||
function withdrawColl(
|
||||
uint256 _amount,
|
||||
address _upperHint,
|
||||
address _lowerHint
|
||||
) external;
|
||||
|
||||
function withdrawLUSD(
|
||||
uint256 _maxFee,
|
||||
uint256 _amount,
|
||||
address _upperHint,
|
||||
address _lowerHint
|
||||
) external;
|
||||
|
||||
function repayLUSD(
|
||||
uint256 _amount,
|
||||
address _upperHint,
|
||||
address _lowerHint
|
||||
) external;
|
||||
|
||||
function closeTrove() external;
|
||||
|
||||
function adjustTrove(
|
||||
uint256 _maxFee,
|
||||
uint256 _collWithdrawal,
|
||||
uint256 _debtChange,
|
||||
bool isDebtIncrease,
|
||||
address _upperHint,
|
||||
address _lowerHint
|
||||
) external payable;
|
||||
|
||||
function claimCollateral() external;
|
||||
}
|
||||
|
||||
interface TroveManagerLike {
|
||||
function getTroveColl(address _borrower) external view returns (uint);
|
||||
function getTroveDebt(address _borrower) external view returns (uint);
|
||||
}
|
||||
|
||||
interface StabilityPoolLike {
|
||||
function provideToSP(uint _amount, address _frontEndTag) external;
|
||||
function withdrawFromSP(uint _amount) external;
|
||||
function withdrawETHGainToTrove(address _upperHint, address _lowerHint) external;
|
||||
function getDepositorETHGain(address _depositor) external view returns (uint);
|
||||
function getDepositorLQTYGain(address _depositor) external view returns (uint);
|
||||
}
|
||||
|
||||
interface StakingLike {
|
||||
function stake(uint _LQTYamount) external;
|
||||
function unstake(uint _LQTYamount) external;
|
||||
function getPendingETHGain(address _user) external view returns (uint);
|
||||
function getPendingLUSDGain(address _user) external view returns (uint);
|
||||
}
|
||||
|
||||
interface CollateralSurplusLike {
|
||||
function getCollateral(address _account) external view returns (uint);
|
||||
}
|
||||
|
||||
interface LqtyTokenLike {
|
||||
function balanceOf(address account) external view returns (uint256);
|
||||
}
|
429
contracts/mainnet/connectors/liquity/main.sol
Normal file
429
contracts/mainnet/connectors/liquity/main.sol
Normal file
|
@ -0,0 +1,429 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
/**
|
||||
* @title Liquity.
|
||||
* @dev Lending & Borrowing.
|
||||
*/
|
||||
import {
|
||||
BorrowerOperationsLike,
|
||||
TroveManagerLike,
|
||||
StabilityPoolLike,
|
||||
StakingLike,
|
||||
CollateralSurplusLike,
|
||||
LqtyTokenLike
|
||||
} from "./interface.sol";
|
||||
import { Stores } from "../../common/stores.sol";
|
||||
import { Helpers } from "./helpers.sol";
|
||||
import { Events } from "./events.sol";
|
||||
|
||||
abstract contract LiquityResolver is Events, Helpers {
|
||||
BorrowerOperationsLike internal constant borrowerOperations =
|
||||
BorrowerOperationsLike(0x24179CD81c9e782A4096035f7eC97fB8B783e007);
|
||||
TroveManagerLike internal constant troveManager =
|
||||
TroveManagerLike(0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2);
|
||||
StabilityPoolLike internal constant stabilityPool =
|
||||
StabilityPoolLike(0x66017D22b0f8556afDd19FC67041899Eb65a21bb);
|
||||
StakingLike internal constant staking =
|
||||
StakingLike(0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d);
|
||||
CollateralSurplusLike internal constant collateralSurplus =
|
||||
CollateralSurplusLike(0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521);
|
||||
LqtyTokenLike internal constant lqtyToken =
|
||||
LqtyTokenLike(0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D);
|
||||
|
||||
// Prevents stack-too-deep error
|
||||
struct AdjustTrove {
|
||||
uint maxFeePercentage;
|
||||
uint withdrawAmount;
|
||||
uint depositAmount;
|
||||
uint borrowAmount;
|
||||
uint repayAmount;
|
||||
bool isBorrow;
|
||||
}
|
||||
|
||||
/* Begin: Trove */
|
||||
|
||||
/**
|
||||
* @dev Deposit native ETH and borrow LUSD
|
||||
* @notice Opens a Trove by depositing ETH and borrowing LUSD
|
||||
* @param depositAmount The amount of ETH to deposit
|
||||
* @param maxFeePercentage The maximum borrow fee that this transaction should permit
|
||||
* @param borrowAmount The amount of LUSD to borrow
|
||||
* @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 should now sit in the ordered Trove list
|
||||
* @param getId Optional storage slot to retrieve ETH from
|
||||
* @param setId Optional storage slot to store the LUSD borrowed against
|
||||
*/
|
||||
function open(
|
||||
uint depositAmount,
|
||||
uint maxFeePercentage,
|
||||
uint borrowAmount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
if (getId != 0 && depositAmount != 0) {
|
||||
revert("open(): Cannot supply a depositAmount if a non-zero getId is supplied");
|
||||
}
|
||||
|
||||
depositAmount = getUint(getId, depositAmount);
|
||||
|
||||
borrowerOperations.openTrove{value: depositAmount}(
|
||||
maxFeePercentage,
|
||||
borrowAmount,
|
||||
upperHint,
|
||||
lowerHint
|
||||
);
|
||||
|
||||
// Allow other spells to use the borrowed amount
|
||||
setUint(setId, borrowAmount);
|
||||
_eventName = "LogOpen(address,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, maxFeePercentage, depositAmount, borrowAmount, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Repay LUSD debt from the DSA account's LUSD balance, and withdraw ETH to DSA
|
||||
* @notice Closes a Trove by repaying LUSD debt
|
||||
* @param setId Optional storage slot to store the ETH withdrawn from the Trove
|
||||
*/
|
||||
function close(uint setId) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint collateral = troveManager.getTroveColl(address(this));
|
||||
borrowerOperations.closeTrove();
|
||||
|
||||
// Allow other spells to use the collateral released from the Trove
|
||||
setUint(setId, collateral);
|
||||
_eventName = "LogClose(address,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Deposit ETH to Trove
|
||||
* @notice Increase Trove collateral (collateral Top up)
|
||||
* @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 should 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
|
||||
*/
|
||||
function deposit(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
if (getId != 0 && amount != 0) {
|
||||
revert("deposit(): Cannot supply an amount if a non-zero getId is supplied");
|
||||
}
|
||||
amount = getUint(getId, amount);
|
||||
borrowerOperations.addColl{value: amount}(upperHint, lowerHint);
|
||||
_eventName = "LogDeposit(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw ETH from Trove
|
||||
* @notice Move Trove collateral 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 should 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
|
||||
*/
|
||||
function withdraw(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
borrowerOperations.withdrawColl(amount, upperHint, lowerHint);
|
||||
|
||||
setUint(setId, amount);
|
||||
_eventName = "LogWithdraw(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Mints LUSD tokens
|
||||
* @notice Borrow LUSD via an existing Trove
|
||||
* @param maxFeePercentage The maximum borrow fee that this transaction should permit
|
||||
* @param amount Amount of LUSD to borrow
|
||||
* @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 should now sit in the ordered Trove list
|
||||
* @param setId Optional storage slot to store the borrowed LUSD in
|
||||
*/
|
||||
function borrow(
|
||||
uint maxFeePercentage,
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
borrowerOperations.withdrawLUSD(maxFeePercentage, amount, upperHint, lowerHint);
|
||||
|
||||
setUint(setId, amount);
|
||||
_eventName = "LogBorrow(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Send LUSD to repay debt
|
||||
* @notice Repay LUSD Trove debt
|
||||
* @param amount Amount of LUSD to repay
|
||||
* @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 should now sit in the ordered Trove list
|
||||
* @param getId Optional storage slot to retrieve the LUSD from
|
||||
*/
|
||||
function repay(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
if (getId != 0 && amount != 0) {
|
||||
revert("repay(): Cannot supply an amount if a non-zero getId is supplied");
|
||||
}
|
||||
amount = getUint(getId, amount);
|
||||
borrowerOperations.repayLUSD(amount, upperHint, lowerHint);
|
||||
_eventName = "LogRepay(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Increase or decrease Trove ETH collateral and LUSD debt in one transaction
|
||||
* @notice Adjust Trove debt and/or collateral
|
||||
* @param maxFeePercentage The maximum borrow fee that this transaction should permit
|
||||
* @param withdrawAmount Amount of ETH to withdraw
|
||||
* @param depositAmount Amount of ETH to deposit
|
||||
* @param borrowAmount Amount of LUSD to borrow
|
||||
* @param repayAmount Amount of LUSD to repay
|
||||
* @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 should now sit in the ordered Trove list
|
||||
* @param getDepositId Optional storage slot to retrieve the ETH to deposit
|
||||
* @param setWithdrawId Optional storage slot to store the withdrawn ETH to
|
||||
* @param getRepayId Optional storage slot to retrieve the LUSD to repay
|
||||
* @param setBorrowId Optional storage slot to store the LUSD borrowed
|
||||
*/
|
||||
function adjust(
|
||||
uint maxFeePercentage,
|
||||
uint withdrawAmount,
|
||||
uint depositAmount,
|
||||
uint borrowAmount,
|
||||
uint repayAmount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getDepositId,
|
||||
uint setWithdrawId,
|
||||
uint getRepayId,
|
||||
uint setBorrowId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
if (getDepositId != 0 && depositAmount != 0) {
|
||||
revert("adjust(): Cannot supply a depositAmount if a non-zero getDepositId is supplied");
|
||||
}
|
||||
if (getRepayId != 0 && repayAmount != 0) {
|
||||
revert("adjust(): Cannot supply a repayAmount if a non-zero getRepayId is supplied");
|
||||
}
|
||||
AdjustTrove memory adjustTrove;
|
||||
|
||||
adjustTrove.maxFeePercentage = maxFeePercentage;
|
||||
adjustTrove.withdrawAmount = withdrawAmount;
|
||||
adjustTrove.depositAmount = getUint(getDepositId, depositAmount);
|
||||
adjustTrove.borrowAmount = borrowAmount;
|
||||
adjustTrove.repayAmount = getUint(getRepayId, repayAmount);
|
||||
adjustTrove.isBorrow = borrowAmount > 0;
|
||||
|
||||
borrowerOperations.adjustTrove{value: adjustTrove.depositAmount}(
|
||||
adjustTrove.maxFeePercentage,
|
||||
adjustTrove.withdrawAmount,
|
||||
adjustTrove.borrowAmount,
|
||||
adjustTrove.isBorrow,
|
||||
upperHint,
|
||||
lowerHint
|
||||
);
|
||||
|
||||
// Allow other spells to use the withdrawn collateral
|
||||
setUint(setWithdrawId, withdrawAmount);
|
||||
|
||||
// Allow other spells to use the borrowed amount
|
||||
setUint(setBorrowId, borrowAmount);
|
||||
|
||||
_eventName = "LogAdjust(address,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, maxFeePercentage, depositAmount, withdrawAmount, borrowAmount, repayAmount, getDepositId, setWithdrawId, getRepayId, setBorrowId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw remaining ETH balance from user's redeemed Trove to their DSA
|
||||
* @param setId Optional storage slot to store the ETH claimed
|
||||
* @notice Claim remaining collateral from Trove
|
||||
*/
|
||||
function claimCollateralFromRedemption(uint setId) external returns(string memory _eventName, bytes memory _eventParam) {
|
||||
uint amount = collateralSurplus.getCollateral(address(this));
|
||||
borrowerOperations.claimCollateral();
|
||||
setUint(setId, amount);
|
||||
|
||||
_eventName = "LogClaimCollateralFromRedemption(address,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, setId);
|
||||
}
|
||||
/* End: Trove */
|
||||
|
||||
/* Begin: Stability Pool */
|
||||
|
||||
/**
|
||||
* @dev Deposit LUSD into Stability Pool
|
||||
* @notice Deposit LUSD into Stability Pool
|
||||
* @param amount Amount of LUSD to deposit into Stability Pool
|
||||
* @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 setEthGainId Optional storage slot to store any ETH gains in
|
||||
* @param setLqtyGainId Optional storage slot to store any LQTY gains in
|
||||
*/
|
||||
function stabilityDeposit(
|
||||
uint amount,
|
||||
address frontendTag,
|
||||
uint getDepositId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
amount = getUint(getDepositId, amount);
|
||||
|
||||
uint ethGain = stabilityPool.getDepositorETHGain(address(this));
|
||||
uint lqtyBalanceBefore = lqtyToken.balanceOf(address(this));
|
||||
|
||||
stabilityPool.provideToSP(amount, frontendTag);
|
||||
|
||||
uint lqtyBalanceAfter = lqtyToken.balanceOf(address(this));
|
||||
uint lqtyGain = sub(lqtyBalanceAfter, lqtyBalanceBefore);
|
||||
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLqtyGainId, lqtyGain);
|
||||
|
||||
_eventName = "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, ethGain, lqtyGain, frontendTag, getDepositId, setEthGainId, setLqtyGainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Withdraw user deposited LUSD from Stability Pool
|
||||
* @notice Withdraw LUSD from Stability Pool
|
||||
* @param amount Amount of LUSD to withdraw from Stability Pool
|
||||
* @param setWithdrawId Optional storage slot to store the withdrawn LUSD
|
||||
* @param setEthGainId Optional storage slot to store any ETH gains in
|
||||
* @param setLqtyGainId Optional storage slot to store any LQTY gains in
|
||||
*/
|
||||
function stabilityWithdraw(
|
||||
uint amount,
|
||||
uint setWithdrawId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint ethGain = stabilityPool.getDepositorETHGain(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(setEthGainId, ethGain);
|
||||
setUint(setLqtyGainId, lqtyGain);
|
||||
|
||||
_eventName = "LogStabilityWithdraw(address,uint256,uint256,uint256,uint256,uint256,uint256)";
|
||||
_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
|
||||
* @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 should 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(
|
||||
address upperHint,
|
||||
address lowerHint
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint amount = stabilityPool.getDepositorETHGain(address(this));
|
||||
stabilityPool.withdrawETHGainToTrove(upperHint, lowerHint);
|
||||
_eventName = "LogStabilityMoveEthGainToTrove(address,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount);
|
||||
}
|
||||
/* End: Stability Pool */
|
||||
|
||||
/* Begin: Staking */
|
||||
|
||||
/**
|
||||
* @dev Sends LQTY tokens from user to Staking Pool
|
||||
* @notice Stake LQTY in Staking Pool
|
||||
* @param amount Amount of LQTY to stake
|
||||
* @param getStakeId Optional storage slot to retrieve the LQTY from
|
||||
* @param setEthGainId Optional storage slot to store any ETH gains
|
||||
* @param setLusdGainId Optional storage slot to store any LUSD gains
|
||||
*/
|
||||
function stake(
|
||||
uint amount,
|
||||
uint getStakeId,
|
||||
uint setEthGainId,
|
||||
uint setLusdGainId
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint ethGain = staking.getPendingETHGain(address(this));
|
||||
uint lusdGain = staking.getPendingLUSDGain(address(this));
|
||||
|
||||
amount = getUint(getStakeId, amount);
|
||||
staking.stake(amount);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLusdGainId, lusdGain);
|
||||
|
||||
_eventName = "LogStake(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, getStakeId, setEthGainId, setLusdGainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sends LQTY tokens from Staking Pool to user
|
||||
* @notice Unstake LQTY in Staking Pool
|
||||
* @param amount Amount of LQTY to unstake
|
||||
* @param setStakeId Optional storage slot to store the unstaked LQTY
|
||||
* @param setEthGainId Optional storage slot to store any ETH gains
|
||||
* @param setLusdGainId Optional storage slot to store any LUSD gains
|
||||
*/
|
||||
function unstake(
|
||||
uint amount,
|
||||
uint setStakeId,
|
||||
uint setEthGainId,
|
||||
uint setLusdGainId
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint ethGain = staking.getPendingETHGain(address(this));
|
||||
uint lusdGain = staking.getPendingLUSDGain(address(this));
|
||||
|
||||
staking.unstake(amount);
|
||||
setUint(setStakeId, amount);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLusdGainId, lusdGain);
|
||||
|
||||
_eventName = "LogUnstake(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, amount, setStakeId, setEthGainId, setLusdGainId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Sends ETH and LUSD gains from Staking to user
|
||||
* @notice Claim ETH and LUSD gains from Staking
|
||||
* @param setEthGainId Optional storage slot to store the claimed ETH
|
||||
* @param setLusdGainId Optional storage slot to store the claimed LUSD
|
||||
*/
|
||||
function claimStakingGains(
|
||||
uint setEthGainId,
|
||||
uint setLusdGainId
|
||||
) external returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint ethGain = staking.getPendingETHGain(address(this));
|
||||
uint lusdGain = staking.getPendingLUSDGain(address(this));
|
||||
|
||||
// Gains are claimed when a user's stake is adjusted, so we unstake 0 to trigger the claim
|
||||
staking.unstake(0);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLusdGainId, lusdGain);
|
||||
|
||||
_eventName = "LogClaimStakingGains(address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(msg.sender, ethGain, lusdGain, setEthGainId, setLusdGainId);
|
||||
}
|
||||
/* End: Staking */
|
||||
|
||||
}
|
||||
|
||||
contract ConnectV2Liquity is LiquityResolver {
|
||||
string public name = "Liquity-v1";
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
require("@nomiclabs/hardhat-waffle");
|
||||
require("@nomiclabs/hardhat-ethers");
|
||||
require("@tenderly/hardhat-tenderly");
|
||||
|
@ -6,7 +5,7 @@ require("@nomiclabs/hardhat-etherscan");
|
|||
require("@nomiclabs/hardhat-web3")
|
||||
require("hardhat-deploy");
|
||||
require("hardhat-deploy-ethers");
|
||||
require('dotenv').config();
|
||||
require("dotenv").config();
|
||||
|
||||
const { utils } = require("ethers");
|
||||
|
||||
|
@ -30,14 +29,14 @@ module.exports = {
|
|||
},
|
||||
{
|
||||
version: "0.6.5"
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
},
|
||||
networks: {
|
||||
// defaultNetwork: "hardhat",
|
||||
kovan: {
|
||||
url: `https://eth-kovan.alchemyapi.io/v2/${ALCHEMY_ID}`,
|
||||
accounts: [`0x${PRIVATE_KEY}`]
|
||||
accounts: [`0x${PRIVATE_KEY}`],
|
||||
},
|
||||
mainnet: {
|
||||
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
|
||||
|
@ -50,20 +49,20 @@ module.exports = {
|
|||
url: `https://eth-mainnet.alchemyapi.io/v2/${ALCHEMY_ID}`,
|
||||
blockNumber: 12433781,
|
||||
},
|
||||
blockGasLimit: 12000000,
|
||||
blockGasLimit: 12000000
|
||||
},
|
||||
matic: {
|
||||
url: "https://rpc-mainnet.maticvigil.com/",
|
||||
accounts: [`0x${PRIVATE_KEY}`],
|
||||
timeout: 150000,
|
||||
gasPrice: parseInt(utils.parseUnits("1", "gwei"))
|
||||
}
|
||||
},
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: process.env.ETHERSCAN_API_KEY
|
||||
},
|
||||
tenderly: {
|
||||
project: process.env.TENDERLY_PROJECT,
|
||||
username: process.env.TENDERLY_USERNAME,
|
||||
}
|
||||
username: process.env.TENDERLY_USERNAME
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
module.exports = {
|
||||
core: {
|
||||
connectorsV2: require("./abi/core/connectorsV2.json"),
|
||||
instaIndex: require("./abi/core/instaIndex.json"),
|
||||
},
|
||||
connectors: {
|
||||
basic: require("./abi/connectors/basic.json"),
|
||||
auth: require("./abi/connectors/auth.json"),
|
||||
},
|
||||
basic: {
|
||||
erc20: require("./abi/basics/erc20.json"),
|
||||
},
|
||||
};
|
||||
|
||||
core: {
|
||||
connectorsV2: require("./abi/core/connectorsV2.json"),
|
||||
instaIndex: require("./abi/core/instaIndex.json"),
|
||||
},
|
||||
connectors: {
|
||||
"Basic-v1": require("./abi/connectors/basic.json"),
|
||||
basic: require("./abi/connectors/basic.json"),
|
||||
auth: require("./abi/connectors/auth.json"),
|
||||
},
|
||||
basic: {
|
||||
erc20: require("./abi/basics/erc20.json"),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,11 +1,10 @@
|
|||
module.exports = {
|
||||
connectors: {
|
||||
basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
|
||||
auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
|
||||
},
|
||||
core: {
|
||||
connectorsV2: "0xFE2390DAD597594439f218190fC2De40f9Cf1179",
|
||||
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723"
|
||||
}
|
||||
};
|
||||
|
||||
connectors: {
|
||||
basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
|
||||
auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
|
||||
},
|
||||
core: {
|
||||
connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11",
|
||||
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
|
||||
},
|
||||
};
|
||||
|
|
95
test/liquity/liquity.contracts.js
Normal file
95
test/liquity/liquity.contracts.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
const TROVE_MANAGER_ADDRESS = "0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2";
|
||||
const TROVE_MANAGER_ABI = [
|
||||
"function getTroveColl(address _borrower) external view returns (uint)",
|
||||
"function getTroveDebt(address _borrower) external view returns (uint)",
|
||||
"function getTroveStatus(address _borrower) external view returns (uint)",
|
||||
"function redeemCollateral(uint _LUSDAmount, address _firstRedemptionHint, address _upperPartialRedemptionHint, address _lowerPartialRedemptionHint, uint _partialRedemptionHintNICR, uint _maxIterations, uint _maxFee) external returns (uint)",
|
||||
"function getNominalICR(address _borrower) external view returns (uint)",
|
||||
"function liquidate(address _borrower) external",
|
||||
"function liquidateTroves(uint _n) external",
|
||||
];
|
||||
|
||||
const BORROWER_OPERATIONS_ADDRESS =
|
||||
"0x24179CD81c9e782A4096035f7eC97fB8B783e007";
|
||||
const BORROWER_OPERATIONS_ABI = [
|
||||
"function openTrove(uint256 _maxFee, uint256 _LUSDAmount, address _upperHint, address _lowerHint) external payable",
|
||||
"function closeTrove() external",
|
||||
];
|
||||
|
||||
const LUSD_TOKEN_ADDRESS = "0x5f98805A4E8be255a32880FDeC7F6728C6568bA0";
|
||||
const LUSD_TOKEN_ABI = [
|
||||
"function transfer(address _to, uint256 _value) public returns (bool success)",
|
||||
"function balanceOf(address account) external view returns (uint256)",
|
||||
"function approve(address spender, uint256 amount) external returns (bool)",
|
||||
];
|
||||
|
||||
const ACTIVE_POOL_ADDRESS = "0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F";
|
||||
const ACTIVE_POOL_ABI = ["function getLUSDDebt() external view returns (uint)"];
|
||||
|
||||
const PRICE_FEED_ADDRESS = "0x4c517D4e2C851CA76d7eC94B805269Df0f2201De";
|
||||
const PRICE_FEED_ABI = ["function fetchPrice() external returns (uint)"];
|
||||
|
||||
const HINT_HELPERS_ADDRESS = "0xE84251b93D9524E0d2e621Ba7dc7cb3579F997C0";
|
||||
const HINT_HELPERS_ABI = [
|
||||
"function getRedemptionHints(uint _LUSDamount, uint _price, uint _maxIterations) external view returns (address firstRedemptionHint, uint partialRedemptionHintNICR, uint truncatedLUSDamount)",
|
||||
"function getApproxHint(uint _CR, uint _numTrials, uint _inputRandomSeed) view returns (address hintAddress, uint diff, uint latestRandomSeed)",
|
||||
"function computeNominalCR(uint _coll, uint _debt) external pure returns (uint)",
|
||||
];
|
||||
|
||||
const SORTED_TROVES_ADDRESS = "0x8FdD3fbFEb32b28fb73555518f8b361bCeA741A6";
|
||||
const SORTED_TROVES_ABI = [
|
||||
"function findInsertPosition(uint256 _ICR, address _prevId, address _nextId) external view returns (address, address)",
|
||||
"function getLast() external view returns (address)",
|
||||
];
|
||||
|
||||
const STABILITY_POOL_ADDRESS = "0x66017D22b0f8556afDd19FC67041899Eb65a21bb";
|
||||
const STABILITY_POOL_ABI = [
|
||||
"function getCompoundedLUSDDeposit(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_ABI = [
|
||||
"function stake(uint _LQTYamount) external",
|
||||
"function unstake(uint _LQTYamount) external",
|
||||
"function getPendingETHGain(address _user) external view returns (uint)",
|
||||
"function getPendingLUSDGain(address _user) external view returns (uint)",
|
||||
];
|
||||
|
||||
const LQTY_TOKEN_ADDRESS = "0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D";
|
||||
const LQTY_TOKEN_ABI = [
|
||||
"function balanceOf(address account) external view returns (uint256)",
|
||||
"function transfer(address _to, uint256 _value) public returns (bool success)",
|
||||
"function approve(address spender, uint256 amount) external returns (bool)",
|
||||
];
|
||||
|
||||
const COLL_SURPLUS_ADDRESS = "0x3D32e8b97Ed5881324241Cf03b2DA5E2EBcE5521";
|
||||
const COLL_SURPLUS_ABI = [
|
||||
"function getCollateral(address _account) external view returns (uint)",
|
||||
];
|
||||
|
||||
module.exports = {
|
||||
TROVE_MANAGER_ADDRESS,
|
||||
TROVE_MANAGER_ABI,
|
||||
BORROWER_OPERATIONS_ADDRESS,
|
||||
BORROWER_OPERATIONS_ABI,
|
||||
LUSD_TOKEN_ADDRESS,
|
||||
LUSD_TOKEN_ABI,
|
||||
STABILITY_POOL_ADDRESS,
|
||||
STABILITY_POOL_ABI,
|
||||
ACTIVE_POOL_ADDRESS,
|
||||
ACTIVE_POOL_ABI,
|
||||
PRICE_FEED_ADDRESS,
|
||||
PRICE_FEED_ABI,
|
||||
HINT_HELPERS_ADDRESS,
|
||||
HINT_HELPERS_ABI,
|
||||
SORTED_TROVES_ADDRESS,
|
||||
SORTED_TROVES_ABI,
|
||||
STAKING_ADDRESS,
|
||||
STAKING_ABI,
|
||||
LQTY_TOKEN_ADDRESS,
|
||||
LQTY_TOKEN_ABI,
|
||||
COLL_SURPLUS_ADDRESS,
|
||||
COLL_SURPLUS_ABI,
|
||||
};
|
343
test/liquity/liquity.helpers.js
Normal file
343
test/liquity/liquity.helpers.js
Normal file
|
@ -0,0 +1,343 @@
|
|||
const hre = require("hardhat");
|
||||
const hardhatConfig = require("../../hardhat.config");
|
||||
|
||||
// Instadapp deployment and testing helpers
|
||||
const deployAndEnableConnector = require("../../scripts/deployAndEnableConnector.js");
|
||||
const encodeSpells = require("../../scripts/encodeSpells.js");
|
||||
const getMasterSigner = require("../../scripts/getMasterSigner");
|
||||
const buildDSAv2 = require("../../scripts/buildDSAv2");
|
||||
|
||||
// Instadapp instadappAddresses/ABIs
|
||||
const instadappAddresses = require("../../scripts/constant/addresses");
|
||||
const instadappAbi = require("../../scripts/constant/abis");
|
||||
|
||||
// Instadapp Liquity Connector artifacts
|
||||
const connectV2LiquityArtifacts = require("../../artifacts/contracts/mainnet/connectors/liquity/main.sol/ConnectV2Liquity.json");
|
||||
const connectV2BasicV1Artifacts = require("../../artifacts/contracts/mainnet/connectors/basic/main.sol/ConnectV2Basic.json");
|
||||
const { ethers } = require("hardhat");
|
||||
|
||||
// Instadapp uses a fake address to represent native ETH
|
||||
const { eth_addr: ETH_ADDRESS } = require("../../scripts/constant/constant");
|
||||
|
||||
const LIQUITY_CONNECTOR = "LIQUITY-v1-TEST";
|
||||
const LUSD_GAS_COMPENSATION = hre.ethers.utils.parseUnits("200", 18); // 200 LUSD gas compensation repaid after loan repayment
|
||||
const LIQUIDATABLE_TROVES_BLOCK_NUMBER = 12478159; // Deterministic block number for tests to run against, if you change this, tests will break.
|
||||
const JUSTIN_SUN_ADDRESS = "0x903d12bf2c57a29f32365917c706ce0e1a84cce3"; // LQTY whale address
|
||||
const LIQUIDATABLE_TROVE_ADDRESS = "0xafbeb4cb97f3b08ec2fe07ef0dac15d37013a347"; // Trove which is liquidatable at blockNumber: LIQUIDATABLE_TROVES_BLOCK_NUMBER
|
||||
const MAX_GAS = hardhatConfig.networks.hardhat.blockGasLimit; // Maximum gas limit (12000000)
|
||||
const INSTADAPP_BASIC_V1_CONNECTOR = "Basic-v1";
|
||||
|
||||
const openTroveSpell = async (
|
||||
dsa,
|
||||
signer,
|
||||
depositAmount,
|
||||
borrowAmount,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
maxFeePercentage
|
||||
) => {
|
||||
let address = signer.address;
|
||||
if (signer.address === undefined) {
|
||||
address = await signer.getAddress();
|
||||
}
|
||||
|
||||
const openTroveSpell = {
|
||||
connector: LIQUITY_CONNECTOR,
|
||||
method: "open",
|
||||
args: [
|
||||
depositAmount,
|
||||
maxFeePercentage,
|
||||
borrowAmount,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
0,
|
||||
0,
|
||||
],
|
||||
};
|
||||
return await dsa
|
||||
.connect(signer)
|
||||
.cast(...encodeSpells([openTroveSpell]), address, {
|
||||
value: depositAmount,
|
||||
});
|
||||
};
|
||||
|
||||
const createDsaTrove = async (
|
||||
dsa,
|
||||
signer,
|
||||
liquity,
|
||||
depositAmount = hre.ethers.utils.parseEther("5"),
|
||||
borrowAmount = hre.ethers.utils.parseUnits("2000", 18)
|
||||
) => {
|
||||
const maxFeePercentage = hre.ethers.utils.parseUnits("0.5", 18); // 0.5% max fee
|
||||
const { upperHint, lowerHint } = await getTroveInsertionHints(
|
||||
depositAmount,
|
||||
borrowAmount,
|
||||
liquity
|
||||
);
|
||||
return await openTroveSpell(
|
||||
dsa,
|
||||
signer,
|
||||
depositAmount,
|
||||
borrowAmount,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
maxFeePercentage
|
||||
);
|
||||
};
|
||||
|
||||
const sendToken = async (token, amount, from, to) => {
|
||||
await hre.network.provider.request({
|
||||
method: "hardhat_impersonateAccount",
|
||||
params: [from],
|
||||
});
|
||||
const signer = await hre.ethers.provider.getSigner(from);
|
||||
|
||||
return await token.connect(signer).transfer(to, amount, {
|
||||
gasPrice: 0,
|
||||
});
|
||||
};
|
||||
|
||||
const resetInitialState = async (walletAddress, contracts, isDebug = false) => {
|
||||
const liquity = await deployAndConnect(contracts, isDebug);
|
||||
const dsa = await buildDSAv2(walletAddress);
|
||||
|
||||
return [liquity, dsa];
|
||||
};
|
||||
|
||||
const resetHardhatBlockNumber = async (blockNumber) => {
|
||||
return await hre.network.provider.request({
|
||||
method: "hardhat_reset",
|
||||
params: [
|
||||
{
|
||||
forking: {
|
||||
jsonRpcUrl: hardhatConfig.networks.hardhat.forking.url,
|
||||
blockNumber,
|
||||
},
|
||||
},
|
||||
],
|
||||
});
|
||||
};
|
||||
|
||||
const deployAndConnect = async (contracts, isDebug = false) => {
|
||||
// Pin Liquity tests to a particular block number to create deterministic state (Ether price etc.)
|
||||
await resetHardhatBlockNumber(LIQUIDATABLE_TROVES_BLOCK_NUMBER);
|
||||
const liquity = {
|
||||
troveManager: null,
|
||||
borrowerOperations: null,
|
||||
stabilityPool: null,
|
||||
lusdToken: null,
|
||||
lqtyToken: null,
|
||||
activePool: null,
|
||||
priceFeed: null,
|
||||
hintHelpers: null,
|
||||
sortedTroves: null,
|
||||
staking: null,
|
||||
collSurplus: null,
|
||||
};
|
||||
|
||||
const masterSigner = await getMasterSigner();
|
||||
const instaConnectorsV2 = await ethers.getContractAt(
|
||||
instadappAbi.core.connectorsV2,
|
||||
instadappAddresses.core.connectorsV2
|
||||
);
|
||||
const connector = await deployAndEnableConnector({
|
||||
connectorName: LIQUITY_CONNECTOR,
|
||||
contractArtifact: connectV2LiquityArtifacts,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2,
|
||||
});
|
||||
isDebug &&
|
||||
console.log(`${LIQUITY_CONNECTOR} Connector address`, connector.address);
|
||||
|
||||
const basicConnector = await deployAndEnableConnector({
|
||||
connectorName: "Basic-v1",
|
||||
contractArtifact: connectV2BasicV1Artifacts,
|
||||
signer: masterSigner,
|
||||
connectors: instaConnectorsV2,
|
||||
});
|
||||
isDebug && console.log("Basic-v1 Connector address", basicConnector.address);
|
||||
|
||||
liquity.troveManager = new ethers.Contract(
|
||||
contracts.TROVE_MANAGER_ADDRESS,
|
||||
contracts.TROVE_MANAGER_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.borrowerOperations = new ethers.Contract(
|
||||
contracts.BORROWER_OPERATIONS_ADDRESS,
|
||||
contracts.BORROWER_OPERATIONS_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.stabilityPool = new ethers.Contract(
|
||||
contracts.STABILITY_POOL_ADDRESS,
|
||||
contracts.STABILITY_POOL_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.lusdToken = new ethers.Contract(
|
||||
contracts.LUSD_TOKEN_ADDRESS,
|
||||
contracts.LUSD_TOKEN_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.lqtyToken = new ethers.Contract(
|
||||
contracts.LQTY_TOKEN_ADDRESS,
|
||||
contracts.LQTY_TOKEN_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.activePool = new ethers.Contract(
|
||||
contracts.ACTIVE_POOL_ADDRESS,
|
||||
contracts.ACTIVE_POOL_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.priceFeed = new ethers.Contract(
|
||||
contracts.PRICE_FEED_ADDRESS,
|
||||
contracts.PRICE_FEED_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.hintHelpers = new ethers.Contract(
|
||||
contracts.HINT_HELPERS_ADDRESS,
|
||||
contracts.HINT_HELPERS_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.sortedTroves = new ethers.Contract(
|
||||
contracts.SORTED_TROVES_ADDRESS,
|
||||
contracts.SORTED_TROVES_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
liquity.staking = new ethers.Contract(
|
||||
contracts.STAKING_ADDRESS,
|
||||
contracts.STAKING_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
liquity.collSurplus = new ethers.Contract(
|
||||
contracts.COLL_SURPLUS_ADDRESS,
|
||||
contracts.COLL_SURPLUS_ABI,
|
||||
ethers.provider
|
||||
);
|
||||
|
||||
return liquity;
|
||||
};
|
||||
|
||||
const getTroveInsertionHints = async (depositAmount, borrowAmount, liquity) => {
|
||||
const nominalCR = await liquity.hintHelpers.computeNominalCR(
|
||||
depositAmount,
|
||||
borrowAmount
|
||||
);
|
||||
|
||||
const {
|
||||
hintAddress,
|
||||
latestRandomSeed,
|
||||
} = await liquity.hintHelpers.getApproxHint(nominalCR, 50, 1298379, {
|
||||
gasLimit: MAX_GAS,
|
||||
});
|
||||
randomSeed = latestRandomSeed;
|
||||
|
||||
const {
|
||||
0: upperHint,
|
||||
1: lowerHint,
|
||||
} = await liquity.sortedTroves.findInsertPosition(
|
||||
nominalCR,
|
||||
hintAddress,
|
||||
hintAddress,
|
||||
{
|
||||
gasLimit: MAX_GAS,
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
upperHint,
|
||||
lowerHint,
|
||||
};
|
||||
};
|
||||
|
||||
let randomSeed = 4223;
|
||||
|
||||
const getRedemptionHints = async (amount, liquity) => {
|
||||
const ethPrice = await liquity.priceFeed.callStatic.fetchPrice();
|
||||
const [
|
||||
firstRedemptionHint,
|
||||
partialRedemptionHintNicr,
|
||||
] = await liquity.hintHelpers.getRedemptionHints(amount, ethPrice, 0);
|
||||
|
||||
const {
|
||||
hintAddress,
|
||||
latestRandomSeed,
|
||||
} = await liquity.hintHelpers.getApproxHint(
|
||||
partialRedemptionHintNicr,
|
||||
50,
|
||||
randomSeed,
|
||||
{
|
||||
gasLimit: MAX_GAS,
|
||||
}
|
||||
);
|
||||
randomSeed = latestRandomSeed;
|
||||
|
||||
const {
|
||||
0: upperHint,
|
||||
1: lowerHint,
|
||||
} = await liquity.sortedTroves.findInsertPosition(
|
||||
partialRedemptionHintNicr,
|
||||
hintAddress,
|
||||
hintAddress,
|
||||
{
|
||||
gasLimit: MAX_GAS,
|
||||
}
|
||||
);
|
||||
|
||||
return {
|
||||
partialRedemptionHintNicr,
|
||||
firstRedemptionHint,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
};
|
||||
};
|
||||
|
||||
const redeem = async (amount, from, wallet, liquity) => {
|
||||
await sendToken(liquity.lusdToken, amount, from, wallet.address);
|
||||
const {
|
||||
partialRedemptionHintNicr,
|
||||
firstRedemptionHint,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
} = await getRedemptionHints(amount, liquity);
|
||||
const maxFeePercentage = ethers.utils.parseUnits("0.5", 18); // 0.5% max fee
|
||||
|
||||
return await liquity.troveManager
|
||||
.connect(wallet)
|
||||
.redeemCollateral(
|
||||
amount,
|
||||
firstRedemptionHint,
|
||||
upperHint,
|
||||
lowerHint,
|
||||
partialRedemptionHintNicr,
|
||||
0,
|
||||
maxFeePercentage,
|
||||
{
|
||||
gasLimit: MAX_GAS, // permit max gas
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
deployAndConnect,
|
||||
resetInitialState,
|
||||
createDsaTrove,
|
||||
sendToken,
|
||||
getTroveInsertionHints,
|
||||
getRedemptionHints,
|
||||
redeem,
|
||||
LIQUITY_CONNECTOR,
|
||||
LUSD_GAS_COMPENSATION,
|
||||
JUSTIN_SUN_ADDRESS,
|
||||
LIQUIDATABLE_TROVE_ADDRESS,
|
||||
MAX_GAS,
|
||||
INSTADAPP_BASIC_V1_CONNECTOR,
|
||||
ETH_ADDRESS,
|
||||
};
|
2693
test/liquity/liquity.test.js
Normal file
2693
test/liquity/liquity.test.js
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user