-
-
Save Reentrants/50898e49155a13b9eddbe69ea52c1a19 to your computer and use it in GitHub Desktop.
E2E Test Setup
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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