Skip to content

Commit

Permalink
Merge pull request #80 from liquity/testing
Browse files Browse the repository at this point in the history
Mocked versions of tests
  • Loading branch information
danielattilasimon authored Nov 22, 2024
2 parents 1926488 + 25fb79c commit e22fa33
Show file tree
Hide file tree
Showing 31 changed files with 691 additions and 463 deletions.
10 changes: 1 addition & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ env:
MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }}
FOUNDRY_PROFILE: ci


jobs:
lint:
runs-on: ubuntu-latest
Expand Down Expand Up @@ -54,7 +53,6 @@ jobs:
echo "✅ Passed" >> $GITHUB_STEP_SUMMARY
test:
needs: ["lint", "build"]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand All @@ -67,14 +65,8 @@ jobs:
- name: Show the Foundry config
run: "forge config"

- name: Generate a fuzz seed that changes weekly to avoid burning through RPC allowance
run: >
echo "FOUNDRY_FUZZ_SEED=$(
echo $(($EPOCHSECONDS - $EPOCHSECONDS % 604800))
)" >> $GITHUB_ENV
- name: Run tests
run: forge test -vvv --gas-report
run: forge test -vvv --gas-report --color always

- name: Add test summary
run: |
Expand Down
2 changes: 1 addition & 1 deletion foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ chain_id = 99
block_timestamp = 2592000

[profile.ci.fuzz]
runs = 5000
runs = 500

[profile.default.fuzz]
runs = 100
Expand Down
22 changes: 11 additions & 11 deletions script/DeploySepolia.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
pragma solidity ^0.8.13;

import {Script} from "forge-std/Script.sol";
import {MockERC20} from "forge-std/mocks/MockERC20.sol";

import {PoolManager, Deployers, Hooks} from "v4-core/test/utils/Deployers.sol";
import {ICurveStableswapFactoryNG} from "../src/interfaces/ICurveStableswapFactoryNG.sol";
Expand All @@ -16,15 +15,17 @@ import {UniV4Donations} from "../src/UniV4Donations.sol";
import {CurveV2GaugeRewards} from "../src/CurveV2GaugeRewards.sol";
import {Hooks} from "../src/utils/BaseHook.sol";

import {MockERC20Tester} from "../test/mocks/MockERC20Tester.sol";
import {MockStakingV1} from "../test/mocks/MockStakingV1.sol";
import {MockStakingV1Deployer} from "../test/mocks/MockStakingV1Deployer.sol";
import {HookMiner} from "./utils/HookMiner.sol";

