Skip to content

Commit

Permalink
unstake logic
Browse files Browse the repository at this point in the history
  • Loading branch information
anajuliabit committed Jun 14, 2024
1 parent cc1e063 commit 86c0727
Showing 1 changed file with 65 additions and 23 deletions.
88 changes: 65 additions & 23 deletions src/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ interface IRewardsDistributor {
function distributeRewards() external;
}

// TODO use safe transfer
// TODO use FixedPointMath
// TODO use ERC20
contract Staking is Ownable2StepUpgradeable {
//// ------------------------------------------------------------
//// ------------------------------------------------------------
Expand Down Expand Up @@ -202,6 +205,9 @@ contract Staking is Ownable2StepUpgradeable {
/// - If caller is not a keyepr anymore, lock period is ignored
/// - Unstake can't never result in a user SHU balance < minStake
/// if user is a keyper
/// - If amount is greater than the keyper stake, the contract will
/// transfer the maximum amount available not the requested amount
/// - amount must be specified in SHU, not shares
/// @param keyper The keyper address
/// @param stakeIndex The index of the stake to unstake
/// @param amount The amount of SHU to unstake
Expand All @@ -219,7 +225,7 @@ contract Staking is Ownable2StepUpgradeable {
// Gets the keyper stake
Stake storage keyperStake = keyperStakes[keyper][_stakeIndex];

// checks below only apply if keyper is still a keyper
// Checks below only apply if keyper is still a keyper
// if keyper is not a keyper anymore, anyone can unstake, lock period is
// ignored and minStake is not enforced
if (keypers[keyper]) {
Expand All @@ -245,36 +251,36 @@ contract Staking is Ownable2StepUpgradeable {
rewardsDistributor.distributeRewards();

// Gets the stake shares
uint256 shares = keyperStake.shares;
uint256 keyperShares = keyperStake.shares;

Check warning on line 254 in src/Staking.sol

View workflow job for this annotation

GitHub Actions / lint

Variable "keyperShares" is unused

// Calculates the amount of SHU the shares are worth
rewards = (shares * shu.balanceOf(address(this))) / totalSupply;
// Prevents the keyper from unstaking more than they have staked
uint256 maxWithdrawAmount = maxWithdraw(keyper);
amount = maxWithdrawAmount < amount ? maxWithdrawAmount : amount;

_burn(sender, userStake.shares);
// Calculates the amounf of shares to burn
uint256 shares = convertToShares(amount);

uint256 amount = userStake.amount + rewards;
// Burn the shares
_burn(sender, shares);

shu.transfer(sender, amount);
// Decrease the amount from the stake
keyperStake.amount -= amount;

// Claim other rewards (e.g., WETH)
for (uint256 i = 0; i < rewardTokenList.length; i++) {
IERC20 rewardToken = IERC20(rewardTokenList[i]);
uint256 rewardAmount = (shares *
rewardToken.balanceOf(address(this))) / totalSupply;

if (rewardAmount > 0) {
IERC20(rewardToken).transfer(sender, rewardAmount);
emit ClaimRewards(sender, address(rewardToken), rewardAmount);
}
// If the stake is empty, remove it
if (keyperStake.amount == 0) {
// Remove the stake from the keyper's stake array
keyperStakes[keyper][_stakeIndex] = keyperStakes[keyper][
keyperStakes[keyper].length - 1
];
keyperStakes[keyper].pop();
}

emit Unstaked(sender, amount, userStake.shares);
/////////////////////////// INTERACTIONS ///////////////////////////

// Transfer the SHU to the keyper
shu.transfer(keyper, amount);

// Remove the stake from the user's stake array
keyperStakes[sender][_stakeIndex] = keyperStakes[sender][
keyperStakes[sender].length - 1
];
keyperStakes[sender].pop();
emit Unstaked(keyper, amount, shares);
}

function claimRewards(address rewardToken, uint256 amount) external {
Expand All @@ -297,6 +303,42 @@ contract Staking is Ownable2StepUpgradeable {
emit ClaimRewards(sender, rewardToken, amount);
}

/// @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) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

return supply == 0 ? assets : assets.mulDivDown(supply, totalAssets());
}

/// @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) {
uint256 supply = totalSupply; // Saves an extra SLOAD if totalSupply is non-zero.

return supply == 0 ? shares : shares.mulDivDown(totalAssets(), supply);
}

/*//////////////////////////////////////////////////////////////
UNSTAKE LIMIT LOGIC
//////////////////////////////////////////////////////////////*/

/// @notice Get the maximum amount of assets a keyper can unstake
/// @param keyper The keyper address
function maxWithdraw(address keyper) public view virtual returns (uint256) {
return convertToAssets(balanceOf[keyper]);
}

/// @notice Get the maximum amount of shares a keyper can unstake
/// @param keyper The keyper address
function maxRedeem(address owner) public view virtual returns (uint256) {
return balanceOf[owner];
}

function _mint(address user, uint256 amount) private {
balances[user] += amount;
totalSupply += amount;
Expand Down

0 comments on commit 86c0727

Please sign in to comment.