From 5872048c112b82ab79a215b6c36d0751a71e87e3 Mon Sep 17 00:00:00 2001 From: limitlxx Date: Wed, 7 Aug 2024 09:29:13 +0100 Subject: [PATCH 1/2] student registration and authorization --- contracts/IStudentRegistry.sol | 11 +++- contracts/MyStudentRegistry.sol | 12 +++-- contracts/Ownable.sol | 22 ++++++-- contracts/Student.sol | 2 + contracts/StudentRegistry.sol | 93 ++++++++++++++++++++++++++------- 5 files changed, 113 insertions(+), 27 deletions(-) diff --git a/contracts/IStudentRegistry.sol b/contracts/IStudentRegistry.sol index b87e8bbe..0c169528 100644 --- a/contracts/IStudentRegistry.sol +++ b/contracts/IStudentRegistry.sol @@ -7,11 +7,18 @@ interface IStudentRegistry { function addStudent( address _studentAddr, string memory _name, - uint8 _age - ) external; + uint8 _age, + uint256 _price + ) external payable; function getStudent(uint8 _studentID) external view returns (Student memory); function getStudentFromMapping(address _studentAddr) external view returns (Student memory); + function confirmAllStudents() external payable; + +} + +interface IOwnable{ + function getBalance() external view returns (uint256); } diff --git a/contracts/MyStudentRegistry.sol b/contracts/MyStudentRegistry.sol index 10562f12..f0b9123d 100644 --- a/contracts/MyStudentRegistry.sol +++ b/contracts/MyStudentRegistry.sol @@ -8,19 +8,23 @@ contract MyStudentRegistry is Ownable { address private StudentRegistryContractAddress; - constructor(address _studentRgistry){ - StudentRegistryContractAddress = _studentRgistry; + constructor(address _studentRegistry){ + StudentRegistryContractAddress = _studentRegistry; } function registerStudent( address _studentAddr, string memory _name, uint8 _age - ) public onlyOwner { + ) public payable { - IStudentRegistry(StudentRegistryContractAddress).addStudent(_studentAddr, _name, _age); + require(msg.value == 1 ether, "You need to send exactly 1 ether to register"); + IStudentRegistry(StudentRegistryContractAddress).addStudent{value: msg.value}(_studentAddr, _name, _age, msg.value); } + function confirmAllStudents() public payable { + IStudentRegistry(StudentRegistryContractAddress).confirmAllStudents(); + } function getStudent2( uint8 _studentId diff --git a/contracts/Ownable.sol b/contracts/Ownable.sol index 624bf251..097b734a 100644 --- a/contracts/Ownable.sol +++ b/contracts/Ownable.sol @@ -5,15 +5,17 @@ pragma solidity >=0.7.0 <0.9.0; contract Ownable { address private owner; + uint256 public fee; event ChangeOwner(address indexed oldOwner, address indexed newOwner); - constructor(){ - owner = msg.sender; + constructor() payable { + owner = payable (msg.sender); + fee = 1 ether; } - modifier onlyOwner { + modifier onlyOwner { require(owner == msg.sender, "Caller not owner"); _; } @@ -30,4 +32,18 @@ contract Ownable { emit ChangeOwner(owner, _newOwner); owner = _newOwner; } + + // Function to withdraw all Ether from this contract. + function withdraw() public payable onlyOwner { + // get the amount of Ether stored in this contract + uint256 amount = address(this).balance; + require(amount > 0, "No student has registered yet."); + + // send all Ether to owner + (bool success,) = owner.call{value: amount}(""); + require(success, "Failed to send Ether"); + } + + + } \ No newline at end of file diff --git a/contracts/Student.sol b/contracts/Student.sol index f7246ea0..5bc285bb 100644 --- a/contracts/Student.sol +++ b/contracts/Student.sol @@ -5,4 +5,6 @@ pragma solidity ^0.8.24; string name; uint256 studentId; uint8 age; + bool hasPaid; } + diff --git a/contracts/StudentRegistry.sol b/contracts/StudentRegistry.sol index 591618e1..a6721cfd 100644 --- a/contracts/StudentRegistry.sol +++ b/contracts/StudentRegistry.sol @@ -8,26 +8,40 @@ contract StudentRegistry is Ownable { //custom erros error NameIsEmpty(); error UnderAge(uint8 age, uint8 expectedAge); - - //custom data type - + event Log(address indexed sender, uint256 amount); + //custom data type //dynamic array of students - Student[] private students; + // Student[] private students; + + // Temporary register + Student[] public tempRegister; + mapping(address => Student) private tempStudentsMapping; - mapping(address => Student) public studentsMapping; + // Permanent register + Student[] public permanentRegister; + mapping(address => Student) private permanentStudentsMapping; + receive() external payable {} modifier isNotAddressZero() { require(msg.sender != address(0), "Invalid Address"); _; } + // Register Student - Required to pay 1 ether function addStudent( address _studentAddr, string memory _name, - uint8 _age - ) public isNotAddressZero { + uint8 _age, + uint256 _price + ) public payable isNotAddressZero { + // Ensure the student exists by checking if the studentAddr is not zero address + require(tempStudentsMapping[_studentAddr].studentAddr == address(0), "Student already exists."); + // Check the value sent with the transaction + require(msg.value == fee, "You need to pay exactly 1 ether"); + require(msg.value == _price, "Amount and Msg.Value doesn't match"); + if (bytes(_name).length == 0) { revert NameIsEmpty(); } @@ -36,17 +50,43 @@ contract StudentRegistry is Ownable { revert UnderAge({age: _age, expectedAge: 18}); } - uint256 _studentId = students.length + 1; + uint256 _studentId = tempRegister.length + 1; Student memory student = Student({ studentAddr: _studentAddr, name: _name, age: _age, - studentId: _studentId + studentId: _studentId, + hasPaid: true }); - students.push(student); - // add student to studentsMapping - studentsMapping[_studentAddr] = student; + // (bool sent,) = address(0).call{value: msg.value}(""); + // require(sent, "Failed to send Ether"); + + // Store the student in the temporary register and mapping + tempRegister.push(student); + tempStudentsMapping[_studentAddr] = student; + } + + + // Function to move all students from the temporary register to the permanent register + function confirmAllStudents() public payable onlyOwner { + // Loop through all students in the tempRegister + for (uint256 i = 0; i < tempRegister.length; i++) { + Student memory student = tempRegister[i]; + + // Add the student to the permanent register and mapping + permanentRegister.push(student); + permanentStudentsMapping[student.studentAddr] = student; + + // Remove the student from the temporary mapping + delete tempStudentsMapping[student.studentAddr]; + } + + // Clear the temporary register array + delete tempRegister; + + // Make withdrawal on confirm + return withdraw(); } function getStudent(uint8 _studentId) @@ -55,8 +95,8 @@ contract StudentRegistry is Ownable { isNotAddressZero returns (Student memory) { - return students[_studentId - 1]; - } + return permanentRegister[_studentId - 1]; + } function getStudentFromMapping(address _studentAddr) public @@ -64,7 +104,7 @@ contract StudentRegistry is Ownable { isNotAddressZero returns (Student memory) { - return studentsMapping[_studentAddr]; + return permanentStudentsMapping[_studentAddr]; } function deleteStudent(address _studentAddr) @@ -73,7 +113,7 @@ contract StudentRegistry is Ownable { isNotAddressZero { require( - studentsMapping[_studentAddr].studentAddr != address(0), + permanentStudentsMapping[_studentAddr].studentAddr != address(0), "Student does not exist" ); @@ -83,14 +123,31 @@ contract StudentRegistry is Ownable { studentAddr: address(0), name: "", age: 0, - studentId: 0 + studentId: 0, + hasPaid: false }); - studentsMapping[_studentAddr] = student; + permanentStudentsMapping[_studentAddr] = student; } function modifyOwner(address _newOwner) public { changeOwner(_newOwner); } + + function getBalance() public view returns (uint256) { + return address(this).balance; + } + + // Function to get the number of permanent registered students + function getPermanentTotalStudents() public view returns (uint256) { + return permanentRegister.length; + } + + // Function to get the number of temp registered students + function getTemperaryTotalStudents() public view returns (uint256) { + return tempRegister.length; + } + + } From a85ba663dee651c07732d60f033158dc490fe9dd Mon Sep 17 00:00:00 2001 From: limitlxx Date: Wed, 14 Aug 2024 07:48:59 +0100 Subject: [PATCH 2/2] Token security check --- .vscode/settings.json | 2 +- README.md | 2 +- contracts/ERC20.sol | 87 ++++++++++++++ contracts/ERC721.sol | 205 ++++++++++++++++++++++++++++++++ contracts/IERC20.sol | 18 +++ contracts/IStudentRegistry.sol | 24 ---- contracts/MyStudentRegistry.sol | 35 ------ contracts/Ownable.sol | 23 +--- contracts/ReentrancyGuard.sol | 20 ++++ contracts/Student.sol | 10 -- contracts/StudentRegistry.sol | 153 ------------------------ 11 files changed, 336 insertions(+), 243 deletions(-) create mode 100644 contracts/ERC20.sol create mode 100644 contracts/ERC721.sol create mode 100644 contracts/IERC20.sol delete mode 100644 contracts/IStudentRegistry.sol delete mode 100644 contracts/MyStudentRegistry.sol create mode 100644 contracts/ReentrancyGuard.sol delete mode 100644 contracts/Student.sol delete mode 100644 contracts/StudentRegistry.sol diff --git a/.vscode/settings.json b/.vscode/settings.json index bc1c7197..19035be5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,3 @@ { - "solidity.compileUsingRemoteVersion": "v0.8.14+commit.80d49f37" + "solidity.compileUsingRemoteVersion": "v0.8.24+commit.e11b9ed9" } \ No newline at end of file diff --git a/README.md b/README.md index e9100817..9fc1c82f 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,2 @@ # BlockHeaderWeb3 Cohort 5 -Introduction to the fundamentals of EVM-based smart contract development \ No newline at end of file +Introduction to the fundamentals of EVM-based smart contract development diff --git a/contracts/ERC20.sol b/contracts/ERC20.sol new file mode 100644 index 00000000..f39eb901 --- /dev/null +++ b/contracts/ERC20.sol @@ -0,0 +1,87 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "./IERC20.sol"; +import "./Ownable.sol"; +import "./ReentrancyGuard.sol"; + +contract ERC20 is IERC20, Ownable, ReentrancyGuard { + event Transfer(address indexed from, address indexed to, uint256 value); + event Approval( + address indexed owner, address indexed spender, uint256 value + ); + + // Proper Events for burn and mint functions + event Mint(address indexed to, uint256 value); + event Burn(address indexed from, uint256 value); + + uint256 public totalSupply; + string public name; + string public symbol; + + // decimal state was missing + uint8 public decimals; + + mapping(address => uint256) public balanceOf; + mapping(address => mapping(address => uint256)) public allowance; + + constructor(string memory _name, string memory _symbol, uint8 _decimals) { + name = _name; + symbol = _symbol; + decimals = _decimals; + } + + function transfer(address recipient, uint256 amount) + external + nonReentrant // Added Reentrancy Guard modifier + returns (bool) + { + require(balanceOf[msg.sender] >= amount, "Insufficient balance"); // Check if there is enough balance to go through + balanceOf[msg.sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(msg.sender, recipient, amount); + + return true; + } + + function approve(address spender, uint256 amount) external onlyOwner returns (bool) { // Only owner can approve spender + allowance[msg.sender][spender] = amount; + emit Approval(msg.sender, spender, amount); + return true; + } + + function transferFrom(address sender, address recipient, uint256 amount) + external + nonReentrant + returns (bool) + { + require(balanceOf[sender] >= amount, "Insufficient balance"); // Check if sender has enough balance to go through + require(allowance[sender][msg.sender] >= amount, "Allowance exceeded"); // Check if address has enough allocation + + allowance[sender][msg.sender] -= amount; + balanceOf[sender] -= amount; + balanceOf[recipient] += amount; + emit Transfer(sender, recipient, amount); + return true; + } + + function _mint(address to, uint256 amount) internal onlyOwner { // Only owner can mint tokens + balanceOf[to] += amount; + totalSupply += amount; + emit Mint(to, amount); // proper log mint action + } + + function _burn(address from, uint256 amount) internal onlyOwner { // Only owner can burn tokens + balanceOf[from] -= amount; + totalSupply -= amount; + emit Burn(from, amount); // proper log burn action + } + + 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/contracts/ERC721.sol b/contracts/ERC721.sol new file mode 100644 index 00000000..da0c2ccf --- /dev/null +++ b/contracts/ERC721.sol @@ -0,0 +1,205 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +import "./Ownable.sol"; +import "./ReentrancyGuard.sol"; + +interface IERC165 { + function supportsInterface(bytes4 interfaceID) + external + view + returns (bool); +} + +interface IERC721 is IERC165 { + function balanceOf(address owner) external view returns (uint256 balance); + function ownerOf(uint256 tokenId) external view returns (address owner); + function safeTransferFrom(address from, address to, uint256 tokenId) + external; + function safeTransferFrom( + address from, + address to, + uint256 tokenId, + bytes calldata data + ) external; + function transferFrom(address from, address to, uint256 tokenId) external; + function approve(address to, uint256 tokenId) external; + function getApproved(uint256 tokenId) + external + view + returns (address operator); + function setApprovalForAll(address operator, bool _approved) external; + function isApprovedForAll(address owner, address operator) + external + view + returns (bool); +} + +interface IERC721Receiver { + function onERC721Received( + address operator, + address from, + uint256 tokenId, + bytes calldata data + ) external returns (bytes4); +} + +contract ERC721 is IERC721, ReentrancyGuard, Ownable { + event Transfer( + address indexed from, address indexed to, uint256 indexed id + ); + event Approval( + address indexed owner, address indexed spender, uint256 indexed id + ); + event ApprovalForAll( + address indexed owner, address indexed operator, bool approved + ); + + // Proper event for MINT/BURN + event Mint( + address indexed to, uint256 indexed id + ); + + event Burn( + address indexed owner, uint256 indexed id + ); + + // Mapping from token ID to owner address + mapping(uint256 => address) internal _ownerOf; + + // Mapping owner address to token count + mapping(address => uint256) internal _balanceOf; + + // Mapping from token ID to approved address + mapping(uint256 => address) internal _approvals; + + // Mapping from owner to operator approvals + mapping(address => mapping(address => bool)) public isApprovedForAll; + + function supportsInterface(bytes4 interfaceId) + external + pure + returns (bool) + { + return interfaceId == type(IERC721).interfaceId + || interfaceId == type(IERC165).interfaceId; + } + + function ownerOf(uint256 id) external view returns (address owner) { + owner = _ownerOf[id]; + require(owner != address(0), "token doesn't exist"); + } + + function balanceOf(address owner) external view returns (uint256) { + require(owner != address(0), "owner = zero address"); + return _balanceOf[owner]; + } + + function setApprovalForAll(address operator, bool approved) external { + isApprovedForAll[msg.sender][operator] = approved; + emit ApprovalForAll(msg.sender, operator, approved); + } + + function approve(address spender, uint256 id) external onlyOwner { + address owner = _ownerOf[id]; + require( + msg.sender == owner || isApprovedForAll[owner][msg.sender], + "not authorized" + ); + + _approvals[id] = spender; + + emit Approval(owner, spender, id); + } + + function getApproved(uint256 id) external view returns (address) { + require(_ownerOf[id] != address(0), "token doesn't exist"); + return _approvals[id]; + } + + function _isApprovedOrOwner(address owner, address spender, uint256 id) + internal + view + returns (bool) + { + return ( + spender == owner || isApprovedForAll[owner][spender] + || spender == _approvals[id] + ); + } + + function transferFrom(address from, address to, uint256 id) public { + require(from == _ownerOf[id], "from != owner"); + require(to != address(0), "transfer to zero address"); + + require(_isApprovedOrOwner(from, msg.sender, id), "not authorized"); + + _balanceOf[from]--; + _balanceOf[to]++; + _ownerOf[id] = to; + + delete _approvals[id]; + + emit Transfer(from, to, id); + } + + function safeTransferFrom(address from, address to, uint256 id) external nonReentrant { // Reentrancy Guard added + transferFrom(from, to, id); + + require( + to.code.length == 0 + || IERC721Receiver(to).onERC721Received(msg.sender, from, id, "") + == IERC721Receiver.onERC721Received.selector, + "unsafe recipient" + ); + } + + function safeTransferFrom( + address from, + address to, + uint256 id, + bytes calldata data + ) external nonReentrant { // Reentrancy Guard added + transferFrom(from, to, id); + + require( + to.code.length == 0 + || IERC721Receiver(to).onERC721Received(msg.sender, from, id, data) + == IERC721Receiver.onERC721Received.selector, + "unsafe recipient" + ); + } + + function _mint(address to, uint256 id) internal nonReentrant { // Reentrancy Guard added + require(to != address(0), "mint to zero address"); + require(_ownerOf[id] == address(0), "already minted"); + + _balanceOf[to]++; + _ownerOf[id] = to; + + emit Mint(to, id); // Proper event for Mint + } + + function _burn(uint256 id) internal nonReentrant { // Reentrancy Guard added + address owner = _ownerOf[id]; + require(owner != address(0), "not minted"); + + _balanceOf[owner] -= 1; + + delete _ownerOf[id]; + delete _approvals[id]; + + emit Burn(owner, id); + } +} + +contract MyNFT is ERC721 { + function mint(address to, uint256 id) external onlyOwner { // Can only be called by contract owner + _mint(to, id); + } + + function burn(uint256 id) external onlyOwner { // Can only be called by contract owner + require(msg.sender == _ownerOf[id], "not owner"); + _burn(id); + } +} \ No newline at end of file diff --git a/contracts/IERC20.sol b/contracts/IERC20.sol new file mode 100644 index 00000000..d3a2c35c --- /dev/null +++ b/contracts/IERC20.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +interface IERC20 { + function totalSupply() external view returns (uint256); + function balanceOf(address account) external view returns (uint256); + function transfer(address recipient, uint256 amount) + external + returns (bool); + function allowance(address owner, address spender) + external + view + returns (uint256); + function approve(address spender, uint256 amount) external returns (bool); + function transferFrom(address sender, address recipient, uint256 amount) + external + returns (bool); +} \ No newline at end of file diff --git a/contracts/IStudentRegistry.sol b/contracts/IStudentRegistry.sol deleted file mode 100644 index 0c169528..00000000 --- a/contracts/IStudentRegistry.sol +++ /dev/null @@ -1,24 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; -import "./Student.sol"; -interface IStudentRegistry { - - - function addStudent( - address _studentAddr, - string memory _name, - uint8 _age, - uint256 _price - ) external payable; - - function getStudent(uint8 _studentID) external view returns (Student memory); - - function getStudentFromMapping(address _studentAddr) external view returns (Student memory); - - function confirmAllStudents() external payable; - -} - -interface IOwnable{ - function getBalance() external view returns (uint256); -} diff --git a/contracts/MyStudentRegistry.sol b/contracts/MyStudentRegistry.sol deleted file mode 100644 index f0b9123d..00000000 --- a/contracts/MyStudentRegistry.sol +++ /dev/null @@ -1,35 +0,0 @@ -// SPDX-License-Identifier: GPL-3.0 -pragma solidity >=0.7.0 <0.9.0; -import "./IStudentRegistry.sol"; -import "./Student.sol"; -import "./Ownable.sol"; - -contract MyStudentRegistry is Ownable { - - address private StudentRegistryContractAddress; - - constructor(address _studentRegistry){ - StudentRegistryContractAddress = _studentRegistry; - } - - function registerStudent( - address _studentAddr, - string memory _name, - uint8 _age - ) public payable { - - require(msg.value == 1 ether, "You need to send exactly 1 ether to register"); - IStudentRegistry(StudentRegistryContractAddress).addStudent{value: msg.value}(_studentAddr, _name, _age, msg.value); - } - - function confirmAllStudents() public payable { - IStudentRegistry(StudentRegistryContractAddress).confirmAllStudents(); - } - - function getStudent2( - uint8 _studentId - ) public view returns (Student memory) { - - return IStudentRegistry(StudentRegistryContractAddress).getStudent(_studentId); - } -} diff --git a/contracts/Ownable.sol b/contracts/Ownable.sol index 097b734a..d12386cd 100644 --- a/contracts/Ownable.sol +++ b/contracts/Ownable.sol @@ -5,21 +5,18 @@ pragma solidity >=0.7.0 <0.9.0; contract Ownable { address private owner; - uint256 public fee; event ChangeOwner(address indexed oldOwner, address indexed newOwner); - constructor() payable { - owner = payable (msg.sender); - fee = 1 ether; - } - - modifier onlyOwner { require(owner == msg.sender, "Caller not owner"); _; } + constructor() payable { + owner = payable (msg.sender); + } + function getOwner() public view returns (address){ return owner; @@ -32,18 +29,6 @@ contract Ownable { emit ChangeOwner(owner, _newOwner); owner = _newOwner; } - - // Function to withdraw all Ether from this contract. - function withdraw() public payable onlyOwner { - // get the amount of Ether stored in this contract - uint256 amount = address(this).balance; - require(amount > 0, "No student has registered yet."); - - // send all Ether to owner - (bool success,) = owner.call{value: amount}(""); - require(success, "Failed to send Ether"); - } - } \ No newline at end of file diff --git a/contracts/ReentrancyGuard.sol b/contracts/ReentrancyGuard.sol new file mode 100644 index 00000000..38e716f0 --- /dev/null +++ b/contracts/ReentrancyGuard.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.24; + +contract ReentrancyGuard { + uint256 private constant UNLOCKED = 1; + uint256 private constant LOCKED = 2; + uint256 private _status; + + constructor() { + _status = UNLOCKED; + } + + modifier nonReentrant() { + require(_status != LOCKED, "Kindly wait a bit!"); + _status = LOCKED; + _; + _status = UNLOCKED; + } + +} \ No newline at end of file diff --git a/contracts/Student.sol b/contracts/Student.sol deleted file mode 100644 index 5bc285bb..00000000 --- a/contracts/Student.sol +++ /dev/null @@ -1,10 +0,0 @@ - // SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; - struct Student { - address studentAddr; - string name; - uint256 studentId; - uint8 age; - bool hasPaid; - } - diff --git a/contracts/StudentRegistry.sol b/contracts/StudentRegistry.sol deleted file mode 100644 index a6721cfd..00000000 --- a/contracts/StudentRegistry.sol +++ /dev/null @@ -1,153 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.24; -import "./Ownable.sol"; -import "./Student.sol"; - - -contract StudentRegistry is Ownable { - //custom erros - error NameIsEmpty(); - error UnderAge(uint8 age, uint8 expectedAge); - event Log(address indexed sender, uint256 amount); - //custom data type - - //dynamic array of students - // Student[] private students; - - // Temporary register - Student[] public tempRegister; - mapping(address => Student) private tempStudentsMapping; - - // Permanent register - Student[] public permanentRegister; - mapping(address => Student) private permanentStudentsMapping; - - receive() external payable {} - - modifier isNotAddressZero() { - require(msg.sender != address(0), "Invalid Address"); - _; - } - - // Register Student - Required to pay 1 ether - function addStudent( - address _studentAddr, - string memory _name, - uint8 _age, - uint256 _price - ) public payable isNotAddressZero { - // Ensure the student exists by checking if the studentAddr is not zero address - require(tempStudentsMapping[_studentAddr].studentAddr == address(0), "Student already exists."); - // Check the value sent with the transaction - require(msg.value == fee, "You need to pay exactly 1 ether"); - require(msg.value == _price, "Amount and Msg.Value doesn't match"); - - if (bytes(_name).length == 0) { - revert NameIsEmpty(); - } - - if (_age < 18) { - revert UnderAge({age: _age, expectedAge: 18}); - } - - uint256 _studentId = tempRegister.length + 1; - Student memory student = Student({ - studentAddr: _studentAddr, - name: _name, - age: _age, - studentId: _studentId, - hasPaid: true - }); - - // (bool sent,) = address(0).call{value: msg.value}(""); - // require(sent, "Failed to send Ether"); - - // Store the student in the temporary register and mapping - tempRegister.push(student); - tempStudentsMapping[_studentAddr] = student; - } - - - // Function to move all students from the temporary register to the permanent register - function confirmAllStudents() public payable onlyOwner { - // Loop through all students in the tempRegister - for (uint256 i = 0; i < tempRegister.length; i++) { - Student memory student = tempRegister[i]; - - // Add the student to the permanent register and mapping - permanentRegister.push(student); - permanentStudentsMapping[student.studentAddr] = student; - - // Remove the student from the temporary mapping - delete tempStudentsMapping[student.studentAddr]; - } - - // Clear the temporary register array - delete tempRegister; - - // Make withdrawal on confirm - return withdraw(); - } - - function getStudent(uint8 _studentId) - public - view - isNotAddressZero - returns (Student memory) - { - return permanentRegister[_studentId - 1]; - } - - function getStudentFromMapping(address _studentAddr) - public - view - isNotAddressZero - returns (Student memory) - { - return permanentStudentsMapping[_studentAddr]; - } - - function deleteStudent(address _studentAddr) - public - onlyOwner - isNotAddressZero - { - require( - permanentStudentsMapping[_studentAddr].studentAddr != address(0), - "Student does not exist" - ); - - // delete studentsMapping[_studentAddr]; - - Student memory student = Student({ - studentAddr: address(0), - name: "", - age: 0, - studentId: 0, - hasPaid: false - }); - - permanentStudentsMapping[_studentAddr] = student; - } - - - function modifyOwner(address _newOwner) public { - changeOwner(_newOwner); - } - - function getBalance() public view returns (uint256) { - return address(this).balance; - } - - // Function to get the number of permanent registered students - function getPermanentTotalStudents() public view returns (uint256) { - return permanentRegister.length; - } - - // Function to get the number of temp registered students - function getTemperaryTotalStudents() public view returns (uint256) { - return tempRegister.length; - } - - -}