contract DeploySepoliaScript is Script, Deployers {
contract DeploySepoliaScript is Script, Deployers, MockStakingV1Deployer {
// Environment Constants
MockERC20 private lqty;
MockERC20 private bold;
address private stakingV1;
MockERC20 private usdc;
MockERC20Tester private lqty;
MockERC20Tester private bold;
MockStakingV1 private stakingV1;
MockERC20Tester private usdc;

PoolManager private constant poolManager = PoolManager(0xE8E23e97Fa135823143d6b9Cba9c699040D51F70);
ICurveStableswapFactoryNG private constant curveFactory =
Expand Down Expand Up @@ -71,17 +72,16 @@ contract DeploySepoliaScript is Script, Deployers {
}

function deployEnvironment() private {
lqty = deployMockERC20("Liquity", "LQTY", 18);
bold = deployMockERC20("Bold", "BOLD", 18);
usdc = deployMockERC20("USD Coin", "USDC", 6);
stakingV1 = address(new MockStakingV1(address(lqty)));
(stakingV1, lqty,) = deployMockStakingV1();
bold = new MockERC20Tester("Bold", "BOLD");
usdc = new MockERC20Tester("USD Coin", "USDC");
}

function deployGovernance() private {
governance = new Governance(
address(lqty),
address(bold),
stakingV1,
address(stakingV1),
address(bold),
IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
Expand Down
9 changes: 5 additions & 4 deletions src/Governance.sol
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,14 @@ contract Governance is Multicall, UserProxyFactory, ReentrancyGuard, Ownable, IG
}

function registerInitialInitiatives(address[] memory _initiatives) public onlyOwner {
uint16 currentEpoch = epoch();

for (uint256 i = 0; i < _initiatives.length; i++) {
initiativeStates[_initiatives[i]] = InitiativeState(0, 0, 0, 0, 0);
registeredInitiatives[_initiatives[i]] = currentEpoch;

emit RegisterInitiative(_initiatives[i], msg.sender, currentEpoch);
// Register initial initiatives in the earliest possible epoch, which lets us make them votable immediately
// post-deployment if we so choose, by backdating the first epoch at least EPOCH_DURATION in the past.
registeredInitiatives[_initiatives[i]] = 1;

emit RegisterInitiative(_initiatives[i], msg.sender, 1);
}

_renounceOwnership();
Expand Down
4 changes: 2 additions & 2 deletions src/UniV4Donations.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,8 @@ contract UniV4Donations is BribeInitiative, BaseHook {
currency0 = _bold;
currency1 = _token;
} else {
currency1 = _token;
currency0 = _bold;
currency0 = _token;
currency1 = _bold;
}
fee = _fee;
tickSpacing = _tickSpacing;
Expand Down
1 change: 0 additions & 1 deletion src/UserProxy.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ contract UserProxy is IUserProxy {
/// @inheritdoc IUserProxy
function stake(uint256 _amount, address _lqtyFrom) public onlyStakingV2 {
lqty.transferFrom(_lqtyFrom, address(this), _amount);
lqty.approve(address(stakingV1), _amount);
stakingV1.stake(_amount);
emit Stake(_amount, _lqtyFrom);
}
Expand Down
5 changes: 4 additions & 1 deletion src/interfaces/ILQTY.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

interface ILQTY {
import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Permit} from "openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";

interface ILQTY is IERC20, IERC20Permit {
function domainSeparator() external view returns (bytes32);
}
2 changes: 2 additions & 0 deletions src/interfaces/ILQTYStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,6 @@ interface ILQTYStaking {
function getPendingLUSDGain(address _user) external view returns (uint256);

function stakes(address _user) external view returns (uint256);

function totalLQTYStaked() external view returns (uint256);
}
9 changes: 9 additions & 0 deletions src/interfaces/ILUSD.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

import {IERC20} from "openzeppelin/contracts/token/ERC20/IERC20.sol";
import {IERC20Permit} from "openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol";

interface ILUSD is IERC20, IERC20Permit {
function mint(address _account, uint256 _amount) external;
}
70 changes: 29 additions & 41 deletions test/BribeInitiative.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,21 @@
pragma solidity ^0.8.24;

import {Test, console2} from "forge-std/Test.sol";
import {MockERC20} from "forge-std/mocks/MockERC20.sol";

import {IGovernance} from "../src/interfaces/IGovernance.sol";
import {IBribeInitiative} from "../src/interfaces/IBribeInitiative.sol";

import {Governance} from "../src/Governance.sol";
import {BribeInitiative} from "../src/BribeInitiative.sol";

import {MockERC20Tester} from "./mocks/MockERC20Tester.sol";
import {MockStakingV1} from "./mocks/MockStakingV1.sol";
import {MockStakingV1Deployer} from "./mocks/MockStakingV1Deployer.sol";

contract BribeInitiativeTest is Test {
MockERC20 private lqty;
MockERC20 private lusd;
address private stakingV1;
contract BribeInitiativeTest is Test, MockStakingV1Deployer {
MockERC20Tester private lqty;
MockERC20Tester private lusd;
MockStakingV1 private stakingV1;
address private constant user1 = address(0xF977814e90dA44bFA03b6295A0616a897441aceC);
address private constant user2 = address(0x10C9cff3c4Faa8A60cB8506a7A99411E6A199038);
address private user3 = makeAddr("user3");
Expand All @@ -41,45 +42,32 @@ contract BribeInitiativeTest is Test {
BribeInitiative private bribeInitiative;

function setUp() public {
lqty = deployMockERC20("Liquity", "LQTY", 18);
lusd = deployMockERC20("Liquity USD", "LUSD", 18);
(stakingV1, lqty, lusd) = deployMockStakingV1();

lqty.mint(lusdHolder, 10_000_000e18);
lusd.mint(lusdHolder, 10_000_000e18);

IGovernance.Configuration memory config = IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
registrationThresholdFactor: REGISTRATION_THRESHOLD_FACTOR,
unregistrationThresholdFactor: UNREGISTRATION_THRESHOLD_FACTOR,
registrationWarmUpPeriod: REGISTRATION_WARM_UP_PERIOD,
unregistrationAfterEpochs: UNREGISTRATION_AFTER_EPOCHS,
votingThresholdFactor: VOTING_THRESHOLD_FACTOR,
minClaim: MIN_CLAIM,
minAccrual: MIN_ACCRUAL,
epochStart: uint32(block.timestamp),
epochDuration: EPOCH_DURATION,
epochVotingCutoff: EPOCH_VOTING_CUTOFF
});

vm.store(address(lqty), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18)));
vm.store(address(lusd), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18)));
vm.store(address(lqty), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18)));
vm.store(address(lusd), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10_000_000e18)));

