QuantAMM

QuantAMM
49,600 OP
View results
Submission Details
Severity: low
Invalid

Hardcoded Version value in pool creation. Oversight Confuses devs and users and opens possibility for phishing.

Summary

In the QuantAMMWeightedPoolFactory contract, there's functions to create and deploy Pools with and without params. Both functions are using a hardcoded value "version" for pool parameter version. This oversight can confuse the devs, auditors (like us), and users and most important it may open a possibility for phishing attacks.

Vulnerability Details

QuantAMMWeightedPoolFactory::createWithoutArgs:

function createWithoutArgs(NewPoolParams memory params) external returns (address pool) {
if (params.roleAccounts.poolCreator != address(0)) {
revert StandardPoolWithCreator();
}
LiquidityManagement memory liquidityManagement = getDefaultLiquidityManagement();
liquidityManagement.enableDonation = params.enableDonation;
// disableUnbalancedLiquidity must be set to true if a hook has the flag enableHookAdjustedAmounts = true.
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
// @info: it's a create without args function, so the poolArgs is not needed
pool = _create(
abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
@> version: "version", // @info: hardcoded value, should be params.version or _poolVersion
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
),
params.salt
);
QuantAMMWeightedPool(pool).initialize(
params._initialWeights,
params._poolSettings,
params._initialMovingAverages,
params._initialIntermediateValues,
params._oracleStalenessThreshold
);
_registerPoolWithVault(
pool,
params.tokens,
params.swapFeePercentage,
false, // not exempt from protocol fees
params.roleAccounts,
params.poolHooksContract,
liquidityManagement
);
}

QuantAMMWeightedPoolFactory::create:

function create(NewPoolParams memory params) external returns (address pool, bytes memory poolArgs) {
if (params.roleAccounts.poolCreator != address(0)) {
revert StandardPoolWithCreator();
}
LiquidityManagement memory liquidityManagement = getDefaultLiquidityManagement();
liquidityManagement.enableDonation = params.enableDonation;
// disableUnbalancedLiquidity must be set to true if a hook has the flag enableHookAdjustedAmounts = true.
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
poolArgs = abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
@> version: "version", // @info: hardcoded value, should be params.version or _poolVersion
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
);
pool = _create(poolArgs, params.salt);
QuantAMMWeightedPool(pool).initialize(
params._initialWeights,
params._poolSettings,
params._initialMovingAverages,
params._initialIntermediateValues,
params._oracleStalenessThreshold
);
_registerPoolWithVault(
pool,
params.tokens,
params.swapFeePercentage,
false, // not exempt from protocol fees
params.roleAccounts,
params.poolHooksContract,
liquidityManagement
);
}

Impact

  • Using Hardcoded values are a great Bad practice.

  • Phishing Attack

    • Hardcoded value is a version string and value is generic "version". This shows and presents standard of the protocol (pool) any bad actor with malicious intentions can deploy a completely different contract and change that hardcoded value to a professional legit looking version value i.e., "QuantAMM@v.1.0" or etc.

Tools Used

Manual review

Recommendations

Mitigations

  • Please use a dynamic value instead of a hardcoded value

  • If current version is permanent then use hardcoded value with a relatable value.

  1. One possible solution:

QuantAMMWeightedPoolFactory::createWithoutArgs:

function createWithoutArgs(NewPoolParams memory params) external returns (address pool) {
.
.
...
// disableUnbalancedLiquidity must be set to true if a hook has the flag enableHookAdjustedAmounts = true.
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
pool = _create(
abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
- version: "version",
+ version: _poolVersion,
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
),
params.salt
);
.
.
...
}

QuantAMMWeightedPoolFactory::create:

function create(NewPoolParams memory params) external returns (address pool, bytes memory poolArgs) {
.
.
...
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
poolArgs = abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
- version: "version",
+ version: _poolVersion,
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
);
pool = _create(poolArgs, params.salt);
.
.
...
}
  1. Another possible solution:

QuantAMMWeightedPoolFactory::createWithoutArgs:

function createWithoutArgs(NewPoolParams memory params) external returns (address pool) {
.
.
...
// disableUnbalancedLiquidity must be set to true if a hook has the flag enableHookAdjustedAmounts = true.
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
pool = _create(
abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
- version: "version",
+ version: params.version,
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
),
params.salt
);
.
.
...
}

QuantAMMWeightedPoolFactory::create:

function create(NewPoolParams memory params) external returns (address pool, bytes memory poolArgs) {
.
.
...
liquidityManagement.disableUnbalancedLiquidity = params.disableUnbalancedLiquidity;
poolArgs = abi.encode(
QuantAMMWeightedPool.NewPoolParams({
name: params.name,
symbol: params.symbol,
numTokens: params.normalizedWeights.length,
- version: "version",
+ version: params.version,
updateWeightRunner: _updateWeightRunner,
poolRegistry: params.poolRegistry,
poolDetails: params.poolDetails
}),
getVault()
);
pool = _create(poolArgs, params.salt);
.
.
...
}
Updates

Lead Judging Commences

n0kto Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity
Assigned finding tags:

invalid_hardcoded_version

Version is immutable as specified in Version.sol and can be what the developer wants. It is hardcoded and will be changed by the admin for every deployment. No real impact here.

Support

FAQs

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

Give us feedback!