diff --git a/contracts/Ownable.sol b/contracts/Ownable.sol index 624bf251..382a2046 100644 --- a/contracts/Ownable.sol +++ b/contracts/Ownable.sol @@ -2,32 +2,32 @@ pragma solidity >=0.7.0 <0.9.0; -contract Ownable { +contract Ownable{ - address private owner; + address payable internal owner; - event ChangeOwner(address indexed oldOwner, address indexed newOwner); + event ChangeOwner(address indexed oldOwner, address indexed newOwner); - constructor(){ - owner = msg.sender; + constructor() payable { + owner = payable(msg.sender); } - modifier onlyOwner { + modifier onlyOwner(){ require(owner == msg.sender, "Caller not owner"); _; } + - - function getOwner() public view returns (address){ + function getOwner() public view returns (address) { return owner; } - function changeOwner(address _newOwner) internal onlyOwner { - require(_newOwner != address(0), "Owner can not be address zero"); - + function changeOwner(address payable _newOwner) internal onlyOwner { + require(_newOwner != address(0), "Owner cannot be address zero"); + emit ChangeOwner(owner, _newOwner); owner = _newOwner; } -} \ No newline at end of file +} diff --git a/contracts/Student.sol b/contracts/Student.sol index f7246ea0..471af1e2 100644 --- a/contracts/Student.sol +++ b/contracts/Student.sol @@ -1,8 +1,9 @@ - // SPDX-License-Identifier: MIT +// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; - struct Student { - address studentAddr; - string name; - uint256 studentId; - uint8 age; - } +struct Student { + address studentAddr; + uint256 studentID; + string name; + uint8 age; + bool hasPaid; +} diff --git a/contracts/StudentRegistry.sol b/contracts/StudentRegistry.sol index 591618e1..ff84b639 100644 --- a/contracts/StudentRegistry.sol +++ b/contracts/StudentRegistry.sol @@ -3,94 +3,110 @@ pragma solidity ^0.8.24; import "./Ownable.sol"; import "./Student.sol"; - contract StudentRegistry is Ownable { - //custom erros + + // custom error error NameIsEmpty(); - error UnderAge(uint8 age, uint8 expectedAge); + error UnderAge(uint8 age, uint8 expectedAge); - //custom data type - - - //dynamic array of students - Student[] private students; + // Dynamic array of student + Student[] private studentsThatPaid; - mapping(address => Student) public studentsMapping; + Student[] private authorizedStudents; + mapping(address => Student) public studentMapping; - modifier isNotAddressZero() { + mapping(address => uint256) public receipt; + + modifier isNotAddressZero () { require(msg.sender != address(0), "Invalid Address"); _; } - function addStudent( - address _studentAddr, - string memory _name, + // Events + event StudentAdded(address indexed studentAddress, uint256 studentId, string name); + event StudentDeleted(address indexed studentAddress, uint256 studentId, string name); + + function registerStudent( + address _studentAddr, + string memory _name, uint8 _age - ) public isNotAddressZero { - if (bytes(_name).length == 0) { + ) public payable { + uint256 registrationFee = msg.value; + + require(receipt[_studentAddr] == 0, "Already Registered"); + require(registrationFee == 1 ether, "Incorrect Registration Fee"); + + if(bytes(_name).length == 0){ revert NameIsEmpty(); } - if (_age < 18) { - revert UnderAge({age: _age, expectedAge: 18}); + revert UnderAge({ age: _age, expectedAge: 18 }); } - uint256 _studentId = students.length + 1; Student memory student = Student({ studentAddr: _studentAddr, name: _name, age: _age, - studentId: _studentId + studentID: 0, + hasPaid: true }); + + studentMapping[_studentAddr] = student; - students.push(student); - // add student to studentsMapping - studentsMapping[_studentAddr] = student; - } + (bool success, ) = address(this).call{value: registrationFee}(""); + require(success, "Failed to send payment"); - function getStudent(uint8 _studentId) - public - view - isNotAddressZero - returns (Student memory) - { - return students[_studentId - 1]; + receipt[_studentAddr] = registrationFee; + + studentsThatPaid.push(student); } - function getStudentFromMapping(address _studentAddr) - public - view - isNotAddressZero - returns (Student memory) - { - return studentsMapping[_studentAddr]; + function studentPaymentStatus (address _studentAddr) public view returns (bool) { + return studentMapping[_studentAddr].hasPaid; } - function deleteStudent(address _studentAddr) - public - onlyOwner - isNotAddressZero - { - require( - studentsMapping[_studentAddr].studentAddr != address(0), - "Student does not exist" - ); + function studentsWhoPaid() public view onlyOwner returns (Student[] memory) { + return studentsThatPaid; + } - // delete studentsMapping[_studentAddr]; + function getAuthorizedStudents() public view onlyOwner returns (Student[] memory) { + return authorizedStudents; + } - Student memory student = Student({ - studentAddr: address(0), - name: "", - age: 0, - studentId: 0 + function authorizeStudentRegistration(address _studentAddr) private onlyOwner isNotAddressZero { + require(studentMapping[_studentAddr].studentID == 0, "Student has Already been authorized"); + require(studentMapping[_studentAddr].hasPaid == true, "Fees have not been paid"); + + uint256 _studentID = authorizedStudents.length + 1; + Student memory _student = Student({ + studentAddr: studentMapping[_studentAddr].studentAddr, + name: studentMapping[_studentAddr].name, + age: studentMapping[_studentAddr].age, + hasPaid: studentMapping[_studentAddr].hasPaid, + studentID: _studentID }); - studentsMapping[_studentAddr] = student; - } + authorizedStudents.push(_student); + //add student to studentMapping + studentMapping[_studentAddr] = _student; + //emit + emit StudentAdded(_studentAddr, _studentID, _student.name); + } + + + function withdraw() public { + uint256 amount = address(this).balance; + require(amount > 0, "No Funds"); + require(msg.sender == owner, "Only the owner can withdraw"); + (bool success, ) = owner.call{value: amount}(""); + require(success, "Failed to withdraw ETH"); + } - function modifyOwner(address _newOwner) public { + function modifyOwner(address payable _newOwner) public { changeOwner(_newOwner); } -} + + receive() external payable {} +} \ No newline at end of file