Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions assignments/fatiudeen/Counter.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/// @title Counter Contract
/// @notice A simple contract that implements a counter with increase, decrease and reset functionality
contract Counter {
/// @notice The current value of the counter
uint public count;

/// @notice Emitted when the counter value is increased
/// @param amount The new value of the counter
/// @param when The timestamp when the increase occurred
event CountIncreased(uint amount, uint when);

/// @notice Emitted when the counter value is decreased
/// @param amount The new value of the counter
/// @param when The timestamp when the decrease occurred
event CountDecreased(uint amount, uint when);

/// @notice Increases the counter by one
/// @dev Reverts if the operation would cause an overflow
function increaseByOne() public {
require(count < type(uint).max, "cannot increase beyond max uint");
count += 1;
emit CountIncreased(count, block.timestamp);
}

/// @notice Increases the counter by a specified value
/// @param _value The amount to increase the counter by
/// @dev Reverts if the operation would cause an overflow
function increaseByValue(uint _value) public {
require(count + _value <= type(uint).max, "cannot increase beyond max uint");
count += _value;
emit CountIncreased(count, block.timestamp);
}

/// @notice Decreases the counter by one
/// @dev Reverts if the operation would cause an underflow
function decreaseByOne() public {
require(count > 0, "cannot decrease below 0");
count -= 1;
emit CountDecreased(count, block.timestamp);
}

/// @notice Decreases the counter by a specified value
/// @param _value The amount to decrease the counter by
/// @dev Reverts if the operation would cause an underflow
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
function resetCount() public {
uint oldCount = count;
if (oldCount != 0) {
count = 0;
emit CountDecreased(count, block.timestamp);
}
}

/// @notice Returns the current value of the counter
/// @return The current counter value
function getCount() public view returns (uint) {
return count;
}

/// @notice Returns the maximum value of uint256
/// @return The maximum value that can be stored in a uint256
/// @dev Uses unchecked arithmetic to intentionally underflow and get max uint
function getMaxUint256() public pure returns (uint) {
uint max;
unchecked {
max = 0 - 1;
}
return max;
}
}
179 changes: 179 additions & 0 deletions assignments/fatiudeen/StudentRegistry.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.24;

/// @title Student Registry Contract
/// @notice A contract for managing student information, attendance, and interests
contract StudentRegistry {
/// @notice Possible attendance statuses
enum Attendance { Present, Absent }

/// @notice Structure to store student information
struct Student {
string name;
Attendance attendance;
string[] interests;
}

/// @notice Maps student addresses to their information
mapping(address => Student) public students;

/// @notice Contract owner address
address public owner;

/// @notice Emitted when a new student is registered
event StudentCreated(address _studentAddress, string _name);
/// @notice Emitted when attendance is updated
event AttendanceStatus(address _studentAddress, Attendance _attendance);
/// @notice Emitted when an interest is added
event InterestAdded(address _studentAddress, string _interest);
/// @notice Emitted when an interest is removed
event InterestRemoved(address _studentAddress, string _interest);

/// @notice Ensures only the owner can call certain functions
modifier onlyOwner() {
require(msg.sender == owner, "Only owner can call this function");
_;
}

/// @notice Ensures the student exists
modifier studentExists(address _address) {
require(bytes(students[_address].name).length > 0, "Student does not exist");
_;
}

/// @notice Ensures the student does not exist
modifier studentDoesNotExist(address _address) {
require(bytes(students[_address].name).length == 0, "Student already exists");
_;
}

/// @notice Sets the contract deployer as the owner
constructor() {
owner = msg.sender;
}

/// @notice Registers a new student with full information
function registerStudent(
string memory _name,
Attendance _attendance,
string[] memory _interests
) public studentDoesNotExist(msg.sender) {
require(bytes(_name).length > 0, "Name cannot be empty");
require(_interests.length <= 5, "Maximum 5 interests allowed");

students[msg.sender] = Student({
name: _name,
attendance: _attendance,
interests: _interests
});

emit StudentCreated(msg.sender, _name);
}

/// @notice Registers a new student with just a name
function registerNewStudent(string memory _name) public studentDoesNotExist(msg.sender) {
require(bytes(_name).length > 0, "Name cannot be empty");

students[msg.sender] = Student({
name: _name,
attendance: Attendance.Absent,
interests: new string[](0)
});

emit StudentCreated(msg.sender, _name);
}

/// @notice Updates a student's attendance
function markAttendance(address _address, Attendance _attendance)
public
onlyOwner
studentExists(_address)
{
students[_address].attendance = _attendance;
emit AttendanceStatus(_address, _attendance);
}

/// @notice Adds an interest to a student's profile
function addInterest(address _address, string memory _interest)
public
studentExists(_address)
{
require(bytes(_interest).length > 0, "Interest cannot be empty");
require(students[_address].interests.length < 5, "Maximum 5 interests allowed");

// Check for duplicates
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);
}

/// @notice Removes an interest from a student's profile
function removeInterest(address _address, string memory _interest)
public
studentExists(_address)
{
string[] storage interests = students[_address].interests;
bool found = false;
uint indexToRemove;

for(uint i = 0; i < interests.length; i++) {
if(keccak256(bytes(interests[i])) == keccak256(bytes(_interest))) {
indexToRemove = i;
found = true;
break;
}
}

require(found, "Interest not found");

// Move the last element to the position of the element to remove
if(indexToRemove != interests.length - 1) {
interests[indexToRemove] = interests[interests.length - 1];
}
interests.pop();

emit InterestRemoved(_address, _interest);
}

/// @notice Gets a student's name
function getStudentName(address _address)
public
view
studentExists(_address)
returns (string memory)
{
return students[_address].name;
}

/// @notice Gets a student's attendance
function getStudentAttendance(address _address)
public
view
studentExists(_address)
returns (Attendance)
{
return students[_address].attendance;
}

/// @notice Gets a student's interests
function getStudentInterests(address _address)
public
view
studentExists(_address)
returns (string[] memory)
{
return students[_address].interests;
}

/// @notice Transfers ownership of the contract
function transferOwnership(address _newOwner) public onlyOwner {
require(_newOwner != address(0), "New owner cannot be zero address");
owner = _newOwner;
}
}
3 changes: 0 additions & 3 deletions submissions/Assignment3/README.md

This file was deleted.

12 changes: 12 additions & 0 deletions submissions/assignment-1.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Assignment 1 Submission

The implementation of the Counter Contract can be found at:
[Counter.sol](../../../assignments/fatiudeen/Counter.sol)

This implementation includes:
- Complete counter functionality with increase/decrease operations
- Overflow and underflow protection
- Event emission for all counter changes
- Comprehensive error handling
- Clear NatSpec documentation
- Pure function for max uint256 calculation
12 changes: 12 additions & 0 deletions submissions/assignment-2.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Assignment 2 Submission

The implementation of the Student Registry can be found at:
[StudentRegistry.sol](../../../assignments/fatiudeen/StudentRegistry.sol)

This implementation includes:
- Full student registration system
- Attendance tracking
- Interest management
- Comprehensive access controls
- Event emission for all major actions
- Security considerations and input validation