diff --git a/Assignments/Assignment-1.md/assignment1 b/Assignments/Assignment-1.md/assignment1 new file mode 100644 index 00000000..4493485b --- /dev/null +++ b/Assignments/Assignment-1.md/assignment1 @@ -0,0 +1,4 @@ +# Assignment 1 + +Here's a link to [Assignment 1](../../contracts/counter.frankhood.sol) + diff --git a/Assignments/Assignment-1.md/counter..FRANKHOOD.sol b/Assignments/Assignment-1.md/counter..FRANKHOOD.sol new file mode 100644 index 00000000..01907118 --- /dev/null +++ b/Assignments/Assignment-1.md/counter..FRANKHOOD.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +/// @title Counter Contract Implementation +/// @author FRANKHOOD +/// @notice this contract defines the count and maximum value of the count +/// @dev All function calls are currently implemented without side effects +contract Counter{ + uint public count = 0; + uint maxValue = getMaxUint256 (); + +/// @notice this event is emitted when the count is increased +/// @param amount the value of the count after increasing +/// @param timestamp the time the count increased +event CountIncreased(uint amount, uint timestamp); + +/// @notice this event is emitted when the count is decreased +/// @param amount the value of the count after decreasing +/// @param timestamp the time the count decreased +event CountDecreased(uint amount, uint timestamp); + +/// @notice this function increases the count by 0ne +/// @notice this function is reverted if it exceeds the maxValue +function increaseByOne() public { + require(count < maxValue, "cannot increase beyond max uint"); + count ++; + emit CountIncreased(count, block.timestamp); +} + +/// @notice this function increases the count by a value that must be greater than 0 +/// @notice this function is reverted if it exceeds the maxValue +function increaseByValue(uint _value) public { + require (_value > 0); + require(count < maxValue, "cannot increase beyond max uint"); + count += _value; + emit CountIncreased(count, block.timestamp); +} + +/// @notice this function decreases the count by 0ne +/// @notice this function is reverted if the value of count is less than 1 +function decreaseByOne() public { + require(count >= 1,"cannot decrease below 0"); + count --; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function decreases the count by a value greater than or equal to one +/// @notice this function is reverted if the result is greater than maxValue +function decreaseByValue(uint _value) public { + require(count >= 1,"cannot decrease below 0"); + require(count + _value <= maxValue); + count += _value; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function resets the count to original value - 0 +function resetCount() public { + count = 0; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function returns the current value of count +function getCount() public view returns (uint){ + return count; +} + +/// @notice this function returns the maximum value of count +function getMaxUint256() public pure returns (uint){ + unchecked { + return uint256 (0)-1; + } +} +} \ No newline at end of file diff --git a/contracts/counter.frankhood.sol b/contracts/counter.frankhood.sol new file mode 100644 index 00000000..01907118 --- /dev/null +++ b/contracts/counter.frankhood.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +/// @title Counter Contract Implementation +/// @author FRANKHOOD +/// @notice this contract defines the count and maximum value of the count +/// @dev All function calls are currently implemented without side effects +contract Counter{ + uint public count = 0; + uint maxValue = getMaxUint256 (); + +/// @notice this event is emitted when the count is increased +/// @param amount the value of the count after increasing +/// @param timestamp the time the count increased +event CountIncreased(uint amount, uint timestamp); + +/// @notice this event is emitted when the count is decreased +/// @param amount the value of the count after decreasing +/// @param timestamp the time the count decreased +event CountDecreased(uint amount, uint timestamp); + +/// @notice this function increases the count by 0ne +/// @notice this function is reverted if it exceeds the maxValue +function increaseByOne() public { + require(count < maxValue, "cannot increase beyond max uint"); + count ++; + emit CountIncreased(count, block.timestamp); +} + +/// @notice this function increases the count by a value that must be greater than 0 +/// @notice this function is reverted if it exceeds the maxValue +function increaseByValue(uint _value) public { + require (_value > 0); + require(count < maxValue, "cannot increase beyond max uint"); + count += _value; + emit CountIncreased(count, block.timestamp); +} + +/// @notice this function decreases the count by 0ne +/// @notice this function is reverted if the value of count is less than 1 +function decreaseByOne() public { + require(count >= 1,"cannot decrease below 0"); + count --; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function decreases the count by a value greater than or equal to one +/// @notice this function is reverted if the result is greater than maxValue +function decreaseByValue(uint _value) public { + require(count >= 1,"cannot decrease below 0"); + require(count + _value <= maxValue); + count += _value; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function resets the count to original value - 0 +function resetCount() public { + count = 0; + emit CountDecreased(count, block.timestamp); +} + +/// @notice this function returns the current value of count +function getCount() public view returns (uint){ + return count; +} + +/// @notice this function returns the maximum value of count +function getMaxUint256() public pure returns (uint){ + unchecked { + return uint256 (0)-1; + } +} +} \ No newline at end of file diff --git a/submissions/Assignment3/KingFRANKHOOD/ERC20.sol b/submissions/Assignment3/KingFRANKHOOD/ERC20.sol new file mode 100644 index 00000000..209bcbf0 --- /dev/null +++ b/submissions/Assignment3/KingFRANKHOOD/ERC20.sol @@ -0,0 +1,64 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.26; + +contract ERC20 { + string public name; + string public symbol; + uint8 public decimals; + uint256 public totalSupply; + + mapping (address => uint256) public balanceOf; + mapping (address => mapping(address => uint256)) public allowance; + + event Transfer (address indexed from, address indexed to, uint256 value); + event Approval (address indexed owner, address indexed spender, uint value); + + constructor(string memory _name, string memory _symbol, uint8 _decimals) { + name = _name; + symbol = _symbol; + decimals = _decimals; + } + + + function transfer(address recipient, uint256 amount) external returns (bool) { + require(balanceOf[msg.sender] >= amount); + balanceOf[msg.sender] -= amount; + balanceOf[recipient] += amount; + + emit Transfer(msg.sender, recipient, amount); + return true; + } + + function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { + allowance[sender][msg.sender] -= amount; + balanceOf[sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(sender, recipient, amount); + return true; + } + + function _mint (address _to, uint256 _amount) virtual public { + require(msg.sender != address(0), "zero address"); + balanceOf[_to] += _amount; + totalSupply += _amount; + + emit Transfer(address(0), _to, _amount); + } + + function _burn (address, uint256 _amount) public { + require(balanceOf[msg.sender] >= _amount, "insufficient funds"); + totalSupply -= _amount; + balanceOf[msg.sender] -= _amount; + balanceOf[address(0)] -= _amount; + + emit Transfer(msg.sender, address(0), _amount); + } + + function mint(address to, uint256 amount) external { + _mint(to, amount); + } + + function burn(address from, uint256 amount) external { + _burn(from, amount); + } +} \ No newline at end of file diff --git a/submissions/Assignment3/KingFRANKHOOD/ERC721.sol b/submissions/Assignment3/KingFRANKHOOD/ERC721.sol new file mode 100644 index 00000000..888986ab --- /dev/null +++ b/submissions/Assignment3/KingFRANKHOOD/ERC721.sol @@ -0,0 +1,77 @@ +// SPDX-License-Identifier:MIT +pragma solidity ^0.8.24; + +import "./IERC721.sol"; + +contract ERC721 is IERC721 { + // Mapping fron tokenId to owner address + mapping (uint256=> address) internal _ownerOf; + + //Mapping from owner address to token count + mapping (address => uint256) internal _balanceOf; + + //Mapping from tokenId to approved address + mapping (uint256 => address) internal _approvals; + + //Mapping from owner to operator approvals + mapping (address => mapping (address => bool)) public isApprovedForAll; + + event NFTTransfer(address indexed from, address indexed to, uint256 indexed id); + event NFTApproval(address indexed owner, address indexed spender, uint256 indexed id); + event ApprovalForAll(address indexed owner, address operator, bool approved); + + function nftBalanceOf(address owner) external view returns (uint256) { + require(owner != address(0), "owner = zero address"); + return _balanceOf[owner]; + } + + function ownerOf(uint256 tokenId) external view returns (address ownerOfToken) { + ownerOfToken = _ownerOf[tokenId]; + require(ownerOfToken != address(0), "token doesn't exist"); + } + + function setApprovalForAll(address operator, bool approved) external { + isApprovedForAll[msg.sender][operator] = approved; + emit ApprovalForAll(msg.sender,operator,approved); + } + + function approve(address to, uint256 tokenId) external { + address owner = _ownerOf[tokenId]; + require(msg.sender == owner || isApprovedForAll[owner][msg.sender], 'not authorised'); + + _approvals[tokenId] = to; + + emit NFTApproval(owner, to, tokenId); + } + + function getApproved(uint256 tokenId) external view returns (address) { + require (_ownerOf[tokenId] !=address(0), "token does not exist"); + return _approvals[tokenId]; + } + + function isApprovedOrOwner(address owner, address spender, uint256 id) private view returns (bool) { + return (spender == owner || isApprovedForAll[owner][spender] || spender == _approvals[id]); + } + + function nftTransferFrom(address from, address to, uint256 tokenId) external { + require(from == _ownerOf[tokenId], "from != owner"); + require(to != address(0), "transfer to zero address"); + require(isApprovedOrOwner(from, msg.sender, tokenId), "not authorised"); + + _balanceOf[from]--; + _balanceOf[to]++; + _ownerOf[tokenId] = to; + + delete _approvals[tokenId]; + } + + function _mintNFT(address to, uint256 tokenId) internal virtual { + require(to != address(0), "mint to zero address"); + require(_ownerOf[tokenId] == address(0), "already minted"); + + _balanceOf[to]++; + _ownerOf[tokenId] = to; + + emit NFTTransfer(address(0), to, tokenId); + } +} diff --git a/submissions/Assignment3/KingFRANKHOOD/IERC721.sol b/submissions/Assignment3/KingFRANKHOOD/IERC721.sol new file mode 100644 index 00000000..b06572bf --- /dev/null +++ b/submissions/Assignment3/KingFRANKHOOD/IERC721.sol @@ -0,0 +1,13 @@ +// SPDX-License-Identifier:MIT +pragma solidity ^0.8.24; + +interface IERC721 { + function nftBalanceOf(address owner) external view returns (uint256 balance); + function ownerOf(uint tokenId) external view returns (address owner); + //function safeTransferFrom(address from, address to, uint tokenId, bytes memory data) external; + //function safeTransferFrom(address from, address to, uint tokenId) external; + function nftTransferFrom(address from, address to, uint tokenId) external; + function approve(address to, uint256 tokenId) external; + function setApprovalForAll(address operator, bool approved) external; + function isApprovedForAll(address owner, address operator) external view returns (bool); +} \ No newline at end of file diff --git a/submissions/Assignment3/KingFRANKHOOD/crowdFunding.sol b/submissions/Assignment3/KingFRANKHOOD/crowdFunding.sol new file mode 100644 index 00000000..8af9db35 --- /dev/null +++ b/submissions/Assignment3/KingFRANKHOOD/crowdFunding.sol @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.28; + +import "./ERC20.sol"; +import "./ERC721.sol"; + +/// @title A CrowdFunding Contract +/// @author FRANKHOOD +/// @notice this contract ERC20 and ERC721 tokens from the crowdFunding folder +abstract contract CrowdFund is ERC20, ERC721{ + uint public amount; + uint public _threshhold; + address private crowdFund; + bool TokenClaimed; + bool NFTClaimed; + +/// @notice funder and alreadyClaimed are the addresses that interact with the contract +/// @dev these addresse hold the ERC20 and ERC721 tokens + mapping (address => uint) funder; + mapping (address => uint) alreadyClaimed; + +/// @param _from is the address that calls this function by adding ERC20 to the crowFund +/// @param _amount is the amount of ERC20 added by the _from address + event ContributionMade(address indexed _from, uint _amount); + event TreshholdExceeded(address indexed _from, uint _amount); + +/// @param _to is the address that calls this function by adding ERC20 to the crowFund + event TokenWithdrawn(address indexed _to, uint _amount); + event RewardReceived(address indexed _to, uint _amount); + + +/// @notice this function is payable so it receives the ERC20 tokens +/// @param _from is the address that calls this function by adding ERC20 to the crowFund +/// @param _amount is the amount of ERC20 added by the _from address + function contribution(address _from, uint _amount) payable public { + require(_amount > 0,"Contribution cannot be 0"); + balanceOf[crowdFund] += _amount; + balanceOf[_from] -= _amount; + + funder[_from] += _amount; + TokenClaimed = false;//this argument says that the address has not received reward tokens yet + + emit ContributionMade(_from, _amount); + } + + +/// @notice this function requires the address to contribute an amount greater than 0 to the crowdFund before executing +/// @notice the receiving address cannot be address(0) +/// @notice the tokenClaimed boolean returns as true after the function executes +/// @param _to is the address that calls this function by adding ERC20 to the crowFund +/// @param _amount is the amount of ERC20 added by the _from address + function _mint (address _to, uint256 _amount) virtual override public { + require(TokenClaimed = false, "already claimed reward"); + require(alreadyClaimed[_to] == funder[_to]); + require(funder[_to] > 0,"amount must be greater than 0"); + require(msg.sender != address(0), "zero address"); + balanceOf[_to] += _amount; + totalSupply += _amount; + + TokenClaimed = true;//returns TokenClaimed boolean as true after execuion + + emit Transfer(address(0), _to, _amount); + emit RewardReceived(_to, amount); + } + +/// @notice this function sets the _threshhold at 10 ether and a requirement for execution + function threshhold(address _from, uint _amount) public returns (uint) { + require(_amount >= 10 ether, "not up to 10 ether"); + _threshhold = _amount; + + balanceOf[crowdFund] += _threshhold; + balanceOf[_from] -= _threshhold; + + funder[_from] += _threshhold; + + emit TreshholdExceeded(_from, _amount); + + return _threshhold; + } + + +/// @notice this function does not mint to address 0 and prevents double minting by returning NFTclaimed boolean as true after execuion +/// @param tokenId is the NFT minted when an address reaches the threshhold + function _mintNFT(address _to, uint256 tokenId) internal override { + require(_to != address(0), "mint to zero address"); + require(_ownerOf[tokenId] == address(0), "already minted"); + require(NFTClaimed = false,"Already Claimed"); + require(funder[_to] >= _threshhold); + _balanceOf[_to]++; + _ownerOf[tokenId] = _to; + + NFTClaimed = true;//returns NFTclaimed boolean as true after execuion + + emit Transfer(address(0), _to, tokenId); + emit RewardReceived(_to, amount); + } + + +/// @notice this function enables the user to withdraw their contribution +/// @notice this function requires the amount withdrawable to be less than their contribution + function withrawal(address _to, uint _amount) public { + require(funder[_to] <= funder[_to], "amount withdrawable cannot exceed amount comitted"); + balanceOf[crowdFund] -= _amount; + balanceOf[_to] += _amount; + + emit TokenWithdrawn(_to, _amount); + } +} \ No newline at end of file