Skip to content

Commit

Permalink
Add initial impl of the unstaking
Browse files Browse the repository at this point in the history
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 Oct 30, 2023
1 parent 3ba358d commit 4bb19d8
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
16 changes: 16 additions & 0 deletions core/contracts/staking/TokenStaking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ contract TokenStaking is IReceiveApproval {
using SafeERC20 for IERC20;

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

IERC20 internal immutable token;

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);
}

function _stake(address account, uint256 amount) private {
require(amount > 0, "Amount is less than minimum");
require(account != address(0), "Can not be the zero address");
Expand Down
38 changes: 38 additions & 0 deletions core/test/staking/TokenStaking.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,4 +86,42 @@ describe("TokenStaking", () => {
})
})
})

describe("unstaking", () => {
beforeEach(async () => {
const tokenBalance = await token.balanceOf(await tokenHolder.getAddress())

// Stake tokens.
await token
.connect(tokenHolder)
.approveAndCall(await tokenStaking.getAddress(), tokenBalance, "0x")
})

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

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

expect(await token.balanceOf(staker)).to.be.equal(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")
})
})
})

0 comments on commit 4bb19d8

Please sign in to comment.