diff --git a/contracts/Number.Registry.sol b/contracts/Number.Registry.sol new file mode 100644 index 00000000..9eb8c3d5 --- /dev/null +++ b/contracts/Number.Registry.sol @@ -0,0 +1,129 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +contract StudentRegistry { + // Enum for attendance status + enum Attendance { Absent, Present } + + // Struct to represent a student + struct Student { + string name; + Attendance attendance; + string[] interests; + } + + // Mapping to store students by their address + mapping(address => Student) public students; + + // Event emitted when a student is registered + event StudentCreated(address indexed studentAddress, string name); + + // Event emitted when attendance is marked + event AttendanceStatus(address indexed studentAddress, Attendance attendance); + + // Event emitted when an interest is added + event InterestAdded(address indexed studentAddress, string interest); + + // Event emitted when an interest is removed + event InterestRemoved(address indexed studentAddress, string interest); + + // Modifier to ensure only registered students can perform actions + modifier onlyRegisteredStudent(address _address) { + require(bytes(students[_address].name).length > 0, "Student not registered"); + _; + } + + // Modifier to ensure only the owner can perform certain actions + address public owner; + modifier onlyOwner() { + require(msg.sender == owner, "Only the owner can perform this action"); + _; + } + + // Constructor to set the contract owner + constructor() { + owner = msg.sender; + } + + // Function to register a new student + function registerNewStudent(string memory _name) public { + require(bytes(_name).length > 0, "Name cannot be empty"); + require(bytes(students[msg.sender].name).length == 0, "Student already registered"); + + // Initialize the student struct + students[msg.sender] = Student({ + name: _name, + attendance: Attendance.Absent, + interests: new string[](0) + }); + + emit StudentCreated(msg.sender, _name); + } + + // Function to mark attendance + function markAttendance(address _address, Attendance _attendance) public onlyRegisteredStudent(_address) { + students[_address].attendance = _attendance; + emit AttendanceStatus(_address, _attendance); + } + + // Function to add an interest + function addInterest(address _address, string memory _interest) public onlyRegisteredStudent(_address) { + require(bytes(_interest).length > 0, "Interest cannot be empty"); + require(students[_address].interests.length <= 5, "Maximum of 5 interests allowed"); + + // Check for duplicate interests + for (uint i = 0; i < students[_address].interests.length; i++) { + require( + keccak256(bytes(students[_address].interests[i])) != keccak256(bytes(_interest)), + "Interest already exists" + ); + } + + students[_address].interests.push(_interest); + emit InterestAdded(_address, _interest); + } + + // Function to remove an interest + function removeInterest(address _address, string memory _interest) public onlyRegisteredStudent(_address) { + string[] storage interests = students[_address].interests; + bool interestFound = false; + + for (uint i = 0; i < interests.length; i++) { + if (keccak256(bytes(interests[i])) == keccak256(bytes(_interest))) { + // Swap with the last element and pop + interests[i] = interests[interests.length - 1]; + interests.pop(); + interestFound = true; + emit InterestRemoved(_address, _interest); + break; + } + } + + require(interestFound, "Interest not found"); + } + + // Getter functions + function getStudentName(address _address) public view onlyRegisteredStudent(_address) returns (string memory) { + return students[_address].name; + } + + function getStudentAttendance(address _address) public view onlyRegisteredStudent(_address) returns (Attendance) { + return students[_address].attendance; + } + + function getStudentInterests(address _address) public view onlyRegisteredStudent(_address) returns (string[] memory) { + return students[_address].interests; + } + + // Ownership management + function transferOwnership(address _newOwner) public onlyOwner { + require(_newOwner != address(0), "Invalid address"); + owner = _newOwner; + } + + // Bonus: Allow a student to update their name + function updateStudentName(string memory _newName) public onlyRegisteredStudent(msg.sender) { + require(bytes(_newName).length > 0, "Name cannot be empty"); + students[msg.sender].name = _newName; + } +} \ No newline at end of file diff --git a/contracts/Number.counter.sol b/contracts/Number.counter.sol new file mode 100644 index 00000000..1a33caf8 --- /dev/null +++ b/contracts/Number.counter.sol @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +/// @title Counter Contract +/// @notice This contract manages a simple numerical counter with functions to increase, decrease, and reset the counter. +/// @dev Prevents overflow and underflow with require statements. +contract Counter { + /// @notice The current value of the counter. + uint public count; +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.24; + +/// @title Counter Contract +/// @notice This contract manages a simple numerical counter with functions to increase, decrease, and reset the counter. +/// @dev Prevents overflow and underflow with require statements. +contract Counter { + /// @notice The current value of the counter. + uint public count; + + /// @notice Emitted when the count is increased. + /// @param amount The new value of the counter after the increase. + /// @param when The timestamp of the increase. + event CountIncreased(uint amount, uint256 when); + + /// @notice Emitted when the count is decreased. + /// @param amount The new value of the counter after the decrease. + /// @param when The timestamp of the decrease. + event CountDecreased(uint amount, uint256 when); + + /// @notice Increases the counter by one. + /// @dev Prevents overflow using require. + function increaseByOne() public { + require(count < type(uint).max, "cannot increase beyond max uint"); + count++; + emit CountIncreased(count, block.timestamp); + } + + /// @notice Increases the counter by a given value. + /// @dev Prevents overflow by checking if count + _value exceeds type(uint).max. + /// @param _value The amount to increase the counter by. + function increaseByValue(uint _value) public { + require(count <= type(uint).max - _value, "cannot increase beyond max uint"); + count += _value; + emit CountIncreased(count, block.timestamp); + } + + /// @notice Decreases the counter by one. + /// @dev Prevents underflow by ensuring count is greater than 0. + function decreaseByOne() public { + require(count > 0, "cannot decrease below 0"); + count--; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Decreases the counter by a given value. + /// @dev Prevents underflow by ensuring count is greater than or equal to _value. + /// @param _value The amount to decrease the counter by. + function decreaseByValue(uint _value) public { + require(count >= _value, "cannot decrease below 0"); + count -= _value; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Resets the counter to zero. + /// @dev Emits a `CountDecreased` event with the new count value (0). + function resetCount() public { + count = 0; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Returns the current value of the counter. + /// @return The current value of the counter. + function getCount() public view returns (uint) { + return count; + } + + /// @notice Returns the maximum value of a uint256. + /// @dev Uses an unchecked block to return the max uint256 value. + /// @return The maximum value of a uint256. + function getMaxUint256() public pure returns (uint) { + unchecked { + return type(uint256).max; + } + } +} + + /// @notice Emitted when the count is increased. + /// @param amount The new value of the counter after the increase. + /// @param when The timestamp of the increase. + event CountIncreased(uint amount, uint256 when); + + /// @notice Emitted when the count is decreased. + /// @param amount The new value of the counter after the decrease. + /// @param when The timestamp of the decrease. + event CountDecreased(uint amount, uint256 when); + + /// @notice Increases the counter by one. + /// @dev Prevents overflow using require. + function increaseByOne() public { + require(count < type(uint).max, "cannot increase beyond max uint"); + count++; + emit CountIncreased(count, block.timestamp); + } + + /// @notice Increases the counter by a given value. + /// @dev Prevents overflow by checking if count + _value exceeds type(uint).max. + /// @param _value The amount to increase the counter by. + function increaseByValue(uint _value) public { + require(count <= type(uint).max - _value, "cannot increase beyond max uint"); + count += _value; + emit CountIncreased(count, block.timestamp); + } + + /// @notice Decreases the counter by one. + /// @dev Prevents underflow by ensuring count is greater than 0. + function decreaseByOne() public { + require(count > 0, "cannot decrease below 0"); + count--; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Decreases the counter by a given value. + /// @dev Prevents underflow by ensuring count is greater than or equal to _value. + /// @param _value The amount to decrease the counter by. + function decreaseByValue(uint _value) public { + require(count >= _value, "cannot decrease below 0"); + count -= _value; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Resets the counter to zero. + /// @dev Emits a `CountDecreased` event with the new count value (0). + function resetCount() public { + count = 0; + emit CountDecreased(count, block.timestamp); + } + + /// @notice Returns the current value of the counter. + /// @return The current value of the counter. + function getCount() public view returns (uint) { + return count; + } + + /// @notice Returns the maximum value of a uint256. + /// @dev Uses an unchecked block to return the max uint256 value. + /// @return The maximum value of a uint256. + function getMaxUint256() public pure returns (uint) { + unchecked { + return type(uint256).max; + } + } +} \ No newline at end of file