Skip to content

Commit

Permalink
Merge branch 'feature/exchange-rate-getters' into feature/aave-v2
Browse files Browse the repository at this point in the history
  • Loading branch information
Evert0x committed Dec 24, 2020
2 parents b5947c7 + 445ea95 commit 37899f9
Show file tree
Hide file tree
Showing 14 changed files with 141 additions and 13 deletions.
8 changes: 8 additions & 0 deletions contracts/callManagers/LendingManager/LendingLogicAave.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,12 @@ contract LendingLogicAave is ILendingLogic {
return(targets, data);
}

function exchangeRate(address) external pure override returns(uint256) {
return 10**18;
}

function exchangeRateView(address) external pure override returns(uint256) {
return 10**18;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ contract LendingLogicCompound is Ownable, ILendingLogic {

return(targets, data);
}

function unlend(address _wrapped, uint256 _amount) external view override returns(address[] memory targets, bytes[] memory data) {
targets = new address[](1);
data = new bytes[](1);
Expand All @@ -72,4 +73,12 @@ contract LendingLogicCompound is Ownable, ILendingLogic {
return(targets, data);
}

function exchangeRate(address _wrapped) external override returns(uint256) {
return ICToken(_wrapped).exchangeRateCurrent();
}

function exchangeRateView(address _wrapped) external view override returns(uint256) {
return ICToken(_wrapped).exchangeRateStored();
}

}
14 changes: 14 additions & 0 deletions contracts/callManagers/LendingManager/StakeSushi.sol
Original file line number Diff line number Diff line change
Expand Up @@ -60,4 +60,18 @@ contract StakingLogicSushi is ILendingLogic {
return(targets, data);
}

function exchangeRate(address _wrapped) external view override returns(uint256) {
return _exchangeRate(_wrapped);
}

function exchangeRateView(address _wrapped) external view override returns(uint256) {
return _exchangeRate(_wrapped);
}

function _exchangeRate(address _wrapped) internal view returns(uint256) {
IERC20 xToken = IERC20(_wrapped);
IERC20 token = IERC20(lendingRegistry.wrappedToUnderlying(_wrapped));
return token.balanceOf(_wrapped) * 10**18 / xToken.totalSupply();
}

}
8 changes: 8 additions & 0 deletions contracts/callManagers/LendingManager/StakingLogicYGov.sol
Original file line number Diff line number Diff line change
Expand Up @@ -59,5 +59,13 @@ contract StakingLogicYGov is ILendingLogic {
function getAPRFromWrapped(address _token) external view override returns(uint256) {
return uint256(-1);
}

function exchangeRate(address _wrapped) external view override returns(uint256) {
return IYVault(_wrapped).getPricePerFullShare();
}

function exchangeRateView(address _wrapped) external view override returns(uint256) {
return IYVault(_wrapped).getPricePerFullShare();
}

}
2 changes: 2 additions & 0 deletions contracts/interfaces/ICToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,6 @@ interface ICToken {
function mint(uint _mintAmount) external returns (uint256);
function redeem(uint _redeemTokens) external returns (uint256);
function supplyRatePerBlock() external view returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function exchangeRateStored() external view returns(uint256);
}
14 changes: 14 additions & 0 deletions contracts/interfaces/ILendingLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,18 @@ interface ILendingLogic {
@return data Calldata of the calls
*/
function unlend(address _wrapped, uint256 _amount) external view returns(address[] memory targets, bytes[] memory data);

/**
@notice Get the underlying wrapped exchange rate
@param _wrapped Address of the wrapped token
@return The exchange rate
*/
function exchangeRate(address _wrapped) external returns(uint256);

/**
@notice Get the underlying wrapped exchange rate in a view (non state changing) way
@param _wrapped Address of the wrapped token
@return The exchange rate
*/
function exchangeRateView(address _wrapped) external view returns(uint256);
}
27 changes: 19 additions & 8 deletions contracts/test/MockCToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,23 @@ pragma experimental ABIEncoderV2;
pragma solidity ^0.7.1;

