Assignment
Add emissions so users can get back ERC-20 in leiu of staking.
- Initialize a new forge contract
forge init --template https://github.com/foundry-rs/forge-template staking-contract
- Add openzeplin contracts
npm init -ynpm install @openzeppelin/contracts
- Add
remapping.txt
@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/
- Create your own token (ERC20.sol)
// SPDX-License-Identifier: MITpragma solidity ^0.8.13;import "@openzeppelin/contracts/token/ERC20/ERC20.sol";import "forge-std/Test.sol";
contract KiratCoin is ERC20 { address stakingContract;
constructor(address _stakingContract) ERC20("KiratCoin", "KIRA") { stakingContract = _stakingContract; }
modifier onlyContract() { require(msg.sender == stakingContract); _; }
function mint(address to, uint256 amount) public onlyContract { _mint(to, amount); }
function updateContract(address newContract) public onlyContract { stakingContract = newContract; }}
- Write tests for your own token (ERC20.t.sol)
// SPDX-License-Identifier: Unlicensepragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "src/ERC20.sol";
contract ERC20ContractTest is Test { KiratCoin c;
function setUp() public { c = new KiratCoin(address(this)); }
function testMint() public { uint value = 10; c.mint(address(this), value);
assert(c.balanceOf(address(this)) == value); }
function testFailMint() public { vm.startPrank(0x587EFaEe4f308aB2795ca35A27Dff8c1dfAF9e3f); c.mint(address(this), value); }}
- Create the staking contract (StakingWithEmissions.sol)
// SPDX-License-Identifier: Unlicensepragma solidity ^0.8.13;
import "forge-std/Test.sol";
import "src/StakingWithEmissions.sol";import "src/ERC20.sol";
contract StakingWithEmissionsTest is Test { StakingWithEmissions stakingContract; KiratCoin kiratToken;
function setUp() public { kiratToken = new KiratCoin(address(this)); // address doesnt matter stakingContract = new StakingWithEmissions(IKiratToken(address(kiratToken))); kiratToken.updateContract(address(stakingContract)); }
function testStake() public { uint value = 10 ether; stakingContract.stake{value: value}(value);
assert(stakingContract.totalStake() == value); }
function testFailStake() public { uint value = 10 ether; stakingContract.stake(value); stakingContract.unstake(value + 1 ether);
}
function testGetRewards() public { uint value = 1 ether; stakingContract.stake{value: value}(value); vm.warp(block.timestamp + 1); uint rewards = stakingContract.getRewards();
assert(rewards == 1 ether); }
function testComplexGetRewards() public { uint value = 1 ether; stakingContract.stake{value: value}(value); vm.warp(block.timestamp + 1); console.log(block.timestamp); stakingContract.stake{value: value}(value); vm.warp(block.timestamp + 1); uint rewards = stakingContract.getRewards();
assert(rewards == 3 ether); }
function testRedeemRewards() public { uint value = 1 ether; stakingContract.stake{value: value}(value); vm.warp(block.timestamp + 1); stakingContract.claimEmissions(); console.log("balance of"); console.log(kiratToken.balanceOf(address(this)));
assert(kiratToken.balanceOf(address(this)) == 1 ether); }
}