Skip to content

Commit

Permalink
test: verify V1 staking in E2E
Browse files Browse the repository at this point in the history
Found and fixed a bug in the deployment script that resulted in not
being able to claim LUSD rewards from V1 staking.
  • Loading branch information
danielattilasimon committed Jan 15, 2025
1 parent 06d335d commit 621c789
Show file tree
Hide file tree
Showing 8 changed files with 261 additions and 124 deletions.
106 changes: 46 additions & 60 deletions contracts/script/DeployGovernance.s.sol
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity 0.8.24;

import {IERC20} from "openzeppelin-contracts/contracts/token/ERC20/IERC20.sol";
import {Strings} from "openzeppelin-contracts/contracts/utils/Strings.sol";

import {Script} from "forge-std/Script.sol";
Expand All @@ -20,9 +19,14 @@ import "forge-std/console2.sol";
contract DeployGovernance is Script {
using Strings for *;

// Environment Constants
address internal lqty;
address internal stakingV1;
struct DeployGovernanceParams {
address deployer;
bytes32 salt;
address stakingV1;
address lqty;
address lusd;
address bold;
}

// Governance Constants
uint128 private constant REGISTRATION_FEE = 1000e18;
Expand All @@ -48,60 +52,48 @@ contract DeployGovernance is Script {
CurveV2GaugeRewards private curveV2GaugeRewards;
ILiquidityGauge private gauge;

function deployGovernance(
address _deployer,
bytes32 _salt,
IERC20 _boldToken,
address _curveFactoryAddress,
address _curvePoolAddress
) internal returns (address, string memory) {
function deployGovernance(DeployGovernanceParams memory p, address _curveFactoryAddress, address _curvePoolAddress)
internal
returns (address, string memory)
{
(address governanceAddress, IGovernance.Configuration memory governanceConfiguration) =
computeGovernanceAddressAndConfig(_deployer, _salt, _boldToken, initialInitiatives);

governance = new Governance{salt: _salt}(
lqty,
address(_boldToken),
stakingV1,
address(_boldToken),
governanceConfiguration,
_deployer,
initialInitiatives
computeGovernanceAddressAndConfig(p);

governance = new Governance{salt: p.salt}(
p.lqty, p.lusd, p.stakingV1, p.bold, governanceConfiguration, p.deployer, initialInitiatives
);

//console2.log("");
//console2.log(governance.owner(), "governance.owner()");
//console2.log(address(governance), "address(governance)");
//console2.log(governanceAddress, "governanceAddress");
assert(governanceAddress == address(governance));

// Curve initiative
if (block.chainid == 1) {
// mainnet
deployCurveV2GaugeRewards(governance, _boldToken, _curveFactoryAddress, _curvePoolAddress);
deployCurveV2GaugeRewards({
_governance: governance,
_bold: p.bold,
_bribeToken: p.lqty, // TODO: this should be CRV
_curveFactoryAddress: _curveFactoryAddress,
_curvePoolAddress: _curvePoolAddress
});

// TODO: BOLD/LUSD pool
}

governance.registerInitialInitiatives{gas: 600000}(initialInitiatives);

return (governanceAddress, _getGovernanceManifestJson(_curvePoolAddress));
return (governanceAddress, _getGovernanceManifestJson(_curvePoolAddress, p.lqty));
}

function computeGovernanceAddress(
address _deployer,
bytes32 _salt,
IERC20 _boldToken,
address[] memory _initialInitiatives
) internal view returns (address) {
(address governanceAddress,) =
computeGovernanceAddressAndConfig(_deployer, _salt, _boldToken, _initialInitiatives);
function computeGovernanceAddress(DeployGovernanceParams memory p) internal view returns (address) {
(address governanceAddress,) = computeGovernanceAddressAndConfig(p);
return governanceAddress;
}

function computeGovernanceAddressAndConfig(
address _deployer,
bytes32 _salt,
IERC20 _boldToken,
address[] memory _initialInitiatives
) internal view returns (address, IGovernance.Configuration memory) {
function computeGovernanceAddressAndConfig(DeployGovernanceParams memory p)
internal
view
returns (address, IGovernance.Configuration memory)
{
IGovernance.Configuration memory governanceConfiguration = IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
registrationThresholdFactor: REGISTRATION_THRESHOLD_FACTOR,
Expand All @@ -115,31 +107,21 @@ contract DeployGovernance is Script {
epochDuration: EPOCH_DURATION,
epochVotingCutoff: EPOCH_VOTING_CUTOFF
});
//console2.log(lqty, "lqty");
//console2.log(address(_boldToken), "address(_boldToken)");
//console2.log(stakingV1, "stakingV1");
//console2.log(_initialInitiatives.length, "_initialInitiatives");

bytes memory bytecode = abi.encodePacked(
type(Governance).creationCode,
abi.encode(
lqty,
address(_boldToken),
stakingV1,
address(_boldToken),
governanceConfiguration,
_deployer,
_initialInitiatives
)
abi.encode(p.lqty, p.lusd, p.stakingV1, p.bold, governanceConfiguration, p.deployer, new address[](0))
);

address governanceAddress = vm.computeCreate2Address(_salt, keccak256(bytecode));
address governanceAddress = vm.computeCreate2Address(p.salt, keccak256(bytecode));

return (governanceAddress, governanceConfiguration);
}

function deployCurveV2GaugeRewards(
IGovernance _governance,
IERC20 _boldToken,
address _bold,
address _bribeToken,
address _curveFactoryAddress,
address _curvePoolAddress
) private {
Expand All @@ -148,10 +130,10 @@ contract DeployGovernance is Script {
gauge = ILiquidityGauge(curveFactory.deploy_gauge(address(curvePool)));

curveV2GaugeRewards =
new CurveV2GaugeRewards(address(_governance), address(_boldToken), lqty, address(gauge), DURATION);
new CurveV2GaugeRewards(address(_governance), _bold, _bribeToken, address(gauge), DURATION);

// add BOLD as reward token
gauge.add_reward(address(_boldToken), address(curveV2GaugeRewards));
gauge.add_reward(_bold, address(curveV2GaugeRewards));

initialInitiatives.push(address(curveV2GaugeRewards));
}
Expand All @@ -178,7 +160,11 @@ contract DeployGovernance is Script {
);
}

function _getGovernanceManifestJson(address _curvePoolAddress) internal view returns (string memory) {
function _getGovernanceManifestJson(address _curvePoolAddress, address _lqty)
internal
view
returns (string memory)
{
return string.concat(
"{",
string.concat(
Expand All @@ -187,7 +173,7 @@ contract DeployGovernance is Script {
string.concat('"curveV2GaugeRewardsInitiative":"', address(curveV2GaugeRewards).toHexString(), '",'),
string.concat('"curvePool":"', _curvePoolAddress.toHexString(), '",'),
string.concat('"gauge":"', address(gauge).toHexString(), '",'),
string.concat('"LQTYToken":"', lqty.toHexString(), '" ') // no comma
string.concat('"LQTYToken":"', _lqty.toHexString(), '" ') // no comma
),
"}"
);
Expand Down
46 changes: 30 additions & 16 deletions contracts/script/DeployLiquity2.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
// V1
address LQTY_ADDRESS = 0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D;
address LQTY_STAKING_ADDRESS = 0x4f9Fbb3f1E99B56e0Fe2892e623Ed36A76Fc605d;
address LUSD_ADDRESS = 0x5f98805A4E8be255a32880FDeC7F6728C6568bA0;

address internal lqty;
address internal stakingV1;
address internal lusd;

// Curve
ICurveStableswapNGFactory curveStableswapFactory;
Expand Down Expand Up @@ -239,6 +244,7 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
balancerFactory = balancerFactoryMainnet;
lqty = LQTY_ADDRESS;
stakingV1 = LQTY_STAKING_ADDRESS;
lusd = LUSD_ADDRESS;
} else {
// sepolia, local
if (block.chainid == 31337) {
Expand All @@ -257,8 +263,8 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
balancerFactory = balancerFactorySepolia;
// Needed for Governance (they will be constants for mainnet)
lqty = address(new ERC20Faucet("Liquity", "LQTY", 100 ether, 1 days));
ERC20Faucet lusd = new ERC20Faucet("Liquity USD", "LUSD", 100 ether, 1 days);
stakingV1 = address(new MockStakingV1(IERC20_GOV(lqty), IERC20_GOV(address(lusd))));
lusd = address(new ERC20Faucet("Liquity USD", "LUSD", 100 ether, 1 days));
stakingV1 = address(new MockStakingV1(IERC20_GOV(lqty), IERC20_GOV(lusd)));

// Let stakingV1 spend anyone's LQTY without approval, like in the real LQTYStaking
ERC20Faucet(lqty).mock_setWildcardSpender(address(stakingV1), true);
Expand All @@ -277,7 +283,17 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
collNames[1] = "Rocket Pool ETH";
collSymbols[1] = "rETH";

DeploymentResult memory deployed = _deployAndConnectContracts(troveManagerParamsArray, collNames, collSymbols);
DeployGovernanceParams memory deployGovernanceParams = DeployGovernanceParams({
deployer: deployer,
salt: SALT,
stakingV1: stakingV1,
lqty: lqty,
lusd: lusd,
bold: address(0) // not yet known; will be set by `_deployAndConnectContracts()`
});

DeploymentResult memory deployed =
_deployAndConnectContracts(troveManagerParamsArray, collNames, collSymbols, deployGovernanceParams);

if (block.chainid == 11155111) {
// Provide liquidity for zaps if we're on Sepolia
Expand Down Expand Up @@ -329,13 +345,9 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
}

// Governance
(address governanceAddress, string memory governanceManifest) = deployGovernance(
deployer, SALT, deployed.boldToken, address(curveStableswapFactory), address(deployed.usdcCurvePool)
);
address computedGovernanceAddress =
computeGovernanceAddress(deployer, SALT, deployed.boldToken, new address[](0));
//console2.log(computedGovernanceAddress, "computedGovernanceAddress");
//console2.log(governanceAddress, "governanceAddress");
(address governanceAddress, string memory governanceManifest) =
deployGovernance(deployGovernanceParams, address(curveStableswapFactory), address(deployed.usdcCurvePool));
address computedGovernanceAddress = computeGovernanceAddress(deployGovernanceParams);
assert(governanceAddress == computedGovernanceAddress);

vm.stopBroadcast();
Expand Down Expand Up @@ -446,7 +458,8 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
function _deployAndConnectContracts(
TroveManagerParams[] memory troveManagerParamsArray,
string[] memory _collNames,
string[] memory _collSymbols
string[] memory _collSymbols,
DeployGovernanceParams memory _deployGovernanceParams
) internal returns (DeploymentResult memory r) {
assert(_collNames.length == troveManagerParamsArray.length - 1);
assert(_collSymbols.length == troveManagerParamsArray.length - 1);
Expand All @@ -458,6 +471,7 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
vars.boldTokenAddress = vm.computeCreate2Address(SALT, keccak256(vars.bytecode));
r.boldToken = new BoldToken{salt: SALT}(deployer);
assert(address(r.boldToken) == vars.boldTokenAddress);
_deployGovernanceParams.bold = address(r.boldToken);

// USDC and USDC-BOLD pool
r.usdcCurvePool = _deployCurveBoldUsdcPool(r.boldToken);
Expand Down Expand Up @@ -536,7 +550,8 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
vars.addressesRegistries[vars.i],
address(vars.troveManagers[vars.i]),
r.hintHelpers,
r.multiTroveGetter
r.multiTroveGetter,
computeGovernanceAddress(_deployGovernanceParams)
);
r.contractsArray[vars.i] = vars.contracts;
}
Expand Down Expand Up @@ -584,7 +599,8 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
IAddressesRegistry _addressesRegistry,
address _troveManagerAddress,
IHintHelpers _hintHelpers,
IMultiTroveGetter _multiTroveGetter
IMultiTroveGetter _multiTroveGetter,
address _governance
) internal returns (LiquityContracts memory contracts) {
LiquityContractAddresses memory addresses;
contracts.collToken = _collToken;
Expand All @@ -600,9 +616,7 @@ contract DeployLiquity2Script is DeployGovernance, UniPriceConverter, StdCheats,
assert(address(contracts.metadataNFT) == addresses.metadataNFT);

contracts.priceFeed = _priceFeed;
//console2.log(computeGovernanceAddress(deployer, SALT, _boldToken, new address[](0)), "computeGovernanceAddress");
contracts.interestRouter =
IInterestRouter(computeGovernanceAddress(deployer, SALT, _boldToken, new address[](0)));
contracts.interestRouter = IInterestRouter(_governance);
addresses.borrowerOperations = vm.computeCreate2Address(
SALT, keccak256(getBytecode(type(BorrowerOperations).creationCode, address(contracts.addressesRegistry)))
);
Expand Down
38 changes: 0 additions & 38 deletions contracts/script/DeployOnlyGovernance.s.sol

This file was deleted.

Loading

0 comments on commit 621c789

Please sign in to comment.