A node operator can call registerBLSPublicKeys() to register a node runner to LSD and create a new smart wallet. The protocol only allows EOAs to be registered as _eoaRepresentative.
The issue is that this can be easily circumvented. As detailed in the isContract() definition by OpenZeppelin:
It is unsafe to assume that an address for which this function returns
false is an externally-owned account (EOA) and not a contract.
Among others, isContract will return false for the following
types of addresses:
an externally-owned account
a contract in construction
an address where a contract will be created
an address where a contract lived, but was destroyed
A user can for instance deploy a smart wallet via a factory using CREATE2, call SELFDESTRUCT on it.
They can then pass the address of that destructed smart contract as _eoaRepresentative to registerBLSPublicKeys().
The operator can then redeploy the same contract to the same address using a CREATE2 call in their factory.
Judge has assessed an item in Issue #400 as M risk. The relevant finding follows:
L01 - EOA restriction of wallet representative can be bypassed https://github.com/code-423n4/2022-11-stakehouse/blob/4b6828e9c807f2f7c569e6d721ca1289f7cf7112/contracts/liquid-staking/LiquidStakingManager.sol#L435
A node operator can call registerBLSPublicKeys() to register a node runner to LSD and create a new smart wallet. The protocol only allows EOAs to be registered as _eoaRepresentative.
The issue is that this can be easily circumvented. As detailed in the isContract() definition by OpenZeppelin:
isContract
will return false for the followingThe operator can then redeploy the same contract to the same address using a CREATE2 call in their factory.
Impact Low