mirror of
https://github.com/vacp2p/staking-reward-streamer.git
synced 2026-01-09 21:18:01 -05:00
chore: introduce IStakeManager interface
This introduces a first version of `IStakeManager`, highly inspired by the changes done in https://github.com/vacp2p/staking-reward-streamer/pull/39. However, in this commit, it only adds the methods that are currently supported by both, `StakeManager` and `RewardStreamerMP`. Future commits will add APIs for locking and leaving.
This commit is contained in:
20
.gas-report
20
.gas-report
@@ -17,19 +17,19 @@
|
||||
| Deployment Cost | Deployment Size | | | | |
|
||||
| 1010922 | 4521 | | | | |
|
||||
| Function Name | min | avg | median | max | # calls |
|
||||
| MAX_LOCKING_PERIOD | 273 | 273 | 273 | 273 | 22 |
|
||||
| MAX_MULTIPLIER | 252 | 252 | 252 | 252 | 28 |
|
||||
| MIN_LOCKING_PERIOD | 273 | 273 | 273 | 273 | 11 |
|
||||
| MAX_LOCKUP_PERIOD | 273 | 273 | 273 | 273 | 22 |
|
||||
| MAX_MULTIPLIER | 274 | 274 | 274 | 274 | 28 |
|
||||
| MIN_LOCKUP_PERIOD | 230 | 230 | 230 | 230 | 11 |
|
||||
| MP_RATE_PER_YEAR | 231 | 231 | 231 | 231 | 3 |
|
||||
| SCALE_FACTOR | 229 | 229 | 229 | 229 | 39 |
|
||||
| STAKING_TOKEN | 273 | 273 | 273 | 273 | 128 |
|
||||
| accountedRewards | 351 | 909 | 351 | 2351 | 68 |
|
||||
| accountedRewards | 373 | 931 | 373 | 2373 | 68 |
|
||||
| getAccount | 1574 | 1574 | 1574 | 1574 | 65 |
|
||||
| rewardIndex | 351 | 380 | 351 | 2351 | 68 |
|
||||
| totalMP | 374 | 374 | 374 | 374 | 71 |
|
||||
| totalMaxMP | 351 | 351 | 351 | 351 | 71 |
|
||||
| totalStaked | 330 | 330 | 330 | 330 | 71 |
|
||||
| updateAccountMP | 34610 | 36848 | 37112 | 37112 | 19 |
|
||||
| totalMP | 330 | 330 | 330 | 330 | 71 |
|
||||
| totalMaxMP | 373 | 373 | 373 | 373 | 71 |
|
||||
| totalStaked | 352 | 352 | 352 | 352 | 71 |
|
||||
| updateAccountMP | 34632 | 36870 | 37134 | 37134 | 19 |
|
||||
| updateGlobalState | 29986 | 55567 | 47365 | 80313 | 25 |
|
||||
|
||||
|
||||
@@ -38,8 +38,8 @@
|
||||
| Deployment Cost | Deployment Size | | | | |
|
||||
| 857122 | 4070 | | | | |
|
||||
| Function Name | min | avg | median | max | # calls |
|
||||
| stake | 194703 | 231763 | 238396 | 258880 | 46 |
|
||||
| unstake | 81435 | 109751 | 98993 | 141658 | 13 |
|
||||
| stake | 194660 | 231720 | 238353 | 258837 | 46 |
|
||||
| unstake | 81452 | 109772 | 99015 | 141680 | 13 |
|
||||
|
||||
|
||||
| src/XPNFTToken.sol:XPNFTToken contract | | | | | |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
IntegrationTest:testStakeFoo() (gas: 1459038)
|
||||
IntegrationTest:testStakeFoo() (gas: 1459151)
|
||||
NFTMetadataGeneratorSVGTest:testGenerateMetadata() (gas: 92874)
|
||||
NFTMetadataGeneratorSVGTest:testSetImageStrings() (gas: 60081)
|
||||
NFTMetadataGeneratorSVGTest:testSetImageStringsRevert() (gas: 35818)
|
||||
@@ -6,37 +6,37 @@ NFTMetadataGeneratorURLTest:testGenerateMetadata() (gas: 109345)
|
||||
NFTMetadataGeneratorURLTest:testSetBaseURL() (gas: 50653)
|
||||
NFTMetadataGeneratorURLTest:testSetBaseURLRevert() (gas: 35993)
|
||||
RewardsStreamerTest:testStake() (gas: 869874)
|
||||
StakeTest:test_StakeMultipleAccounts() (gas: 484237)
|
||||
StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 629617)
|
||||
StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 796183)
|
||||
StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 490118)
|
||||
StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 511520)
|
||||
StakeTest:test_StakeOneAccount() (gas: 279766)
|
||||
StakeTest:test_StakeOneAccountAndRewards() (gas: 425142)
|
||||
StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 485820)
|
||||
StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 480886)
|
||||
StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 293512)
|
||||
StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 293543)
|
||||
StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 293654)
|
||||
UnstakeTest:test_StakeMultipleAccounts() (gas: 484259)
|
||||
UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 629594)
|
||||
UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 796205)
|
||||
UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 490095)
|
||||
UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 511542)
|
||||
UnstakeTest:test_StakeOneAccount() (gas: 279789)
|
||||
UnstakeTest:test_StakeOneAccountAndRewards() (gas: 425164)
|
||||
UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 485842)
|
||||
UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 480866)
|
||||
UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 293557)
|
||||
UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 293543)
|
||||
UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 293632)
|
||||
UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 495149)
|
||||
UnstakeTest:test_UnstakeMultipleAccounts() (gas: 672560)
|
||||
UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 991506)
|
||||
UnstakeTest:test_UnstakeOneAccount() (gas: 468535)
|
||||
UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 483413)
|
||||
UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 574857)
|
||||
UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 504995)
|
||||
StakeTest:test_StakeMultipleAccounts() (gas: 484173)
|
||||
StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 629575)
|
||||
StakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 796295)
|
||||
StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 490055)
|
||||
StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 511457)
|
||||
StakeTest:test_StakeOneAccount() (gas: 279745)
|
||||
StakeTest:test_StakeOneAccountAndRewards() (gas: 425143)
|
||||
StakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 485909)
|
||||
StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 480997)
|
||||
StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 293513)
|
||||
StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 293501)
|
||||
StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 293612)
|
||||
UnstakeTest:test_StakeMultipleAccounts() (gas: 484195)
|
||||
UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 629552)
|
||||
UnstakeTest:test_StakeMultipleAccountsMPIncreasesMaxMPDoesNotChange() (gas: 796317)
|
||||
UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 490032)
|
||||
UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 511479)
|
||||
UnstakeTest:test_StakeOneAccount() (gas: 279768)
|
||||
UnstakeTest:test_StakeOneAccountAndRewards() (gas: 425165)
|
||||
UnstakeTest:test_StakeOneAccountMPIncreasesMaxMPDoesNotChange() (gas: 485931)
|
||||
UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 480977)
|
||||
UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 293558)
|
||||
UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 293501)
|
||||
UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 293590)
|
||||
UnstakeTest:test_UnstakeBonusMPAndAccuredMP() (gas: 495129)
|
||||
UnstakeTest:test_UnstakeMultipleAccounts() (gas: 672552)
|
||||
UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 991588)
|
||||
UnstakeTest:test_UnstakeOneAccount() (gas: 468592)
|
||||
UnstakeTest:test_UnstakeOneAccountAndAccruedMP() (gas: 483480)
|
||||
UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 574902)
|
||||
UnstakeTest:test_UnstakeOneAccountWithLockUpAndAccruedMP() (gas: 505042)
|
||||
XPNFTTokenTest:testApproveNotAllowed() (gas: 10507)
|
||||
XPNFTTokenTest:testGetApproved() (gas: 10531)
|
||||
XPNFTTokenTest:testIsApprovedForAll() (gas: 10705)
|
||||
|
||||
@@ -3,9 +3,10 @@ pragma solidity ^0.8.26;
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import { ReentrancyGuard } from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||
import { IStakeManager } from "./interfaces/IStakeManager.sol";
|
||||
|
||||
// Rewards Streamer with Multiplier Points
|
||||
contract RewardsStreamerMP is ReentrancyGuard {
|
||||
contract RewardsStreamerMP is ReentrancyGuard, IStakeManager {
|
||||
error StakingManager__AmountCannotBeZero();
|
||||
error StakingManager__TransferFailed();
|
||||
error StakingManager__InsufficientBalance();
|
||||
@@ -19,8 +20,8 @@ contract RewardsStreamerMP is ReentrancyGuard {
|
||||
uint256 public constant SCALE_FACTOR = 1e18;
|
||||
uint256 public constant MP_RATE_PER_YEAR = 1e18;
|
||||
|
||||
uint256 public constant MIN_LOCKING_PERIOD = 90 days;
|
||||
uint256 public constant MAX_LOCKING_PERIOD = 4 * 365 days;
|
||||
uint256 public constant MIN_LOCKUP_PERIOD = 90 days;
|
||||
uint256 public constant MAX_LOCKUP_PERIOD = 4 * 365 days;
|
||||
uint256 public constant MAX_MULTIPLIER = 4;
|
||||
|
||||
uint256 public totalStaked;
|
||||
@@ -52,7 +53,7 @@ contract RewardsStreamerMP is ReentrancyGuard {
|
||||
revert StakingManager__AmountCannotBeZero();
|
||||
}
|
||||
|
||||
if (lockPeriod != 0 && (lockPeriod < MIN_LOCKING_PERIOD || lockPeriod > MAX_LOCKING_PERIOD)) {
|
||||
if (lockPeriod != 0 && (lockPeriod < MIN_LOCKUP_PERIOD || lockPeriod > MAX_LOCKUP_PERIOD)) {
|
||||
revert StakingManager__InvalidLockingPeriod();
|
||||
}
|
||||
|
||||
@@ -77,7 +78,7 @@ contract RewardsStreamerMP is ReentrancyGuard {
|
||||
uint256 bonusMP = 0;
|
||||
|
||||
if (lockPeriod != 0) {
|
||||
uint256 lockMultiplier = (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR) / MAX_LOCKING_PERIOD;
|
||||
uint256 lockMultiplier = (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR) / MAX_LOCKUP_PERIOD;
|
||||
bonusMP = amount * lockMultiplier / SCALE_FACTOR;
|
||||
account.lockUntil = block.timestamp + lockPeriod;
|
||||
} else {
|
||||
|
||||
@@ -4,7 +4,7 @@ pragma solidity ^0.8.26;
|
||||
|
||||
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
import { RewardsStreamerMP } from "./RewardsStreamerMP.sol";
|
||||
import { IStakeManager } from "./interfaces/IStakeManager.sol";
|
||||
|
||||
/**
|
||||
* @title StakeVault
|
||||
@@ -19,11 +19,11 @@ contract StakeVault is Ownable {
|
||||
error StakeVault__StakingFailed();
|
||||
error StakeVault__UnstakingFailed();
|
||||
|
||||
//STAKING_TOKEN must be kept as an immutable, otherwise, RewardStreamerMP would accept StakeVaults with any token
|
||||
//if is needed that STAKING_TOKEN to be a variable, RewardStreamerMP should be changed to check codehash and
|
||||
//STAKING_TOKEN must be kept as an immutable, otherwise, StakeManager would accept StakeVaults with any token
|
||||
//if is needed that STAKING_TOKEN to be a variable, StakeManager should be changed to check codehash and
|
||||
//StakeVault(msg.sender).STAKING_TOKEN()
|
||||
IERC20 public immutable STAKING_TOKEN;
|
||||
RewardsStreamerMP private stakeManager;
|
||||
IStakeManager private stakeManager;
|
||||
|
||||
/**
|
||||
* @dev Emitted when tokens are staked.
|
||||
@@ -44,9 +44,9 @@ contract StakeVault is Ownable {
|
||||
/**
|
||||
* @notice Initializes the contract with the owner, staked token, and stake manager.
|
||||
* @param _owner The address of the owner.
|
||||
* @param _stakeManager The address of the RewardStreamerMP contract.
|
||||
* @param _stakeManager The address of the StakeManager contract.
|
||||
*/
|
||||
constructor(address _owner, RewardsStreamerMP _stakeManager) Ownable(_owner) {
|
||||
constructor(address _owner, IStakeManager _stakeManager) Ownable(_owner) {
|
||||
STAKING_TOKEN = _stakeManager.STAKING_TOKEN();
|
||||
stakeManager = _stakeManager;
|
||||
}
|
||||
|
||||
26
src/interfaces/IStakeManager.sol
Normal file
26
src/interfaces/IStakeManager.sol
Normal file
@@ -0,0 +1,26 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.26;
|
||||
|
||||
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||
|
||||
interface IStakeManager {
|
||||
error StakeManager__FundsLocked();
|
||||
error StakeManager__InvalidLockTime();
|
||||
error StakeManager__InsufficientFunds();
|
||||
error StakeManager__StakeIsTooLow();
|
||||
|
||||
function stake(uint256 _amount, uint256 _seconds) external;
|
||||
function unstake(uint256 _amount) external;
|
||||
|
||||
function totalStaked() external view returns (uint256);
|
||||
function totalMP() external view returns (uint256);
|
||||
function totalMaxMP() external view returns (uint256);
|
||||
function getStakedBalance(address _vault) external view returns (uint256 _balance);
|
||||
|
||||
function STAKING_TOKEN() external view returns (IERC20);
|
||||
function REWARD_TOKEN() external view returns (IERC20);
|
||||
function MIN_LOCKUP_PERIOD() external view returns (uint256);
|
||||
function MAX_LOCKUP_PERIOD() external view returns (uint256);
|
||||
function MP_RATE_PER_YEAR() external view returns (uint256);
|
||||
function MAX_MULTIPLIER() external view returns (uint256);
|
||||
}
|
||||
@@ -107,7 +107,7 @@ contract RewardsStreamerMPTest is Test {
|
||||
|
||||
function _calculateBonusMP(uint256 amount, uint256 lockupTime) public view returns (uint256) {
|
||||
return amount
|
||||
* (lockupTime * streamer.MAX_MULTIPLIER() * streamer.SCALE_FACTOR() / streamer.MAX_LOCKING_PERIOD())
|
||||
* (lockupTime * streamer.MAX_MULTIPLIER() * streamer.SCALE_FACTOR() / streamer.MAX_LOCKUP_PERIOD())
|
||||
/ streamer.SCALE_FACTOR();
|
||||
}
|
||||
|
||||
@@ -535,7 +535,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
|
||||
function test_StakeOneAccountWithMinLockUp() public {
|
||||
uint256 stakeAmount = 10e18;
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKING_PERIOD();
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKUP_PERIOD();
|
||||
uint256 expectedBonusMP = _calculateBonusMP(stakeAmount, lockUpPeriod);
|
||||
|
||||
_stake(alice, stakeAmount, lockUpPeriod);
|
||||
@@ -543,7 +543,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
checkStreamer(
|
||||
CheckStreamerParams({
|
||||
totalStaked: stakeAmount,
|
||||
// 10e18 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKING_PERIOD) / SCALE_FACTOR)
|
||||
// 10e18 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKUP_PERIOD) / SCALE_FACTOR)
|
||||
totalMP: stakeAmount + expectedBonusMP,
|
||||
totalMaxMP: 52_465_753_424_657_534_240,
|
||||
stakingBalance: stakeAmount,
|
||||
@@ -556,7 +556,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
|
||||
function test_StakeOneAccountWithMaxLockUp() public {
|
||||
uint256 stakeAmount = 10e18;
|
||||
uint256 lockUpPeriod = streamer.MAX_LOCKING_PERIOD();
|
||||
uint256 lockUpPeriod = streamer.MAX_LOCKUP_PERIOD();
|
||||
uint256 expectedBonusMP = _calculateBonusMP(stakeAmount, lockUpPeriod);
|
||||
|
||||
_stake(alice, stakeAmount, lockUpPeriod);
|
||||
@@ -564,7 +564,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
checkStreamer(
|
||||
CheckStreamerParams({
|
||||
totalStaked: stakeAmount,
|
||||
// 10 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKING_PERIOD) / SCALE_FACTOR)
|
||||
// 10 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKUP_PERIOD) / SCALE_FACTOR)
|
||||
totalMP: stakeAmount + expectedBonusMP,
|
||||
totalMaxMP: 90e18,
|
||||
stakingBalance: stakeAmount,
|
||||
@@ -577,7 +577,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
|
||||
function test_StakeOneAccountWithRandomLockUp() public {
|
||||
uint256 stakeAmount = 10e18;
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKING_PERIOD() + 13 days;
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKUP_PERIOD() + 13 days;
|
||||
uint256 expectedBonusMP = _calculateBonusMP(stakeAmount, lockUpPeriod);
|
||||
|
||||
_stake(alice, stakeAmount, lockUpPeriod);
|
||||
@@ -585,7 +585,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
checkStreamer(
|
||||
CheckStreamerParams({
|
||||
totalStaked: stakeAmount,
|
||||
// 10 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKING_PERIOD) / SCALE_FACTOR)
|
||||
// 10 + (amount * (lockPeriod * MAX_MULTIPLIER * SCALE_FACTOR / MAX_LOCKUP_PERIOD) / SCALE_FACTOR)
|
||||
totalMP: stakeAmount + expectedBonusMP,
|
||||
totalMaxMP: 52_821_917_808_219_178_080,
|
||||
stakingBalance: stakeAmount,
|
||||
@@ -860,7 +860,7 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
|
||||
function test_StakeMultipleAccountsWithMinLockUp() public {
|
||||
uint256 aliceStakeAmount = 10e18;
|
||||
uint256 aliceLockUpPeriod = streamer.MIN_LOCKING_PERIOD();
|
||||
uint256 aliceLockUpPeriod = streamer.MIN_LOCKUP_PERIOD();
|
||||
uint256 aliceExpectedBonusMP = _calculateBonusMP(aliceStakeAmount, aliceLockUpPeriod);
|
||||
|
||||
uint256 bobStakeAmount = 30e18;
|
||||
@@ -891,11 +891,11 @@ contract StakeTest is RewardsStreamerMPTest {
|
||||
|
||||
function test_StakeMultipleAccountsWithRandomLockUp() public {
|
||||
uint256 aliceStakeAmount = 10e18;
|
||||
uint256 aliceLockUpPeriod = streamer.MAX_LOCKING_PERIOD() - 21 days;
|
||||
uint256 aliceLockUpPeriod = streamer.MAX_LOCKUP_PERIOD() - 21 days;
|
||||
uint256 aliceExpectedBonusMP = _calculateBonusMP(aliceStakeAmount, aliceLockUpPeriod);
|
||||
|
||||
uint256 bobStakeAmount = 30e18;
|
||||
uint256 bobLockUpPeriod = streamer.MIN_LOCKING_PERIOD() + 43 days;
|
||||
uint256 bobLockUpPeriod = streamer.MIN_LOCKUP_PERIOD() + 43 days;
|
||||
uint256 bobExpectedBonusMP = _calculateBonusMP(bobStakeAmount, bobLockUpPeriod);
|
||||
|
||||
// alice stakes with lockup period
|
||||
@@ -1157,7 +1157,7 @@ contract UnstakeTest is StakeTest {
|
||||
test_StakeOneAccountWithMinLockUp();
|
||||
|
||||
uint256 stakeAmount = 10e18;
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKING_PERIOD();
|
||||
uint256 lockUpPeriod = streamer.MIN_LOCKUP_PERIOD();
|
||||
// 10e18 is what's used in `test_StakeOneAccountWithMinLockUp`
|
||||
uint256 expectedBonusMP = _calculateBonusMP(stakeAmount, lockUpPeriod);
|
||||
|
||||
@@ -1230,7 +1230,7 @@ contract UnstakeTest is StakeTest {
|
||||
function test_UnstakeBonusMPAndAccuredMP() public {
|
||||
// setup variables
|
||||
uint256 amountStaked = 10e18;
|
||||
uint256 secondsLocked = streamer.MIN_LOCKING_PERIOD();
|
||||
uint256 secondsLocked = streamer.MIN_LOCKUP_PERIOD();
|
||||
uint256 reducedStake = 5e18;
|
||||
uint256 increasedTime = 365 days;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user