Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -297,8 +297,6 @@ library LibStakingStorage {
mapping(address => address) nodeAddressToStakerAddress;
mapping(address => address) stakerAddressToNodeAddress;
mapping(address => address) operatorAddressToStakerAddress;
// this mapping lets you go from the userStakerAddress to the stakerAddress.
mapping(address => address) userStakerAddressToStakerAddress;
// Mapping of the complaint reason code to the config for that reason
mapping(uint256 => ComplaintConfig) complaintReasonToConfig;
// Thunderhead - Staking Vaults & rewards
Expand Down
61 changes: 61 additions & 0 deletions blockchain/contracts/contracts/lit-node/Staking/Staking.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,67 @@ contract StakingTest is Test, SetupAndUtils {
}
}

/// @notice This test is when a delegating staker stakes against multiple validators
/// and then claims reward for one of them, that the correct stake record is updated
/// and the other stake record is not affected.
function testFuzz_DelegatingStakerStakesAgainstMultipleValidators(
uint256 amount,
uint256 timeLock
) public {
amount = bound(amount, 32 ether, 1_000_000 ether);
timeLock = bound(timeLock, 90 days, 365 * 2 days);

// Setup validators
address[] memory operatorStakers = _generateAddresses(4);
_setupValidators(
1,
operatorStakers,
amount * 10,
amount,
timeLock,
_generateUint256s(4)
);

// Setup delegating staker
address delegatingStaker = address(0x999);
_fundAddressWithTokensAndApprove(delegatingStaker, amount * 2);

// Delegating staker stakes with the first validator
vm.prank(delegatingStaker);
stakingFacet.stake(amount, timeLock, operatorStakers[0]);

// Delegating staker stakes with the second validator
vm.prank(delegatingStaker);
stakingFacet.stake(amount, timeLock, operatorStakers[1]);

// Advance to epoch 6 to earn rewards
_advanceEpochs(1, 5, operatorStakers, 1);

// Get a reference of the stake records
LibStakingStorage.StakeRecord memory stakeRecord1 = stakingViewsFacet
.getStakeRecord(operatorStakers[0], 1, delegatingStaker);
LibStakingStorage.StakeRecord memory stakeRecord2 = stakingViewsFacet
.getStakeRecord(operatorStakers[1], 1, delegatingStaker);

// Claim rewards from the first validator
vm.prank(delegatingStaker);
stakingFacet.claimStakeRewards(1, operatorStakers[0], 1, 0);

// Get a reference of the new stake records
LibStakingStorage.StakeRecord memory newStakeRecord1 = stakingViewsFacet
.getStakeRecord(operatorStakers[0], 1, delegatingStaker);
LibStakingStorage.StakeRecord memory newStakeRecord2 = stakingViewsFacet
.getStakeRecord(operatorStakers[1], 1, delegatingStaker);

// Assert that the stake record for the first validator is updated correctly
assertGt(newStakeRecord1.lastUpdateTimestamp, stakeRecord1.lastUpdateTimestamp);
assertGt(newStakeRecord1.lastRewardEpochClaimed, stakeRecord1.lastRewardEpochClaimed + 1);

// Assert that the stake record for the second validator is not affected
assertEq(newStakeRecord2.lastUpdateTimestamp, stakeRecord2.lastUpdateTimestamp);
assertEq(newStakeRecord2.lastRewardEpochClaimed, stakeRecord2.lastRewardEpochClaimed);
}

/// @notice This test is when a node operator / validator calls stakeAndJoin
/// that the reward epoch and global stats are updated correctly.
function testFuzz_StakeAndJoin_ValidatorState(
Expand Down
28 changes: 0 additions & 28 deletions blockchain/contracts/contracts/lit-node/Staking/StakingFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -770,8 +770,6 @@ contract StakingFacet is StakingCommon, ERC2771 {
stakeRecord.lastUpdateTimestamp = block.timestamp;
stakeRecord.lastRewardEpochClaimed = lastRewardEpochClaimed;

updateStakeRecord(LibERC2771._msgSender(), stakeRecord.id, stakeRecord);

SafeERC20.safeTransfer(
IERC20(views().getTokenContractAddress()),
LibERC2771._msgSender(),
Expand Down Expand Up @@ -923,32 +921,6 @@ contract StakingFacet is StakingCommon, ERC2771 {
);
}

/**
* @notice Updates the stake record in the staker's vault
* @param userAddress The address of the staker
* @param stakeId The ID of the stake record
* @param newState The new state of the stake record
*/
function updateStakeRecord(
address userAddress,
uint256 stakeId,
LibStakingStorage.StakeRecord memory newState
) internal {
address stakerAddress = s().userStakerAddressToStakerAddress[
userAddress
];
LibStakingStorage.StakeRecord[30] storage userStakes = s()
.vaults[stakerAddress][userAddress].stakes;
for (uint256 i = 0; i < userStakes.length; i++) {
if (userStakes[i].id == stakeId) {
userStakes[i] = newState;
break;
}
}

emit StakeRecordUpdated(stakerAddress, stakeId);
}

/**
* @notice Migrates a stake record to a new validator
* @param operatorAddressToMigrateFrom The address of the operator staker to migrate from
Expand Down
4 changes: 2 additions & 2 deletions rust/lit-core/lit-blockchain-lite/abis/PKPHelper.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions rust/lit-core/lit-blockchain-lite/src/contracts/pkp_helper.rs

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions rust/lit-core/lit-blockchain/abis/PKPHelper.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions rust/lit-core/lit-blockchain/src/contracts/pkp_helper.rs

Large diffs are not rendered by default.

Loading