FoundrySolidityLayer 2
7.25 ETH
Submission Details
Impact: medium
Likelihood: medium
Invalid

Inconsistent/Fake Safe Harbor Registry can be supplied during Clone Initialization

Author Revealed upon completion

Root + Impact

The initialize function of the cloned ConfidencePool does not verify whether the provided agreement_ belongs to or is consistent with the specified safeHarborRegistry_. An attacker can initialize a pool with a malicious, custom-deployed registry that returns arbitrary state to hijack pool outcomes.

Description

The factory contract deploys non-upgradeable clones of ConfidencePool and calls their initialize function. This function takes agreement_ and safeHarborRegistry_ as separate arguments.

The issue is that while initialize checks whether the agreement is registered as valid under the registry via isAgreementValid(agreement_), it does not enforce any strict architectural binding between them. An attacker can deploy a fake registry contract that returns true for isAgreementValid but provides an attacker-controlled mock AttackRegistry. Because the pool reads live state via safeHarborRegistry.getAttackRegistry(), initializing a clone with an inconsistent/mock registry allows the attacker to completely control state transitions (such as fabricating a false CORRUPTED state to sweep honest stakers' principal).

function initialize(
address agreement_,
address stakeToken_,
address safeHarborRegistry_,
// ...
) external initializer {
// ...
@> if (!IBattleChainSafeHarborRegistry(safeHarborRegistry_).isAgreementValid(agreement_)) {
@> revert InvalidAgreement();
@> }
}

Risk

Likelihood:

  • Occurs when a pool is created, either via direct interaction with the implementation proxy or if the factory owner incorrectly configures the registry parameters.

  • Allows deployment of deceptive "honeypot" pools that mirror legitimate agreements but are backed by a malicious state machine.

Impact:

  • Direct loss of principal for honest depositors who stake in the mismatched pool.

  • Arbitrary outcome manipulation (unauthorized sweeps of both principal and bonus).

Proof of Concept

function test_PoC_InitializeRegistryInconsistency() public {
FakeRegistry fakeRegistry = new FakeRegistry();
ConfidencePool p = ConfidencePool(Clones.clone(address(new ConfidencePool())));
p.initialize(agreement, address(token), address(fakeRegistry), moderator, block.timestamp + 31 days, ONE, recovery, alice, _defaultScope());
assertEq(address(p.safeHarborRegistry()), address(fakeRegistry));
}

Recommended Mitigation

Validate the registry relationship or retrieve the canonical registry directly from a trusted factory or global contract mapping rather than allowing arbitrary addresses to be set during clone initialization.

Updates

Lead Judging Commences

inallhonesty Lead Judge
20 days ago
inallhonesty Lead Judge 2 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
inallhonesty Lead Judge 2 days ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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

Give us feedback!