No Zero-Address Validation in Constructor Parameters
Description
The __init__ constructor accepts token addresses, price feed addresses, and the DSC address without validating that they are non-zero:
@deploy
def __init__(
token_addresses: address[2],
price_feed_addresses: address[2],
dsc_address: address,
):
DSC = i_decentralized_stable_coin(dsc_address)
COLLATERAL_TOKENS = token_addresses
self.token_address_to_price_feed[token_addresses[0]] = price_feed_addresses[0]
self.token_address_to_price_feed[token_addresses[1]] = price_feed_addresses[1]
No assertions like:
assert token_addresses[0] != empty(address), "DSCEngine__ZeroAddress"
assert price_feed_addresses[0] != empty(address), "DSCEngine__ZeroAddress"
assert dsc_address != empty(address), "DSCEngine__ZeroAddress"
Risk
Likelihood: Low -- This is a deployment-time issue. A careful deployer would use correct addresses. However, automated deployment scripts or misconfigured deployments could pass zero addresses.
Impact: Medium -- If deployed with zero addresses:
Zero token address: deposit_collateral would call transferFrom on address(0), which reverts
Zero price feed: _get_usd_value would call latestRoundData() on address(0), which reverts
Zero DSC address: _mint_dsc would call mint() on address(0), which reverts
In all cases, the contract would be deployed but non-functional, requiring redeployment
Since the contract has no upgrade mechanism, a misconfigured deployment wastes gas and creates confusion
Proof of Concept
def test_constructor_accepts_zero_token_address(self, dsc, eth_usd, btc_usd, weth):
zero = "0x0000000000000000000000000000000000000000"
engine = dsc_engine.deploy(
[zero, weth.address],
[eth_usd.address, btc_usd.address],
dsc.address,
)
assert engine.address != zero
tokens = engine.get_collateral_tokens()
assert tokens[0] == zero
Recommended Mitigation
Add zero-address checks in the constructor:
@deploy
def __init__(
token_addresses: address[2],
price_feed_addresses: address[2],
dsc_address: address,
):
assert token_addresses[0] != empty(address), "DSCEngine__ZeroAddress"
assert token_addresses[1] != empty(address), "DSCEngine__ZeroAddress"
assert price_feed_addresses[0] != empty(address), "DSCEngine__ZeroAddress"
assert price_feed_addresses[1] != empty(address), "DSCEngine__ZeroAddress"
assert dsc_address != empty(address), "DSCEngine__ZeroAddress"
assert token_addresses[0] != token_addresses[1], "DSCEngine__DuplicateToken"
DSC = i_decentralized_stable_coin(dsc_address)
COLLATERAL_TOKENS = token_addresses
self.token_address_to_price_feed[token_addresses[0]] = price_feed_addresses[0]
self.token_address_to_price_feed[token_addresses[1]] = price_feed_addresses[1]