Description:Description\
The cvgControlTower implementation address is hard coded in the StakingServiceBase, but the deployed version of this contract does not have any implementations for cvxConvergenceLocker and cvxStakingPositionManager. These are only implemented in version 2 of the control tower. Which is not deployed at that address.
Attack Scenario\
With the address hardcode as it is now it will be impossible toi initialise the cvxConvergenceLocker. The situation is also the same for the following contracts
CvgFraxLpStakingServiceCvxAssetStakingService
Attachments
Proof of Concept (PoC) File
The following Foundry test proves that the initialisation of the CvgCvxStakingPositionService will fail. Help can be provided in order to set up a foundry test suite if required.
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;
import {Test, console} from "forge-std/Test.sol";
import "../lib/openzeppelin-contracts/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";
import "../lib/openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol";
import {ICrvPoolPlain} from "../src/contracts/interfaces/ICrvPoolPlain.sol";
import {CvgCvxStakingPositionService, ICvx1} from "../src/contracts/Staking/Convex/cvgCVX/CvgCvxStakingPositionService.sol";
contract CvgCvxStakingPositionServiceTest is Test {
uint256 mainnetFork;
TransparentUpgradeableProxy proxy;
ProxyAdmin admin;
CvgCvxStakingPositionService public cvgCvxStakingPositionService;
CvgCvxStakingPositionService public wrappedProxy;
function setUp() public {
mainnetFork = vm.createFork("eth");
vm.selectFork(mainnetFork);
admin = new ProxyAdmin();
cvgCvxStakingPositionService = new CvgCvxStakingPositionService();
proxy = new TransparentUpgradeableProxy(address(cvgCvxStakingPositionService), address(admin), "");
wrappedProxy = CvgCvxStakingPositionService(address(proxy));
}
function test_Initialise() public {
address _cvxConvergenceLocker = vm.addr(1);
ICrvPoolPlain _curvePool = ICrvPoolPlain(vm.addr(2));
ICvx1 _cvx = ICvx1(vm.addr(3));
string memory _symbol = "CVXCRV";
wrappedProxy.initialize(
_cvxConvergenceLocker,
_curvePool,
_cvx,
_symbol
);
assert(true);
}
}
Add an initialize function to the stakingBaseController allowing the deployer to provide the address of the correct deployed version of the cvgControlTower and remove the hardcoded initialization.
function initialize(address cvgController) public initializer {
__Ownable2Step_init();
cvgControlTower = ICvgControlTowerV2(cvgController);
}
Github username: @jonsey Twitter username: rnemes4 Submission hash (on-chain): 0xefbc10313a3e38adcd61ce3f0b2cdd39a21222061d4dfa2f4b751f24cb0546c1 Severity: low
Description: Description\ The
cvgControlTower
implementation address is hard coded in theStakingServiceBase
, but the deployed version of this contract does not have any implementations forcvxConvergenceLocker
andcvxStakingPositionManager
. These are only implemented in version 2 of the control tower. Which is not deployed at that address.Attack Scenario\ With the address hardcode as it is now it will be impossible toi initialise the
cvxConvergenceLocker
. The situation is also the same for the following contractsCvgFraxLpStakingService
CvxAssetStakingService
Attachments
CvgCvxStakingPositionService
will fail. Help can be provided in order to set up a foundry test suite if required.Output
Add an initialize function to the
stakingBaseController
allowing the deployer to provide the address of the correct deployed version of the cvgControlTower and remove the hardcoded initialization.Files: