diff --git a/.gitignore b/.gitignore index e8c12ff..96cdab9 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ node_modules # Hardhat Ignition default folder for deployments against a local node ignition/deployments/chain-31337 + diff --git a/contracts/BlockHeaderToken.sol b/contracts/BlockHeaderToken.sol index c0c2fa9..1ec5439 100644 --- a/contracts/BlockHeaderToken.sol +++ b/contracts/BlockHeaderToken.sol @@ -1,38 +1,38 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.0; +// pragma solidity ^0.8.0; -import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +// import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -contract BlockToken is ERC20{ +// contract BlockToken is ERC20{ - address public owner; +// address public owner; - modifier onlyOwner { - require(msg.sender == owner, "BlockToken:: Unauthorized User"); - _; - } +// modifier onlyOwner { +// require(msg.sender == owner, "BlockToken:: Unauthorized User"); +// _; +// } - modifier notAmount0(uint256 _amount){ - require(_amount != 0, "BlockToken:: Zero amount not supported"); - _; - } - constructor(string memory _name, string memory _symbol, address _owner) ERC20(_name, _symbol){ - require(_owner != address(0), "BlockToken:: Zero address not supported"); - owner = _owner; - } +// modifier notAmount0(uint256 _amount){ +// require(_amount != 0, "BlockToken:: Zero amount not supported"); +// _; +// } +// constructor(string memory _name, string memory _symbol, address _owner) ERC20(_name, _symbol){ +// require(_owner != address(0), "BlockToken:: Zero address not supported"); +// owner = _owner; +// } - function mint(uint256 _amount, address _recepient) onlyOwner notAmount0(_amount) external { - _mint(_recepient, _amount); - } +// function mint(uint256 _amount, address _recepient) onlyOwner notAmount0(_amount) external { +// _mint(_recepient, _amount); +// } - function burn(uint256 _amount) notAmount0(_amount) external { - _burn(msg.sender, _amount); - } +// function burn(uint256 _amount) notAmount0(_amount) external { +// _burn(msg.sender, _amount); +// } - function burnFrom(address _user, uint256 _amount)onlyOwner notAmount0(_amount) external { - _burn(_user, _amount); - } +// function burnFrom(address _user, uint256 _amount)onlyOwner notAmount0(_amount) external { +// _burn(_user, _amount); +// } -} +// } diff --git a/contracts/BlockheaderToken.sol b/contracts/BlockheaderToken.sol new file mode 100644 index 0000000..476afaa --- /dev/null +++ b/contracts/BlockheaderToken.sol @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; + +contract BlockToken is ERC20 { + address public owner; + + modifier onlyOwner() { + require(msg.sender == owner, "BlockToken:: Unauthorized User"); + _; + } + + modifier notAmount0(uint256 _amount) { + require(_amount != 0, "BlockToken:: Zero amount not supported"); + _; + } + + constructor(string memory _name, string memory _symbol, address _owner) ERC20(_name, _symbol) { + require(_owner != address(0), "BlockToken:: Zero Address not supported"); + owner = _owner; + } + + function mint(uint256 _amount, address _recipient) onlyOwner notAmount0(_amount) external { + // require(msg.sender == owner, "BlockToken:: Unauthorized User"); + _mint(_recipient, _amount); + } + + function burn(uint256 _amount) external { + _burn(msg.sender, _amount); + } + + function burnFrom(address _user, uint256 _amount) onlyOwner notAmount0(_amount) external { + _burn(_user, _amount); + } +} \ No newline at end of file diff --git a/contracts/Counter.sol b/contracts/Counter.sol index fa8560c..35d90dd 100644 --- a/contracts/Counter.sol +++ b/contracts/Counter.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MIT -pragma solidity 0.8.28; +pragma solidity ^0.8.28; interface ICounter { function setCount(uint256 _count) external; diff --git a/contracts/CounterV2.sol b/contracts/CounterV2.sol new file mode 100644 index 0000000..4224fb2 --- /dev/null +++ b/contracts/CounterV2.sol @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MIT + +pragma solidity >= 0.7.0 < 0.9.0; + +interface ICounterV2{ + function setCount(uint256 _count) external; + function getCount() external view returns(uint256); + function resetCount() external; + function decrementCount() external; +} + +contract CounterV2 is ICounterV2{ + address public owner; + uint256 public count; + + constructor(){ + owner = msg.sender; + } + + function setCount(uint256 _count) external { + require(msg.sender == owner, "Unauthorized Caller"); + require(_count > 0, "Cannot pass zero value as argument"); + + count = _count; + } + + function getCount() external view returns(uint256) { + return count; + } + + function resetCount() external { + require(msg.sender == owner, "Unauthorized Caller"); + if (count > 0) { + count = 0; + } + } + + function decrementCount() external { + count -= 1; + } + + function getOwner() external view returns(address) { + return owner; + } +} + +contract CounterV2Caller { + ICounterV2 public _iCounterV2; + address public contractCounterV2Address; + + constructor(address _contractCounterV2Address) { + contractCounterV2Address = _contractCounterV2Address; + _iCounterV2 = ICounterV2(_contractCounterV2Address); + } + + function callDecrement() external { + _iCounterV2.decrementCount(); + } +} + +// Reset count (if count > 0, then count =0) and to be called by only owner +// Set count (if count === 0, else cannot pass in zero value as arg) and only owner should set count +// write an Interface +// Decrement function (count by 1) +// Create an instance of counter v2 where it will decrease the counter \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index cc2bf83..1b42c40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,6 +10,7 @@ }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@types/minimatch": "^5.1.2", "hardhat": "^2.26.1" } }, @@ -1687,15 +1688,11 @@ } }, "node_modules/@types/minimatch": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-6.0.0.tgz", - "integrity": "sha512-zmPitbQ8+6zNutpwgcQuLcsEpn/Cj54Kbn7L5pX0Os5kdWplB7xPgEh/g+SWOB/qmows2gpuCaPyduq8ZZRnxA==", - "deprecated": "This is a stub types definition. minimatch provides its own type definitions, so you do not need this installed.", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, - "peer": true, - "dependencies": { - "minimatch": "*" - } + "license": "MIT" }, "node_modules/@types/mocha": { "version": "10.0.10", @@ -1839,17 +1836,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/amdefine": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz", - "integrity": "sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg==", - "dev": true, - "optional": true, - "peer": true, - "engines": { - "node": ">=0.4.2" - } - }, "node_modules/ansi-align": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", @@ -4001,6 +3987,7 @@ "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.26.1.tgz", "integrity": "sha512-CXWuUaTtehxiHPCdlitntctfeYRgujmXkNX5gnrD5jdA6HhRQt+WWBZE/gHXbE29y/wDmmUL2d652rI0ctjqjw==", "dev": true, + "license": "MIT", "dependencies": { "@ethereumjs/util": "^9.1.0", "@ethersproject/abi": "^5.1.2", @@ -6445,20 +6432,6 @@ "node": ">= 4.0.0" } }, - "node_modules/source-map": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.2.0.tgz", - "integrity": "sha512-CBdZ2oa/BHhS4xj5DlhjWNHcan57/5YuvfdLf17iVmIpd9KRm+DFLmC6nBNj+6Ua7Kt3TmOjDpQT1aTYOQtoUA==", - "dev": true, - "optional": true, - "peer": true, - "dependencies": { - "amdefine": ">=0.0.4" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", @@ -7124,20 +7097,6 @@ "node": ">=8" } }, - "node_modules/uglify-js": { - "version": "3.19.3", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz", - "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==", - "dev": true, - "optional": true, - "peer": true, - "bin": { - "uglifyjs": "bin/uglifyjs" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/undici": { "version": "5.29.0", "resolved": "https://registry.npmjs.org/undici/-/undici-5.29.0.tgz", diff --git a/package.json b/package.json index a7c3ef4..a7b8f3b 100644 --- a/package.json +++ b/package.json @@ -2,13 +2,15 @@ "name": "hardhat-project", "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", + "@types/minimatch": "^5.1.2", "hardhat": "^2.26.1" }, "scripts": { - "test": "npx hardhat test", - "compile": "npx hardhat compile", - "node": "npx hardhat node" - }, + "test": "npx hardhat test", + "compile": "npx hardhat compile", + "node": "npx hardhat node", + "coverage": "npx hardhat coverage" +}, "dependencies": { "@openzeppelin/contracts": "^5.4.0" } diff --git a/test/BlockToken.js b/test/BlockToken.js index f51869d..4e85d40 100644 --- a/test/BlockToken.js +++ b/test/BlockToken.js @@ -1,82 +1,82 @@ -const { - loadFixture, -} = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +// const { +// loadFixture, +// } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); // const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); -const { expect } = require("chai"); +// const { expect } = require("chai"); // util functon -const deployBlockToken = async () => { - // target the BlockToken contract within our contract folder - let name_ = "BlockToken"; - let symbol_ = "BCT"; - const [owner_, addr1, addr2] = await ethers.getSigners(); - const BlockTokenContract = await ethers.getContractFactory("BlockToken"); // target BlockToken.sol - const BlockToken = await BlockTokenContract.deploy( - name_, - symbol_, - owner_.address - ); // deploy the BlockToken contract - return { BlockToken, owner_, addr1, addr2, name_, symbol_ }; // return the deployed instance of our BlockToken contract -}; +// const deployBlockToken = async () => { +// // target the BlockToken contract within our contract folder +// let name_ = "BlockToken"; +// let symbol_ = "BCT"; +// const [owner_, addr1, addr2] = await ethers.getSigners(); +// const BlockTokenContract = await ethers.getContractFactory("BlockToken"); // target BlockToken.sol +// const BlockToken = await BlockTokenContract.deploy( +// name_, +// symbol_, +// owner_.address +// ); // deploy the BlockToken contract +// return { BlockToken, owner_, addr1, addr2, name_, symbol_ }; // return the deployed instance of our BlockToken contract +// }; // BlockToken Test Suite -describe("BlockToken Test Suite", () => { - describe("Deployment", () => { - it("Should return set values upon deployment", async () => { - const { BlockToken, name_, symbol_, owner_ } = await loadFixture( - deployBlockToken - ); - expect(await BlockToken.name()).to.eq(name_); - expect(await BlockToken.symbol()).to.eq(symbol_); - expect(await BlockToken.owner()).to.eq(owner_); - }); +// describe("BlockToken Test Suite", () => { +// describe("Deployment", () => { +// it("Should return set values upon deployment", async () => { +// const { BlockToken, name_, symbol_, owner_ } = await loadFixture( +// deployBlockToken +// ); +// expect(await BlockToken.name()).to.eq(name_); +// expect(await BlockToken.symbol()).to.eq(symbol_); +// expect(await BlockToken.owner()).to.eq(owner_); +// }); - it("Should revert if owner is zero address", async () => { - const BlockTokenContract = await ethers.getContractFactory("BlockToken"); - let ZeroAddress = "0x0000000000000000000000000000000000000000"; - await expect( - BlockTokenContract.deploy("hh", "tt", ZeroAddress) - ).to.be.revertedWith("BlockToken:: Zero address not supported"); - }); - }); +// it("Should revert if owner is zero address", async () => { +// const BlockTokenContract = await ethers.getContractFactory("BlockToken"); +// let ZeroAddress = "0x0000000000000000000000000000000000000000"; +// await expect( +// BlockTokenContract.deploy("hh", "tt", ZeroAddress) +// ).to.be.revertedWith("BlockToken:: Zero address not supported"); +// }); +// }); - describe("Minting", () => { - it("Should allow onlyOwner Mint", async () => { - const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); - // test owner mints successfully - await BlockToken.connect(owner_).mint(1000, addr1); - expect(await BlockToken.balanceOf(addr1)).to.eq(1000); +// describe("Minting", () => { +// it("Should allow onlyOwner Mint", async () => { +// const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); +// // test owner mints successfully +// await BlockToken.connect(owner_).mint(1000, addr1); +// expect(await BlockToken.balanceOf(addr1)).to.eq(1000); - // test that another user cant call successfully - let malicioustxn = BlockToken.connect(addr1).mint(1000, addr1); - await expect(malicioustxn).to.be.revertedWith( - "BlockToken:: Unauthorized User" - ); - }); +// // test that another user cant call successfully +// let malicioustxn = BlockToken.connect(addr1).mint(1000, addr1); +// await expect(malicioustxn).to.be.revertedWith( +// "BlockToken:: Unauthorized User" +// ); +// }); - it("Should revert if minting amount is zero", async () => { - const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); - await expect( - BlockToken.connect(owner_).mint(0, addr1) - ).to.be.revertedWith("BlockToken:: Zero amount not supported"); - }); - }); +// it("Should revert if minting amount is zero", async () => { +// const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); +// await expect( +// BlockToken.connect(owner_).mint(0, addr1) +// ).to.be.revertedWith("BlockToken:: Zero amount not supported"); +// }); +// }); - describe("Burning", () => { - it("Should not burn if user doesn't have tokens", async () => { - const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); - await expect( - BlockToken.connect(addr1).burn(1000) - ).to.be.revertedWithCustomError(BlockToken, "ERC20InsufficientBalance"); - }); +// describe("Burning", () => { +// it("Should not burn if user doesn't have tokens", async () => { +// const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); +// await expect( +// BlockToken.connect(addr1).burn(1000) +// ).to.be.revertedWithCustomError(BlockToken, "ERC20InsufficientBalance"); +// }); - it("Should Burn Tokens Successfully", async () => { - const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); - await BlockToken.connect(owner_).mint(1000, owner_); - expect(await BlockToken.balanceOf(owner_)).to.eq(1000); +// it("Should Burn Tokens Successfully", async () => { +// const { BlockToken, owner_, addr1 } = await loadFixture(deployBlockToken); +// await BlockToken.connect(owner_).mint(1000, owner_); +// expect(await BlockToken.balanceOf(owner_)).to.eq(1000); - await BlockToken.connect(owner_).burn(100); - expect(await BlockToken.balanceOf(owner_)).to.eq(900); - }); - }); -}); +// await BlockToken.connect(owner_).burn(100); +// expect(await BlockToken.balanceOf(owner_)).to.eq(900); +// }); +// }); +// }); diff --git a/test/BlockheaderToken.js b/test/BlockheaderToken.js new file mode 100644 index 0000000..ec15c70 --- /dev/null +++ b/test/BlockheaderToken.js @@ -0,0 +1,291 @@ +const { + loadFixture, +} = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +const { expect } = require("chai"); + +const deployContract = async () => { + let _name = "BlockToken"; + let _symbol = "BCT"; + const [_owner, addr1, addr2] = await ethers.getSigners(); + const BlockTokenContract = await ethers.getContractFactory("BlockToken"); + const BlockToken = await BlockTokenContract.deploy( + _name, + _symbol, + _owner.address + ); + + return { BlockToken, _owner, addr1, addr2, _name, _symbol }; +}; + +describe("BlockToken Test Suite", () => { + describe("Deployment", () => { + it("Should return set values upon deployment", async () => { + const { BlockToken, _name, _symbol, _owner } = await loadFixture( + deployContract + ); + // console.log(_owner.address); + expect(await BlockToken.name()).to.eq(_name); + expect(await BlockToken.symbol()).to.eq(_symbol); + expect(await BlockToken.owner()).to.eq(_owner.address); + }); + + it("Should revert if owner is zero address", async () => { + const BlockTokenContract = await ethers.getContractFactory("BlockToken"); + const zeroAddress = "0x0000000000000000000000000000000000000000"; + + await expect( + BlockTokenContract.deploy("Token", "TKN", zeroAddress) + ).to.be.revertedWith("BlockToken:: Zero Address not supported"); + }); + }); + + describe("Minting", () => { + it("Should allow only owner to mint", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + await BlockToken.connect(_owner).mint(10, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(10); + + await expect( + BlockToken.connect(addr1).mint(1000, addr2) + ).to.be.revertedWith("BlockToken:: Unauthorized User"); + }); + + it("Should revert if minting amount is zero", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + await expect( + BlockToken.connect(_owner).mint(0, addr1) + ).to.be.revertedWith("BlockToken:: Zero amount not supported"); + }); + }); + + describe("Burning", () => { + it("Should not burn if user doesn't have tokens", async () => { + const { BlockToken, addr1 } = await loadFixture(deployContract); + + await expect( + BlockToken.connect(addr1).burn(1000) + ).to.be.revertedWithCustomError(BlockToken, "ERC20InsufficientBalance"); + }); + + it("Should burn tokens successfully", async () => { + const { BlockToken, _owner } = await loadFixture(deployContract); + + await BlockToken.connect(_owner).mint(1000, _owner); + + const balance = await BlockToken.balanceOf(_owner); + expect(balance).to.eq(1000); + + await BlockToken.connect(_owner).burn(100); + const balance2 = await BlockToken.balanceOf(_owner); + expect(balance2).to.eq(900); + }); + + it("Should allow only owner to burnFrom", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + // Check if address 1 can burn from his address + await expect( + BlockToken.connect(addr1).burnFrom(addr1, 800) + ).to.be.revertedWith("BlockToken:: Unauthorized User"); + + await BlockToken.connect(_owner).mint(900, addr2); + expect(await BlockToken.balanceOf(addr2)).to.eq(900); + + // Check if address 1 can burn from another address + await expect( + BlockToken.connect(addr1).burnFrom(addr2, 800) + ).to.be.revertedWith("BlockToken:: Unauthorized User"); + + // Check if owner can burn from successfully + await BlockToken.connect(_owner).burnFrom(addr1, 200); + + const balance = await BlockToken.balanceOf(addr1); + expect(balance).to.eq(800); + }); + + it("Should not burn zero amount", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await expect( + BlockToken.connect(_owner).burnFrom(addr1, 0) + ).to.be.revertedWith("BlockToken:: Zero amount not supported"); + }); + }); + + describe("Transactions", () => { + describe("Transfers", () => { + it("Should transfer tokens from one account to another", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + const zeroAddress = "0x0000000000000000000000000000000000000000"; + + // Transfer to zero address + await expect(BlockToken.connect(_owner).transfer(zeroAddress, 800)).to + .be.reverted; + + await BlockToken.connect(_owner).mint(1000, _owner); + expect(await BlockToken.balanceOf(_owner)).to.eq(1000); + + // Transfer from owner to other account + await BlockToken.connect(_owner).transfer(addr1, 800); + expect(await BlockToken.balanceOf(_owner)).to.eq(200); + expect(await BlockToken.balanceOf(addr1)).to.eq(800); + + // Transfer from account to account + await BlockToken.connect(addr1).transfer(addr2, 400); + expect(await BlockToken.balanceOf(addr1)).to.eq(400); + expect(await BlockToken.balanceOf(addr2)).to.eq(400); + }); + + it("Should transfer tokens less than or equal to balance", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + + await BlockToken.connect(_owner).mint(1000, _owner); + expect(await BlockToken.balanceOf(_owner)).to.eq(1000); + + await BlockToken.connect(_owner).transfer(addr1, 1000); + expect(await BlockToken.balanceOf(_owner)).to.eq(0); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await expect( + BlockToken.connect(_owner).transfer(addr1, 100) + ).to.be.revertedWithCustomError(BlockToken, "ERC20InsufficientBalance"); + expect(await BlockToken.balanceOf(_owner)).to.eq(0); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + }); + + it("Should approve for transferFrom function", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + + await BlockToken.connect(_owner).mint(1000, _owner); + expect(await BlockToken.balanceOf(_owner)).to.eq(1000); + + await BlockToken.connect(_owner).approve(addr1, 500); + expect(await BlockToken.allowance(_owner, addr1)).to.eq(500); + }); + + it("Should transferFrom based on approve and allowance", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await BlockToken.connect(addr1).approve(_owner, 500); + expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + 500 + ); + await BlockToken.connect(_owner).transferFrom(addr1, addr2, 400); + + expect(await BlockToken.connect(addr2).balanceOf(addr2)).to.eq(400); + }); + + it("Should revert if balance of 'from' is insufficient", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await BlockToken.connect(addr1).approve(_owner, 500); + expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + 500 + ); + await expect( + BlockToken.connect(_owner).transferFrom(addr1, addr2, 700) + ).to.be.revertedWithCustomError( + BlockToken, + "ERC20InsufficientAllowance" + ); + }); + + // it("Should revert if balance of 'from' is insufficient", async () => { + // const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + // deployContract + // ); + + // await BlockToken.connect(_owner).mint(1000, addr1); + // expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + // await BlockToken.connect(addr1).approve(_owner, 500); + // expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + // 500 + // ); + // await expect( + // BlockToken.connect(_owner).transferFrom(addr1, addr2, 700) + // ).to.be.revertedWithCustomError( + // BlockToken, + // "ERC20InsufficientAllowance" + // ); + // }); + + it("Should revert if allowance is zero for spender", async () => { + const { BlockToken, _owner, addr1, addr2 } = await loadFixture( + deployContract + ); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await BlockToken.connect(addr1).approve(_owner, 0); + expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + 0 + ); + await expect( + BlockToken.connect(_owner).transferFrom(addr1, addr2, 700) + ).to.be.revertedWithCustomError( + BlockToken, + "ERC20InsufficientAllowance" + ); + }); + + it("Should revert if 'to' is address zero", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + const zeroAddress = "0x0000000000000000000000000000000000000000"; + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await BlockToken.connect(addr1).approve(_owner, 500); + expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + 500 + ); + await expect( + BlockToken.connect(_owner).transferFrom(addr1, zeroAddress, 400) + ).to.be.revertedWithCustomError(BlockToken, "ERC20InvalidReceiver"); + }); + + it("Should revert if allowance is incremented and not replaced", async () => { + const { BlockToken, _owner, addr1 } = await loadFixture(deployContract); + + await BlockToken.connect(_owner).mint(1000, addr1); + expect(await BlockToken.balanceOf(addr1)).to.eq(1000); + + await BlockToken.connect(addr1).approve(_owner, 500); + + await BlockToken.connect(addr1).approve(_owner, 700); + expect(await BlockToken.connect(addr1).allowance(addr1, _owner)).to.eq( + 700 + ); + }); + }); + }); +}); + +// Test onlyowner, notAmount, revert if user tries to burn insufficient amount +// Test all the public and external functions from the ERC20 diff --git a/test/Counter.js b/test/Counter.js index 507bd94..e083541 100644 --- a/test/Counter.js +++ b/test/Counter.js @@ -1,10 +1,10 @@ // const { // loadFixture, // } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); -// // const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); +// const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); // const { expect } = require("chai"); -// // util functon +// util functon // const deployCounter = async () => { // // target the Counter contract within our contract folder // const CounterContract = await ethers.getContractFactory("Counter"); // target Counter.sol @@ -12,7 +12,7 @@ // return counter; // return the deployed instance of our counter contract // }; -// // Counter Test Suite +// Counter Test Suite // describe("Counter Test Suite", () => { // describe("Deployment", () => { // it("Should return default values upon deployment", async () => { @@ -24,7 +24,7 @@ // describe("Transactions", () => { // describe("SetCount", () => { // it("Should set appropriate count values", async () => { -// const counter = await loadFixture(deployCounter); // extract deployed counter instace +// const counter = await loadFixture(deployCounter); // extract deployed counter instance // let count1 = await counter.getCount(); // check initial count value before txn // expect(count1).to.eq(0); // await counter.setCount(10); // assert that count = 0 upon deployment @@ -34,56 +34,61 @@ // }); // it("Should set appropriate values for multiple setCount txns", async () => { -// const data = await loadFixture(deployCounter); +// const counter = await loadFixture(deployCounter); +// let count1 = await counter.getCount(); +// expect(count1).to.eq(0); +// await counter.setCount(10); + +// let count2 = await counter.getCount(); +// expect(count2).to.eq(10); +// await counter.setCount(20); -// // tx one -// let counter = await data.getCount(); -// expect(counter).to.eq(0); +// let count3 = await counter.getCount(); +// expect(count3).to.eq(20); +// await counter.setCount(30); -// await data.setCount(32); -// let counter1 = await data.getCount(); -// expect(counter1).to.eq(32); +// let count4 = await counter.getCount(); +// expect(count4).to.eq(30); // }); // }); // describe("IncreaseCountByOne", () => { // it("Should set appropriate increaseCountByOne value", async () => { -// const data = await loadFixture(deployCounter); -// let data1 = await data.getCount(); -// expect(data1).to.eq(0); +// const counter = await loadFixture(deployCounter); +// let count1 = await counter.getCount(); +// expect(count1).to.eq(0); +// await counter.increaseCountByOne(); -// await data.increaseCountByOne(); -// let data2 = await data.getCount(); -// expect(data2).to.eq(1); +// let count2 = await counter.getCount(); +// expect(count2).to.eq(1); // }); // it("Should set appropriate values for multiple increaseCountByOne txns", async () => { // const counter = await loadFixture(deployCounter); -// await counter.setCount(10); -// let counter1 = await counter.getCount(); -// expect(counter1).to.eq(10); +// // let count1 = await counter.getCount(); +// // expect(count1).to.eq(0); +// // await counter.increaseCountByOne(); -// for (let i = 0; i < 5; i++) { -// await counter.increaseCountByOne(); -// } -// let counter2 = await counter.getCount(); -// expect(counter2).to.eq(15); +// // let count2 = await counter.getCount(); +// // expect(count2).to.eq(1); +// // await counter.increaseCountByOne(); -// while (true) { -// await counter.increaseCountByOne(); -// if ((await counter.getCount()) == 25) { -// break; -// } -// } -// expect(await counter.getCount()).to.eq(25); +// // let count3 = await counter.getCount(); +// // expect(count3).to.eq(2); +// // await counter.increaseCountByOne(); + +// // let count4 = await counter.getCount(); +// // expect(count4).to.eq(3); +// await counter.setCount(30); +// let count1 = await counter.getCount(); +// expect(count1).to.eq(30); -// i = 0; -// while (i < 10) { +// for (let i = 0; i < 5; i++) { // await counter.increaseCountByOne(); -// i++; // } -// expect(await counter.getCount()).to.eq(35); +// let count2 = await counter.getCount(); +// expect(count2).to.eq(35); // }); // }); // }); diff --git a/test/CounterV2.js b/test/CounterV2.js new file mode 100644 index 0000000..a9286f2 --- /dev/null +++ b/test/CounterV2.js @@ -0,0 +1,147 @@ +// const { +// loadFixture, +// } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +// const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); +// const { expect } = require("chai"); +// const { ethers } = require("hardhat"); + +// util functon +// const deployCounter = async () => { +// // target the CounterV2 contract within our contract folder +// const CounterContract1 = await ethers.getContractFactory("CounterV2"); +// const counterV2 = await CounterContract1.deploy(); + +// // target the CounterV2Caller contract within our contract folder +// const CounterContract2 = await ethers.getContractFactory("CounterV2Caller"); +// const targetAddress = await counterV2.getAddress(); +// // console.log(targetAddress); + +// // deploy the contract with the target address we got from calling the getContractFactory() method on the ethers.js library passing in the target contract +// const counterV2caller = await CounterContract2.deploy(targetAddress); + +// // console.log("This is the counterV2 object:", counterV2); +// // console.log("This is the counterV2Caller object:", counterV2caller); + +// return { counterV2, counterV2caller }; // Returns the deployed contracts as an object +// }; + +// Counter Test Suite +// describe("CounterV2 Test Suite", () => { +// describe("Deployment", () => { +// describe("CounterV2 Deployment", () => { +// it("Should return default values upon deployment", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// expect(await counterV2.count()).to.eq(0); +// }); + +// it("Should set the default owner to the deployer", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// const [owner] = await ethers.getSigners(); +// expect(await counterV2.getOwner()).to.eq(owner.address); +// }); +// }); +// }); + +// describe("Transactions", () => { +// describe("SetCount from counterV2", () => { +// it("Should return count value set by user from the counterV2 contract", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// let count1 = await counterV2.getCount(); +// expect(count1).to.eq(0); +// await counterV2.setCount(10); + +// let count2 = await counterV2.getCount(); +// expect(count2).to.eq(10); +// }); +// }); + +// describe("DecreaseCountByOne", () => { +// it("Should decrease the count by one from the contractV2caller contract", async () => { +// const { counterV2, counterV2caller } = await loadFixture(deployCounter); +// let count1 = await counterV2.getCount(); +// expect(count1).to.eq(0); +// await counterV2.setCount(10); + +// let count2 = await counterV2.getCount(); +// expect(count2).to.eq(10); +// await counterV2caller.callDecrement(); + +// let count3 = await counterV2.getCount(); +// expect(count3).to.eq(9); +// await counterV2caller.callDecrement(); + +// let count4 = await counterV2.getCount(); +// expect(count4).to.eq(8); +// }); +// }); + +// describe("ResetCount", () => { +// it("Should reset the count set by the user", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// let count1 = await counterV2.getCount(); +// expect(count1).to.eq(0); +// await counterV2.setCount(10); + +// let count2 = await counterV2.getCount(); +// expect(count2).to.eq(10); +// await counterV2.setCount(40); + +// let count3 = await counterV2.getCount(); +// expect(count3).to.eq(40); +// await counterV2.resetCount(); + +// let count4 = await counterV2.getCount(); +// expect(count4).to.eq(0); +// }); +// }); +// }); + +// describe("Reverts", () => { +// describe("Unauthorized Caller of the setCount() function", () => { +// it("Should revert if the caller is unauthorized", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// // console.log(await ethers.getSigners()); +// const [, attacker] = await ethers.getSigners(); // This returns an array of accounts object and we destructure immediately to get the second account in the array as the first account is the default deployer/signer of the message + +// await expect( +// counterV2.connect(attacker).setCount(10) +// ).to.be.revertedWith("Unauthorized Caller"); // The .connect(attacker) calls the counterV2 contract instance with a different signer and the ".to.be.revertedWith()" expects the same string message passed in your require statement in the solidity contract function you wrote +// }); +// }); + +// describe("Unauthorized Caller of the resetCount() function", () => { +// it("Should revert if the caller is unauthorized", async () => { +// const { counterV2 } = await loadFixture(deployCounter); +// const [, attacker] = await ethers.getSigners(); + +// await counterV2.setCount(20); +// await expect( +// counterV2.connect(attacker).resetCount() +// ).to.be.revertedWith("Unauthorized Caller"); +// }); +// }); + +// describe("Zero value argument in setCount() function", () => { +// it("Should revert if the user passes in zero as the argument for the setCount() function", async () => { +// const { counterV2 } = await loadFixture(deployCounter); + +// await expect(counterV2.setCount(0)).to.be.revertedWith( +// "Cannot pass zero value as argument" +// ); +// }); +// }); +// }); + +// describe("Indirect Interaction", () => { +// it("Should successfully decrement count in counterV2 via counterV2Caller", async () => { +// const { counterV2, counterV2caller } = await loadFixture(deployCounter); + +// await counterV2.setCount(10); + +// await counterV2caller.callDecrement(); + +// const countAfterChange = await counterV2.count(); +// expect(countAfterChange).to.eq(9); +// }); +// }); +// });