forked from unitprotocol/core
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request unitprotocol#29 from unitprotocol/dev
Dev
- Loading branch information
Showing
10 changed files
with
270 additions
and
48 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
// SPDX-License-Identifier: bsl-1.1 | ||
|
||
/* | ||
Copyright 2020 Unit Protocol: Artem Zakharov ([email protected]). | ||
*/ | ||
pragma solidity 0.7.6; | ||
|
||
import "../VaultParameters.sol"; | ||
import "../interfaces/IForceTransferAssetStore.sol"; | ||
|
||
|
||
/** | ||
* @title ForceTransferAssetStore | ||
**/ | ||
contract ForceTransferAssetStore is Auth, IForceTransferAssetStore { | ||
|
||
/* | ||
Mapping of assets that require a transfer of at least 1 unit of token | ||
to update internal logic related to staking rewards in case of full liquidation | ||
*/ | ||
mapping(address => bool) public override shouldForceTransfer; | ||
|
||
event ForceTransferAssetAdded(address indexed asset); | ||
|
||
constructor(address _vaultParameters, address[] memory initialAssets) Auth(_vaultParameters) { | ||
for (uint i = 0; i < initialAssets.length; i++) { | ||
require(!shouldForceTransfer[initialAssets[i]], "Unit Protocol: Already exists"); | ||
shouldForceTransfer[initialAssets[i]] = true; | ||
emit ForceTransferAssetAdded(initialAssets[i]); | ||
} | ||
} | ||
|
||
/** | ||
* @notice Only manager is able to call this function | ||
* @dev Mark asset as `shouldForceTransfer` | ||
* @param asset The address of the asset | ||
**/ | ||
function add(address asset) external override onlyManager { | ||
require(!shouldForceTransfer[asset], "Unit Protocol: Already exists"); | ||
require(asset != address(0), "Unit Protocol: ZERO_ADDRESS"); | ||
shouldForceTransfer[asset] = true; | ||
emit ForceTransferAssetAdded(asset); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
interface IForceTransferAssetStore { | ||
function shouldForceTransfer ( address ) external view returns ( bool ); | ||
function add ( address asset ) external; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
interface IcyToken { | ||
function underlying() external view returns (address); | ||
function implementation() external view returns (address); | ||
function decimals() external view returns (uint8); | ||
function exchangeRateStored() external view returns (uint); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
// SPDX-License-Identifier: bsl-1.1 | ||
|
||
pragma solidity 0.7.6; | ||
|
||
import "../helpers/SafeMath.sol"; | ||
import "../helpers/ERC20Like.sol"; | ||
import "../interfaces/IcyToken.sol"; | ||
import "../interfaces/IOracleUsd.sol"; | ||
import "../interfaces/IOracleRegistry.sol"; | ||
import "../interfaces/IOracleEth.sol"; | ||
import "../VaultParameters.sol"; | ||
|
||
/** | ||
* @title CyTokensOracle | ||
* @dev Wrapper to quote cyToken assets like cyWETH, cyDAI, cyUSDT, cyUSDC | ||
* @dev cyToken list: https://docs.cream.finance/iron-bank/iron-bank#yearn-token-cytoken | ||
**/ | ||
|
||
contract CyTokenOracle is IOracleUsd, Auth { | ||
using SafeMath for uint; | ||
|
||
uint constant expScale = 1e18; | ||
|
||
address public cytokenImplementation; | ||
|
||
IOracleRegistry public immutable oracleRegistry; | ||
|
||
event NewImplementation(address indexed implementation); | ||
|
||
constructor(address _vaultParameters, address _oracleRegistry, address _cytokenImplementation) Auth(_vaultParameters) { | ||
require(_vaultParameters != address(0) && _oracleRegistry != address(0), "Unit Protocol: ZERO_ADDRESS"); | ||
oracleRegistry = IOracleRegistry(_oracleRegistry); | ||
cytokenImplementation = _cytokenImplementation; | ||
} | ||
|
||
function setNewImplementation(address newImplementation) external onlyManager { | ||
cytokenImplementation = newImplementation; | ||
emit NewImplementation(newImplementation); | ||
} | ||
|
||
// returns Q112-encoded value | ||
function assetToUsd(address bearing, uint amount) public override view returns (uint) { | ||
if (amount == 0) return 0; | ||
(address underlying, uint underlyingAmount) = bearingToUnderlying(bearing, amount); | ||
IOracleUsd _oracleForUnderlying = IOracleUsd(oracleRegistry.oracleByAsset(underlying)); | ||
require(address(_oracleForUnderlying) != address(0), "Unit Protocol: ORACLE_NOT_FOUND"); | ||
return _oracleForUnderlying.assetToUsd(underlying, underlyingAmount); | ||
} | ||
|
||
function bearingToUnderlying(address bearing, uint amount) public view returns (address, uint) { | ||
address _underlying = IcyToken(bearing).underlying(); | ||
require(_underlying != address(0), "Unit Protocol: UNDEFINED_UNDERLYING"); | ||
address _implementation = IcyToken(bearing).implementation(); | ||
require(_implementation == cytokenImplementation, "Unit Protocol: CYTOKEN_IMPLEMENTATION_CHANGED"); | ||
uint _exchangeRateStored = IcyToken(bearing).exchangeRateStored(); | ||
uint _totalSupply = ERC20Like(bearing).totalSupply(); | ||
require(amount <= _totalSupply, "Unit Protocol: AMOUNT_EXCEEDS_SUPPLY"); | ||
return (_underlying, amount.mul(_exchangeRateStored).div(expScale)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
// SPDX-License-Identifier: bsl-1.1 | ||
|
||
/* | ||
Copyright 2020 Unit Protocol: Artem Zakharov ([email protected]). | ||
*/ | ||
pragma solidity 0.7.6; | ||
|
||
import "./EmptyToken.sol"; | ||
|
||
|
||
contract CyWETH is EmptyToken { | ||
|
||
address public underlying; | ||
|
||
address public implementation; | ||
|
||
uint public exchangeRateStoredInternal; | ||
|
||
constructor( | ||
uint _totalSupply, | ||
address _underlying, | ||
address _implementation, | ||
uint _exchangeRateStoredInternal | ||
) EmptyToken( | ||
"Yearn Wrapped Ether", | ||
"cyWETH", | ||
8, | ||
_totalSupply, | ||
msg.sender | ||
) | ||
public { | ||
underlying = _underlying; | ||
implementation = _implementation; | ||
exchangeRateStoredInternal = _exchangeRateStoredInternal; | ||
} | ||
|
||
function exchangeRateStored() public view returns (uint) { | ||
return exchangeRateStoredInternal; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
const BN = web3.utils.BN | ||
const { expect } = require('chai') | ||
const utils = require('./helpers/utils') | ||
|
||
const Q112 = new BN('2').pow(new BN('112')) | ||
|
||
contract('CyTokenOracle', function([ | ||
account1, | ||
foundation, | ||
]) { | ||
// deploy & initial settings | ||
beforeEach(async function() { | ||
this.utils = utils(this, 'cyWETHsample') | ||
this.deployer = account1 | ||
this.foundation = foundation; | ||
await this.utils.deploy() | ||
}); | ||
|
||
it('Should check implementation of cyWETH with data from CyTokenOracle', async function () { | ||
const oracleImplementation = await this.CyTokenOracle.cytokenImplementation(); | ||
const tokenImplementation = await this.cyWETH.implementation(); | ||
expect(tokenImplementation).to.equal(oracleImplementation); | ||
}); | ||
|
||
it('Should check that underlying of cyWETH equal to WETH address', async function () { | ||
const underlying = await this.cyWETH.underlying(); | ||
expect(underlying).to.equal(this.weth.address); | ||
}); | ||
|
||
let cyWETHamount = 20000000000; | ||
|
||
it('Should check that cyWETH totalSupply not less then cyWETH amount', async function () { | ||
const supply = await this.cyWETH.totalSupply(); | ||
expect(!(supply < cyWETHamount)).to.be.true; | ||
}); | ||
|
||
it('Should quote cyWETH', async function () { | ||
const storedRate = await this.cyWETH.exchangeRateStored(); | ||
const rate = await this.CyTokenOracle.bearingToUnderlying(this.cyWETH.address, cyWETHamount); | ||
// since 1 WETH token costs 250$ | ||
const expectedUsdValue_q112 = rate[1].mul(Q112).mul(new BN('250')); | ||
const usd_q112 = await this.CyTokenOracle.assetToUsd(this.cyWETH.address, cyWETHamount); | ||
expect(usd_q112).to.be.bignumber.equal(expectedUsdValue_q112); | ||
}); | ||
}); |
Oops, something went wrong.