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

test(Staking): ERC20 token contract and Staking contract #54

Open
wants to merge 5 commits into
base: testing-with-foundry
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
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
6 changes: 5 additions & 1 deletion src/ERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ contract ERC20 is IERC20 {
revert InvalidRecipient();
}

if (balanceOf[msg.sender] < amount) {
revert InsufficientBalance();
}

unchecked {
balanceOf[msg.sender] -= amount;
balanceOf[recipient] += amount;
Expand Down Expand Up @@ -160,7 +164,7 @@ contract ERC20 is IERC20 {
address recipient,
uint256 amount
) external returns (bool) {
require(msg.sender != recipient, "cannot transfer to self");
//require(msg.sender != recipient, "cannot transfer to self");
if (recipient == address(0)) {
revert InvalidRecipient();
}
Expand Down
4 changes: 4 additions & 0 deletions src/Staking.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ contract StakingContract {
address public rewardTokenAddress;
uint256 public totalStaked;

function getStakers(address _addr) public view returns (StakeDetail memory) {
return stakers[_addr];
}

//////////////////
// CONSTANTS
//////////////////
Expand Down
293 changes: 217 additions & 76 deletions test/ERC20.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,140 +2,281 @@
pragma solidity ^0.8.19;

import "forge-std/Test.sol";
import "forge-std/console.sol";
import {ERC20} from "../src/ERC20.sol";

contract ERC20ContractTest is Test {
ERC20 public erc20Contract;
ERC20 public erc20contract;
address ownerAddress = address(0x0101);
address randomAddress = address(0x3892);
address scammer = address(0x9987);
address randomAddress = address(0x9333);
address recipient = address(0x5676);
address caller = address(0x2575);

event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
event Approval(address indexed owner, address indexed spender, uint256 value);
event Owned(address indexed old, address indexed newAddress);

error InvalidRecipient();
error InsufficientBalance();

function setUp() public {
vm.prank(ownerAddress);
erc20Contract = new ERC20("My Token", "MTK", 0);
vm.prank(ownerAddress); // address deploying the contract
erc20contract = new ERC20("MyToken", "MTK", 0);
}

function test_ContractWasDeployedSuccessfully() public view {
assertEq(erc20Contract.name(), "My Token");
assertEq(erc20Contract.symbol(), "MTK");
assertEq(erc20Contract.decimals(), 0);
function test_ContractDeployedSuccessfully() public view {
assertEq(erc20contract.name(), "MyToken");
assertEq(erc20contract.symbol(), "MTK");
assertEq(erc20contract.decimals(), 0);
console.log(erc20contract.decimals());
}

function test_OwnerisSetCorrectly() public view {
function testFail_OwnerIsSetCorrectly() public view {
address notOwner = address(0x9998);
assertEq(
erc20Contract.owner(),
ownerAddress,
erc20contract.owner(),
notOwner,
"owner address not set correctly"
);
}

function test_MintWillRevertWhenMintFromUnauthorizedAddress() public {
address scammer = address(0x5555);
function test_MintRevertByNonOwner() public {
vm.startPrank(scammer);
vm.expectRevert("Unauthorized");
erc20Contract.mint(scammer, 1000);
erc20contract.mint(scammer, 1000);
vm.stopPrank();
}

function test_MintWillRevertWhenMintToZeroAddress() public {
// Set msg.sender to `ownerAddress`
function test_MintWillRevertWhenTryingToMintToAddressZero() public {
vm.prank(ownerAddress);
// Expect function call to revert
vm.expectRevert(InvalidRecipient.selector);
// Mint 1000 tokens to zero address
erc20Contract.mint(address(0), 1000);
erc20contract.mint(address(0), 1000);
}

function test_MintWasSuccessful() public {
uint256 totalSupplyBeforeMint = erc20Contract.totalSupply();
uint256 totalSupplyBeforeMint = erc20contract.totalSupply();
uint256 mintAmount = 1000;
// Check balance before mint
// check balance before mint
assertEq(
erc20Contract.balanceOf(randomAddress),
erc20contract.balanceOf(randomAddress),
0,
"expected random address balance to be 0"
);
// Set msg.sender to `ownerAddress`
// Set the msg.sender to the 'ownerAddress'
vm.prank(ownerAddress);
// mint to randomAddress
erc20contract.mint(randomAddress, mintAmount);

vm.expectEmit(true, true, false, true);
emit Transfer(address(0), randomAddress, mintAmount);
// Mint 1000 tokens to random address
erc20Contract.mint(randomAddress, mintAmount);
uint256 totalSupplyAfterMint = erc20Contract.totalSupply();
// Verify mint was successful
uint256 totalSupplyAfterMint = erc20contract.totalSupply();
// check balance before mint
assertEq(
erc20Contract.balanceOf(randomAddress),
mintAmount,
"incorrect mint amount"
erc20contract.balanceOf(randomAddress),
1000,
"expected random address balance to be 1000"
);
assertEq(totalSupplyBeforeMint + mintAmount, totalSupplyAfterMint);
}

function test_TransferFrom() public {
address recipient = address(0x2938);
address caller = address(0x2373);
uint256 amount = 500;

// set msg.sender to owner address
vm.startPrank(ownerAddress);
// Mint 500 tokens to random address
erc20Contract.mint(randomAddress, amount);
// Verify tokens was minted successfully
assertEq(erc20Contract.balanceOf(randomAddress), amount);
// Stop prank
erc20contract.mint(randomAddress, 500);
assertEq(erc20contract.balanceOf(randomAddress), 500);
vm.stopPrank();

// Set msg.sender to random address
vm.startPrank(randomAddress);

vm.expectEmit(true, true, false, true);
emit Approval(randomAddress, caller, amount);
// random address approves caller to spend `amount` tokens
erc20Contract.approve(caller, amount);
// Stop prank
erc20contract.approve(caller, amount);
vm.stopPrank();

assertEq(erc20Contract.balanceOf(recipient), 0);
assertEq(erc20contract.balanceOf(recipient), 0);

uint256 balanceOfSenderBeforeTransfer = erc20Contract.balanceOf(
randomAddress
);
uint256 allowanceOfCallerBeforeTransfer = erc20Contract.allowance(
randomAddress,
caller
);
uint256 balanceOfSenderBeforeTransfer = erc20contract.balanceOf(randomAddress);

vm.startPrank(caller);
erc20Contract.transferFrom(randomAddress, recipient, amount);
uint256 allowanceOfCallerBeforeTransfer = erc20contract.allowance(randomAddress, caller);

// recipient balance increased accordingly
assertEq(erc20Contract.balanceOf(recipient), amount);
// sender balance decrease accordingly
uint256 balanceOfSenderAfterTransfer = erc20Contract.balanceOf(
randomAddress
);
vm.startPrank(caller);
erc20contract.transferFrom(randomAddress, recipient, amount);

// recipient address increase successfully
assertEq(erc20contract.balanceOf(recipient), amount);
// randomAddress decrease successfully
uint256 balanceOfSenderAfterTransfer = erc20contract.balanceOf(randomAddress);
uint256 allowanceOfCallerAfterTransfer = erc20contract.allowance(randomAddress, caller);
assertEq(
balanceOfSenderBeforeTransfer - amount,
balanceOfSenderAfterTransfer
);

uint256 allowanceOfCallerAfterTransfer = erc20Contract.allowance(
randomAddress,
caller
balanceOfSenderBeforeTransfer - amount, balanceOfSenderAfterTransfer
);

assertEq(
allowanceOfCallerBeforeTransfer - amount,
allowanceOfCallerAfterTransfer
);
}

function test_Approval() public {
vm.startPrank(ownerAddress);

uint amount = 3000;
erc20contract.mint(ownerAddress, amount);
assertEq(erc20contract.balanceOf(ownerAddress), amount);

vm.expectRevert(InvalidRecipient.selector);
erc20contract.approve(address(0), 2000);

vm.stopPrank();
}

function test_SuccessFulApproval() public {
vm.startPrank(ownerAddress);

uint amount = 3000;

uint allowanceBefore = erc20contract.allowance(ownerAddress, randomAddress);
assertEq(allowanceBefore, 0);

erc20contract.mint(ownerAddress, amount);
assertEq(erc20contract.balanceOf(ownerAddress), amount);

erc20contract.approve(randomAddress, amount);
uint allowanceAfter = erc20contract.allowance(ownerAddress, randomAddress);
assertEq(allowanceAfter, amount);

vm.stopPrank();
}


function test_Transfer() public {
vm.startPrank(randomAddress);
vm.expectRevert(InsufficientBalance.selector);
erc20contract.transfer(recipient, 1000);
vm.stopPrank();

vm.startPrank(ownerAddress);
uint amount = 3000;

uint ownerBalanceBeforeMint = erc20contract.balanceOf(ownerAddress);

uint recipientBalanceBeforeTransfer = erc20contract.balanceOf(recipient);

erc20contract.mint(ownerAddress, amount);

uint ownerBalanceAfterMint = erc20contract.balanceOf(ownerAddress);
assertEq(ownerBalanceBeforeMint + amount, ownerBalanceAfterMint);

erc20contract.transfer(recipient, 1000);

uint recipientBalanceAfterTransfer = erc20contract.balanceOf(recipient);
assertEq(recipientBalanceBeforeTransfer + 1000, recipientBalanceAfterTransfer);

vm.stopPrank();
}

function test_changeOwner() public {
vm.startPrank(randomAddress);
vm.expectRevert("Unauthorized");
erc20contract.changeOwner(recipient);
vm.stopPrank();

vm.startPrank(ownerAddress);
erc20contract.changeOwner(randomAddress);
assertEq(erc20contract.owner(), randomAddress);
vm.stopPrank();
}

function test_Burn() public {
uint amount = 1000;
vm.startPrank(ownerAddress);
erc20contract.mint(recipient, amount);
erc20contract.burn(recipient, 20);
assertEq(erc20contract.balanceOf(recipient), amount - 20);
vm.stopPrank();

vm.startPrank(randomAddress);
vm.expectRevert("Unauthorized");
erc20contract.burn(recipient, 20);
vm.stopPrank();
}

// EVENTS
function test_TransferEvents() public {
vm.startPrank(ownerAddress);

erc20contract.mint(randomAddress, 1000);
assertEq(erc20contract.balanceOf(randomAddress), 1000);

vm.stopPrank();

vm.startPrank(randomAddress);
vm.expectEmit(true, true, false, true);
emit Transfer(randomAddress, recipient, 500);
erc20contract.transfer(recipient, 500);
vm.stopPrank();
}

function test_ApprovalEvents() public {
vm.startPrank(ownerAddress);
vm.expectEmit(true, true, false, true);
emit Approval(ownerAddress, randomAddress, 1000);
erc20contract.approve(randomAddress, 1000);
vm.stopPrank();
}

function test_TransferFromEvents() public {
vm.startPrank(ownerAddress);

erc20contract.mint(ownerAddress, 1000);
assertEq(erc20contract.balanceOf(ownerAddress), 1000);

erc20contract.approve(randomAddress, 500);
vm.stopPrank();

vm.startPrank(randomAddress);
vm.expectEmit(true, true, false, true);
emit Transfer(ownerAddress, recipient, 500);
erc20contract.transferFrom(ownerAddress, recipient, 500);

assertEq(erc20contract.balanceOf(recipient), 500);
vm.stopPrank();
}

function test_MintEvents() public {
vm.startPrank(ownerAddress);
uint totalSupplyBeforeMint = erc20contract.totalSupply();
vm.expectEmit(true, true, false, true);
emit Transfer(address(0), randomAddress, 1000);
erc20contract.mint(randomAddress, 1000);

uint totalSupplyAfterMint = erc20contract.totalSupply();
assertEq(erc20contract.balanceOf(randomAddress), 1000);
assertEq(totalSupplyBeforeMint + 1000, totalSupplyAfterMint);
vm.stopPrank();
}

function test_BurnEvents() public {
// uint totalSupply = erc20contract.totalSupply();

vm.startPrank(ownerAddress);

erc20contract.mint(randomAddress, 1000);
assertEq(erc20contract.balanceOf(randomAddress), 1000);
assertEq(erc20contract.totalSupply(), 1000);

vm.expectEmit(true, true, false, true);
emit Transfer(randomAddress, address(0), 500);
erc20contract.burn(randomAddress, 500);

assertEq(erc20contract.totalSupply(), 500);
vm.stopPrank();
}

function test_ChangeOwnerEvent() public {
vm.startPrank(ownerAddress);
vm.expectEmit(true, true, false, false);
emit Owned(ownerAddress, randomAddress);
erc20contract.changeOwner(randomAddress);
vm.stopPrank();

assertEq(erc20contract.owner(), randomAddress);
}
}

Loading