Skip to content

Commit

Permalink
Merge branch 'master' into votes-wrapper
Browse files Browse the repository at this point in the history
  • Loading branch information
aazhou1 authored Oct 29, 2024
2 parents caf578b + e5384e4 commit f328305
Show file tree
Hide file tree
Showing 10 changed files with 91 additions and 58 deletions.
1 change: 1 addition & 0 deletions .github/workflows/deploy-sepolia-strategy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,5 @@ jobs:
REPOTOKEN_CONCENTRATION_LIMIT: ${{ github.event.inputs.repoTokenConcentrationLimit }}
ADMIN_ADDRESS: ${{ vars.ADMIN_ADDRESS }}
DEVOPS_ADDRESS: ${{ vars.DEVOPS_ADDRESS }}
GOVERNOR_ROLE_ADDRESS: ${{ vars.GOVERNOR_ROLE_ADDRESS }}

4 changes: 3 additions & 1 deletion script/Strategy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ contract DeployStrategy is Script {
address discountRateAdapterAddress = vm.envAddress("DISCOUNT_RATE_ADAPTER_ADDRESS");
address admin = vm.envAddress("ADMIN_ADDRESS");
address devops = vm.envAddress("DEVOPS_ADDRESS");
address governorRoleAddress = vm.envAddress("GOVERNOR_ROLE_ADDRESS");
address termController = vm.envOr("TERM_CONTROLLER_ADDRESS", address(0));
uint256 discountRateMarkup = vm.envOr("DISCOUNT_RATE_MARKUP", uint256(0));
address collateralTokenAddr = vm.envOr("COLLATERAL_TOKEN_ADDR", address(0));
Expand All @@ -36,7 +37,8 @@ contract DeployStrategy is Script {
name,
yearnVaultAddress,
discountRateAdapterAddress,
address(eventEmitter)
address(eventEmitter),
governorRoleAddress
);

console.log("deployed strateghy contract to");
Expand Down
8 changes: 7 additions & 1 deletion src/RepoTokenList.sol
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,13 @@ library RepoTokenList {
}
}
} else {
discountRate = discountRateAdapter.getDiscountRate(address(repoToken));
try discountRateAdapter.getDiscountRate(address(repoToken)) returns (uint256 rate) {
discountRate = rate;

} catch {
discountRate = INVALID_AUCTION_RATE;
return (false, discountRate, redemptionTimestamp);
}

bool isRepoTokenValid;

Expand Down
35 changes: 21 additions & 14 deletions src/Strategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {ITermAuction} from "./interfaces/term/ITermAuction.sol";
import {RepoTokenList, RepoTokenListData} from "./RepoTokenList.sol";
import {TermAuctionList, TermAuctionListData, PendingOffer} from "./TermAuctionList.sol";
import {RepoTokenUtils} from "./RepoTokenUtils.sol";
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";

// Import interfaces for many popular DeFi projects, or add your own!
//import "../interfaces/<protocol>/<Interface>.sol";
Expand All @@ -33,7 +34,7 @@ import {RepoTokenUtils} from "./RepoTokenUtils.sol";

// NOTE: To implement permissioned functions you can use the onlyManagement, onlyEmergencyAuthorized and onlyKeepers modifiers

contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
contract Strategy is BaseStrategy, Pausable, AccessControl, ReentrancyGuard {
using SafeERC20 for IERC20;
using RepoTokenList for RepoTokenListData;
using TermAuctionList for TermAuctionListData;
Expand All @@ -47,6 +48,8 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
error RepoTokenBlacklisted(address repoToken);
error DepositPaused();

bytes32 public constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");

// Immutable state variables
ITermVaultEvents public immutable TERM_VAULT_EVENT_EMITTER;
uint256 public immutable PURCHASE_TOKEN_PRECISION;
Expand Down Expand Up @@ -81,23 +84,23 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
/**
* @notice Pause the contract
*/
function pauseDeposit() external onlyManagement {
function pauseDeposit() external onlyRole(GOVERNOR_ROLE) {
depositLock = true;
TERM_VAULT_EVENT_EMITTER.emitDepositPaused();
}

/**
* @notice Unpause the contract
*/
function unpauseDeposit() external onlyManagement {
function unpauseDeposit() external onlyRole(GOVERNOR_ROLE) {
depositLock = false;
TERM_VAULT_EVENT_EMITTER.emitDepositUnpaused();
}

/**
* @notice Pause the contract
*/
function pauseStrategy() external onlyManagement {
function pauseStrategy() external onlyRole(GOVERNOR_ROLE) {
_pause();
depositLock = true;
TERM_VAULT_EVENT_EMITTER.emitStrategyPaused();
Expand All @@ -106,7 +109,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
/**
* @notice Unpause the contract
*/
function unpauseStrategy() external onlyManagement {
function unpauseStrategy() external onlyRole(GOVERNOR_ROLE) {
_unpause();
depositLock = false;
TERM_VAULT_EVENT_EMITTER.emitStrategyUnpaused();
Expand All @@ -118,7 +121,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setTermController(
address newTermController
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
require(newTermController != address(0));
require(ITermController(newTermController).getProtocolReserveAddress() != address(0));
address current = address(currTermController);
Expand All @@ -136,7 +139,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setDiscountRateAdapter(
address newAdapter
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
ITermDiscountRateAdapter newDiscountRateAdapter = ITermDiscountRateAdapter(newAdapter);
require(address(newDiscountRateAdapter.TERM_CONTROLLER()) != address(0));
TERM_VAULT_EVENT_EMITTER.emitDiscountRateAdapterUpdated(
Expand All @@ -152,7 +155,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setTimeToMaturityThreshold(
uint256 newTimeToMaturityThreshold
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitTimeToMaturityThresholdUpdated(
timeToMaturityThreshold,
newTimeToMaturityThreshold
Expand All @@ -167,7 +170,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setRequiredReserveRatio(
uint256 newRequiredReserveRatio
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitRequiredReserveRatioUpdated(
requiredReserveRatio,
newRequiredReserveRatio
Expand All @@ -181,7 +184,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setRepoTokenConcentrationLimit(
uint256 newRepoTokenConcentrationLimit
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitRepoTokenConcentrationLimitUpdated(
repoTokenConcentrationLimit,
newRepoTokenConcentrationLimit
Expand All @@ -195,7 +198,7 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
*/
function setDiscountRateMarkup(
uint256 newDiscountRateMarkup
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitDiscountRateMarkupUpdated(
discountRateMarkup,
newDiscountRateMarkup
Expand All @@ -210,15 +213,15 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
function setCollateralTokenParams(
address tokenAddr,
uint256 minCollateralRatio
) external onlyManagement {
) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitMinCollateralRatioUpdated(
tokenAddr,
minCollateralRatio
);
repoTokenListData.collateralTokenParams[tokenAddr] = minCollateralRatio;
}

function setRepoTokenBlacklist(address repoToken, bool blacklisted) external onlyManagement {
function setRepoTokenBlacklist(address repoToken, bool blacklisted) external onlyRole(GOVERNOR_ROLE) {
TERM_VAULT_EVENT_EMITTER.emitRepoTokenBlacklistUpdated(repoToken, blacklisted);
repoTokenBlacklist[repoToken] = blacklisted;
}
Expand Down Expand Up @@ -1091,13 +1094,15 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
* @param _yearnVault The address of the Yearn vault
* @param _discountRateAdapter The address of the discount rate adapter
* @param _eventEmitter The address of the event emitter
* @param _governorAddress The address of the governor
*/
constructor(
address _asset,
string memory _name,
address _yearnVault,
address _discountRateAdapter,
address _eventEmitter
address _eventEmitter,
address _governorAddress
) BaseStrategy(_asset, _name) {
YEARN_VAULT = IERC4626(_yearnVault);
TERM_VAULT_EVENT_EMITTER = ITermVaultEvents(_eventEmitter);
Expand All @@ -1111,6 +1116,8 @@ contract Strategy is BaseStrategy, Pausable, ReentrancyGuard {
requiredReserveRatio = 0.2e18;
discountRateMarkup = 0.005e18;
repoTokenConcentrationLimit = 0.1e18;

_grantRole(GOVERNOR_ROLE, _governorAddress);
}

/*//////////////////////////////////////////////////////////////
Expand Down
22 changes: 11 additions & 11 deletions src/test/TestUSDCIntegration.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ contract TestUSDCIntegration is Setup {
repoToken1MonthAuction = new MockTermAuction(repoToken1Month);
repoToken1YearAuction = new MockTermAuction(repoToken1Year);

vm.startPrank(management);
vm.startPrank(governor);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0.5e18);
termStrategy.setTimeToMaturityThreshold(3 weeks);
termStrategy.setRepoTokenConcentrationLimit(1e18);
Expand Down Expand Up @@ -248,7 +248,7 @@ contract TestUSDCIntegration is Setup {

termController.setOracleRate(repoToken1Month.termRepoId(), 0.05e6);

vm.startPrank(management);
vm.startPrank(governor);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0.5e18);
termStrategy.setTimeToMaturityThreshold(3 weeks);
vm.stopPrank();
Expand Down Expand Up @@ -303,11 +303,11 @@ contract TestUSDCIntegration is Setup {
function testRepoTokenBlacklist() public {
address testUser = vm.addr(0x11111);
vm.prank(testUser);
vm.expectRevert("!management");
vm.expectRevert();
termStrategy.setRepoTokenBlacklist(address(repoToken1Week), true);
vm.stopPrank();

vm.prank(management);
vm.prank(governor);
termStrategy.setRepoTokenBlacklist(address(repoToken1Week), true);
vm.stopPrank();

Expand All @@ -320,13 +320,13 @@ contract TestUSDCIntegration is Setup {
address testUser = vm.addr(0x11111);
mockUSDC.mint(testUser, 1e18);
vm.prank(testUser);
vm.expectRevert("!management");
vm.expectRevert();
termStrategy.pauseDeposit();
vm.expectRevert("!management");
vm.expectRevert();
termStrategy.unpauseDeposit();
vm.stopPrank();

vm.prank(management);
vm.prank(governor);
termStrategy.pauseDeposit();
vm.stopPrank();

Expand All @@ -338,7 +338,7 @@ contract TestUSDCIntegration is Setup {
IERC4626(address(termStrategy)).deposit(1e6, testUser);
vm.stopPrank();

vm.prank(management);
vm.prank(governor);
termStrategy.unpauseDeposit();
vm.stopPrank();

Expand All @@ -354,14 +354,14 @@ contract TestUSDCIntegration is Setup {
TermDiscountRateAdapter valid = new TermDiscountRateAdapter(address(termController), adminWallet);

vm.prank(testUser);
vm.expectRevert("!management");
vm.expectRevert();
termStrategy.setDiscountRateAdapter(address(valid));

vm.prank(management);
vm.prank(governor);
vm.expectRevert();
termStrategy.setDiscountRateAdapter(address(invalid));

vm.prank(management);
vm.prank(governor);
termStrategy.setDiscountRateAdapter(address(valid));
vm.stopPrank();

Expand Down
10 changes: 7 additions & 3 deletions src/test/TestUSDCOffers.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ contract TestUSDCSubmitOffer is Setup {
repoToken1WeekAuction = new MockTermAuction(repoToken1Week);
repoToken100WeekAuction = new MockTermAuction(repoToken100Week);

vm.startPrank(management);
vm.startPrank(governor);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0.5e18);
termStrategy.setTimeToMaturityThreshold(3 weeks);
termStrategy.setRepoTokenConcentrationLimit(1e18);
Expand Down Expand Up @@ -88,9 +88,11 @@ contract TestUSDCSubmitOffer is Setup {
}

function testSubmitOfferBelowLiquidReserveRatio() public {
vm.startPrank(management);
vm.startPrank(governor);
termStrategy.setRequiredReserveRatio(0.5e18);
vm.stopPrank();

vm.startPrank(management);
vm.expectRevert(abi.encodeWithSelector(Strategy.BalanceBelowRequiredReserveRatio.selector));
termStrategy.submitAuctionOffer(
repoToken1WeekAuction, address(repoToken1Week), bytes32("offer id hash 1"), bytes32("test price"), 51e6
Expand Down Expand Up @@ -132,9 +134,11 @@ contract TestUSDCSubmitOffer is Setup {
}

function testSubmitOfferFailsIfMinCollatRatioisZero() public {
vm.startPrank(management);
vm.startPrank(governor);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0);
vm.stopPrank();

vm.startPrank(management);
vm.expectRevert(abi.encodeWithSelector(RepoTokenList.InvalidRepoToken.selector, address(repoToken1Week)));
termStrategy.submitAuctionOffer(
repoToken1WeekAuction, address(repoToken1Week), bytes32("offer id hash 1"), bytes32("test price"), 1e6
Expand Down
Loading

0 comments on commit f328305

Please sign in to comment.