DeFiFoundry
60,000 USDC
View results
Submission Details
Severity: low
Valid

CustomReferralConfiguration and Referral do not follow EIP 7201

Lines of code

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/Referral.sol#L8

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/Referral.sol#L16

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/CustomReferralConfiguration.sol#L5

https://github.com/Cyfrin/2024-07-zaros/blob/d687fe96bb7ace8652778797052a38763fbcbb1b/src/perpetuals/leaves/CustomReferralConfiguration.sol#L16

Impact

Even though the TreeProxy Pattern is designed to be compatible with EIP-7201, when determining the storage slots for CustomReferralConfiguration and Referral, this standard is not implemented. This can lead to potential vulnerabilities in the contract, including:

  • Inability to correctly manage storage slots, which may result in data corruption.

  • Increased risk of unauthorized access to sensitive data.

  • Potential for unexpected behavior in contract interactions, leading to loss of funds or other critical failures.

Proof of Concept

To follow EIP-7201 a contract needs to encode the storage location with the following formular:

keccak256(abi.encode(uint256(keccak256(bytes(id))) - 1)) & ~bytes32(uint256(0xff))

Both CustomReferralConfiguration and Referral do not use this pattern. Instead they use a simple string for determining the storage location:

string internal constant CUSTOM_REFERRAL_CONFIGURATION_DOMAIN = "fi.zaros.CustomReferralConfiguration";
function load(string memory customReferralCode)
internal
pure
returns (Data storage customReferralConfigurationTestnet)
{
bytes32 slot = keccak256(abi.encode(CUSTOM_REFERRAL_CONFIGURATION_DOMAIN, customReferralCode));
assembly {
customReferralConfigurationTestnet.slot := slot
}
}

Recommended Mitigation Steps

To follow the EIP 7201 standard make sure to encode the string identifier properly for CustomReferralConfiguration:

library CustomReferralConfiguration {
- string internal constant CUSTOM_REFERRAL_CONFIGURATION_DOMAIN = "fi.zaros.CustomReferralConfiguration";
+ string internal constant CUSTOM_REFERRAL_CONFIGURATION_DOMAIN = keccak256(abi.encode(uint256(keccak256("fi.zaros.CustomReferralConfiguration ")) - 1)) & ~bytes32(uint256(0xff));
struct Data {
address referrer;
}
function load(string memory customReferralCode)
internal
pure
returns (Data storage customReferralConfigurationTestnet)
{
bytes32 slot = keccak256(abi.encode(CUSTOM_REFERRAL_CONFIGURATION_DOMAIN, customReferralCode));
assembly {
customReferralConfigurationTestnet.slot := slot
}
}
}

And for Referral:

library Referral {
- string internal constant REFERRAL_DOMAIN = "fi.zaros.Referral";
+ string internal constant REFERRAL_DOMAIN = keccak256(abi.encode(uint256(keccak256("fi.zaros. Referral")) - 1)) & ~bytes32(uint256(0xff));
struct Data {
bytes referralCode;
bool isCustomReferralCode;
}
function load(address accountOwner) internal pure returns (Data storage referralTestnet) {
bytes32 slot = keccak256(abi.encode(REFERRAL_DOMAIN, accountOwner));
assembly {
referralTestnet.slot := slot
}
}
function getReferrerAddress(Data storage self) internal view returns (address referrer) {
if (!self.isCustomReferralCode) {
referrer = abi.decode(self.referralCode, (address));
} else {
referrer = CustomReferralConfiguration.load(string(self.referralCode)).referrer;
}
}
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Storage computation formula of ERC7201 is not followed. ERC7201 non compliance.

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.