Skip to content

Commit

Permalink
Add adapter for Stake DAO farm
Browse files Browse the repository at this point in the history
  • Loading branch information
gvladika committed Jul 4, 2021
1 parent f36b5c6 commit f651291
Show file tree
Hide file tree
Showing 3 changed files with 161 additions and 2 deletions.
81 changes: 81 additions & 0 deletions contracts/StakeDaoFarmAdapter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
//SPDX-License-Identifier: GPLV3
pragma solidity ^0.8.0;

import "./IAdapter.sol";
import "./Controller.sol";
import "./interfaces/StakeDaoInterfaces.sol";
import "./oz/token/ERC20/IERC20.sol";
import "hardhat/console.sol";

contract StakeDaoFarmAdapter is IAdapter {
address private controllerAddress;

constructor(address _controllerAddress) {
controllerAddress = _controllerAddress;
}

mapping(address => uint256) public userToStakedLpTokens;

function invest(
address onBehalfOf,
uint256[] calldata amounts,
address to,
address pullFrom,
address transferTo
) external payable override returns (uint256[] memory amountsTransferred) {
address inputToken = Controller(controllerAddress).getMarketInputTokens(
to
)[0];

(address market, , ) = Controller(controllerAddress).markets(to);

// transfer LP tokens to adapter
IERC20(inputToken).transferFrom(pullFrom, address(this), amounts[0]);
IERC20(inputToken).approve(market, amounts[0]);

// stake LP tokens into farm to get rewards
userToStakedLpTokens[onBehalfOf] += amounts[0];
IStakeDaoYieldFarm(market).deposit(0, amounts[0]);

return amounts;
}

function redeem(
address onBehalfOf,
uint256[] calldata amounts,
address from,
address pullFrom,
address transferTo
) external override returns (uint256[] memory amountsTransferred) {
(address market, , ) = Controller(controllerAddress).markets(from);

// unstake LP tokens from farm
require(userToStakedLpTokens[onBehalfOf] >= amounts[0]);
userToStakedLpTokens[onBehalfOf] -= amounts[0];
IStakeDaoYieldFarm(market).withdraw(0, amounts[0]);

// transfer LP tokens back to user
address inputToken = Controller(controllerAddress).getMarketInputTokens(
from
)[0];
IERC20(inputToken).transfer(transferTo, amounts[0]);

return amounts;
}

function borrow(
address onBehalfOf,
uint256[] calldata amounts,
address from,
address pullFrom,
address transferTo
) external override returns (uint256[] memory amountsTransferred) {}

function repay(
address onBehalfOf,
uint256[] calldata amounts,
address to,
address pullFrom,
address transferTo
) external payable override returns (uint256[] memory amountsTransferred) {}
}
6 changes: 6 additions & 0 deletions contracts/interfaces/StakeDaoInterfaces.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,10 @@ interface IStakeDaoYieldFarm {
function poolLength() external view returns (uint256);

function deposit(uint256 _pid, uint256 _amount) external;

function withdraw(uint256 _pid, uint256 _amount) external;

function userInfo(uint256 _pid, address _user)
external
returns (uint256, uint256);
}
76 changes: 74 additions & 2 deletions test/stakedao-test.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
const { expect, assert } = require("chai");
const { ethers } = require("hardhat");

let controller, stakeDaoAdapter, stakeDaoLpPool;
let controller, stakeDaoAdapter, stakeDaoFarmAdapter, stakeDaoLpPool;
let testAccount, testSigner;
let amount_of_sdam3Crv_staked;

