diff --git a/contracts/BlockToken.sol b/contracts/BlockToken.sol new file mode 100644 index 0000000..c0c2fa9 --- /dev/null +++ b/contracts/BlockToken.sol @@ -0,0 +1,38 @@ +// 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 _recepient) onlyOwner notAmount0(_amount) external { + _mint(_recepient, _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); + } + + +} + diff --git a/contracts/counterV2.sol b/contracts/counterV2.sol new file mode 100644 index 0000000..807ca29 --- /dev/null +++ b/contracts/counterV2.sol @@ -0,0 +1,69 @@ +// SPDX-License-Identifier: MIT + +pragma solidity ^0.8.28; + +interface ICounterV2{ + function setCount(uint256 _count) external; + + function getCount() external view returns(uint256); + + function increaseCountByOne() external; + + function resetCount() external; + + function decreaseCountByOne() external; +} + +contract CounterV2 is ICounterV2 { + uint256 public count; + address owner; + + constructor(){ + owner = msg.sender; + } + + function setCount(uint256 _count) public { + require(_count > 0, "Count must be greater than 0"); + require(msg.sender == owner, "You are unauthorised"); + count = _count; + } + + function getCount() public view returns(uint256) { + return count; + } + + function getOwner() public view returns(address) { + return owner; + } + + function increaseCountByOne() public { + require(msg.sender == owner, "You are unauthorised"); + count+=1; + } + + function resetCount() public { + require(count > 0,"Cannot reset value , It's already at default"); + require(msg.sender == owner, "You are Unauthorised"); + count = 0; + } + + function decreaseCountByOne() external { + require(msg.sender == owner, "You are unauthorised"); + count-=1; + } +} + +contract callerCounterV2 { + ICounterV2 public _IC; + address public contractAddress; + constructor (address _contractAddress) { + contractAddress = _contractAddress; + _IC = ICounterV2(contractAddress); + + } + + function callDecreaseCountByOne() public { + _IC.decreaseCountByOne(); + } +} + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 656a34f..cc2bf83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,6 +5,9 @@ "packages": { "": { "name": "hardhat-project", + "dependencies": { + "@openzeppelin/contracts": "^5.4.0" + }, "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", "hardhat": "^2.26.1" @@ -1305,6 +1308,12 @@ "node": ">= 12" } }, + "node_modules/@openzeppelin/contracts": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-5.4.0.tgz", + "integrity": "sha512-eCYgWnLg6WO+X52I16TZt8uEjbtdkgLC0SUX/xnAksjjrQI4Xfn4iBRoI5j55dmlOhDv1Y7BoR3cU7e3WWhC6A==", + "license": "MIT" + }, "node_modules/@scure/base": { "version": "1.2.6", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", diff --git a/package.json b/package.json index 0586079..a7c3ef4 100644 --- a/package.json +++ b/package.json @@ -3,10 +3,13 @@ "devDependencies": { "@nomicfoundation/hardhat-toolbox": "^5.0.0", "hardhat": "^2.26.1" - }, + }, "scripts": { - "test": "npx hardhat test", - "compile": "npx hardhat compile", + "test": "npx hardhat test", + "compile": "npx hardhat compile", "node": "npx hardhat node" + }, + "dependencies": { + "@openzeppelin/contracts": "^5.4.0" } } diff --git a/solidity-cohort-7 b/solidity-cohort-7 new file mode 160000 index 0000000..3e67ebe --- /dev/null +++ b/solidity-cohort-7 @@ -0,0 +1 @@ +Subproject commit 3e67ebe07a61f61516150ebf30710b9c4748f74b diff --git a/test/BlockToken.js b/test/BlockToken.js new file mode 100644 index 0000000..612ba3c --- /dev/null +++ b/test/BlockToken.js @@ -0,0 +1,82 @@ +const { + loadFixture, +} = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +// const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); +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 +}; + +// 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_); + }); + + 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); + + + 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"); + }); + }); + + 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); + + await BlockToken.connect(owner_).burn(100); + expect(await BlockToken.balanceOf(owner_)).to.eq(900); + }); + }); +}); diff --git a/test/Counter.js b/test/Counter.js index 99b2931..507bd94 100644 --- a/test/Counter.js +++ b/test/Counter.js @@ -1,49 +1,90 @@ -const {loadFixture } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); -// const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); -const { expect } = require("chai"); - -// util functon -const deployCounter = async () => { - // target the Counter contract within our contract folder - const CounterContract = await ethers.getContractFactory("Counter"); // target Counter.sol - const counter = await CounterContract.deploy(); // deploy the Counter contract - return counter ; // return the deployed instance of our counter contract -} - -// Counter Test Suite -describe("Counter Test Suite", () => { - describe("Deployment", () => { - it("Should return default values upon deployment", async () => { - const counter = await loadFixture(deployCounter); - expect(await counter.count()).to.eq(0); // assert that count = 0 upon deployment - }) - }) - - describe("Transactions", () => { - describe("SetCount", () => { - it("Should set appropriate count values", async () => { - const counter = await loadFixture(deployCounter); // extract deployed counter instace - 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 - - let count2 = await counter.getCount(); // check initial count value before txn - expect(count2).to.eq(10) // check final count = 10 - }) - - it("Should set appropriate values for multiple setCount txns", async () => { - - }) - }) - - describe("IncreaseCountByOne", () => { - it("Should set appropriate increaseCountByOne value", async () => { - - }) - - it("Should set appropriate values for multiple increaseCountByOne txns", async () => { - - }) - }) - }) -}) \ No newline at end of file +// const { +// loadFixture, +// } = require("@nomicfoundation/hardhat-toolbox/network-helpers"); +// // const { anyValue } = require("@nomicfoundation/hardhat-chai-matchers/withArgs"); +// const { expect } = require("chai"); + +// // util functon +// const deployCounter = async () => { +// // target the Counter contract within our contract folder +// const CounterContract = await ethers.getContractFactory("Counter"); // target Counter.sol +// const counter = await CounterContract.deploy(); // deploy the Counter contract +// return counter; // return the deployed instance of our counter contract +// }; + +// // Counter Test Suite +// describe("Counter Test Suite", () => { +// describe("Deployment", () => { +// it("Should return default values upon deployment", async () => { +// const counter = await loadFixture(deployCounter); +// expect(await counter.count()).to.eq(0); // assert that count = 0 upon deployment +// }); +// }); + +// describe("Transactions", () => { +// describe("SetCount", () => { +// it("Should set appropriate count values", async () => { +// const counter = await loadFixture(deployCounter); // extract deployed counter instace +// 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 + +// let count2 = await counter.getCount(); // check initial count value before txn +// expect(count2).to.eq(10); // check final count = 10 +// }); + +// it("Should set appropriate values for multiple setCount txns", async () => { +// const data = await loadFixture(deployCounter); + +// // tx one +// let counter = await data.getCount(); +// expect(counter).to.eq(0); + +// await data.setCount(32); +// let counter1 = await data.getCount(); +// expect(counter1).to.eq(32); +// }); +// }); + +// describe("IncreaseCountByOne", () => { +// it("Should set appropriate increaseCountByOne value", async () => { +// const data = await loadFixture(deployCounter); +// let data1 = await data.getCount(); +// expect(data1).to.eq(0); + +// await data.increaseCountByOne(); +// let data2 = await data.getCount(); +// expect(data2).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); + +// for (let i = 0; i < 5; i++) { +// await counter.increaseCountByOne(); +// } +// let counter2 = await counter.getCount(); +// expect(counter2).to.eq(15); + +// while (true) { +// await counter.increaseCountByOne(); +// if ((await counter.getCount()) == 25) { +// break; +// } +// } +// expect(await counter.getCount()).to.eq(25); + +// i = 0; +// while (i < 10) { +// await counter.increaseCountByOne(); +// i++; +// } + +// expect(await counter.getCount()).to.eq(35); +// }); +// }); +// }); +// });