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

Mocked versions of tests #80

Merged
merged 21 commits into from
Nov 22, 2024
Merged
Show file tree
Hide file tree
Changes from 20 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
6ef567f
fix: unnecessary approval given to `LQTYStaking`
danielattilasimon Nov 19, 2024
a92385d
chore: remove unused import
danielattilasimon Nov 19, 2024
ee3e805
test: improved `MockStakingV1`
danielattilasimon Nov 19, 2024
b4e5140
chore: remove unused imports
danielattilasimon Nov 19, 2024
32d322e
test: mocked & forked `UserProxy` tests
danielattilasimon Nov 20, 2024
992f6f8
chore: update forge-std
danielattilasimon Nov 20, 2024
4c8055a
test: mocked & forked `Governance` tests
danielattilasimon Nov 20, 2024
a0de52f
test: mocked & forked `Governance` attack tests
danielattilasimon Nov 20, 2024
49b7f11
ci: use a different fuzz seed each time
danielattilasimon Nov 20, 2024
e38d05d
test: mocked & forked `UniV4Donations` tests
danielattilasimon Nov 20, 2024
12bdf39
test: mocked & forked voting power tests
danielattilasimon Nov 21, 2024
8e6f374
test: fix failing tests
danielattilasimon Nov 21, 2024
eaac7be
test: clean up `Governance` setup in some test contracts
danielattilasimon Nov 21, 2024
22ece8a
test: ensure all forked tests are prefixed with `Forked`
danielattilasimon Nov 21, 2024
4941886
chore: fix typo in comment
danielattilasimon Nov 21, 2024
0f49049
ci: add color
danielattilasimon Nov 21, 2024
7e9c169
test: fix excessive `vm.assume()` rejection
danielattilasimon Nov 21, 2024
613bf67
ci: alternative attempt at color
danielattilasimon Nov 21, 2024
7f3abac
ci: remove unnecessary dependency on lint & build
danielattilasimon Nov 21, 2024
19c5621
ci: tone down fuzz runs
danielattilasimon Nov 21, 2024
25fb79c
Merge remote-tracking branch 'origin/main' into testing
danielattilasimon Nov 22, 2024
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
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 @@ -37,7 +37,6 @@ contract UserProxy is IUserProxy {
/// @inheritdoc IUserProxy
function stake(uint256 _amount, address _lqtyFrom) public onlyStakingV2 {
lqty.safeTransferFrom(_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