const STAKE_DAO_LP = "0x7d60F21072b585351dFd5E8b17109458D97ec120";
const STAKE_DAO_YIELD_FARM = "0x68456B298c230415E2DE7aD4897A79Ee3f1A965a";
Expand All @@ -19,6 +20,12 @@ describe("StakeDaoAdapter", function () {

// get contracts
stakeDaoLpPool = await ethers.getContractAt("IStakeDaoLpPool", STAKE_DAO_LP, testSigner);
stakeDaoFarm = await ethers.getContractAt(
"IStakeDaoYieldFarm",
STAKE_DAO_YIELD_FARM,
testSigner
);

curveLpToken = await ethers.getContractAt("IERC20", CURVE_AAVE_LP_TOKEN, testSigner);

// deploy controller
Expand Down Expand Up @@ -87,7 +94,7 @@ describe("StakeDaoAdapter", function () {
const sdam3CrvBalanceBefore = await sdam3Crv.balanceOf(testAccount);

// approve LP token for burning and unstake
const sdam3CrvToUnstake = sdam3CrvBalanceBefore / 2;
const sdam3CrvToUnstake = sdam3CrvBalanceBefore.div(2);
await sdam3Crv.approve(stakeDaoAdapter.address, sdam3CrvToUnstake);
await stakeDaoAdapter.redeem(
testAccount,
Expand All @@ -104,6 +111,45 @@ describe("StakeDaoAdapter", function () {
assert(am3CrvBalanceBefore < am3CrvBalanceAfter);
assert(sdam3CrvBalanceBefore > sdam3CrvBalanceAfter);
});

it("should stake sdam3Crv to Stake Dao yield farm", async function () {
await initStakeDaoFarm();

const sdam3Crv = await ethers.getContractAt("IERC20", STAKE_DAO_LP, testSigner);
const sdam3CrvBalanceBefore = await sdam3Crv.balanceOf(testAccount);

// approve sdam3Crv and stake
await sdam3Crv.approve(stakeDaoFarmAdapter.address, sdam3CrvBalanceBefore);
await stakeDaoFarmAdapter.invest(
testAccount,
[sdam3CrvBalanceBefore],
STAKE_DAO_YIELD_FARM,
testAccount,
testAccount
);

amount_of_sdam3Crv_staked = sdam3CrvBalanceBefore;

const sdam3CrvBalanceAfter = await sdam3Crv.balanceOf(testAccount);
assert(sdam3CrvBalanceAfter < sdam3CrvBalanceBefore);
});

it("should unstake sdam3Crv from Stake Dao yield farm", async function () {
const sdam3Crv = await ethers.getContractAt("IERC20", STAKE_DAO_LP, testSigner);
const sdam3CrvBalanceBefore = await sdam3Crv.balanceOf(testAccount);

// unstake sdam3Crv
await stakeDaoFarmAdapter.redeem(
testAccount,
[amount_of_sdam3Crv_staked.div(2)],
STAKE_DAO_YIELD_FARM,
testAccount,
testAccount
);

const sdam3CrvBalanceAfter = await sdam3Crv.balanceOf(testAccount);
assert(sdam3CrvBalanceAfter > sdam3CrvBalanceBefore);
});
});

/**
Expand All @@ -127,6 +173,32 @@ async function initBalances(testAccount) {
});
}

/**
* Deploy and register Stake Dao adapter
*/
async function initStakeDaoFarm() {
// deploy Stake Dao adapter
const StakeDaoFarmAdapter = await ethers.getContractFactory("StakeDaoFarmAdapter");
tempAdapter = await StakeDaoFarmAdapter.deploy(controller.address);
await tempAdapter.deployed();
stakeDaoFarmAdapter = await ethers.getContractAt("IAdapter", tempAdapter.address, testSigner);

// add adapter and market data
await controller.addProtocolAdapter(
ethers.utils.formatBytes32String("Stake Dao farm adapter"),
stakeDaoAdapter.address
);
await controller.addMarket(
ethers.utils.formatBytes32String("Stake Dao farm adapter"),
STAKE_DAO_YIELD_FARM,
STAKE_DAO_YIELD_FARM,
STAKE_DAO_YIELD_FARM,
wMATIC,
[STAKE_DAO_LP],
[STAKE_DAO_TOKEN]
);
}

/**
* Format to ETH
*/
Expand Down

0 comments on commit f651291

Please sign in to comment.