stakingV1 = address(new MockStakingV1(address(lqty)));

bribeInitiative = new BribeInitiative(
address(vm.computeCreateAddress(address(this), vm.getNonce(address(this)) + 1)),
address(lusd),
address(lqty)
governance = new Governance(
address(lqty), address(lusd), address(stakingV1), address(lusd), config, address(this), new address[](0)
);

bribeInitiative = new BribeInitiative(address(governance), address(lusd), address(lqty));
initialInitiatives.push(address(bribeInitiative));

governance = new Governance(
address(lqty),
address(lusd),
stakingV1,
address(lusd),
IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
registrationThresholdFactor: REGISTRATION_THRESHOLD_FACTOR,
unregistrationThresholdFactor: UNREGISTRATION_THRESHOLD_FACTOR,
registrationWarmUpPeriod: REGISTRATION_WARM_UP_PERIOD,
unregistrationAfterEpochs: UNREGISTRATION_AFTER_EPOCHS,
votingThresholdFactor: VOTING_THRESHOLD_FACTOR,
minClaim: MIN_CLAIM,
minAccrual: MIN_ACCRUAL,
epochStart: uint32(block.timestamp),
epochDuration: EPOCH_DURATION,
epochVotingCutoff: EPOCH_VOTING_CUTOFF
}),
address(this),
initialInitiatives
);
governance.registerInitialInitiatives(initialInitiatives);

