diff --git a/src/BaseStaking.sol b/src/BaseStaking.sol new file mode 100644 index 0000000..9f8c757 --- /dev/null +++ b/src/BaseStaking.sol @@ -0,0 +1,231 @@ +// SPDX-License-Identifier: MIT +pragma solidity 0.8.26; + +import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; +import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; +import {ERC20VotesUpgradeable} from "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; + +import {IERC20} from "./interfaces/IERC20.sol"; +import {SafeTransferLib} from "./libraries/SafeTransferLib.sol"; +import {FixedPointMathLib} from "./libraries/FixedPointMathLib.sol"; +import {IRewardsDistributor} from "./interfaces/IRewardsDistributor.sol"; + +interface IStaking { + function keypers(address user) external returns (bool); +} + +abstract contract BaseStaking is OwnableUpgradeable, ERC20VotesUpgradeable { + /*////////////////////////////////////////////////////////////// + LIBRARIES + //////////////////////////////////////////////////////////////*/ + + using SafeTransferLib for IERC20; + + using FixedPointMathLib for uint256; + + /*////////////////////////////////////////////////////////////// + VARIABLES + //////////////////////////////////////////////////////////////*/ + + /// @notice the staking token, i.e. SHU + /// @dev set in initialize, can't be changed + IERC20 public stakingToken; + + /// @notice the rewards distributor contract + /// @dev only owner can change + IRewardsDistributor public rewardsDistributor; + + /// @notice Unique identifier that will be used for the next stake. + uint256 internal nextStakeId; + + /// @notice the lock period in seconds + /// @dev only owner can change + uint256 public lockPeriod; + + /*////////////////////////////////////////////////////////////// + MAPPINGS + //////////////////////////////////////////////////////////////*/ + + /// @notice how many SHU a user has locked + mapping(address user => uint256 totalLocked) public totalLocked; + + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + /// @notice Emitted when a keyper claims rewards + event RewardsClaimed(address indexed user, uint256 rewards); + + /// @notice Emitted when the rewards distributor is changed + event NewRewardsDistributor(address indexed rewardsDistributor); + + event NewLockPeriod(uint256 indexed lockPeriod); + + /*////////////////////////////////////////////////////////////// + ERRORS + //////////////////////////////////////////////////////////////*/ + + /// @notice Thrown when someone try to unstake a amount that is greater than + /// the stake amount belonging to the stake id + error WithdrawAmountTooHigh(); + + /// @notice Thrown when transfer/tranferFrom is called + error TransferDisabled(); + + /// @notice Thrown when a user has no shares + error UserHasNoShares(); + + /// @notice Thrown when a user try to claim rewards but has no rewards to + /// claim + error NoRewardsToClaim(); + + /// @notice Thrown when the argument is the zero address + error AddressZero(); + + /*////////////////////////////////////////////////////////////// + MODIFIERS + //////////////////////////////////////////////////////////////*/ + + /// @notice Update rewards for a keyper + modifier updateRewards() { + // Distribute rewards + rewardsDistributor.collectRewards(); + + _; + } + + /// @notice Ensure logic contract is unusable + constructor() { + _disableInitializers(); + } + + /// @notice Claim rewards + /// - If no amount is specified, will claim all the rewards + /// - If the amount is specified, the amount must be less than the + /// maximum withdrawable amount. The maximum withdrawable amount + /// is the total amount of assets the user has minus the + /// total locked amount + /// - If the claim results in a balance less than the total locked + /// amount, the claim will be rejected + /// - The keyper can claim the rewards at any time as longs there is + /// a reward to claim + /// @param amount The amount of rewards to claim + function claimRewards( + uint256 amount + ) external updateRewards returns (uint256 rewards) { + address user = msg.sender; + + // Prevents the keyper from claiming more than they should + uint256 maxWithdrawAmount = maxWithdraw(user); + + rewards = _calculateWithdrawAmount(amount, maxWithdrawAmount); + + require(rewards > 0, NoRewardsToClaim()); + + // Calculates the amount of shares to burn + uint256 shares = previewWithdraw(rewards); + + _burn(user, shares); + + stakingToken.safeTransfer(user, rewards); + + emit RewardsClaimed(user, rewards); + } + + /*////////////////////////////////////////////////////////////// + RESTRICTED FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /// @notice Set the rewards distributor contract + /// @param _rewardsDistributor The address of the rewards distributor contract + function setRewardsDistributor( + address _rewardsDistributor + ) external onlyOwner { + require(_rewardsDistributor != address(0), AddressZero()); + rewardsDistributor = IRewardsDistributor(_rewardsDistributor); + + emit NewRewardsDistributor(_rewardsDistributor); + } + + /// @notice Set the lock period + /// @param _lockPeriod The lock period in seconds + function setLockPeriod(uint256 _lockPeriod) external onlyOwner { + lockPeriod = _lockPeriod; + + emit NewLockPeriod(_lockPeriod); + } + + /*////////////////////////////////////////////////////////////// + TRANSFER LOGIC + //////////////////////////////////////////////////////////////*/ + + /// @notice Transfer is disabled + function transfer(address, uint256) public pure override returns (bool) { + revert TransferDisabled(); + } + + /// @notice Transfer is disabled + function transferFrom( + address, + address, + uint256 + ) public pure override returns (bool) { + revert TransferDisabled(); + } + + /*////////////////////////////////////////////////////////////// + VIEW FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function previewWithdraw( + uint256 assets + ) public view virtual returns (uint256) { + // sum + 1 on both sides to prevent donation attack + return assets.mulDivUp(totalSupply() + 1, _totalAssets() + 1); + } + + /// @notice Get the total amount of shares the assets are worth + /// @param assets The amount of assets + function convertToShares( + uint256 assets + ) public view virtual returns (uint256) { + // sum + 1 on both sides to prevent donation attack + return assets.mulDivDown(totalSupply() + 1, _totalAssets() + 1); + } + + /// @notice Get the total amount of assets the shares are worth + /// @param shares The amount of shares + function convertToAssets( + uint256 shares + ) public view virtual returns (uint256) { + // sum + 1 on both sides to prevent donation attack + return shares.mulDivDown(_totalAssets() + 1, totalSupply() + 1); + } + + function maxWithdraw(address user) public view virtual returns (uint256); + + /*////////////////////////////////////////////////////////////// + INTERNAL FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /// @notice Get the amount of SHU staked for all keypers + function _totalAssets() internal view virtual returns (uint256) { + return stakingToken.balanceOf(address(this)); + } + + /// @notice Calculates the amount to withdraw + /// @param _amount The amount to withdraw + /// @param maxWithdrawAmount The maximum amount that can be withdrawn + function _calculateWithdrawAmount( + uint256 _amount, + uint256 maxWithdrawAmount + ) internal pure returns (uint256 amount) { + // If the amount is 0, withdraw all available amount + if (_amount == 0) { + amount = maxWithdrawAmount; + } else { + require(_amount <= maxWithdrawAmount, WithdrawAmountTooHigh()); + amount = _amount; + } + } +} diff --git a/src/DelegateStaking.sol b/src/DelegateStaking.sol index 8e6be3e..7dce618 100644 --- a/src/DelegateStaking.sol +++ b/src/DelegateStaking.sol @@ -73,7 +73,7 @@ contract DelegateStaking is ERC20VotesUpgradeable, OwnableUpgradeable { mapping(address user => EnumerableSet.UintSet stakeIds) private userStakes; /// @notice how many SHU a user has locked - mapping(address keyper => uint256 totalLocked) public totalLocked; + mapping(address user => uint256 totalLocked) public totalLocked; /*////////////////////////////////////////////////////////////// EVENTS @@ -183,7 +183,7 @@ contract DelegateStaking is ERC20VotesUpgradeable, OwnableUpgradeable { /// @notice Stake SHU /// - amount will be locked in the contract for the lock period /// - user must approve the contract to spend the SHU before staking - /// - this function will mint sdSHU to the keyper + /// - this function will mint dSHU to the keyper //// - dSHU is non-transferable /// @param amount The amount of SHU to stake /// @return stakeId The index of the stake diff --git a/src/Staking.sol b/src/Staking.sol index 115fd02..585517b 100644 --- a/src/Staking.sol +++ b/src/Staking.sol @@ -2,49 +2,33 @@ pragma solidity 0.8.26; import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; -import {OwnableUpgradeable} from "@openzeppelin-upgradeable/contracts/access/OwnableUpgradeable.sol"; import {ERC20VotesUpgradeable} from "@openzeppelin-upgradeable/contracts/token/ERC20/extensions/ERC20VotesUpgradeable.sol"; import {IERC20} from "./interfaces/IERC20.sol"; import {SafeTransferLib} from "./libraries/SafeTransferLib.sol"; import {FixedPointMathLib} from "./libraries/FixedPointMathLib.sol"; import {IRewardsDistributor} from "./interfaces/IRewardsDistributor.sol"; +import {BaseStaking} from "./BaseStaking.sol"; /// @notice Shutter Staking Contract /// Allows keypers to stake SHU for a lock period and earn rewards in exchange -contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { +contract Staking is BaseStaking { /*////////////////////////////////////////////////////////////// LIBRARIES //////////////////////////////////////////////////////////////*/ + using EnumerableSet for EnumerableSet.UintSet; using SafeTransferLib for IERC20; - using FixedPointMathLib for uint256; - /*////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////*/ - /// @notice the staking token, i.e. SHU - /// @dev set in initialize, can't be changed - IERC20 public stakingToken; - - /// @notice the rewards distributor contract - /// @dev only owner can change - IRewardsDistributor public rewardsDistributor; - - /// @notice the lock period in seconds - /// @dev only owner can change - uint256 public lockPeriod; - /// @notice the minimum stake amount /// @dev only owner can change uint256 public minStake; - /// @notice Unique identifier that will be used for the next stake. - uint256 internal nextStakeId; - /*////////////////////////////////////////////////////////////// STRUCTS //////////////////////////////////////////////////////////////*/ @@ -61,44 +45,27 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { MAPPINGS //////////////////////////////////////////////////////////////*/ + // @notice stake ids belonging to a user + mapping(address user => EnumerableSet.UintSet stakeIds) internal userStakes; + /// @notice stores the metadata associated with a given stake mapping(uint256 id => Stake _stake) public stakes; - // @notice stake ids belonging to a keyper - mapping(address keyper => EnumerableSet.UintSet stakeIds) - private keyperStakes; - /// @notice keypers mapping mapping(address keyper => bool isKeyper) public keypers; - /// @notice how many SHU a keyper has locked - mapping(address keyper => uint256 totalLocked) public totalLocked; - - /*////////////////////////////////////////////////////////////// - EVENTS - //////////////////////////////////////////////////////////////*/ - /// @notice Emitted when a keyper stakes SHU event Staked(address indexed user, uint256 amount, uint256 lockPeriod); /// @notice Emitted when a keyper unstakes SHU event Unstaked(address indexed user, uint256 amount, uint256 shares); - /// @notice Emitted when a keyper claims rewards - event RewardsClaimed(address indexed user, uint256 rewards); - /// @notice Emitted when a keyper is added or removed event KeyperSet(address indexed keyper, bool isKeyper); - /// @notice Emitted when the lock period is changed - event NewLockPeriod(uint256 indexed lockPeriod); - /// @notice Emitted when the minimum stake is changed event NewMinStake(uint256 indexed minStake); - /// @notice Emitted when the rewards distributor is changed - event NewRewardsDistributor(address indexed rewardsDistributor); - /*////////////////////////////////////////////////////////////// ERRORS //////////////////////////////////////////////////////////////*/ @@ -106,12 +73,6 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { /// @notice Thrown when a non-keyper attempts a call for which only keypers are allowed error OnlyKeyper(); - /// @notice Thrown when transfer/tranferFrom is called - error TransferDisabled(); - - /// @notice Thrown when a keyper has no shares - error UserHasNoShares(); - /// @notice Thrown when a keyper has staking for the first time and the /// amount is less than the minimum stake set by the DAO error FirstStakeLessThanMinStake(); @@ -126,20 +87,9 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { /// @notice Thrown when someone try to unstake a stake that doesn't exist error StakeDoesNotExist(); - /// @notice Thrown when someone try to unstake a amount that is greater than - /// the stake amount belonging to the stake id - error WithdrawAmountTooHigh(); - /// @notice Thrown when someone try to unstake a stake that is still locked error StakeIsStillLocked(); - /// @notice Thrown when a keyper try to claim rewards but has no rewards to - /// claim - error NoRewardsToClaim(); - - /// @notice Thrown when the argument is the zero address - error AddressZero(); - /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ @@ -150,14 +100,6 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { _; } - /// @notice Update rewards for a keyper - modifier updateRewards() { - // Distribute rewards - rewardsDistributor.collectRewards(); - - _; - } - /// @notice Ensure logic contract is unusable constructor() { _disableInitializers(); @@ -207,7 +149,7 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { address keyper = msg.sender; // Get the keyper stakes - EnumerableSet.UintSet storage stakesIds = keyperStakes[keyper]; + EnumerableSet.UintSet storage stakesIds = userStakes[keyper]; // If the keyper has no stakes, the first stake must be at least the minimum stake if (stakesIds.length() == 0) { @@ -264,7 +206,7 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { uint256 _amount ) external returns (uint256 amount) { require( - keyperStakes[keyper].contains(stakeId), + userStakes[keyper].contains(stakeId), StakeDoesNotBelongToKeyper() ); Stake memory keyperStake = stakes[stakeId]; @@ -307,7 +249,7 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { ); } - // Calculates the amounf of shares to burn + // Calculates the amount of shares to burn uint256 shares = previewWithdraw(amount); // Burn the shares @@ -325,7 +267,7 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { delete stakes[stakeId]; // Remove the stake from the keyper stakes - keyperStakes[keyper].remove(stakeId); + userStakes[keyper].remove(stakeId); } // Transfer the SHU to the keyper @@ -334,62 +276,9 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { emit Unstaked(keyper, amount, shares); } - /// @notice Claim rewards - /// - If no amount is specified, will claim all the rewards - /// - If the amount is specified, the amount must be less than the - /// maximum withdrawable amount. The maximum withdrawable amount - /// is the total amount of assets the keyper has minus either the - /// total locked amount or the minimum stake, whichever is greater - /// - If the claim results in a balance less than the total locked - /// amount, the claim will be rejected - /// - The keyper can claim the rewards at any time as longs there is - /// a reward to claim - /// @param amount The amount of rewards to claim - function claimRewards( - uint256 amount - ) external updateRewards returns (uint256 rewards) { - address keyper = msg.sender; - - // Prevents the keyper from claiming more than they should - uint256 maxWithdrawAmount = maxWithdraw(keyper); - - rewards = _calculateWithdrawAmount(amount, maxWithdrawAmount); - - require(rewards > 0, NoRewardsToClaim()); - - // Calculates the amount of shares to burn - uint256 shares = previewWithdraw(rewards); - - _burn(keyper, shares); - - stakingToken.safeTransfer(keyper, rewards); - - emit RewardsClaimed(keyper, rewards); - } - /*////////////////////////////////////////////////////////////// RESTRICTED FUNCTIONS //////////////////////////////////////////////////////////////*/ - - /// @notice Set the rewards distributor contract - /// @param _rewardsDistributor The address of the rewards distributor contract - function setRewardsDistributor( - address _rewardsDistributor - ) external onlyOwner { - require(_rewardsDistributor != address(0), AddressZero()); - rewardsDistributor = IRewardsDistributor(_rewardsDistributor); - - emit NewRewardsDistributor(_rewardsDistributor); - } - - /// @notice Set the lock period - /// @param _lockPeriod The lock period in seconds - function setLockPeriod(uint256 _lockPeriod) external onlyOwner { - lockPeriod = _lockPeriod; - - emit NewLockPeriod(_lockPeriod); - } - /// @notice Set the minimum stake amount /// @param _minStake The minimum stake amount function setMinStake(uint256 _minStake) external onlyOwner { @@ -408,70 +297,29 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { emit KeyperSet(keyper, isKeyper); } - /*////////////////////////////////////////////////////////////// - TRANSFER LOGIC - //////////////////////////////////////////////////////////////*/ - - /// @notice Transfer is disabled - function transfer(address, uint256) public pure override returns (bool) { - revert TransferDisabled(); - } - - /// @notice Transfer is disabled - function transferFrom( - address, - address, - uint256 - ) public pure override returns (bool) { - revert TransferDisabled(); - } - /*////////////////////////////////////////////////////////////// VIEW FUNCTIONS //////////////////////////////////////////////////////////////*/ - /// @notice Get the stake ids belonging to a keyper - function getKeyperStakeIds( - address keyper - ) external view returns (uint256[] memory) { - return keyperStakes[keyper].values(); - } - - function previewWithdraw( - uint256 assets - ) public view virtual returns (uint256) { - // sum + 1 on both sides to prevent donation attack - return assets.mulDivUp(totalSupply() + 1, _totalAssets() + 1); - } - - /// @notice Get the total amount of shares the assets are worth - /// @param assets The amount of assets - function convertToShares( - uint256 assets - ) public view virtual returns (uint256) { - // sum + 1 on both sides to prevent donation attack - return assets.mulDivDown(totalSupply() + 1, _totalAssets() + 1); - } - - /// @notice Get the total amount of assets the shares are worth - /// @param shares The amount of shares - function convertToAssets( - uint256 shares - ) public view virtual returns (uint256) { - // sum + 1 on both sides to prevent donation attack - return shares.mulDivDown(_totalAssets() + 1, totalSupply() + 1); - } - /// @notice Get the maximum amount of assets that a keyper can withdraw //// - if the keyper has no shares, the function will revert /// - if the keyper sSHU balance is less or equal than the minimum stake or the total /// locked amount, the function will return 0 /// @param keyper The keyper address /// @return amount The maximum amount of assets that a keyper can withdraw - function maxWithdraw(address keyper) public view virtual returns (uint256) { + function maxWithdraw( + address keyper + ) public view override returns (uint256) { return _maxWithdraw(keyper, 0); } + /// @notice Get the stake ids belonging to a user + function getUserStakeIds( + address user + ) external view returns (uint256[] memory) { + return userStakes[user].values(); + } + /*////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ @@ -499,25 +347,4 @@ contract Staking is ERC20VotesUpgradeable, OwnableUpgradeable { // need the first branch as convertToAssets rounds down amount = compare >= assets ? 0 : assets - compare; } - - /// @notice Get the amount of SHU staked for all keypers - function _totalAssets() internal view virtual returns (uint256) { - return stakingToken.balanceOf(address(this)); - } - - /// @notice Calculates the amount to withdraw - /// @param _amount The amount to withdraw - /// @param maxWithdrawAmount The maximum amount that can be withdrawn - function _calculateWithdrawAmount( - uint256 _amount, - uint256 maxWithdrawAmount - ) internal pure returns (uint256 amount) { - // If the amount is 0, withdraw all available amount - if (_amount == 0) { - amount = maxWithdrawAmount; - } else { - require(_amount <= maxWithdrawAmount, WithdrawAmountTooHigh()); - amount = _amount; - } - } } diff --git a/test/Staking.t.sol b/test/Staking.t.sol index b159c77..576bfa1 100644 --- a/test/Staking.t.sol +++ b/test/Staking.t.sol @@ -8,6 +8,7 @@ import {FixedPointMathLib} from "@solmate/utils/FixedPointMathLib.sol"; import {TransparentUpgradeableProxy, ITransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {Staking} from "src/Staking.sol"; +import {BaseStaking} from "src/BaseStaking.sol"; import {RewardsDistributor} from "src/RewardsDistributor.sol"; import {IRewardsDistributor} from "src/interfaces/IRewardsDistributor.sol"; import {MockGovToken} from "test/mocks/MockGovToken.sol"; @@ -869,7 +870,7 @@ contract ClaimRewards is StakingTest { vm.prank(_depositor); vm.expectEmit(true, true, false, false); - emit Staking.RewardsClaimed( + emit BaseStaking.RewardsClaimed( _depositor, REWARD_RATE * (vm.getBlockTimestamp() - timestampBefore) ); @@ -1119,7 +1120,7 @@ contract ClaimRewards is StakingTest { vm.prank(_depositor); - vm.expectRevert(Staking.NoRewardsToClaim.selector); + vm.expectRevert(BaseStaking.NoRewardsToClaim.selector); staking.claimRewards(0); } @@ -1130,7 +1131,7 @@ contract ClaimRewards is StakingTest { ); vm.prank(_depositor); - vm.expectRevert(Staking.UserHasNoShares.selector); + vm.expectRevert(BaseStaking.UserHasNoShares.selector); staking.claimRewards(0); } @@ -1160,7 +1161,7 @@ contract ClaimRewards is StakingTest { _stake(_depositor2, _amount2); vm.prank(_depositor2); - vm.expectRevert(Staking.NoRewardsToClaim.selector); + vm.expectRevert(BaseStaking.NoRewardsToClaim.selector); staking.claimRewards(0); } } @@ -1340,7 +1341,7 @@ contract Unstake is StakingTest { assertEq(govToken.balanceOf(_depositor), _amount * 2, "Wrong balance"); - uint256[] memory stakeIds = staking.getKeyperStakeIds(_depositor); + uint256[] memory stakeIds = staking.getUserStakeIds(_depositor); assertEq(stakeIds.length, 0, "Wrong stake ids"); } @@ -1410,7 +1411,7 @@ contract Unstake is StakingTest { assertEq(govToken.balanceOf(_depositor), _amount2, "Wrong balance"); - uint256[] memory stakeIds = staking.getKeyperStakeIds(_depositor); + uint256[] memory stakeIds = staking.getUserStakeIds(_depositor); assertEq(stakeIds.length, 1, "Wrong stake ids"); (uint256 amount, , ) = staking.stakes(stakeIds[0]); @@ -1487,7 +1488,7 @@ contract Unstake is StakingTest { _jumpAhead(vm.getBlockTimestamp() + LOCK_PERIOD); vm.prank(depositor); - vm.expectRevert(Staking.WithdrawAmountTooHigh.selector); + vm.expectRevert(BaseStaking.WithdrawAmountTooHigh.selector); staking.unstake(depositor, stakeId, MIN_STAKE); } @@ -1530,7 +1531,7 @@ contract Unstake is StakingTest { uint256 stakeId = _stake(_depositor, _amount); vm.prank(_depositor); - vm.expectRevert(Staking.WithdrawAmountTooHigh.selector); + vm.expectRevert(BaseStaking.WithdrawAmountTooHigh.selector); staking.unstake(_depositor, stakeId, _amount + 1); } @@ -1574,7 +1575,7 @@ contract OwnableFunctions is StakingTest { ); vm.expectEmit(); - emit Staking.NewRewardsDistributor(_newRewardsDistributor); + emit BaseStaking.NewRewardsDistributor(_newRewardsDistributor); staking.setRewardsDistributor(_newRewardsDistributor); assertEq( @@ -1586,7 +1587,7 @@ contract OwnableFunctions is StakingTest { function testFuzz_setLockPeriod(uint256 _newLockPeriod) public { vm.expectEmit(); - emit Staking.NewLockPeriod(_newLockPeriod); + emit BaseStaking.NewLockPeriod(_newLockPeriod); staking.setLockPeriod(_newLockPeriod); assertEq(staking.lockPeriod(), _newLockPeriod, "Wrong lock period"); @@ -1700,7 +1701,7 @@ contract ViewFunctions is StakingTest { function testFuzz_Revertif_MaxWithdrawDepositorHasNoStakes( address _depositor ) public { - vm.expectRevert(Staking.UserHasNoShares.selector); + vm.expectRevert(BaseStaking.UserHasNoShares.selector); staking.maxWithdraw(_depositor); } @@ -1828,7 +1829,7 @@ contract ViewFunctions is StakingTest { uint256 stakeId1 = _stake(_depositor, _amount1); uint256 stakeId2 = _stake(_depositor, _amount2); - uint256[] memory stakeIds = staking.getKeyperStakeIds(_depositor); + uint256[] memory stakeIds = staking.getUserStakeIds(_depositor); assertEq(stakeIds.length, 2, "Wrong stake ids"); assertEq(stakeIds[0], stakeId1, "Wrong stake id"); @@ -1849,7 +1850,7 @@ contract Transfer is StakingTest { _stake(_from, _amount); - vm.expectRevert(Staking.TransferDisabled.selector); + vm.expectRevert(BaseStaking.TransferDisabled.selector); staking.transfer(_to, _amount); } @@ -1865,7 +1866,7 @@ contract Transfer is StakingTest { _stake(_from, _amount); - vm.expectRevert(Staking.TransferDisabled.selector); + vm.expectRevert(BaseStaking.TransferDisabled.selector); staking.transferFrom(_from, _to, _amount); } }