Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

operator role for auction submissions, management for parameter setting #97

Merged
merged 2 commits into from
Nov 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ src = 'src'
out = 'out'
libs = ['lib']
solc = "0.8.23"
via_ir = true
optimizer = true
optimizer_runs = 200

remappings = [
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
Expand Down
47 changes: 27 additions & 20 deletions src/Strategy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
* @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
* @param _operatorAddress The address of the operator
* @param _termController The address of the term controller
* @param _repoTokenConcentrationLimit The concentration limit for repoTokens
* @param _timeToMaturityThreshold The time to maturity threshold
Expand All @@ -57,7 +57,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
address _yearnVault;
address _discountRateAdapter;
address _eventEmitter;
address _governorAddress;
address _operatorAddress;
address _termController;
uint256 _repoTokenConcentrationLimit;
uint256 _timeToMaturityThreshold;
Expand All @@ -68,7 +68,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
struct StrategyState {
address assetVault;
address eventEmitter;
address governorAddress;
address operatorAddress;
address prevTermController;
address currTermController;
address discountRateAdapter;
Expand All @@ -90,7 +90,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
error ZeroPurchaseTokenAmount();
error OfferNotFound();

bytes32 internal constant GOVERNOR_ROLE = keccak256("GOVERNOR_ROLE");
bytes32 internal constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");

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

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

/**
* @notice Pause the contract
*/
function pauseStrategy() external onlyRole(GOVERNOR_ROLE) {
function pauseStrategy() external onlyManagement {
_pause();
depositLock = true;
TERM_VAULT_EVENT_EMITTER.emitStrategyPaused();
Expand All @@ -153,7 +153,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
/**
* @notice Unpause the contract
*/
function unpauseStrategy() external onlyRole(GOVERNOR_ROLE) {
function unpauseStrategy() external onlyManagement {
_unpause();
depositLock = false;
TERM_VAULT_EVENT_EMITTER.emitStrategyUnpaused();
Expand All @@ -165,7 +165,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setTermController(
address newTermControllerAddr
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
require(newTermControllerAddr != address(0));
require(ITermController(newTermControllerAddr).getProtocolReserveAddress() != address(0));
ITermController newTermController = ITermController(newTermControllerAddr);
Expand All @@ -183,6 +183,8 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
);
prevTermController = ITermController(current);
currTermController = newTermController;
strategyState.prevTermController = current;
strategyState.currTermController = newTermControllerAddr;
}

/**
Expand All @@ -191,14 +193,15 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setDiscountRateAdapter(
address newAdapter
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
ITermDiscountRateAdapter newDiscountRateAdapter = ITermDiscountRateAdapter(newAdapter);
require(address(newDiscountRateAdapter.currTermController()) != address(0));
TERM_VAULT_EVENT_EMITTER.emitDiscountRateAdapterUpdated(
address(discountRateAdapter),
newAdapter
);
discountRateAdapter = newDiscountRateAdapter;
strategyState.discountRateAdapter = newAdapter;
}

/**
Expand All @@ -207,12 +210,13 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setTimeToMaturityThreshold(
uint256 newTimeToMaturityThreshold
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitTimeToMaturityThresholdUpdated(
timeToMaturityThreshold,
newTimeToMaturityThreshold
);
timeToMaturityThreshold = newTimeToMaturityThreshold;
strategyState.timeToMaturityThreshold = newTimeToMaturityThreshold;
}

/**
Expand All @@ -222,12 +226,13 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setRequiredReserveRatio(
uint256 newRequiredReserveRatio
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitRequiredReserveRatioUpdated(
requiredReserveRatio,
newRequiredReserveRatio
);
requiredReserveRatio = newRequiredReserveRatio;
strategyState.requiredReserveRatio = newRequiredReserveRatio;
}

/**
Expand All @@ -236,12 +241,13 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setRepoTokenConcentrationLimit(
uint256 newRepoTokenConcentrationLimit
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitRepoTokenConcentrationLimitUpdated(
repoTokenConcentrationLimit,
newRepoTokenConcentrationLimit
);
repoTokenConcentrationLimit = newRepoTokenConcentrationLimit;
strategyState.repoTokenConcentrationLimit = newRepoTokenConcentrationLimit;
}

/**
Expand All @@ -250,12 +256,13 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
*/
function setDiscountRateMarkup(
uint256 newDiscountRateMarkup
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitDiscountRateMarkupUpdated(
discountRateMarkup,
newDiscountRateMarkup
);
discountRateMarkup = newDiscountRateMarkup;
strategyState.discountRateMarkup = newDiscountRateMarkup;
}
/**
* @notice Set the collateral token parameters
Expand All @@ -265,15 +272,15 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
function setCollateralTokenParams(
address tokenAddr,
uint256 minCollateralRatio
) external onlyRole(GOVERNOR_ROLE) {
) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitMinCollateralRatioUpdated(
tokenAddr,
minCollateralRatio
);
repoTokenListData.collateralTokenParams[tokenAddr] = minCollateralRatio;
}

function setRepoTokenBlacklist(address repoToken, bool blacklisted) external onlyRole(GOVERNOR_ROLE) {
function setRepoTokenBlacklist(address repoToken, bool blacklisted) external onlyManagement {
TERM_VAULT_EVENT_EMITTER.emitRepoTokenBlacklistUpdated(repoToken, blacklisted);
repoTokenBlacklist[repoToken] = blacklisted;
}
Expand Down Expand Up @@ -864,7 +871,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
external
whenNotPaused
notBlacklisted(repoToken)
onlyManagement
onlyRole(OPERATOR_ROLE)
returns (bytes32[] memory offerIds)
{
if(purchaseTokenAmount == 0) {
Expand Down Expand Up @@ -1019,7 +1026,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
function deleteAuctionOffers(
address termAuction,
bytes32[] calldata offerIds
) external onlyManagement {
) external onlyRole(OPERATOR_ROLE) {
// Validate if the term auction is deployed by term
if (!_isTermDeployed(termAuction)) {
revert InvalidTermAuction(termAuction);
Expand Down Expand Up @@ -1182,7 +1189,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
strategyState = StrategyState({
assetVault: address(YEARN_VAULT),
eventEmitter: address(TERM_VAULT_EVENT_EMITTER),
governorAddress: _params._governorAddress,
operatorAddress: _params._operatorAddress,
prevTermController: address(0),
currTermController: address(currTermController),
discountRateAdapter: address(discountRateAdapter),
Expand All @@ -1192,7 +1199,7 @@ contract Strategy is BaseStrategy, Pausable, AccessControl {
repoTokenConcentrationLimit: repoTokenConcentrationLimit
});

_grantRole(GOVERNOR_ROLE, _params._governorAddress);
_grantRole(OPERATOR_ROLE, _params._operatorAddress);
}

/*//////////////////////////////////////////////////////////////
Expand Down
34 changes: 15 additions & 19 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(governor);
vm.startPrank(management);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0.5e18);
termStrategy.setTimeToMaturityThreshold(3 weeks);
termStrategy.setRepoTokenConcentrationLimit(1e18);
Expand All @@ -78,12 +78,12 @@ contract TestUSDCIntegration is Setup {

function _submitOffer(bytes32 idHash, uint256 offerAmount, MockTermAuction auction, MockTermRepoToken repoToken) private returns (bytes32) {
// test: only management can submit offers
vm.expectRevert("!management");
vm.expectRevert();
bytes32[] memory offerIds = termStrategy.submitAuctionOffer(
auction, address(repoToken), idHash, bytes32("test price"), offerAmount
);

vm.prank(management);
vm.prank(operator);
offerIds = termStrategy.submitAuctionOffer(
auction, address(repoToken), idHash, bytes32("test price"), offerAmount
);
Expand Down Expand Up @@ -248,7 +248,7 @@ contract TestUSDCIntegration is Setup {

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

vm.startPrank(governor);
vm.startPrank(management);
termStrategy.setCollateralTokenParams(address(mockCollateral), 0.5e18);
termStrategy.setTimeToMaturityThreshold(3 weeks);
vm.stopPrank();
Expand All @@ -266,7 +266,7 @@ contract TestUSDCIntegration is Setup {
function testSuccessfulUnlockedOfferFromCancelledAuction() public {
address testUser = vm.addr(0x11111);

vm.prank(management);
vm.prank(operator);
termStrategy.submitAuctionOffer(
repoToken1WeekAuction, address(repoToken1Week), bytes32("offer 1"), bytes32("test price"), 1e6
);
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();
vm.expectRevert("!management");
termStrategy.setRepoTokenBlacklist(address(repoToken1Week), true);
vm.stopPrank();

vm.prank(governor);
vm.prank(management);
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();
vm.expectRevert("!management");
termStrategy.pauseDeposit();
vm.expectRevert();
vm.expectRevert("!management");
termStrategy.unpauseDeposit();
vm.stopPrank();

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

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

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

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

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

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

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

(
address assetVault,
address assetVault,
address eventEmitter,
address governorAddr,
address operatorAddr,
address prevTermController,
address currTermController,
address discountRateAdapter,
Expand Down
Loading