vm.startPrank(lusdHolder);
lqty.transfer(user1, 1_000_000e18);
Expand Down Expand Up @@ -703,7 +691,7 @@ contract BribeInitiativeTest is Test {
lqty.approve(address(bribeInitiative), 1e18);
lusd.approve(address(bribeInitiative), 1e18);

vm.expectRevert("BribeInitiative: only-future-epochs");
vm.expectRevert("BribeInitiative: now-or-future-epochs");
bribeInitiative.depositBribe(1e18, 1e18, uint16(0));

vm.stopPrank();
Expand Down
19 changes: 7 additions & 12 deletions test/BribeInitiativeAllocate.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ pragma solidity ^0.8.24;

import {Test} from "forge-std/Test.sol";
import {console} from "forge-std/console.sol";
import {MockERC20} from "forge-std/mocks/MockERC20.sol";

import {Governance} from "../src/Governance.sol";
import {BribeInitiative} from "../src/BribeInitiative.sol";

import {IGovernance} from "../src/interfaces/IGovernance.sol";

import {MockStakingV1} from "./mocks/MockStakingV1.sol";
import {MockERC20Tester} from "./mocks/MockERC20Tester.sol";
import {MockGovernance} from "./mocks/MockGovernance.sol";

// new epoch:
Expand All @@ -33,9 +31,8 @@ import {MockGovernance} from "./mocks/MockGovernance.sol";
// veto to veto: set 0 user allocation, do nothing to total allocation

contract BribeInitiativeAllocateTest is Test {
MockERC20 private lqty;
MockERC20 private lusd;
address private stakingV1;
MockERC20Tester private lqty;
MockERC20Tester private lusd;
address private constant user = address(0xF977814e90dA44bFA03b6295A0616a897441aceC);
address private constant user2 = address(0xcA7f01403C4989d2b1A9335A2F09dD973709957c);
address private constant lusdHolder = address(0xcA7f01403C4989d2b1A9335A2F09dD973709957c);
Expand All @@ -44,13 +41,11 @@ contract BribeInitiativeAllocateTest is Test {
BribeInitiative private bribeInitiative;

function setUp() public {
lqty = deployMockERC20("Liquity", "LQTY", 18);
lusd = deployMockERC20("Liquity USD", "LUSD", 18);
lqty = new MockERC20Tester("Liquity", "LQTY");
lusd = new MockERC20Tester("Liquity USD", "LUSD");

vm.store(address(lqty), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10000e18)));
vm.store(address(lusd), keccak256(abi.encode(address(lusdHolder), 4)), bytes32(abi.encode(10000e18)));

stakingV1 = address(new MockStakingV1(address(lqty)));
lqty.mint(lusdHolder, 10000e18);
lusd.mint(lusdHolder, 10000e18);

governance = new MockGovernance();

Expand Down
41 changes: 17 additions & 24 deletions test/CurveV2GaugeRewards.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,7 @@ import {ILiquidityGauge} from "./../src/interfaces/ILiquidityGauge.sol";
import {CurveV2GaugeRewards} from "../src/CurveV2GaugeRewards.sol";
import {Governance} from "../src/Governance.sol";

import {MockGovernance} from "./mocks/MockGovernance.sol";

contract CurveV2GaugeRewardsTest is Test {
contract ForkedCurveV2GaugeRewardsTest is Test {
IERC20 private constant lqty = IERC20(address(0x6DEA81C8171D0bA574754EF6F8b412F2Ed88c54D));
IERC20 private constant lusd = IERC20(address(0x5f98805A4E8be255a32880FDeC7F6728C6568bA0));
IERC20 private constant usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
Expand Down Expand Up @@ -77,29 +75,24 @@ contract CurveV2GaugeRewardsTest is Test {
604800
);

initialInitiatives = new address[](1);
initialInitiatives[0] = address(curveV2GaugeRewards);
initialInitiatives.push(address(curveV2GaugeRewards));

IGovernance.Configuration memory config = IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
registrationThresholdFactor: REGISTRATION_THRESHOLD_FACTOR,
unregistrationThresholdFactor: UNREGISTRATION_THRESHOLD_FACTOR,
registrationWarmUpPeriod: REGISTRATION_WARM_UP_PERIOD,
unregistrationAfterEpochs: UNREGISTRATION_AFTER_EPOCHS,
votingThresholdFactor: VOTING_THRESHOLD_FACTOR,
minClaim: MIN_CLAIM,
minAccrual: MIN_ACCRUAL,
epochStart: uint32(block.timestamp),
epochDuration: EPOCH_DURATION,
epochVotingCutoff: EPOCH_VOTING_CUTOFF
});

governance = new Governance(
address(lqty),
address(lusd),
stakingV1,
address(lusd),
IGovernance.Configuration({
registrationFee: REGISTRATION_FEE,
registrationThresholdFactor: REGISTRATION_THRESHOLD_FACTOR,
unregistrationThresholdFactor: UNREGISTRATION_THRESHOLD_FACTOR,
registrationWarmUpPeriod: REGISTRATION_WARM_UP_PERIOD,
unregistrationAfterEpochs: UNREGISTRATION_AFTER_EPOCHS,
votingThresholdFactor: VOTING_THRESHOLD_FACTOR,
minClaim: MIN_CLAIM,
minAccrual: MIN_ACCRUAL,
epochStart: uint32(block.timestamp),
epochDuration: EPOCH_DURATION,
epochVotingCutoff: EPOCH_VOTING_CUTOFF
}),
address(this),
initialInitiatives
address(lqty), address(lusd), stakingV1, address(lusd), config, address(this), initialInitiatives
);

vm.startPrank(curveFactory.admin());
Expand Down
Loading

0 comments on commit e22fa33

Please sign in to comment.