mirror of
https://github.com/Instadapp/dsa-resolvers-deprecated.git
synced 2024-07-29 22:38:16 +00:00
Merge pull request #1 from liquity/add-liquity-resolver
Instadapp: add Liquity resolver (read-only positional data)
This commit is contained in:
commit
65a02a4fa2
|
|
@ -28,7 +28,7 @@ contract Resolver {
|
||||||
tokensBal[i] = Balances({
|
tokensBal[i] = Balances({
|
||||||
flusher: flushers[i],
|
flusher: flushers[i],
|
||||||
balance: bals,
|
balance: bals,
|
||||||
isDeployed: isContractDeployed(flushers[i]);
|
isDeployed: isContractDeployed(flushers[i])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return tokensBal;
|
return tokensBal;
|
||||||
|
|
|
||||||
127
contracts/protocols/mainnet/liquity.sol
Normal file
127
contracts/protocols/mainnet/liquity.sol
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
pragma solidity ^0.6.0;
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
|
interface TroveManagerLike {
|
||||||
|
function getBorrowingRateWithDecay() external view returns (uint);
|
||||||
|
function getTCR(uint _price) external view returns (uint);
|
||||||
|
function getCurrentICR(address _borrower, uint _price) external view returns (uint);
|
||||||
|
function checkRecoveryMode(uint _price) external view returns (bool);
|
||||||
|
function getEntireDebtAndColl(address _borrower) external view returns (
|
||||||
|
uint debt,
|
||||||
|
uint coll,
|
||||||
|
uint pendingLUSDDebtReward,
|
||||||
|
uint pendingETHReward
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StabilityPoolLike {
|
||||||
|
function getCompoundedLUSDDeposit(address _depositor) external view returns (uint);
|
||||||
|
function getDepositorETHGain(address _depositor) external view returns (uint);
|
||||||
|
function getDepositorLQTYGain(address _depositor) external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StakingLike {
|
||||||
|
function stakes(address owner) external view returns (uint);
|
||||||
|
function getPendingETHGain(address _user) external view returns (uint);
|
||||||
|
function getPendingLUSDGain(address _user) external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PoolLike {
|
||||||
|
function getETH() external view returns (uint);
|
||||||
|
}
|
||||||
|
|
||||||
|
contract DSMath {
|
||||||
|
function add(uint x, uint y) internal pure returns (uint z) {
|
||||||
|
require((z = x + y) >= x, "math-not-safe");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract Helpers is DSMath {
|
||||||
|
TroveManagerLike internal constant troveManager =
|
||||||
|
TroveManagerLike(0xA39739EF8b0231DbFA0DcdA07d7e29faAbCf4bb2);
|
||||||
|
|
||||||
|
StabilityPoolLike internal constant stabilityPool =
|
||||||
|
StabilityPoolLike(0x66017D22b0f8556afDd19FC67041899Eb65a21bb);
|
||||||
|
|
||||||
|
StakingLike internal constant staking =
|
||||||
|
StakingLike(0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d);
|
||||||
|
|
||||||
|
PoolLike internal constant activePool =
|
||||||
|
PoolLike(0xDf9Eb223bAFBE5c5271415C75aeCD68C21fE3D7F);
|
||||||
|
|
||||||
|
PoolLike internal constant defaultPool =
|
||||||
|
PoolLike(0x896a3F03176f05CFbb4f006BfCd8723F2B0D741C);
|
||||||
|
|
||||||
|
struct Trove {
|
||||||
|
uint collateral;
|
||||||
|
uint debt;
|
||||||
|
uint icr;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct StabilityDeposit {
|
||||||
|
uint deposit;
|
||||||
|
uint ethGain;
|
||||||
|
uint lqtyGain;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Stake {
|
||||||
|
uint amount;
|
||||||
|
uint ethGain;
|
||||||
|
uint lusdGain;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Position {
|
||||||
|
Trove trove;
|
||||||
|
StabilityDeposit stability;
|
||||||
|
Stake stake;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct System {
|
||||||
|
uint borrowFee;
|
||||||
|
uint ethTvl;
|
||||||
|
uint tcr;
|
||||||
|
bool isInRecoveryMode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
contract Resolver is Helpers {
|
||||||
|
function getTrove(address owner, uint oracleEthPrice) public view returns (Trove memory) {
|
||||||
|
(uint debt, uint collateral, , ) = troveManager.getEntireDebtAndColl(owner);
|
||||||
|
uint icr = troveManager.getCurrentICR(owner, oracleEthPrice);
|
||||||
|
return Trove(collateral, debt, icr);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStabilityDeposit(address owner) public view returns (StabilityDeposit memory) {
|
||||||
|
uint deposit = stabilityPool.getCompoundedLUSDDeposit(owner);
|
||||||
|
uint ethGain = stabilityPool.getDepositorETHGain(owner);
|
||||||
|
uint lqtyGain = stabilityPool.getDepositorLQTYGain(owner);
|
||||||
|
return StabilityDeposit(deposit, ethGain, lqtyGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getStake(address owner) public view returns (Stake memory) {
|
||||||
|
uint amount = staking.stakes(owner);
|
||||||
|
uint ethGain = staking.getPendingETHGain(owner);
|
||||||
|
uint lusdGain = staking.getPendingLUSDGain(owner);
|
||||||
|
return Stake(amount, ethGain, lusdGain);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getPosition(address owner, uint oracleEthPrice) external view returns (Position memory) {
|
||||||
|
Trove memory trove = getTrove(owner, oracleEthPrice);
|
||||||
|
StabilityDeposit memory stability = getStabilityDeposit(owner);
|
||||||
|
Stake memory stake = getStake(owner);
|
||||||
|
return Position(trove, stability, stake);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSystemState(uint oracleEthPrice) external view returns (System memory) {
|
||||||
|
uint borrowFee = troveManager.getBorrowingRateWithDecay();
|
||||||
|
uint ethTvl = add(activePool.getETH(), defaultPool.getETH());
|
||||||
|
uint tcr = troveManager.getTCR(oracleEthPrice);
|
||||||
|
bool isInRecoveryMode = troveManager.checkRecoveryMode(oracleEthPrice);
|
||||||
|
return System(borrowFee, ethTvl, tcr, isInRecoveryMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
contract InstaLiquityResolver is Resolver {
|
||||||
|
string public constant name = "Liquity-Resolver-v1";
|
||||||
|
}
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
"description": "The smart contracts which simplifies read operations.",
|
"description": "The smart contracts which simplifies read operations.",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "echo \"Error: no test specified\" && exit 1"
|
"test": "hardhat test"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
|
|
|
||||||
129
test/liquity.js
Normal file
129
test/liquity.js
Normal file
|
|
@ -0,0 +1,129 @@
|
||||||
|
const { expect } = require("chai");
|
||||||
|
const hardhatConfig = require("../hardhat.config");
|
||||||
|
const { BigNumber } = hre.ethers;
|
||||||
|
|
||||||
|
// Deterministic block number to run these tests from on forked mainnet. If you change this, tests will break.
|
||||||
|
const BLOCK_NUMBER = 12478959;
|
||||||
|
|
||||||
|
// Liquity user with a Trove, Stability deposit, and Stake
|
||||||
|
const JUSTIN_SUN_ADDRESS = "0x903d12bf2c57a29f32365917c706ce0e1a84cce3";
|
||||||
|
|
||||||
|
// Liquity price oracle
|
||||||
|
const PRICE_FEED_ADDRESS = "0x4c517D4e2C851CA76d7eC94B805269Df0f2201De";
|
||||||
|
const PRICE_FEED_ABI = ["function fetchPrice() external returns (uint)"];
|
||||||
|
|
||||||
|
/* Begin: Mock test data (based on specified BLOCK_NUMBER and JUSTIN_SUN_ADDRESS) */
|
||||||
|
const expectedTrovePosition = [
|
||||||
|
/* collateral */ BigNumber.from("582880000000000000000000"),
|
||||||
|
/* debt */ BigNumber.from("372000200000000000000000000"),
|
||||||
|
/* icr */ BigNumber.from("3859882210893925325"),
|
||||||
|
];
|
||||||
|
const expectedStabilityPosition = [
|
||||||
|
/* deposit */ BigNumber.from("299979329615565997640451998"),
|
||||||
|
/* ethGain */ BigNumber.from("8629038660000000000"),
|
||||||
|
/* lqtyGain */ BigNumber.from("53244322633874479119945"),
|
||||||
|
];
|
||||||
|
const expectedStakePosition = [
|
||||||
|
/* amount */ BigNumber.from("981562996504090969804965"),
|
||||||
|
/* ethGain */ BigNumber.from("18910541408996344243"),
|
||||||
|
/* lusdGain */ BigNumber.from("66201062534511228032281"),
|
||||||
|
];
|
||||||
|
|
||||||
|
const expectedSystemState = [
|
||||||
|
/* borrowFee */ BigNumber.from("6900285109012952"),
|
||||||
|
/* ethTvl */ BigNumber.from("852500462432421494350957"),
|
||||||
|
/* tcr */ BigNumber.from("3250195441371082828"),
|
||||||
|
/* isInRecoveryMode */ false,
|
||||||
|
];
|
||||||
|
/* End: Mock test data */
|
||||||
|
|
||||||
|
describe("InstaLiquityResolver", () => {
|
||||||
|
let liquity;
|
||||||
|
let liquityPriceOracle;
|
||||||
|
|
||||||
|
before(async () => {
|
||||||
|
await resetHardhatBlockNumber(BLOCK_NUMBER); // Start tests from clean mainnet fork at BLOCK_NUMBER
|
||||||
|
|
||||||
|
const liquityFactory = await hre.ethers.getContractFactory(
|
||||||
|
"InstaLiquityResolver"
|
||||||
|
);
|
||||||
|
|
||||||
|
liquityPriceOracle = new hre.ethers.Contract(
|
||||||
|
PRICE_FEED_ADDRESS,
|
||||||
|
PRICE_FEED_ABI,
|
||||||
|
hre.ethers.provider
|
||||||
|
);
|
||||||
|
|
||||||
|
liquity = await liquityFactory.deploy();
|
||||||
|
await liquity.deployed();
|
||||||
|
});
|
||||||
|
|
||||||
|
it("deploys the resolver", () => {
|
||||||
|
expect(liquity.address).to.exist;
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getTrove()", () => {
|
||||||
|
it("returns a user's Trove position", async () => {
|
||||||
|
const oracleEthPrice = await liquityPriceOracle.callStatic.fetchPrice();
|
||||||
|
const trovePosition = await liquity.getTrove(
|
||||||
|
JUSTIN_SUN_ADDRESS,
|
||||||
|
oracleEthPrice
|
||||||
|
);
|
||||||
|
expect(trovePosition).to.eql(expectedTrovePosition);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getStabilityDeposit()", () => {
|
||||||
|
it("returns a user's Stability Pool position", async () => {
|
||||||
|
const stabilityPosition = await liquity.getStabilityDeposit(
|
||||||
|
JUSTIN_SUN_ADDRESS
|
||||||
|
);
|
||||||
|
expect(stabilityPosition).to.eql(expectedStabilityPosition);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getStake()", () => {
|
||||||
|
it("returns a user's Stake position", async () => {
|
||||||
|
const stakePosition = await liquity.getStake(JUSTIN_SUN_ADDRESS);
|
||||||
|
expect(stakePosition).to.eql(expectedStakePosition);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getPosition()", () => {
|
||||||
|
it("returns a user's Liquity position", async () => {
|
||||||
|
const oracleEthPrice = await liquityPriceOracle.callStatic.fetchPrice();
|
||||||
|
const position = await liquity.getPosition(
|
||||||
|
JUSTIN_SUN_ADDRESS,
|
||||||
|
oracleEthPrice
|
||||||
|
);
|
||||||
|
const expectedPosition = [
|
||||||
|
expectedTrovePosition,
|
||||||
|
expectedStabilityPosition,
|
||||||
|
expectedStakePosition,
|
||||||
|
];
|
||||||
|
expect(position).to.eql(expectedPosition);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe("getSystemState()", () => {
|
||||||
|
it("returns Liquity system state", async () => {
|
||||||
|
const oracleEthPrice = await liquityPriceOracle.callStatic.fetchPrice();
|
||||||
|
const systemState = await liquity.getSystemState(oracleEthPrice);
|
||||||
|
expect(systemState).to.eql(expectedSystemState);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
const resetHardhatBlockNumber = async (blockNumber) => {
|
||||||
|
return await hre.network.provider.request({
|
||||||
|
method: "hardhat_reset",
|
||||||
|
params: [
|
||||||
|
{
|
||||||
|
forking: {
|
||||||
|
jsonRpcUrl: hardhatConfig.networks.hardhat.forking.url,
|
||||||
|
blockNumber,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue
Block a user