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 31, 2023
1 parent a492db3 commit 0cbfb52
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 2 deletions.
18 changes: 17 additions & 1 deletion 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 staker, uint256 amount);
event Unstaked(address indexed staker, uint256 amount);

IERC20 internal immutable token;

Expand Down Expand Up @@ -58,14 +59,29 @@ contract TokenStaking is IReceiveApproval {
// governable params.
return 1;
}

/// @notice Returns maximum amount of staking tokens.
function maximumStake() public pure returns (uint256) {
// TODO: Fetch this param from "parameters" contract that stores
// governable params.
return 100 ether;
}

/// @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 staker, uint256 amount) private {
require(amount >= minimumStake(), "Amount is less than minimum");
require(amount <= maximumStake(), "Amount is greater than maxium");
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 @@ -102,4 +102,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")
})
})
})

0 comments on commit 0cbfb52

Please sign in to comment.