import "./MockToken.sol";
import "../interfaces/ICToken.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";


contract MockCToken is MockToken {
contract MockCToken is MockToken, ICToken {
using SafeMath for uint256;
// representable value taken from cEth
uint256 public exchangeRate = 1 ether / 5;
MockToken public underlying;
uint256 someValue;

uint256 public errorCode;
constructor(address _underlying) MockToken("cTOKEN", "cToken") public {
underlying = MockToken(_underlying);
}

function mint(uint256 _amount) external returns(uint256) {
function mint(uint256 _amount) external override returns(uint256) {
require(underlying.transferFrom(msg.sender, address(this), _amount), "MockCToken.mint: transferFrom failed");

uint256 mintAmount = _amount.mul(10**18).div(exchangeRate);
Expand All @@ -25,11 +28,7 @@ contract MockCToken is MockToken {
return errorCode;
}

function exchangeRateStored() external view returns(uint256) {
return exchangeRate;
}

function redeem(uint256 _amount) external returns(uint256) {
function redeem(uint256 _amount) external override returns(uint256) {
_burn(msg.sender, _amount);

uint256 underlyingAmount = _amount.mul(exchangeRate).div(10**18);
Expand All @@ -55,7 +54,19 @@ contract MockCToken is MockToken {
errorCode = _value;
}

function supplyRatePerBlock() external view returns (uint256) {
function supplyRatePerBlock() external override view returns (uint256) {
return 20000000000;
}

function exchangeRateCurrent() external override returns(uint256) {
// To make function state changing
someValue ++;
return exchangeRate;
}

function exchangeRateStored() external override view returns(uint256) {
// To make function non pure;
someValue;
return exchangeRate;
}
}
8 changes: 8 additions & 0 deletions contracts/test/MockLendingLogic.sol
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,12 @@ contract MockLendingLogic is ILendingLogic {
targets[0] = _wrapped;
data[0] = bytes(abi.encode(_amount));
}

function exchangeRate(address) external pure override returns(uint256) {
return 10**18;
}

function exchangeRateView(address) external pure override returns(uint256) {
return 10**18;
}
}
1 change: 1 addition & 0 deletions contracts/test/MockToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pragma solidity ^0.7.1;
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

contract MockToken is ERC20 {

constructor(string memory _name, string memory _symbol)
ERC20(_name, _symbol)
{}
Expand Down
1 change: 0 additions & 1 deletion contracts/test/MockXSushi.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ pragma solidity ^0.7.1;
import "./MockToken.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";


contract MockXSushi is MockToken {
using SafeMath for uint256;
uint256 public exchangeRate = 1 ether / 5;
Expand Down
12 changes: 12 additions & 0 deletions test/lendingLogicAave.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,5 +121,17 @@ describe("LendingLogicAave", function() {
const apr = await lendingLogic.getAPRFromWrapped(aToken.address);
expect(apr).to.eq(ethers.BigNumber.from("10").pow(16)) // one percent
})

it("exchangeRate()", async() => {
const exchangeRate = await lendingLogic.exchangeRate(aToken.address);
// 1 wrapped = 1
expect(exchangeRate).to.eq( ethers.BigNumber.from("10").pow(18))
})

it("exchangeRateView()", async() => {
const exchangeRate = await lendingLogic.exchangeRateView(aToken.address);
// 1 wrapped == 1
expect(exchangeRate).to.eq( ethers.BigNumber.from("10").pow(18))
})

});
13 changes: 13 additions & 0 deletions test/lendingLogicCompound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,4 +142,17 @@ describe("LendingLogicCompound", function() {
expect(apr).to.eq(ethers.BigNumber.from("10").pow(16).mul(4)) // 4 percent
})

it("exchangeRate()", async() => {
await cToken.exchangeRateCurrent()
await lendingLogic.exchangeRate(cToken.address);
})

it("exchangeRateView()", async() => {
const exchangeRate = await cToken.exchangeRateStored()
// 1 wrapped (8 decimals) = 0.2 (8 decimals)
expect(exchangeRate).to.eq(ethers.BigNumber.from("10").pow(17).mul(2))
const exchangeRateLending = await lendingLogic.exchangeRateView(cToken.address);
expect(exchangeRate).to.eq(exchangeRateLending)
})

});
17 changes: 17 additions & 0 deletions test/stakingLogicSushi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ describe("StakingLogicSushi", function() {

await lendingRegistry.setProtocolToLogic(PLACEHOLDER_PROTOCOL, lendingLogic.address);
await lendingRegistry.setWrappedToProtocol(xSUSHI.address, PLACEHOLDER_PROTOCOL);
await lendingRegistry.setWrappedToUnderlying(xSUSHI.address, token.address);
await lendingRegistry.setUnderlyingToProtocolWrapped(token.address, PLACEHOLDER_PROTOCOL, xSUSHI.address);

await timeTraveler.snapshot();
Expand Down Expand Up @@ -127,5 +128,21 @@ describe("StakingLogicSushi", function() {
const apr = await lendingLogic.getAPRFromWrapped(xSUSHI.address);
expect(apr).to.eq(ethers.BigNumber.from("2").pow(256).sub(1))
})

it("exchangeRate()", async() => {
await token.approve(xSUSHI.address, constants.MaxUint256);
await xSUSHI["mint(uint256)"](mintAmount);

await lendingLogic.exchangeRate(xSUSHI.address)
})

it("exchangeRateView()", async() => {
await token.approve(xSUSHI.address, constants.MaxUint256);
await xSUSHI["mint(uint256)"](mintAmount);

const exchangeRate = await lendingLogic.exchangeRateView(xSUSHI.address);
// 1 xToken = 0.2
expect(exchangeRate).to.eq(ethers.BigNumber.from("10").pow(16).mul(20))
})

});
20 changes: 16 additions & 4 deletions test/stakingLogicYVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ describe("StakingLogicYGov", function() {
signers = await ethers.getSigners();
account = await signers[0].getAddress();
timeTraveler = new TimeTraveler(ethereum);

const tokenFactory = new MockTokenFactory(signers[0]);
const yGOVFactory = new MockYVaultFactory(signers[0]);

Expand All @@ -50,11 +50,11 @@ describe("StakingLogicYGov", function() {

lendingRegistry = await (new LendingRegistryFactory(signers[0])).deploy();
lendingLogic = await deployContract(signers[0], StakingLogicYGovArtifact, [lendingRegistry.address, PLACEHOLDER_PROTOCOL]) as StakingLogicYGov;

await lendingRegistry.setProtocolToLogic(PLACEHOLDER_PROTOCOL, lendingLogic.address);
await lendingRegistry.setWrappedToProtocol(yGov.address, PLACEHOLDER_PROTOCOL);
await lendingRegistry.setUnderlyingToProtocolWrapped(token.address, PLACEHOLDER_PROTOCOL, yGov.address);

await timeTraveler.snapshot();
});

Expand Down Expand Up @@ -105,7 +105,7 @@ describe("StakingLogicYGov", function() {

expect(calls.targets.length).to.eq(1);
expect(calls.data.length).to.eq(1);

await signers[0].sendTransaction({
to: calls.targets[0],
data: calls.data[0]
Expand All @@ -118,4 +118,16 @@ describe("StakingLogicYGov", function() {
expect(yGovBalance).to.eq(0);
});

it("exchangeRate()", async() => {
const exchangeRate = await lendingLogic.exchangeRate(yGov.address);
// 1 wrapped = 0.2
expect(exchangeRate).to.eq(ethers.BigNumber.from("10").pow(16).mul(20))
})

it("exchangeRateView()", async() => {
const exchangeRate = await lendingLogic.exchangeRateView(yGov.address);
// 1 wrapped == 0.2
expect(exchangeRate).to.eq( ethers.BigNumber.from("10").pow(16).mul(20))
})

});

0 comments on commit 37899f9

Please sign in to comment.