Skip to content

Instantly share code, notes, and snippets.

@Reentrants
Last active July 5, 2024 03:57
Show Gist options
  • Save Reentrants/50898e49155a13b9eddbe69ea52c1a19 to your computer and use it in GitHub Desktop.
Save Reentrants/50898e49155a13b9eddbe69ea52c1a19 to your computer and use it in GitHub Desktop.
E2E Test Setup
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "forge-std/Test.sol";
import "openzeppelin-contracts-upgradeable/access/OwnableUpgradeable.sol";
import "../src/rewarders/MasterChefRewarder.sol";
import "../src/rewarders/BribeRewarder.sol";
import "../src/rewarders/RewarderFactory.sol";
import "../src/transparent/TransparentUpgradeableProxy2Step.sol";
import "./mocks/ERC20.sol";
import "../src/Voter.sol";
import "../src/MasterchefV2.sol";
import "../src/MlumStaking.sol";
contract E2ETest is Test {
Voter voter;
MasterChefRewarder rewarder;
BribeRewarder bribeRewarder;
MasterChef masterChef;
MlumStaking staking;
RewarderFactory rewarderFactory;
IERC20 tokenA;
IERC20 tokenB;
IERC20 stakingToken;
IERC20 masterChefRewardToken; // LUM
IERC20 rewardToken; // for Mlum staking rewards
IERC20 extraRewardToken;
address alice = makeAddr("alice");
address bob = makeAddr("bob");
address owner = makeAddr("owner");
address treasury = makeAddr("treasury");
address pool = makeAddr("pool");
address lbHooks = makeAddr("lbHooks");
uint256 CURRENT_TIME = 1720062900; // 3:15 am, Jul 4 2024
function setUp() public {
vm.warp(CURRENT_TIME);
tokenA = IERC20(new ERC20Mock("Token A", "TA", 18));
tokenB = IERC20(new ERC20Mock("Token B", "TB", 18));
stakingToken = IERC20(new ERC20Mock("mlum", "MLUM", 18));
masterChefRewardToken = IERC20(new ERC20Mock("Lum", "LUM", 18));
rewardToken = IERC20(new ERC20Mock("USDC", "USDC", 6));
extraRewardToken = IERC20(new ERC20Mock("USDT", "USDT", 6));
address factoryImpl = address(new RewarderFactory());
rewarderFactory = RewarderFactory(
address(
new TransparentUpgradeableProxy2Step(
factoryImpl,
ProxyAdmin2Step(address(1)),
abi.encodeWithSelector(
RewarderFactory.initialize.selector, owner, new uint8[](0), new address[](0)
)
)
)
);
masterChef = new MasterChef(
ILum(address(stakingToken)),
IVoter(address(0)),
IRewarderFactory(address(rewarderFactory)),
lbHooks,
Constants.PRECISION / 100
);
TransparentUpgradeableProxy2Step proxy = new TransparentUpgradeableProxy2Step(
address(masterChef),
ProxyAdmin2Step(address(1)),
abi.encodeWithSelector(
MasterChef.initialize.selector, owner, treasury
)
);
masterChef = MasterChef(address(proxy));
address poolImpl = address(new MlumStaking(stakingToken, rewardToken));
staking = MlumStaking(
address(
new TransparentUpgradeableProxy2Step(
poolImpl, ProxyAdmin2Step(address(1)), abi.encodeWithSelector(MlumStaking.initialize.selector, owner)
)
)
);
address voterImpl = address(new Voter(masterChef, staking, IRewarderFactory(address(rewarderFactory))));
voter = Voter(
address(
new TransparentUpgradeableProxy2Step(
voterImpl, ProxyAdmin2Step(address(1)), abi.encodeWithSelector(Voter.initialize.selector, owner)
)
)
);
vm.startPrank(owner);
masterChef.setVoter(IVoter(address(voter)));
rewarderFactory.setRewarderImplementation(
IRewarderFactory.RewarderType.MasterChefRewarder, IRewarder(address(new MasterChefRewarder(address(masterChef))))
);
rewarderFactory.setRewarderImplementation(
IRewarderFactory.RewarderType.BribeRewarder, IRewarder(address(new BribeRewarder(address(voter))))
);
masterChef.add(tokenA, IMasterChefRewarder(address(0)));
rewarder = MasterChefRewarder(payable(address(rewarderFactory.createRewarder(IRewarderFactory.RewarderType.MasterChefRewarder, rewardToken, 0))));
masterChef.setExtraRewarder(0, rewarder);
uint256[] memory pids = new uint[](1);
uint256[] memory weights = new uint[](1);
weights[0] = 100;
voter.setTopPoolIdsWithWeights(pids, weights);
vm.stopPrank();
///////////////////
/// DEAL TOKENS ///
///////////////////
deal(alice, 1 ether);
deal(address(tokenA), alice, 10e18);
deal(address(tokenB), alice, 20e18);
deal(address(stakingToken), alice, 10e18);
deal(bob, 1 ether);
deal(address(tokenA), bob, 50e18);
deal(address(tokenB), bob, 100e18);
deal(address(stakingToken), bob, 100e18);
deal(owner, 1 ether);
deal(address(masterChefRewardToken), owner, 1000e18);
deal(address(rewardToken), owner, 10_000e6);
deal(address(extraRewardToken), owner, 10_000e6);
deal(address(masterChefRewardToken), address(masterChef), 1000e18);
/////////////////
/// APPROVALS ///
/////////////////
vm.startPrank(alice);
tokenA.approve(address(masterChef), type(uint256).max);
tokenB.approve(address(masterChef), type(uint256).max);
stakingToken.approve(address(staking), type(uint256).max);
vm.startPrank(bob);
tokenA.approve(address(masterChef), type(uint256).max);
tokenB.approve(address(masterChef), type(uint256).max);
stakingToken.approve(address(staking), type(uint256).max);
vm.stopPrank();
/////////////
/// LABEL ///
/////////////
vm.label(address(tokenA), "tokenA");
vm.label(address(tokenB), "tokenB");
vm.label(address(stakingToken), "stakingToken");
vm.label(address(rewardToken), "rewardToken");
vm.label(address(extraRewardToken), "extraRewardToken");
vm.label(address(voter), "voter");
vm.label(address(masterChef), "masterChef");
vm.label(address(staking), "staking");
vm.label(address(rewarder), "rewarder");
vm.label(address(rewarderFactory), "rewarderFactory");
}
function test_sanity_verify_setup() public {
assertEq(rewarder.getCaller(), address(masterChef));
}
function test_incorrect_modify_check() public {
vm.startPrank(alice);
staking.createPosition(1e18, 180 days);
bribeRewarder = BribeRewarder(payable(address(rewarderFactory.createBribeRewarder(IERC20(address(0)), address(tokenA)))));
bribeRewarder.fundAndBribe{value: 100 wei}(1, 100, 1);
vm.startPrank(owner);
voter.startNewVotingPeriod();
vm.startPrank(alice);
address[] memory pools = new address[](1);
pools[0] = address(tokenA);
uint256[] memory deltaAmounts = new uint256[](1);
deltaAmounts[0] = 100;
// voting reverts from incorrect staking NFT owner check
vm.expectRevert(IBribeRewarder.BribeRewarder__NotOwner.selector);
voter.vote(1, pools, deltaAmounts);
}
function test_DoS_bribe_creation() public {
vm.startPrank(alice);
for (uint i; i < 5; ++i) {
bribeRewarder = BribeRewarder(payable(address(rewarderFactory.createBribeRewarder(IERC20(address(0)), address(tokenA)))));
// 1000 periods, minimal wei amount per period
bribeRewarder.fundAndBribe{value: 1000 wei}(1, 100, 1);
}
vm.startPrank(bob);
bribeRewarder = BribeRewarder(payable(address(rewarderFactory.createBribeRewarder(IERC20(address(0)), address(tokenA)))));
vm.expectRevert("too much bribes");
bribeRewarder.fundAndBribe{value: 1000 wei}(1, 100, 1);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment