Anchor Address Reuse Across Different Registry Versions
The function _generateAnchor() in the Registry contract has a potential flaw where, under specific conditions, it may reuse an Anchor contract address from a previous Registry deployment rather than creating a new one. Registry address could be updated with updateRegistry() in Allo.sol. The primary reason is that the salt used for the CREATE3 deployment is solely based on the profileId and the profile name. If a new Registry contract is deployed and tries to recreate an existing profile, it will end up with the same Anchor address from the previous Registry.
Vulnerability Detail
The _generateAnchor() function uses CREATE3 to generate or fetch a pre-calculated address for the Anchor contract.
The salt for the CREATE3 deployment is created by hashing _profileId and _name.
If a profile with the same profileId and _name is created in a new version of the Registry, the salt will remain the same, resulting in the same pre-calculated address.
The function checks if a contract already exists at that address. If it does, it reuses that address without checking if the existing contract references the current Registry.
Impact
Profiles created in a newer version of the Registry might reference Anchor contracts tied to a previous version of the Registry. This means the Anchor contract could be checking for ownership in an outdated Registry, potentially leading to unauthorized access or operational inconsistencies.
Proof of Concept
Deploy the Registry contract, create a profile, and note the associated Anchor address.
Deploy a new version of the Registry contract.
In the new Registry, create a profile with the same profileId and _name as the profile from step 1.
The new profile will be associated with the Anchor from the old Registry (and could not be changed) rather than having a new Anchor.
It is crucial to include a unique identifier for each version of the Registry in the salt used for CREATE3. This will ensure that even if profiles have the same profileId and _name, their Anchor addresses will be unique across different Registry versions.
Modified _generateAnchor() function:
function _generateAnchor(bytes32 _profileId, string memory _name) internal returns (address anchor) {
// Incorporate the current registry address into the salt to ensure uniqueness across versions
bytes32 salt = keccak256(abi.encodePacked(_profileId, _name, address(this)));
address preCalculatedAddress = CREATE3.getDeployed(salt);
// check if the contract already exists and if the profileId matches
if (preCalculatedAddress.code.length > 0) {
if (Anchor(payable(preCalculatedAddress)).profileId() != _profileId) revert ANCHOR_ERROR();
anchor = preCalculatedAddress;
} else {
bytes memory creationCode = abi.encodePacked(type(Anchor).creationCode, abi.encode(_profileId));
// Use CREATE3 to deploy the anchor contract
anchor = CREATE3.deploy(salt, creationCode, 0);
}
}
alexzoid
medium
Anchor
Address Reuse Across DifferentRegistry
VersionsThe function
_generateAnchor()
in theRegistry
contract has a potential flaw where, under specific conditions, it may reuse anAnchor
contract address from a previousRegistry
deployment rather than creating a new one.Registry
address could be updated withupdateRegistry()
inAllo.sol
. The primary reason is that the salt used for theCREATE3
deployment is solely based on theprofileId
and the profilename
. If a newRegistry
contract is deployed and tries to recreate an existing profile, it will end up with the sameAnchor
address from the previousRegistry
.Vulnerability Detail
_generateAnchor()
function usesCREATE3
to generate or fetch a pre-calculated address for theAnchor
contract.CREATE3
deployment is created by hashing_profileId
and_name
.profileId
and_name
is created in a new version of theRegistry
, the salt will remain the same, resulting in the same pre-calculated address.Registry
.Impact
Profiles created in a newer version of the
Registry
might referenceAnchor
contracts tied to a previous version of theRegistry
. This means theAnchor
contract could be checking for ownership in an outdatedRegistry
, potentially leading to unauthorized access or operational inconsistencies.Proof of Concept
Registry
contract, create a profile, and note the associatedAnchor
address.Registry
contract.Registry
, create a profile with the sameprofileId
and_name
as the profile from step 1.Anchor
from the oldRegistry
(and could not be changed) rather than having a newAnchor
.Code Snippet
Tool used
Manual review
Recommendation
It is crucial to include a unique identifier for each version of the
Registry
in the salt used forCREATE3
. This will ensure that even if profiles have the sameprofileId
and_name
, theirAnchor
addresses will be unique across differentRegistry
versions.Modified
_generateAnchor()
function: