mirror of
https://github.com/Instadapp/dsa-connectors.git
synced 2024-07-29 22:37:00 +00:00
Merge branch 'dep/compound-mapping-update' of https://github.com/InstaDApp/dsa-connectors-new into dep/compound-mapping-update
This commit is contained in:
commit
5b6e1af5fd
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,
|
||||
uint256[] getIds,
|
||||
uint256[] setIds
|
||||
);
|
||||
event LogClose(address indexed borrower, uint setId);
|
||||
event LogDeposit(address indexed borrower, uint amount, uint getId, uint setId);
|
||||
event LogWithdraw(address indexed borrower, uint amount, uint getId, uint setId);
|
||||
event LogBorrow(address indexed borrower, uint amount, uint getId, uint setId);
|
||||
event LogRepay(address indexed borrower, uint amount, uint getId, uint setId);
|
||||
event LogAdjust(
|
||||
address indexed borrower,
|
||||
uint maxFeePercentage,
|
||||
uint depositAmount,
|
||||
uint withdrawAmount,
|
||||
uint borrowAmount,
|
||||
uint repayAmount,
|
||||
uint256[] getIds,
|
||||
uint256[] setIds
|
||||
);
|
||||
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 setDepositId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
);
|
||||
event LogStabilityWithdraw(address indexed borrower,
|
||||
uint amount,
|
||||
uint ethGain,
|
||||
uint lqtyGain,
|
||||
uint getWithdrawId,
|
||||
uint setWithdrawId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
);
|
||||
event LogStabilityMoveEthGainToTrove(address indexed borrower, uint amount);
|
||||
|
||||
/* Staking */
|
||||
event LogStake(address indexed borrower, uint amount, uint getStakeId, uint setStakeId, uint setEthGainId, uint setLusdGainId);
|
||||
event LogUnstake(address indexed borrower, uint amount, uint getUnstakeId, uint setUnstakeId, uint setEthGainId, uint setLusdGainId);
|
||||
event LogClaimStakingGains(address indexed borrower, uint ethGain, uint lusdGain, uint setEthGainId, uint setLusdGainId);
|
||||
}
|
37
contracts/mainnet/connectors/liquity/helpers.sol
Normal file
37
contracts/mainnet/connectors/liquity/helpers.sol
Normal file
|
@ -0,0 +1,37 @@
|
|||
pragma solidity ^0.7.6;
|
||||
|
||||
import { DSMath } from "../../common/math.sol";
|
||||
import { Basic } from "../../common/basic.sol";
|
||||
|
||||
import { TokenInterface } from "../../common/interfaces.sol";
|
||||
|
||||
import {
|
||||
BorrowerOperationsLike,
|
||||
TroveManagerLike,
|
||||
StabilityPoolLike,
|
||||
StakingLike,
|
||||
CollateralSurplusLike,
|
||||
LqtyTokenLike
|
||||
} from "./interface.sol";
|
||||
|
||||
abstract contract Helpers is DSMath, Basic {
|
||||
|
||||
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);
|
||||
TokenInterface internal constant lusdToken = TokenInterface(0x5f98805A4E8be255a32880FDeC7F6728C6568bA0);
|
||||
|
||||
// Prevents stack-too-deep error
|
||||
struct AdjustTrove {
|
||||
uint maxFeePercentage;
|
||||
uint withdrawAmount;
|
||||
uint depositAmount;
|
||||
uint borrowAmount;
|
||||
uint repayAmount;
|
||||
bool isBorrow;
|
||||
}
|
||||
|
||||
}
|
74
contracts/mainnet/connectors/liquity/interface.sol
Normal file
74
contracts/mainnet/connectors/liquity/interface.sol
Normal file
|
@ -0,0 +1,74 @@
|
|||
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);
|
||||
function getCompoundedLUSDDeposit(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);
|
||||
function stakes(address owner) external view returns (uint);
|
||||
}
|
||||
|
||||
interface CollateralSurplusLike {
|
||||
function getCollateral(address _account) external view returns (uint);
|
||||
}
|
||||
|
||||
interface LqtyTokenLike {
|
||||
function balanceOf(address account) external view returns (uint256);
|
||||
}
|
458
contracts/mainnet/connectors/liquity/main.sol
Normal file
458
contracts/mainnet/connectors/liquity/main.sol
Normal file
|
@ -0,0 +1,458 @@
|
|||
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 {
|
||||
|
||||
|
||||
/* 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 getIds Optional (default: 0) Optional storage slot to get deposit & borrow amounts stored using other spells
|
||||
* @param setIds Optional (default: 0) Optional storage slot to set deposit & borrow amounts to be used in future spells
|
||||
*/
|
||||
function open(
|
||||
uint depositAmount,
|
||||
uint maxFeePercentage,
|
||||
uint borrowAmount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint[] memory getIds,
|
||||
uint[] memory setIds
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
|
||||
depositAmount = getUint(getIds[0], depositAmount);
|
||||
borrowAmount = getUint(getIds[1], borrowAmount);
|
||||
|
||||
depositAmount = depositAmount == uint(-1) ? address(this).balance : depositAmount;
|
||||
|
||||
borrowerOperations.openTrove{value: depositAmount}(
|
||||
maxFeePercentage,
|
||||
borrowAmount,
|
||||
upperHint,
|
||||
lowerHint
|
||||
);
|
||||
|
||||
setUint(setIds[0], depositAmount);
|
||||
setUint(setIds[1], borrowAmount);
|
||||
|
||||
_eventName = "LogOpen(address,uint256,uint256,uint256,uint256[],uint256[])";
|
||||
_eventParam = abi.encode(address(this), maxFeePercentage, depositAmount, borrowAmount, getIds, setIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 payable 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(address(this), 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
|
||||
* @param setId Optional storage slot to set the ETH deposited
|
||||
*/
|
||||
function deposit(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
|
||||
uint _amount = getUint(getId, amount);
|
||||
|
||||
_amount = _amount == uint(-1) ? address(this).balance : _amount;
|
||||
|
||||
borrowerOperations.addColl{value: _amount}(upperHint, lowerHint);
|
||||
|
||||
setUint(setId, _amount);
|
||||
|
||||
_eventName = "LogDeposit(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), _amount, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 getId Optional storage slot to get the amount of ETH to withdraw
|
||||
* @param setId Optional storage slot to store the withdrawn ETH in
|
||||
*/
|
||||
function withdraw(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint _amount = getUint(getId, amount);
|
||||
|
||||
_amount = _amount == uint(-1) ? troveManager.getTroveColl(address(this)) : _amount;
|
||||
|
||||
borrowerOperations.withdrawColl(_amount, upperHint, lowerHint);
|
||||
|
||||
setUint(setId, _amount);
|
||||
_eventName = "LogWithdraw(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), _amount, getId, 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 getId Optional storage slot to retrieve the amount of LUSD to borrow
|
||||
* @param setId Optional storage slot to store the final amount of LUSD borrowed
|
||||
*/
|
||||
function borrow(
|
||||
uint maxFeePercentage,
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint _amount = getUint(getId, amount);
|
||||
|
||||
borrowerOperations.withdrawLUSD(maxFeePercentage, _amount, upperHint, lowerHint);
|
||||
|
||||
setUint(setId, _amount);
|
||||
|
||||
_eventName = "LogBorrow(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), _amount, getId, 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 amount of LUSD from
|
||||
* @param setId Optional storage slot to store the final amount of LUSD repaid
|
||||
*/
|
||||
function repay(
|
||||
uint amount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint getId,
|
||||
uint setId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint _amount = getUint(getId, amount);
|
||||
|
||||
if (_amount == uint(-1)) {
|
||||
uint _lusdBal = lusdToken.balanceOf(address(this));
|
||||
uint _totalDebt = troveManager.getTroveDebt(address(this));
|
||||
_amount = _lusdBal > _totalDebt ? _totalDebt : _lusdBal;
|
||||
}
|
||||
|
||||
borrowerOperations.repayLUSD(_amount, upperHint, lowerHint);
|
||||
|
||||
setUint(setId, _amount);
|
||||
|
||||
_eventName = "LogRepay(address,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), _amount, getId, setId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 getIds Optional Get Ids for deposit, withdraw, borrow & repay
|
||||
* @param setIds Optional Set Ids for deposit, withdraw, borrow & repay
|
||||
*/
|
||||
function adjust(
|
||||
uint maxFeePercentage,
|
||||
uint depositAmount,
|
||||
uint withdrawAmount,
|
||||
uint borrowAmount,
|
||||
uint repayAmount,
|
||||
address upperHint,
|
||||
address lowerHint,
|
||||
uint[] memory getIds,
|
||||
uint[] memory setIds
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
AdjustTrove memory adjustTrove;
|
||||
|
||||
adjustTrove.maxFeePercentage = maxFeePercentage;
|
||||
|
||||
depositAmount = getUint(getIds[0], depositAmount);
|
||||
adjustTrove.depositAmount = depositAmount == uint(-1) ? address(this).balance : depositAmount;
|
||||
|
||||
withdrawAmount = getUint(getIds[1], withdrawAmount);
|
||||
adjustTrove.withdrawAmount = withdrawAmount == uint(-1) ? troveManager.getTroveColl(address(this)) : withdrawAmount;
|
||||
|
||||
adjustTrove.borrowAmount = getUint(getIds[2], borrowAmount);
|
||||
|
||||
repayAmount = getUint(getIds[3], repayAmount);
|
||||
if (repayAmount == uint(-1)) {
|
||||
uint _lusdBal = lusdToken.balanceOf(address(this));
|
||||
uint _totalDebt = troveManager.getTroveDebt(address(this));
|
||||
repayAmount = _lusdBal > _totalDebt ? _totalDebt : _lusdBal;
|
||||
}
|
||||
adjustTrove.repayAmount = repayAmount;
|
||||
|
||||
adjustTrove.isBorrow = borrowAmount > 0;
|
||||
|
||||
borrowerOperations.adjustTrove{value: adjustTrove.depositAmount}(
|
||||
adjustTrove.maxFeePercentage,
|
||||
adjustTrove.withdrawAmount,
|
||||
adjustTrove.borrowAmount,
|
||||
adjustTrove.isBorrow,
|
||||
upperHint,
|
||||
lowerHint
|
||||
);
|
||||
|
||||
setUint(setIds[0], adjustTrove.depositAmount);
|
||||
setUint(setIds[1], adjustTrove.withdrawAmount);
|
||||
setUint(setIds[2], adjustTrove.borrowAmount);
|
||||
setUint(setIds[3], adjustTrove.repayAmount);
|
||||
|
||||
_eventName = "LogAdjust(address,uint256,uint256,uint256,uint256,uint256,uint256[],uint256[])";
|
||||
_eventParam = abi.encode(address(this), maxFeePercentage, adjustTrove.depositAmount, adjustTrove.withdrawAmount, adjustTrove.borrowAmount, adjustTrove.repayAmount, getIds, setIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 payable 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(address(this), 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 amount of LUSD from
|
||||
* @param setDepositId Optional storage slot to store the final amount of LUSD deposited
|
||||
* @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 setDepositId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
amount = getUint(getDepositId, amount);
|
||||
|
||||
amount = amount == uint(-1) ? lusdToken.balanceOf(address(this)) : 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(setDepositId, amount);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLqtyGainId, lqtyGain);
|
||||
|
||||
_eventName = "LogStabilityDeposit(address,uint256,uint256,uint256,address,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), amount, ethGain, lqtyGain, frontendTag, getDepositId, setDepositId, 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 getWithdrawId Optional storage slot to retrieve the amount of LUSD to withdraw from
|
||||
* @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 getWithdrawId,
|
||||
uint setWithdrawId,
|
||||
uint setEthGainId,
|
||||
uint setLqtyGainId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
amount = getUint(getWithdrawId, amount);
|
||||
|
||||
amount = amount == uint(-1) ? stabilityPool.getCompoundedLUSDDeposit(address(this)) : amount;
|
||||
|
||||
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,uint256)";
|
||||
_eventParam = abi.encode(address(this), amount, ethGain, lqtyGain, getWithdrawId, 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 payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
uint amount = stabilityPool.getDepositorETHGain(address(this));
|
||||
stabilityPool.withdrawETHGainToTrove(upperHint, lowerHint);
|
||||
_eventName = "LogStabilityMoveEthGainToTrove(address,uint256)";
|
||||
_eventParam = abi.encode(address(this), 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 amount of LQTY to stake
|
||||
* @param setStakeId Optional storage slot to store the final staked amount (can differ if requested with max balance: uint(-1))
|
||||
* @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 setStakeId,
|
||||
uint setEthGainId,
|
||||
uint setLusdGainId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
amount = getUint(getStakeId, amount);
|
||||
amount = amount == uint(-1) ? lqtyToken.balanceOf(address(this)) : amount;
|
||||
|
||||
uint ethGain = staking.getPendingETHGain(address(this));
|
||||
uint lusdGain = staking.getPendingLUSDGain(address(this));
|
||||
|
||||
staking.stake(amount);
|
||||
setUint(setStakeId, amount);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLusdGainId, lusdGain);
|
||||
|
||||
_eventName = "LogStake(address,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), amount, getStakeId, setStakeId, 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 getUnstakeId Optional storage slot to retrieve the amount of LQTY to unstake
|
||||
* @param setUnstakeId 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 getUnstakeId,
|
||||
uint setUnstakeId,
|
||||
uint setEthGainId,
|
||||
uint setLusdGainId
|
||||
) external payable returns (string memory _eventName, bytes memory _eventParam) {
|
||||
amount = getUint(getUnstakeId, amount);
|
||||
amount = amount == uint(-1) ? staking.stakes(address(this)) : amount;
|
||||
|
||||
uint ethGain = staking.getPendingETHGain(address(this));
|
||||
uint lusdGain = staking.getPendingLUSDGain(address(this));
|
||||
|
||||
staking.unstake(amount);
|
||||
setUint(setUnstakeId, amount);
|
||||
setUint(setEthGainId, ethGain);
|
||||
setUint(setLusdGainId, lusdGain);
|
||||
|
||||
_eventName = "LogUnstake(address,uint256,uint256,uint256,uint256,uint256)";
|
||||
_eventParam = abi.encode(address(this), amount, getUnstakeId, setUnstakeId, 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 payable 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(address(this), ethGain, lusdGain, setEthGainId, setLusdGainId);
|
||||
}
|
||||
/* End: Staking */
|
||||
|
||||
}
|
||||
|
||||
contract ConnectV2Liquity is LiquityResolver {
|
||||
string public name = "Liquity-v1";
|
||||
}
|
|
@ -37,8 +37,7 @@ abstract contract Helpers is DSMath, Basic {
|
|||
* @dev Return Reflexer mapping Address.
|
||||
*/
|
||||
function getGebMappingAddress() internal pure returns (address) {
|
||||
// TODO: Set the real deployed Reflexer mapping address
|
||||
return 0x0000000000000000000000000000000000000000;
|
||||
return 0x573e5132693C046D1A9F75Bac683889164bA41b4;
|
||||
}
|
||||
|
||||
function getCollateralJoinAddress(bytes32 collateralType) internal view returns (address) {
|
||||
|
|
|
@ -20,8 +20,7 @@ contract Helpers {
|
|||
ConnectorsInterface public constant connectors = ConnectorsInterface(0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11); // InstaConnectorsV2
|
||||
IndexInterface public constant instaIndex = IndexInterface(0x2971AdFa57b20E5a416aE5a708A8655A9c74f723);
|
||||
|
||||
// TODO: add address for MappingController
|
||||
MappingControllerInterface public constant mappingController = MappingControllerInterface(address(0));
|
||||
MappingControllerInterface public constant mappingController = MappingControllerInterface(0xDdd075D5e1024901E4038461e1e4BbC3A48a08d4);
|
||||
uint public version = 1;
|
||||
|
||||
mapping (bytes32 => address) public collateralJoinMapping;
|
||||
|
@ -55,8 +54,8 @@ contract Helpers {
|
|||
|
||||
}
|
||||
|
||||
contract GebMapping is Helpers {
|
||||
string constant public name = "Reflexer-Mapping-v1";
|
||||
contract InstaReflexerGebMapping is Helpers {
|
||||
string constant public name = "Reflexer-Geb-Mapping-v1";
|
||||
|
||||
constructor() public {
|
||||
address[] memory collateralJoins = new address[](1);
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
{
|
||||
"connectors":
|
||||
{
|
||||
"connectors": {
|
||||
"1" : {
|
||||
"AUTHORITY-A": "0x351Bb32e90C35647Df7a584f3c1a3A0c38F31c68",
|
||||
"BASIC-A": "0x9926955e0Dd681Dc303370C52f4Ad0a4dd061687",
|
||||
|
@ -24,7 +23,8 @@
|
|||
"MAKERDAO-CLAIM-A": "0x2f8cBE650af98602a215b6482F2aD60893C5A4E8",
|
||||
"WETH-A": "0x22075fa719eFb02Ca3cF298AFa9C974B7465E5D3",
|
||||
"REFINANCE-A": "0x9eA34bE6dA51aa9F6408FeA79c946FDCFA424442",
|
||||
"INST-A": "0x52C2C4a0db049255fF345EB9D3Fb1f555b7a924A"
|
||||
"INST-A": "0x52C2C4a0db049255fF345EB9D3Fb1f555b7a924A",
|
||||
"REFLEXER-A": "0xaC6dc28a6251F49Bbe5755E630107Dccde9ae2C8"
|
||||
},
|
||||
"137" : {
|
||||
"1INCH-A": "0xC0d9210496afE9763F5d8cEb8deFfBa817232A9e",
|
||||
|
@ -38,5 +38,6 @@
|
|||
"mappings": {
|
||||
"InstaMappingController": "0xDdd075D5e1024901E4038461e1e4BbC3A48a08d4",
|
||||
"InstaCompoundMapping": "0xe7a85d0adDB972A4f0A4e57B698B37f171519e88"
|
||||
"InstaReflexerGebMapping": "0x573e5132693C046D1A9F75Bac683889164bA41b4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
|
||||
require("@nomiclabs/hardhat-waffle");
|
||||
require("@nomiclabs/hardhat-ethers");
|
||||
require("@tenderly/hardhat-tenderly");
|
||||
require("@nomiclabs/hardhat-etherscan");
|
||||
require("@nomiclabs/hardhat-web3")
|
||||
require("@nomiclabs/hardhat-web3");
|
||||
require("hardhat-deploy");
|
||||
require("hardhat-deploy-ethers");
|
||||
require('dotenv').config();
|
||||
require("dotenv").config();
|
||||
|
||||
const { utils } = require("ethers");
|
||||
|
||||
|
@ -28,32 +27,32 @@ module.exports = {
|
|||
settings: {
|
||||
optimizer: {
|
||||
enabled: false,
|
||||
runs: 200
|
||||
}
|
||||
}
|
||||
runs: 200,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
version: "0.6.0"
|
||||
version: "0.6.0",
|
||||
},
|
||||
{
|
||||
version: "0.6.2"
|
||||
version: "0.6.2",
|
||||
},
|
||||
{
|
||||
version: "0.6.5"
|
||||
}
|
||||
]
|
||||
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}`,
|
||||
accounts: [`0x${PRIVATE_KEY}`],
|
||||
timeout: 150000,
|
||||
gasPrice: parseInt(utils.parseUnits("30", "gwei"))
|
||||
gasPrice: parseInt(utils.parseUnits("30", "gwei")),
|
||||
},
|
||||
hardhat: {
|
||||
forking: {
|
||||
|
@ -66,17 +65,17 @@ module.exports = {
|
|||
url: "https://rpc-mainnet.maticvigil.com/",
|
||||
accounts: [`0x${PRIVATE_KEY}`],
|
||||
timeout: 150000,
|
||||
gasPrice: parseInt(utils.parseUnits("1", "gwei"))
|
||||
}
|
||||
gasPrice: parseInt(utils.parseUnits("1", "gwei")),
|
||||
},
|
||||
},
|
||||
etherscan: {
|
||||
apiKey: process.env.ETHERSCAN_API_KEY
|
||||
apiKey: process.env.ETHERSCAN_API_KEY,
|
||||
},
|
||||
tenderly: {
|
||||
project: process.env.TENDERLY_PROJECT,
|
||||
username: process.env.TENDERLY_USERNAME,
|
||||
},
|
||||
mocha: {
|
||||
timeout: 100 * 1000
|
||||
}
|
||||
timeout: 100 * 1000,
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
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"),
|
||||
"INSTAPOOL-A": require("./abi/connectors/instapool.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"),
|
||||
"INSTAPOOL-A": require("./abi/connectors/instapool.json"),
|
||||
},
|
||||
basic: {
|
||||
erc20: require("./abi/basics/erc20.json"),
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
module.exports = {
|
||||
connectors: {
|
||||
basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
|
||||
auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
|
||||
"INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2"
|
||||
},
|
||||
core: {
|
||||
connectorsV2: "0x97b0B3A8bDeFE8cB9563a3c610019Ad10DB8aD11",
|
||||
instaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723",
|
||||
}
|
||||
};
|
||||
|
||||
connectors: {
|
||||
basic: "0xe5398f279175962E56fE4c5E0b62dc7208EF36c6",
|
||||
auth: "0xd1aff9f2acf800c876c409100d6f39aea93fc3d9",
|
||||
"INSTAPOOL-A": "0x5806af7ab22e2916fa582ff05731bf7c682387b2",
|
||||
},
|
||||
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,
|
||||
};
|
344
test/liquity/liquity.helpers.js
Normal file
344
test/liquity/liquity.helpers.js
Normal file
|
@ -0,0 +1,344 @@
|
|||
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],
|
||||
[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,
|
||||
};
|
2708
test/liquity/liquity.test.js
Normal file
2708
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