diff --git a/contracts/contracts/governance/Strategizable.sol b/contracts/contracts/governance/Strategizable.sol index 62a3c0c028..4d823d6d1a 100644 --- a/contracts/contracts/governance/Strategizable.sol +++ b/contracts/contracts/governance/Strategizable.sol @@ -15,7 +15,7 @@ contract Strategizable is Governable { /** * @dev Verifies that the caller is either Governor or Strategist. */ - modifier onlyGovernorOrStrategist() { + modifier onlyGovernorOrStrategist() virtual { require( msg.sender == strategistAddr || isGovernor(), "Caller is not the Strategist or Governor" diff --git a/contracts/contracts/strategies/crosschain/AbstractCCTPIntegrator.sol b/contracts/contracts/strategies/crosschain/AbstractCCTPIntegrator.sol index 0878d68cae..fd151f161f 100644 --- a/contracts/contracts/strategies/crosschain/AbstractCCTPIntegrator.sol +++ b/contracts/contracts/strategies/crosschain/AbstractCCTPIntegrator.sol @@ -81,7 +81,7 @@ abstract contract AbstractCCTPIntegrator is Governable, IMessageHandlerV2 { * Can be 1000 (safe, after 1 epoch) or 2000 (finalized, after 2 epochs). * Ref: https://developers.circle.com/cctp/technical-guide#finality-thresholds * @dev When configuring the contract for fast transfer we should check the available - * allowance of USDC that can be bridged using fast mode: + * allowance of USDC that can be bridged using fast mode: * wget https://iris-api.circle.com/v2/fastBurn/USDC/allowance */ uint16 public minFinalityThreshold; diff --git a/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol b/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol index 3665840f53..c39dc5fdfe 100644 --- a/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol +++ b/contracts/contracts/strategies/crosschain/CrossChainRemoteStrategy.sol @@ -17,10 +17,12 @@ import { Generalized4626Strategy } from "../Generalized4626Strategy.sol"; import { AbstractCCTPIntegrator } from "./AbstractCCTPIntegrator.sol"; import { CrossChainStrategyHelper } from "./CrossChainStrategyHelper.sol"; import { InitializableAbstractStrategy } from "../../utils/InitializableAbstractStrategy.sol"; +import { Strategizable } from "../../governance/Strategizable.sol"; contract CrossChainRemoteStrategy is AbstractCCTPIntegrator, - Generalized4626Strategy + Generalized4626Strategy, + Strategizable { using SafeERC20 for IERC20; using CrossChainStrategyHelper for bytes; @@ -28,15 +30,6 @@ contract CrossChainRemoteStrategy is event DepositUnderlyingFailed(string reason); event WithdrawalFailed(uint256 amountRequested, uint256 amountAvailable); event WithdrawUnderlyingFailed(string reason); - event StrategistUpdated(address _address); - - /** - * @notice Address of the strategist. - * This is important to have the variable name same as in IVault. - * Because the parent contract (Generalized4626Strategy) uses this - * function to get the strategist address. - */ - address public strategistAddr; modifier onlyOperatorOrStrategistOrGovernor() { require( @@ -48,6 +41,24 @@ contract CrossChainRemoteStrategy is _; } + /** + * @dev Overriding this modifier is important because the parent + * contract`Generalized4626Strategy` uses `IVault.strategistAddr()` + * in its implementation and there's no Vault on the remote strategy. + * So, we set the Vault address of remote to be the proxy address and + * inherit from Strategizable to get the same function signature. + * Essentially, any calls to `IVault.strategistAddr()` will be equal to + * calling `address(this).strategistAddr()`. + */ + modifier onlyGovernorOrStrategist() + override(InitializableAbstractStrategy, Strategizable) { + require( + msg.sender == strategistAddr || isGovernor(), + "Caller is not the Strategist or Governor" + ); + _; + } + constructor( BaseStrategyConfig memory _baseConfig, CCTPIntegrationConfig memory _cctpConfig @@ -91,26 +102,6 @@ contract CrossChainRemoteStrategy is ); } - /** - * @notice Set address of Strategist. - * This is important to have the function name same as IVault. - * Because the parent contract (Generalized4626Strategy) uses this - * function to get/set the strategist address. - * @param _address Address of Strategist - */ - function setStrategistAddr(address _address) external onlyGovernor { - _setStrategistAddr(_address); - } - - /** - * @dev Set the strategist address - * @param _address Address of the strategist - */ - function _setStrategistAddr(address _address) internal { - strategistAddr = _address; - emit StrategistUpdated(_address); - } - /// @inheritdoc Generalized4626Strategy function deposit(address _asset, uint256 _amount) external diff --git a/contracts/contracts/utils/InitializableAbstractStrategy.sol b/contracts/contracts/utils/InitializableAbstractStrategy.sol index 890da82e57..dbb4adb097 100644 --- a/contracts/contracts/utils/InitializableAbstractStrategy.sol +++ b/contracts/contracts/utils/InitializableAbstractStrategy.sol @@ -81,7 +81,7 @@ abstract contract InitializableAbstractStrategy is Initializable, Governable { /** * @dev Verifies that the caller is the Governor or Strategist. */ - modifier onlyGovernorOrStrategist() { + modifier onlyGovernorOrStrategist() virtual { require( isGovernor() || msg.sender == IVault(vaultAddress).strategistAddr(), "Caller is not the Strategist or Governor"