Quiet Ocean Boar
Medium
The protocol describes a few invariants that should not be broken otherwise they would result in a valid issue. The invariant are listed below:
One address may be associated with maximum one profile. Profile creation requires at least one active invitation. One may not write to Ethos contracts until a (non-mock) profile is created.
The invariant One address may be associated with maximum one profile
is broken because the createProfile
function does not check if an address is compromised.
in EthosProfile.sol ln 158 https://github.com/sherlock-audit/2024-10-ethos-network/blob/main/ethos/packages/contracts/contracts/EthosProfile.sol#L158
function createProfile(uint256 inviterId) external whenNotPaused {
(
bool inviteSenderVerified,
bool inviteSenderArchived,
bool inviteSenderIsMock
) = profileStatusById(inviterId);
if (!inviteSenderVerified || inviteSenderArchived || inviteSenderIsMock) {
revert InvalidSender();
}
_inviterProfileAuthorizedSender(inviterId, msg.sender);
uint256 newID = _createProfile(msg.sender);
profiles[newID].inviteInfo.invitedBy = inviterId;
profiles[inviterId].inviteInfo.acceptedIds.push(newID);
}
The function does not check if an address is compromised, thus allowing compromised addresses to create a profile.
a compromised account is associated with a profile already as can be observed by the code comments from the function below:
* - In case of account compromises, a profile can unregister an account and mark it as compromised.
* - After registration, an address can never again be registered to another profile, even if it is archived.
* - Unregistered accounts still remain associated with their original profile for historical tracking.
specifically i want to highlight this sentence Unregistered accounts still remain associated with their original profile for historical tracking.
We can conlude from this that a unregistered account to a profile counts as association with that profile.
The problem occurs because an address that holds atleast 1 invite and is compromised can create a profile and thus be associated with 2 profiles at once.
the function InviteAddress does check if an address is compromised by using the modifier checkIfCompromised
function inviteAddress(
address invitee
) public whenNotPaused onlyNonZeroAddress(invitee) checkIfCompromised(invitee)
this can be bypassed if the address was invited prior to being set as compromised.
Thus since an address will be associated with 2 profiles, we can conclude the following invariant has been broken and thus the issue is a valid medium .
One address may be associated with maximum one profile.
From sherlock docs we can confirm the issues validity by the following rules:
The protocol team can use the README (and only the README) to define language that indicates the codebase's restrictions and/or expected functionality. Additionally, the protocol team can use only the following question to define the protocol's invariants/properties:
What properties/invariants do you want to hold even if breaking them has a low/unknown impact?
Issues that break the invariants from the above question, irrespective of whether the impact is low/unknown, will be assigned Medium severity. High severity will be applied only if the issue falls into the High severity category in the judging guidelines.
Example: The README states "Admin can only call XYZ function once" but the code allows the Admin to call XYZ function twice; this is a valid Medium
- an address must have atleast 1 invite
- the address must be set as compromised for a profile
- the address must create a profile
- the address is now associated with 2 profiles
none
- an address holds atleast 1 invite
- the address is set to compromised
- the compromised address creates a profile
- invariant is broken
Protocol invariant is broken
No response
do not allow compromised addresses to create profiles by adding the checkIfCompromised
modifier to the createProfile
function.
function createProfile(uint256 inviterId) external whenNotPaused checkIfCompromised(msg.sender)