Title: Floating Pragma Allows Deployment with Any 0.7.x Compiler Version
Impact: Low
Likelihood: Medium
The PuppyRaffle contract uses a floating pragma pragma solidity ^0.7.6, which allows the contract to be compiled with any Solidity compiler version from 0.7.6 up to (but not including) 0.8.0. Best practice is to lock the pragma to a specific compiler version to ensure deterministic and reproducible deployments.
Different patch versions within the 0.7.x range can introduce subtle behavioral differences in compilation output. A contract compiled with 0.7.6 may produce different bytecode than one compiled with 0.7.5 or 0.7.4, even if the source code is identical. This creates uncertainty about the exact behavior of the deployed contract and can introduce unexpected bugs that only manifest under specific compiler versions.
Likelihood:
Every deployment of this contract is at risk of being compiled with a different 0.7.x patch version. Developers working across different environments (CI/CD pipelines, local machines, team members) may each use a slightly different compiler version without realizing it.
Dependency management tools like Foundry or Hardhat may resolve to different patch versions depending on when the project is first set up, leading to inconsistent builds across different developer machines and deployment environments.
Impact:
Compiler bugs in specific 0.7.x patch versions could introduce vulnerabilities in the compiled bytecode. Solidity has a history of compiler bugs being discovered and fixed across patch versions, and deploying with an untested patch version means trusting that version has no known or unknown compiler bugs.
The lack of a locked pragma makes it impossible to guarantee that the deployed bytecode matches the audited source code. A malicious actor with deployment access could recompile with a buggy compiler version to introduce a backdoor, and the floating pragma would mask this change since the source code itself remains identical.
This PoC is environmental rather than code-based, because the issue lies in the build configuration rather than the contract logic. The key demonstration is that two different developers using the same source code but different 0.7.x compiler versions will produce different deployed bytecode. This means an audit verifying the contract at one compiler version does not guarantee safety at another version. On Ethereum mainnet, this has real consequences: if a compiler bug in 0.7.4 causes incorrect arithmetic or memory layout, and a deployer happens to use 0.7.4 instead of the audited 0.7.6, the contract could behave differently than expected despite passing all audit checks.
Locking the pragma to the exact version 0.7.6 (without the ^ operator) ensures that the contract can only be compiled with that specific version. This guarantees deterministic builds, reproducible deployments, and a direct mapping between the audited source code and the deployed bytecode. Every developer, CI/CD pipeline, and deployment environment will produce identical bytecode, eliminating an entire class of supply-chain and compiler-version attack vectors. The deployment script already uses pragma solidity 0.7.6 (locked), so this change simply aligns the main contract with existing best practice already present in the project.
The contest is live. Earn rewards by submitting a finding.
Submissions are being reviewed by our AI judge. Results will be available in a few minutes.
View all submissionsThe contest is complete and the rewards are being distributed.