Skip to content

Instantly share code, notes, and snippets.

@franckc
Last active January 27, 2021 21:56
Show Gist options
  • Save franckc/6fcec3a50386bbd38f9aaf1296ea0ea0 to your computer and use it in GitHub Desktop.
Save franckc/6fcec3a50386bbd38f9aaf1296ea0ea0 to your computer and use it in GitHub Desktop.
Deploy 12 - contracts diff
#> git diff deploy-011 master contracts
diff --git a/contracts/contracts/interfaces/IComptroller.sol b/contracts/contracts/interfaces/IComptroller.sol
new file mode 100644
index 00000000..8be07f69
--- /dev/null
+++ b/contracts/contracts/interfaces/IComptroller.sol
@@ -0,0 +1,9 @@
+pragma solidity 0.5.11;
+
+interface IComptroller {
+ /**
+ * @notice Claim all the comp accrued by holder in all markets
+ * @param holder The address to claim COMP for
+ */
+ function claimComp(address holder) external;
+}
diff --git a/contracts/contracts/interfaces/IVault.sol b/contracts/contracts/interfaces/IVault.sol
index d536de1e..51f37cc4 100644
--- a/contracts/contracts/interfaces/IVault.sol
+++ b/contracts/contracts/interfaces/IVault.sol
@@ -45,6 +45,10 @@ interface IVault {
function uniswapAddr() external view returns (address);
+ function setMaxSupplyDiff(uint256 _maxSupplyDiff) external;
+
+ function maxSupplyDiff() external view returns (uint256);
+
function supportAsset(address _asset) external;
function approveStrategy(address _addr) external;
diff --git a/contracts/contracts/mocks/MockCToken.sol b/contracts/contracts/mocks/MockCToken.sol
index e1fe8fa7..be64fa5b 100644
--- a/contracts/contracts/mocks/MockCToken.sol
+++ b/contracts/contracts/mocks/MockCToken.sol
@@ -19,8 +19,9 @@ contract MockCToken is ICERC20, ERC20, ERC20Detailed, ERC20Mintable {
// underlying = cToken * exchangeRate
// cToken = underlying / exchangeRate
uint256 exchangeRate;
+ address public comptroller;
- constructor(ERC20Detailed _underlyingToken)
+ constructor(ERC20Detailed _underlyingToken, address _comptroller)
public
ERC20Detailed("cMock", "cMK", 8)
{
@@ -36,6 +37,7 @@ contract MockCToken is ICERC20, ERC20, ERC20Detailed, ERC20Mintable {
exchangeRate = 1e18;
}
underlyingToken = _underlyingToken;
+ comptroller = _comptroller;
}
function mint(uint256 mintAmount) external returns (uint256) {
diff --git a/contracts/contracts/mocks/MockComptroller.sol b/contracts/contracts/mocks/MockComptroller.sol
new file mode 100644
index 00000000..938ef90f
--- /dev/null
+++ b/contracts/contracts/mocks/MockComptroller.sol
@@ -0,0 +1,5 @@
+pragma solidity 0.5.11;
+
+contract MockComptroller {
+ function claimComp(address _holder) external {}
+}
diff --git a/contracts/contracts/strategies/CompoundStrategy.sol b/contracts/contracts/strategies/CompoundStrategy.sol
index a918be7a..91156967 100644
--- a/contracts/contracts/strategies/CompoundStrategy.sol
+++ b/contracts/contracts/strategies/CompoundStrategy.sol
@@ -6,6 +6,7 @@ pragma solidity 0.5.11;
* @author Origin Protocol Inc
*/
import { ICERC20 } from "./ICompound.sol";
+import { IComptroller } from "../interfaces/IComptroller.sol";
import {
IERC20,
InitializableAbstractStrategy
@@ -14,6 +15,21 @@ import {
contract CompoundStrategy is InitializableAbstractStrategy {
event SkippedWithdrawal(address asset, uint256 amount);
+ /**
+ * @dev Collect accumulated COMP and send to Vault.
+ */
+ function collectRewardToken() external onlyVault nonReentrant {
+ // Claim COMP from Comptroller
+ ICERC20 cToken = _getCTokenFor(assetsMapped[0]);
+ IComptroller comptroller = IComptroller(cToken.comptroller());
+ comptroller.claimComp(address(this));
+ // Transfer COMP to Vault
+ IERC20 rewardToken = IERC20(rewardTokenAddress);
+ uint256 balance = rewardToken.balanceOf(address(this));
+ emit RewardTokenCollected(vaultAddress, balance);
+ rewardToken.safeTransfer(vaultAddress, balance);
+ }
+
/**
* @dev Deposit asset into Compound
* @param _asset Address of asset to deposit
diff --git a/contracts/contracts/strategies/ICompound.sol b/contracts/contracts/strategies/ICompound.sol
index cef7e170..11b50d3b 100644
--- a/contracts/contracts/strategies/ICompound.sol
+++ b/contracts/contracts/strategies/ICompound.sol
@@ -58,4 +58,9 @@ interface ICERC20 {
* @notice Get the supply rate per block for supplying the token to Compound.
*/
function supplyRatePerBlock() external view returns (uint256);
+
+ /**
+ * @notice Address of the Compound Comptroller.
+ */
+ function comptroller() external view returns (address);
}
diff --git a/contracts/contracts/strategies/ICurvePool.sol b/contracts/contracts/strategies/ICurvePool.sol
index 975ff0f7..b4c945c3 100644
--- a/contracts/contracts/strategies/ICurvePool.sol
+++ b/contracts/contracts/strategies/ICurvePool.sol
@@ -1,7 +1,7 @@
pragma solidity 0.5.11;
interface ICurvePool {
- function get_virtual_price() external returns (uint256);
+ function get_virtual_price() external view returns (uint256);
function add_liquidity(uint256[3] calldata _amounts, uint256 _min) external;
diff --git a/contracts/contracts/strategies/ThreePoolStrategy.sol b/contracts/contracts/strategies/ThreePoolStrategy.sol
index aa2fb950..f9e60f4e 100644
--- a/contracts/contracts/strategies/ThreePoolStrategy.sol
+++ b/contracts/contracts/strategies/ThreePoolStrategy.sol
@@ -34,7 +34,7 @@ contract ThreePoolStrategy is InitializableAbstractStrategy {
* @param _vaultAddress Address of the vault
* @param _rewardTokenAddress Address of CRV
* @param _asset Address of the supported asset
- * @param _pToken Correspond platform token addres (i.e. 3Crv)
+ * @param _pToken Correspond platform token address (i.e. 3Crv)
* @param _crvGaugeAddress Address of the Curve DAO gauge for this pool
* @param _crvMinterAddress Address of the CRV minter for rewards
*/
@@ -196,16 +196,19 @@ contract ThreePoolStrategy is InitializableAbstractStrategy {
view
returns (uint256 balance)
{
+ require(assetToPToken[_asset] != address(0), "Unsupported asset");
// LP tokens in this contract. This should generally be nothing as we
// should always stake the full balance in the Gauge, but include for
// safety
(, , uint256 totalPTokens) = _getTotalPTokens();
- balance = 0;
- if (totalPTokens > 0) {
- balance += ICurvePool(platformAddress).calc_withdraw_one_coin(
- totalPTokens,
- poolCoinIndex
- );
+ ICurvePool curvePool = ICurvePool(platformAddress);
+
+ uint256 pTokenTotalSupply = IERC20(assetToPToken[_asset]).totalSupply();
+ if (pTokenTotalSupply > 0) {
+ uint256 curveBalance = IERC20(_asset).balanceOf(address(curvePool));
+ if (curveBalance > 0) {
+ balance = totalPTokens.mul(curveBalance).div(pTokenTotalSupply);
+ }
}
}
diff --git a/contracts/contracts/token/OUSD.sol b/contracts/contracts/token/OUSD.sol
index dcabf171..74626651 100644
--- a/contracts/contracts/token/OUSD.sol
+++ b/contracts/contracts/token/OUSD.sol
@@ -256,7 +256,7 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
* @dev Mints new tokens, increasing totalSupply.
*/
function mint(address _account, uint256 _amount) external onlyVault {
- return _mint(_account, _amount);
+ _mint(_account, _amount);
}
/**
@@ -296,7 +296,7 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
* @dev Burns tokens, decreasing totalSupply.
*/
function burn(address account, uint256 amount) external onlyVault {
- return _burn(account, amount);
+ _burn(account, amount);
}
/**
@@ -312,6 +312,9 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
*/
function _burn(address _account, uint256 _amount) internal nonReentrant {
require(_account != address(0), "Burn from the zero address");
+ if (_amount == 0) {
+ return;
+ }
bool isNonRebasingAccount = _isNonRebasingAccount(_account);
uint256 creditAmount = _amount.mulTruncate(_creditsPerToken(_account));
@@ -361,44 +364,16 @@ contract OUSD is Initializable, InitializableERC20Detailed, Governable {
}
/**
- * @dev Is an account's balance non-rebasing, i.e. does not alter with rebases.
- * By default contracts are non-rebasing and EOA's are rebasing.
- * Or the address could have chosen to override this.
+ * @dev Is an account using rebasing accounting or non-rebasing accounting?
+ * Also, ensure contracts are non-rebasing if they have not opted in.
* @param _account Address of the account.
*/
function _isNonRebasingAccount(address _account) internal returns (bool) {
- RebaseOptions accountRebaseState = rebaseState[_account];
- if (accountRebaseState == RebaseOptions.OptIn) {
- // The address has chosen to be rebasing.
- return false;
- } else if (accountRebaseState == RebaseOptions.OptOut) {
- // The address has chosen to be non-rebasing.
- return true;
- } else {
- // The address has not chosen explicitly, so use the default
- // for its type.
- if (Address.isContract(_account)) {
- // Contracts default to be non-rebasing.
-
- // Migrate if needed, making sure the rebasing/non-rebasing
- // supply is updated and fixed credits per token is set
- // for this account.
- _ensureRebasingMigration(_account);
- return true;
- } else {
- // User accounts default to be rebasing.
-
- // Disallow contracts from interacting with OUSD if the following
- // sequence has occurred: The contract has self-destructed, been
- // recreated at the same address with CREATE2, and then is interacting
- // with OUSD again from the contract's constructor.
- require(
- nonRebasingCreditsPerToken[_account] == 0,
- "Previous Contract"
- );
- return false;
- }
+ bool isContract = Address.isContract(_account);
+ if (isContract && rebaseState[_account] == RebaseOptions.NotSet) {
+ _ensureRebasingMigration(_account);
}
+ return nonRebasingCreditsPerToken[_account] > 0;
}
/**
diff --git a/contracts/contracts/vault/VaultAdmin.sol b/contracts/contracts/vault/VaultAdmin.sol
index e96d85ec..e9f5f3a7 100644
--- a/contracts/contracts/vault/VaultAdmin.sol
+++ b/contracts/contracts/vault/VaultAdmin.sol
@@ -12,12 +12,12 @@ import { IUniswapV2Router } from "../interfaces/uniswap/IUniswapV2Router02.sol";
contract VaultAdmin is VaultStorage {
/**
- * @dev Verifies that the caller is the Vault or Governor.
+ * @dev Verifies that the caller is the Vault, Governor, or Strategist.
*/
- modifier onlyVaultOrGovernor() {
+ modifier onlyVaultOrGovernorOrStrategist() {
require(
- msg.sender == address(this) || isGovernor(),
- "Caller is not the Vault or Governor"
+ msg.sender == address(this) || msg.sender == strategistAddr || isGovernor(),
+ "Caller is not the Vault, Governor, or Strategist"
);
_;
}
@@ -240,7 +240,7 @@ contract VaultAdmin is VaultStorage {
/**
* @dev Set the deposit paused flag to true to prevent rebasing.
*/
- function pauseRebase() external onlyGovernor {
+ function pauseRebase() external onlyGovernorOrStrategist {
rebasePaused = true;
emit RebasePaused();
}
@@ -264,7 +264,7 @@ contract VaultAdmin is VaultStorage {
/**
* @dev Set the deposit paused flag to false to enable capital movement.
*/
- function unpauseCapital() external onlyGovernorOrStrategist {
+ function unpauseCapital() external onlyGovernor {
capitalPaused = false;
emit CapitalUnpaused();
}
@@ -283,6 +283,7 @@ contract VaultAdmin is VaultStorage {
external
onlyGovernor
{
+ require(!assets[_asset].isSupported, "Only unsupported assets");
IERC20(_asset).safeTransfer(governor(), _amount);
}
@@ -290,7 +291,7 @@ contract VaultAdmin is VaultStorage {
* @dev Collect reward tokens from all strategies and swap for supported
* stablecoin via Uniswap
*/
- function harvest() external onlyGovernor {
+ function harvest() external onlyGovernorOrStrategist {
for (uint256 i = 0; i < allStrategies.length; i++) {
_harvest(allStrategies[i]);
}
@@ -298,12 +299,12 @@ contract VaultAdmin is VaultStorage {
/**
* @dev Collect reward tokens for a specific strategy and swap for supported
- * stablecoin via Uniswap
+ * stablecoin via Uniswap. Called from the vault.
* @param _strategyAddr Address of the strategy to collect rewards from
*/
function harvest(address _strategyAddr)
external
- onlyVaultOrGovernor
+ onlyVaultOrGovernorOrStrategist
returns (uint256[] memory)
{
return _harvest(_strategyAddr);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment