Skip to content

Commit

Permalink
Merge pull request #1 from sayandcode/feature/staking-and-reward-tokens
Browse files Browse the repository at this point in the history
Feature/staking and reward tokens
  • Loading branch information
sayandcode authored Jan 7, 2024
2 parents 6e967fb + 433e073 commit 3654634
Show file tree
Hide file tree
Showing 8 changed files with 152 additions and 1 deletion.
8 changes: 7 additions & 1 deletion .github/workflows/test-contracts.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
name: Test Contracts

on: workflow_dispatch
on:
pull_request:
types:
- opened
- synchronize
- reopened
- edited

env:
FOUNDRY_PROFILE: ci
Expand Down
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
[submodule "contracts/lib/forge-std"]
path = contracts/lib/forge-std
url = https://github.com/foundry-rs/forge-std
[submodule "contracts/lib/openzeppelin-contracts"]
path = contracts/lib/openzeppelin-contracts
url = https://github.com/OpenZeppelin/openzeppelin-contracts
1 change: 1 addition & 0 deletions contracts/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
src = "src"
out = "out"
libs = ["lib"]
remappings = ['@openzeppelin/contracts=lib/openzeppelin-contracts/contracts']

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
1 change: 1 addition & 0 deletions contracts/lib/openzeppelin-contracts
Submodule openzeppelin-contracts added at 01ef44
28 changes: 28 additions & 0 deletions contracts/src/FinthetixRewardToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.23;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

/**
* @title FinthetixRewardtoken
* @author sayandcode
* @notice This token is paid out by the Finthetix Staking Contract as a reward
* @dev This contract needs to be deployed by the Staking Contract in order for it to be able to
* generate rewards periodically. This is because only the owner of this Token Contract can mint
* more tokens
*/
contract FinthetixRewardToken is ERC20, Ownable {
constructor() ERC20("FinthetixRewardToken", "FRT") Ownable(msg.sender) {}

/**
*
* @param to The address of the recipient of the funds
* @param amtToMint The amount of tokens to allocate to the recipient
* @notice This function will be called by the staking contract when it is time to generate rewards for stakers
* @dev This is intended to be only used by the Staking Contract
*/
function mint(address to, uint256 amtToMint) external onlyOwner {
_mint(to, amtToMint);
}
}
32 changes: 32 additions & 0 deletions contracts/src/FinthetixStakingToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.23;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";

interface FSTEvents {
/**
*
* @param requesterAddr The address of the user requesting a sample of FST tokens
* @dev This event is emitted when the user requests a sample of FST tokens
*/
event SampleTokenRequested(address requesterAddr);
}

/**
* @title FinthetixStakingToken
* @author sayandcode
* @notice This is the staking token used by the Finthetix Staking Contract. Users lock up this token
* to gain rewards in the token chosen by the staking contract.
*/
contract FinthetixStakingToken is ERC20, FSTEvents {
constructor() ERC20("FinthetixStakingToken", "FST") {}

/**
* @notice Users can call this function to get a few sample tokens, in order to try out the
* staking contract
*/
function requestSampleTokens() public {
_mint(msg.sender, 5 ether);
emit SampleTokenRequested(msg.sender);
}
}
47 changes: 47 additions & 0 deletions contracts/test/FinthetixRewardToken.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.23;

import {FinthetixRewardToken} from "src/FinthetixRewardToken.sol";
import {Test} from "forge-std/Test.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

contract RewardToken_UnitTest is Test {
string private constant TOKEN_SYMBOL = "FRT";
string private constant TOKEN_NAME = "FinthetixRewardToken";
address private immutable contractOwnerAddr = vm.addr(0xB0b);

FinthetixRewardToken private tokenContract;

function setUp() public {
vm.prank(contractOwnerAddr);
tokenContract = new FinthetixRewardToken();
}

function test_HasCorrectLabels() public {
assertEq(tokenContract.symbol(), TOKEN_SYMBOL, "Incorrect Token Symbol");
assertEq(tokenContract.name(), TOKEN_NAME, "Incorrect Token Name");
}

function test_CanMintToken(uint256 amtToMint) public {
address receiverAddr = address(1);

uint256 balanceBefore = tokenContract.balanceOf(receiverAddr);
assertEq(balanceBefore, 0);

vm.prank(contractOwnerAddr);
tokenContract.mint(receiverAddr, amtToMint);

uint256 balanceAfter = tokenContract.balanceOf(receiverAddr);
assertEq(balanceAfter, amtToMint);
}

function test_NonOwnersCannotMint(address senderAddr) public {
vm.assume(senderAddr != contractOwnerAddr);

uint8 amtToMint = 2;

vm.expectRevert(abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, senderAddr));
vm.prank(senderAddr);
tokenContract.mint(senderAddr, amtToMint);
}
}
33 changes: 33 additions & 0 deletions contracts/test/FinthetixStakingToken.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// SPDX-License-Identifier: SEE LICENSE IN LICENSE
pragma solidity 0.8.23;

import {FinthetixStakingToken, FSTEvents} from "src/FinthetixStakingToken.sol";
import {Test} from "forge-std/Test.sol";

contract StakingToken_UnitTest is Test {
string private constant TOKEN_NAME = "FinthetixStakingToken";
string private constant TOKEN_SYMBOL = "FST";
uint256 private constant SAMPLE_TOKEN_QTY = 5 ether;
FinthetixStakingToken private tokenContract;

function setUp() public {
tokenContract = new FinthetixStakingToken();
}

function test_HasCorrectLabels() public {
assertEq(tokenContract.name(), TOKEN_NAME);
assertEq(tokenContract.symbol(), TOKEN_SYMBOL);
}

function test_RequestSampleTokensFn() public {
uint256 tokensBefore = tokenContract.balanceOf(address(this));
assertEq(tokensBefore, 0);

vm.expectEmit(address(tokenContract));
emit FSTEvents.SampleTokenRequested(address(this));
tokenContract.requestSampleTokens();

uint256 tokensAfter = tokenContract.balanceOf(address(this));
assertEq(tokensAfter, SAMPLE_TOKEN_QTY);
}
}

0 comments on commit 3654634

Please sign in to comment.