Skip to content

Commit

Permalink
Merge pull request #5 from studydefi/master
Browse files Browse the repository at this point in the history
Updating master branch
  • Loading branch information
marcelomorgado authored May 31, 2020
2 parents a57599d + 2fe8b6e commit e061e10
Show file tree
Hide file tree
Showing 16 changed files with 1,739 additions and 33 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,12 @@ Protocols supported:
- DappSys
- DyDx
- ERC20
- Idle V3
- Kyber.Network
- MakerDAO
- OneSplit
- UMA Protocol
- Uniswap v1
- Kyber.Network

Importing specific protocols is also supported:

Expand Down
4 changes: 3 additions & 1 deletion docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
- DappSys
- DyDx
- ERC20
- Idle V3
- Kyber.Network
- MakerDAO
- OneSplit
- UMA
- Uniswap v1
- Kyber.Network
1 change: 1 addition & 0 deletions docs/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
- [Compound](compound.md)
- [CurveFi](curvefi.md)
- [DyDx](dydx.md)
- [Idle V3](idle.md)
- [Kyber Network](kyber.md)
- [Maker](maker.md)
- [OneSplit](onesplit.md)
Expand Down
161 changes: 156 additions & 5 deletions docs/aave.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
_Special thanks to [mrdavey](https://github.com/mrdavey/) for his [ez-flashloan example](https://github.com/mrdavey/ez-flashloan)._

Flashloans are a bit tricky as they require you deploy a smart contract before you can start ultilizing it. The current standard way to interact with flashloans is by:

1. Deploying a smart contract with specific logic that will return you a profit (e.g. arbitrage, liquidating acounts).
2. Interacting with the application specific smart contract from step 1.

Expand All @@ -13,7 +14,8 @@ One thing to note about flashloan supported smart contracts is that they can get
### Flashloan Logic (Solidity)

Your smart contract will need to inherit from `FlashLoanReceiverBase` and have two functions:
1. An entrypoint function where __you__ call to initiate the flashloan (`initateFlashLoan` in the example below).

1. An entrypoint function where **you** call to initiate the flashloan (`initateFlashLoan` in the example below).
2. A callback function called `executeOperation` that contains the action logic to perform once the loan is given to us.

```js
Expand Down Expand Up @@ -98,14 +100,14 @@ const contractWithFlashLoanAddress =
const contractWithFlashLoan = new ethers.Contract(
contractWithFlashLoanAddress,
ContractWithFlashLoanArtifact.abi,
wallet
wallet,
);

const main = async () => {
// Encoding our custom data
const myCustomDataEncoded = ethers.utils.defaultAbiCoder.encode(
["address", "uint"],
["0x0000000000000000000000000000000000000000", 42]
["0x0000000000000000000000000000000000000000", 42],
);

const tx = await contractWithFlashLoan.initateFlashLoan(
Expand All @@ -115,8 +117,157 @@ const main = async () => {
myCustomDataEncoded, // _params encoded
{
gasLimit: 4000000,
}
},
);
await tx.wait();
};
```
```

## Examples (JavaScript)

### Supplying/Borrowing Tokens

```js
// ../tests/aave.test.ts#L43-L62

test("lend 10 ETH (i.e. mint aETH)", async () => {
// given
const ethToLend = 10;
const before = await aEthContract.balanceOf(wallet.address);

// when
const { address: reserveAddress } = erc20.eth;
const amount = parseEther(ethToLend.toString());
const referralCode = "0";
await lendingPool.deposit(reserveAddress, amount, referralCode, {
gasLimit: 1500000,
value: amount,
});

// then
const after = await aEthContract.balanceOf(wallet.address);

const ethLended = parseFloat(fromWei(after.sub(before)));
expect(ethLended).toBeCloseTo(ethToLend);
});
```

```js
// ../tests/aave.test.ts#L64-L85

test("borrow 20 DAI", async () => {
// given
const before = await daiContract.balanceOf(wallet.address);

// when
const { address: reserveAddress } = erc20.dai;
const amount = parseEther("20");
const interestRateMode = 1; // 1 = STABLE RATE, 2 = VARIABLE RATE
const referralCode = "0";
await lendingPool.borrow(
reserveAddress,
amount,
interestRateMode,
referralCode,
{ gasLimit: 1500000 },
);

// then
const after = await daiContract.balanceOf(wallet.address);
const daiBorrowed = parseFloat(fromWei(after.sub(before)));
expect(daiBorrowed).toBe(20);
});
```

### Retrieve Supply/Borrow Balance

```js
// ../tests/aave.test.ts#L111-L121

test("get supply/borrow balances for DAI", async () => {
// when
const {
currentATokenBalance: daiLended,
currentBorrowBalance: daiBorrowed,
} = await lendingPool.getUserReserveData(erc20.dai.address, wallet.address);

// then
expect(parseFloat(fromWei(daiBorrowed))).toBeCloseTo(20);
expect(parseFloat(fromWei(daiLended))).toBeCloseTo(5);
});
```

### Withdraw Supply

```js
// ../tests/aave.test.ts#L123-L139

test("withdraw 1 ETH from collateral", async () => {
// given
const ethBefore = await wallet.getBalance();
const ethToRedeem = 1;
const ethToRedeemInWei = parseEther(ethToRedeem.toString());

// when
await aEthContract.redeem(ethToRedeemInWei, {
gasLimit: 1500000,
});

// then
const ethAfter = await wallet.getBalance();

const ethGained = parseFloat(fromWei(ethAfter.sub(ethBefore)));
expect(ethGained).toBeCloseTo(ethToRedeem, 1);
});
```

### Repay Debt

```js
// ../tests/aave.test.ts#L141-L165

test("repay 1 DAI of debt", async () => {
// given
const daiToRepay = 1;
const daiToRepayInWei = parseEther(daiToRepay.toString());

const daiBefore = await daiContract.balanceOf(wallet.address);

// when
await daiContract.approve(aave.LendingPoolCore.address, daiToRepayInWei);

await lendingPool.repay(
erc20.dai.address,
daiToRepayInWei,
wallet.address,
{
gasLimit: 1500000,
},
);

// then
const daiAfter = await daiContract.balanceOf(wallet.address);

const daiSpent = parseFloat(fromWei(daiBefore.sub(daiAfter)));
expect(daiSpent).toBe(daiToRepay);
});
```

### Retrieve Health Factor

The health factor should be > 1 otherwise the user's positions can be liquidated.
See more: https://docs.aave.com/developers/developing-on-aave/the-protocol/lendingpool#liquidationcall

```js
// ../tests/aave.test.ts#L167-L175

test("retrieve current health factor", async () => {
// when
const { healthFactor } = await lendingPool.getUserAccountData(
wallet.address,
);

// then
expect(parseFloat(fromWei(healthFactor))).toBeGreaterThan(1);
});
```
63 changes: 63 additions & 0 deletions docs/idle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Idle (V3)

[Official Idle documentation](https://developers.idle.finance/)

## Examples

Import `@studydefi/money-legos/idle` package

```js
const idle = require("@studydefi/money-legos/idle");
```

List of all available contracts

```js
idle.maxYield.dai.address;
idle.maxYield.usdc.address;
idle.maxYield.usdt.address;

idle.riskAdjusted.dai.address;
idle.riskAdjusted.usdc.address;
idle.riskAdjusted.usdt.address;

idle.abi; // the same abi for each idle v3 contract

idle.decimals; // idle mints ERC-20 tokens
```

### JavaScript

#### `mintIdleToken`

```js
const { ethers } = require("ethers");
const erc20 = require("@studydefi/money-legos/erc20");
const idle = require("@studydefi/money-legos/idle");

const provider = new ethers.providers.JsonRpcProvider("http://localhost:8545");
const wallet = new ethers.Wallet(process.env.GANACHE_PRIV_KEY, provider);

// init contracts
const daiContract = new ethers.Contract(erc20.dai.address, erc20.abi, wallet);
const idleContract = new ethers.Contract(
idle.maxYield.dai.address,
idle.abi,
wallet,
);

// approve Idle to spend your DAI
const daiBalanceWei = await daiContract.balanceOf(wallet.address);
await daiContract.approve(idle.maxYield.dai.address, daiBalanceWei);

// mint idleDAIYield
await idleContract.mintIdleToken(daiBalanceWei, true, {
gasLimit: 4000000,
});

// check idleDAI balance
const idleDaiBalance = await idleContract.balanceOf(wallet.address);
console.log(
`idleDAI: ${ethers.utils.formatUnits(idleDaiBalance, idle.decimals)}`,
);
```
27 changes: 11 additions & 16 deletions docs/kyber.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,8 @@ contract KyberNetworkProxy is KyberNetworkProxyInterface, SimpleNetworkInterface
```js
const { ethers } = require("ethers");
const { getLegosFor, networks } = require("@studydefi/money-legos");

const legos = getLegosFor(networks.mainnet);
const erc20 = require("@studydefi/money-legos/erc20");
const kyber = require("@studydefi/money-legos/kyber");

const provider = new ethers.providers.JsonRpcProvider(
process.env.PROVIDER_URL || "http://localhost:8545",
Expand All @@ -69,20 +68,16 @@ const swapOnKyber = async (fromAddress, toAddress, fromAmountWei) => {
const minConversionRate = 1;

const kyberNetwork = new ethers.Contract(
legos.kyber.contracts.network.address,
legos.kyber.contracts.factnetworkry.abi,
kyber.network.address,
kyber.network.abi,
wallet,
);

// ERC20 contract
const fromTokenContract = new ethers.Contract(
fromAddress,
legos.erc20.contracts.abi,
wallet,
);
const fromTokenContract = new ethers.Contract(fromAddress, erc20.abi, wallet);

// ETH -> Token
if (fromAddress === legos.erc20.contracts.eth.address) {
if (fromAddress === erc20.eth.address) {
return kyberNetwork.swapEtherToToken(toAddress, minConversionRate, {
gasLimit,
value: fromAmountWei,
Expand All @@ -93,7 +88,7 @@ const swapOnKyber = async (fromAddress, toAddress, fromAmountWei) => {
await fromTokenContract.approve(kyberNetwork.address, fromAmountWei);

// Token -> ETH
if (toAddress === legos.erc20.contracts.eth.address) {
if (toAddress === erc20.eth.address) {
return fromExchangeContract.swapTokenToEther(
fromAddress,
fromAmountWei,
Expand Down Expand Up @@ -125,7 +120,7 @@ const swapAndLog = async (fromToken, toToken, amount) => {
ethers.utils.parseUnits(amount.toString(), fromToken.decimals),
);

if (toToken === legos.erc20.contracts.eth) {
if (toToken === erc20.eth) {
const ethBalWei = await wallet.getBalance();
console.log(
`${toToken.symbol} balance: ${ethers.utils.formatEther(ethBalWei)}`,
Expand All @@ -145,9 +140,9 @@ const swapAndLog = async (fromToken, toToken, amount) => {
};

const main = async () => {
await swapAndLog(legos.erc20.contracts.eth, legos.erc20.contracts.dai, 1);
await swapAndLog(legos.erc20.contracts.dai, legos.erc20.contracts.rep, 50);
await swapAndLog(legos.erc20.contracts.rep, legos.erc20.contracts.eth, 2);
await swapAndLog(erc20.eth, erc20.dai, 1);
await swapAndLog(erc20.dai, erc20.rep, 50);
await swapAndLog(erc20.rep, erc20.eth, 2);
};

main();
Expand Down
20 changes: 19 additions & 1 deletion docs/overview_mainnet_address.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
- cWBTC: [0xc11b1268c1a384e55c48c2391d8d480264a3a7f4](https://etherscan.io/address/0xc11b1268c1a384e55c48c2391d8d480264a3a7f4)
- cZRX: [0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407](https://etherscan.io/address/0xb3319f5d18bc0d84dd1b4825dcde5d5f7266d407)
- comptroller: [0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b](https://etherscan.io/address/0x3d9819210a31b4961b30ef54be2aed79b9c9cd3b)
- priceOracle: [0x1d8aedc9e924730dd3f9641cdb4d1b92b848b4bd](https://etherscan.io/address/0x1d8aedc9e924730dd3f9641cdb4d1b92b848b4bd)
- priceOracle: [0xDDc46a3B076aec7ab3Fc37420A8eDd2959764Ec4](https://etherscan.io/address/0xDDc46a3B076aec7ab3Fc37420A8eDd2959764Ec4)

## Curvefi

Expand Down Expand Up @@ -105,6 +105,24 @@
- weth: [0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2](https://etherscan.io/address/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)
- zrx: [0xE41d2489571d322189246DaFA5ebDe1F4699F498](https://etherscan.io/address/0xE41d2489571d322189246DaFA5ebDe1F4699F498)

## Idle

[Link to ABIs](https://github.com/studydefi/money-legos/tree/master/src/idle/abi)

#### maxYield


- dai: [0x78751b12da02728f467a44eac40f5cbc16bd7934](https://etherscan.io/address/0x78751b12da02728f467a44eac40f5cbc16bd7934)
- usdc: [0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6](https://etherscan.io/address/0x12B98C621E8754Ae70d0fDbBC73D6208bC3e3cA6)
- usdt: [0x63D27B3DA94A9E871222CB0A32232674B02D2f2D](https://etherscan.io/address/0x63D27B3DA94A9E871222CB0A32232674B02D2f2D)

#### riskAdjusted


- dai: [0x1846bdfDB6A0f5c473dEc610144513bd071999fB](https://etherscan.io/address/0x1846bdfDB6A0f5c473dEc610144513bd071999fB)
- usdc: [0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C](https://etherscan.io/address/0xcDdB1Bceb7a1979C6caa0229820707429dd3Ec6C)
- usdt: [0x42740698959761baf1b06baa51efbd88cb1d862b](https://etherscan.io/address/0x42740698959761baf1b06baa51efbd88cb1d862b)

## Kyber

[Link to ABIs](https://github.com/studydefi/money-legos/tree/master/src/kyber/abi)
Expand Down
Loading

0 comments on commit e061e10

Please sign in to comment.