Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Token Staking - unstaking #5

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
Next Next commit
Add initial impl of the unstaking
Add `unstake` function to the `TokenStaking` contract - this function
reduces stake amount by the provided amount and withdraws tokens to the
owner.
  • Loading branch information
r-czajkowski committed Nov 2, 2023
commit fd5f2cbf12169e7bd9533cfe274a18417c61dc84
16 changes: 16 additions & 0 deletions core/contracts/staking/TokenStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ contract TokenStaking is IReceiveApproval {
mapping(address => uint256) public balanceOf;

event Staked(address indexed staker, uint256 amount);
event Unstaked(address indexed staker, uint256 amount);

constructor(IERC20 _token) {
require(
Expand Down Expand Up @@ -51,6 +52,21 @@ contract TokenStaking is IReceiveApproval {
_stake(msg.sender, amount);
}

/// @notice Reduces stake amount by the provided amount and
/// withdraws tokens to the owner.
/// @param amount Amount to unstake and withdraw.
function unstake(uint256 amount) external {
require((amount > 0), "Amount can not be zero");

uint256 balance = balanceOf[msg.sender];
require(balance >= amount, "Insufficient funds");

balanceOf[msg.sender] -= amount;

emit Unstaked(msg.sender, amount);
token.safeTransfer(msg.sender, amount);
}

/// @notice Returns minimum amount of staking tokens to participate in
/// protocol.
function minimumStake() public pure returns (uint256) {
Expand Down
2 changes: 1 addition & 1 deletion core/contracts/test/TestToken.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity 0.8.20;
pragma solidity ^0.8.20;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "../shared/IReceiveApproval.sol";
Expand Down
41 changes: 41 additions & 0 deletions core/test/staking/TokenStaking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,45 @@ describe("TokenStaking", () => {
})
})
})

describe("unstaking", () => {
const amountToStake = WeiPerEther * 10n

beforeEach(async () => {
// Stake tokens.
await token
.connect(tokenHolder)
.approveAndCall(await tokenStaking.getAddress(), amountToStake, "0x")
})

it("should unstake tokens", async () => {
const staker = await tokenHolder.getAddress()
const stakingBalance = await tokenStaking.balanceOf(staker)
const balanceBeforeUnstaking = await token.balanceOf(staker)

await expect(tokenStaking.connect(tokenHolder).unstake(stakingBalance))
.to.emit(tokenStaking, "Unstaked")
.withArgs(staker, stakingBalance)

expect(await token.balanceOf(staker)).to.be.equal(
balanceBeforeUnstaking + stakingBalance,
)
expect(await tokenStaking.balanceOf(staker)).to.be.eq(0)
})

it("should revert if the unstaked amount is equal 0", async () => {
await expect(
tokenStaking.connect(tokenHolder).unstake(0),
).to.be.revertedWith("Amount can not be zero")
})

it("should revert if the user wants to unstake more tokens than currently staked", async () => {
const staker = await tokenHolder.getAddress()
const stakingBalance = await tokenStaking.balanceOf(staker)

await expect(
tokenStaking.connect(tokenHolder).unstake(stakingBalance + 10n),
).to.be.revertedWith("Insufficient funds")
})
})
})