Opcode Summary
| Property | Value |
|---|---|
| Opcode | 0x3A |
| Mnemonic | GASPRICE |
| Gas | 2 |
| Stack Input | (none) |
| Stack Output | tx.gasprice |
| Behavior | Returns the gas price of the current transaction in wei. Pre-EIP-1559: the literal gasPrice field. Post-EIP-1559: the effective gas price, calculated as min(maxFeePerGas, baseFee + maxPriorityFeePerGas). |
Threat Surface
GASPRICE returns a value that is entirely controlled by the transaction sender (within the constraint of satisfying the block’s base fee). This makes it one of the most dangerous opcodes to use as an input to contract logic, because any contract behavior that branches on tx.gasprice is trivially manipulable by any user.
The threat surface spans three core areas:
-
Sender-controlled value used in contract logic: Unlike block-level values (
BASEFEE,TIMESTAMP), the gas price is chosen by the individual transaction sender. Any contract logic that conditions ontx.gasprice— for randomness, access control, rate-limiting, front-running detection, or pricing — hands the attacker a control knob over the contract’s behavior. -
MEV and transaction ordering: Gas price is the primary mechanism for influencing transaction ordering in the public mempool. Pre-EIP-1559, miners selected transactions by gas price. Post-EIP-1559, the priority fee still influences ordering within a block. This creates a direct link between GASPRICE and front-running, sandwich attacks, and general MEV extraction.
-
Semantic shift under EIP-1559: Before the London hard fork (August 2021),
GASPRICEreturned the rawgasPricefield from the transaction. After EIP-1559, it returns the effective gas price (baseFee + actualPriorityFee), which depends on both the sender’smaxFeePerGas/maxPriorityFeePerGasand the block’sbaseFee. Contracts deployed before London that relied on the old semantics may behave unexpectedly. The value is no longer purely sender-controlled — it’s partially determined by protocol-level base fee dynamics.
Smart Contract Threats
T1: GASPRICE as Randomness Source (Critical)
Using tx.gasprice as an entropy source for pseudo-random number generation is trivially exploitable. The sender chooses their own gas price, so they can set it to whatever value produces the desired “random” outcome.
// Vulnerable lottery contract
function drawWinner() external {
// tx.gasprice is chosen by the caller -- not random at all
uint256 seed = uint256(keccak256(abi.encodePacked(
block.timestamp, tx.gasprice, msg.sender
)));
uint256 winner = seed % participants.length;
payable(participants[winner]).transfer(prize);
}An attacker deploys a contract that pre-computes the winning gas price by iterating over possible values, then submits the transaction with that exact gas price. This generalizes to any scheme that mixes tx.gasprice into a hash for randomness: the attacker controls an input to the hash, so they control the output.
T2: Gas Price-Dependent Logic (High)
Contracts that gate functionality based on gas price — for fee calculation, access control, or anti-front-running measures — are exploitable because the sender controls the value.
// Vulnerable: dynamic fee based on gas price
function swap(uint256 amountIn) external returns (uint256) {
// "Higher gas price = higher urgency = higher fee"
// Attacker uses a Flashbots bundle with zero priority fee
uint256 fee;
if (tx.gasprice > 50 gwei) {
fee = amountIn * 30 / 10000; // 0.3%
} else {
fee = amountIn * 5 / 10000; // 0.05%
}
return _executeSwap(amountIn, fee);
}The attacker submits through a private relay (Flashbots) with a minimal priority fee and a direct coinbase payment, getting the low-fee path while still being included in a block. This also applies to contracts that attempt to detect front-running by checking if tx.gasprice is “suspiciously high” — post-EIP-1559, the priority fee component is small and the base fee is protocol-determined, making such heuristics unreliable.
T3: Front-Running Detection via Gas Price (Medium)
Some contracts attempted to deter front-running by rejecting transactions with gas prices above a threshold. This was always fragile and is now effectively broken post-EIP-1559.
// Pre-EIP-1559 anti-front-running attempt
function commitOrder(bytes32 commitment) external {
// "Reject high gas price to prevent front-running"
require(tx.gasprice <= maxGasPrice, "Gas price too high");
commitments[msg.sender] = commitment;
}Why this fails: (1) Attackers can use Flashbots or private relays to front-run without raising gas price in the public mempool. (2) Post-EIP-1559, the effective gas price includes the base fee, which fluctuates with network congestion — a legitimate user during high congestion may be rejected while a front-runner using a private relay passes. (3) Validators/proposers can include their own transactions at any gas price.
T4: Gas Refund Gaming (Medium)
Contracts that use tx.gasprice in refund calculations are vulnerable to manipulation. If a contract refunds gasUsed * tx.gasprice to callers as a reimbursement mechanism, users can inflate their gas price to extract more value than they spent.
// Vulnerable gas reimbursement pattern
function executeAndRefund(bytes calldata data) external {
uint256 gasBefore = gasleft();
_execute(data);
uint256 gasUsed = gasBefore - gasleft();
// Refund caller for gas spent
// Attacker sets tx.gasprice = 1000 gwei, gets reimbursed at inflated rate
uint256 refund = gasUsed * tx.gasprice;
payable(msg.sender).transfer(refund);
}The attacker sets a very high gas price, executes the function, and receives a refund far exceeding their actual cost. This pattern was common in gas station network (GSN) and meta-transaction relayer designs.
T5: Cross-EIP-1559 Semantic Breakage (Medium)
Contracts deployed before London that compare tx.gasprice against hardcoded thresholds may break when the base fee rises. Pre-EIP-1559, a tx.gasprice of 20 gwei was typical. Post-EIP-1559, the effective gas price is baseFee + priorityFee, and the base fee alone can exceed previous expectations during congestion spikes (>100 gwei during NFT mints, >500 gwei during extreme events).
// Deployed pre-London, assumes gas price is always < 100 gwei
function processWithinBudget() external {
require(tx.gasprice < 100 gwei, "Gas too expensive");
// Post-EIP-1559: base fee alone can exceed 100 gwei
// This function becomes uncallable during congestion
_process();
}Protocol-Level Threats
P1: EIP-1559 Changed GASPRICE Semantics (Medium)
Before London, GASPRICE returned the transaction’s gasPrice field directly — a single value set by the sender. After London, EIP-1559 transactions use maxFeePerGas and maxPriorityFeePerGas instead. The GASPRICE opcode now returns the effective gas price:
effectiveGasPrice = min(maxFeePerGas, baseFee + maxPriorityFeePerGas)
This means GASPRICE now depends on the block’s base fee, which the sender does not control. The value is no longer purely sender-determined. This semantic shift is relevant for:
- go-ethereum Pull #24001 and #28130: Both fixed bugs in how effective gas price was calculated and exposed through RPC, confirming the complexity of the new semantics.
- Contracts comparing GASPRICE across transactions: Two transactions with identical
maxFeePerGasandmaxPriorityFeePerGaswill report differentGASPRICEvalues if included in blocks with different base fees.
P2: Transaction Ordering and MEV (High)
Gas price is the primary ordering signal in the public mempool. Higher gas price → higher priority → earlier inclusion. This creates a direct feedback loop between GASPRICE and MEV:
- Sandwich attacks: MEV bots sandwich victim transactions by submitting front-run and back-run transactions with carefully chosen gas prices. In 2023 alone, users lost ~$500M to MEV bot attacks, with sandwich attacks occurring more than once per block on average.
- Priority gas auctions (PGAs): Before Flashbots, competing arbitrage bots engaged in gas price bidding wars that consumed block space and drove up gas costs for all users.
- Builder concentration: Two MEV builders now produce ~80% of Ethereum blocks, giving them significant power over transaction ordering regardless of individual gas prices.
P3: Zero Gas Price in Private Transactions (Low)
Flashbots bundles and other private relay systems allow transactions with zero or near-zero gas price. These transactions pay validators through direct coinbase transfers instead. This means:
- Contracts that use
tx.gasprice > 0as a liveness check may fail for privately relayed transactions. - The assumption that
tx.gaspricereflects the “cost” of inclusion is broken in private relay contexts. - Gas price of 0 is valid in Flashbots bundles, which is an unusual edge case that contracts rarely account for.
Edge Cases
| Edge Case | Behavior | Security Implication |
|---|---|---|
| Legacy transaction (type 0) | Returns gasPrice field directly | Sender has full control over the value |
| EIP-1559 transaction (type 2) | Returns min(maxFeePerGas, baseFee + maxPriorityFeePerGas) | Partially protocol-determined via base fee |
maxFeePerGas == baseFee | Effective gas price = baseFee, priority fee = 0 | Sender pays minimum; validators have no priority incentive to include |
maxPriorityFeePerGas == 0 | Effective gas price = baseFee | Legal; common in Flashbots bundles that pay via coinbase transfer |
maxFeePerGas >> baseFee | Effective gas price = baseFee + maxPriorityFeePerGas | Overpaying maxFeePerGas doesn’t increase GASPRICE return value |
GASPRICE inside DELEGATECALL | Returns the original transaction’s gas price | Not the calling contract’s context; inherits from the top-level tx |
GASPRICE inside STATICCALL | Returns the original transaction’s gas price | Same as above; read-only context doesn’t change the value |
| Zero gas price (Flashbots bundle) | Returns 0 | Contracts using tx.gasprice for fee calculation will compute zero fees |
| Extremely high base fee (>1000 gwei) | GASPRICE reflects the spike | Hardcoded gas price thresholds in contracts may be exceeded |
| EIP-4844 blob transactions (type 3) | GASPRICE returns effective gas price for execution gas (not blob gas) | Blob base fee is separate; accessed via BLOBBASEFEE (0x4A) |
Real-World Exploits
Exploit 1: FOMO3D Airdrop Manipulation via Predictable On-Chain Inputs (2018)
Root cause: Using sender-controlled and block-level variables (including gas price) as entropy for randomness.
Details: FOMO3D was a viral Ethereum game that included an “airdrop” lottery feature. The lottery’s pseudo-random seed was derived from on-chain data including block.timestamp, sender address, and gas-related values. Attackers deployed contracts that pre-calculated the lottery outcome by replicating the seed computation, only committing the transaction when the result was favorable. If the outcome was unfavorable, the attacking contract simply reverted. This pattern was found in ~15% of smart contract audits surveyed in 2025.
GASPRICE’s role: Gas price was one of the inputs that the attacker controlled entirely. Combined with other predictable block variables, it gave the attacker a tunable parameter to brute-force favorable outcomes.
Impact: Attackers systematically won airdrop prizes at rates far exceeding chance. The game’s later rounds were dominated by automated exploit contracts, making it unplayable for legitimate participants.
References:
- Apriorit: FOMO3D Vulnerability Explained
- Zhongqiang Chen: Randomness in Smart Contracts is Predictable
Exploit 2: Flashbots Relay Race Condition — MEV Auction Gaming (2026)
Root cause: Race condition in Flashbots MEV relay infrastructure that allowed attackers to win transaction auctions without paying the required bid.
Details: A critical vulnerability was discovered in Flashbots’ MEV relay system exploiting a “check-then-act” race condition in Redis database calls. The flaw allowed attackers to win transaction ordering auctions (which determine gas price priority) without actually paying the bid amount. This effectively allowed conversion of standard arbitrage trades into multi-million-dollar windfalls by capturing the validator’s share of profits. The attack demonstrates that gas price as an ordering mechanism is vulnerable not just at the smart contract level but at the infrastructure layer.
GASPRICE’s role: The MEV relay system uses effective gas price to determine bundle ordering and validator payments. The race condition allowed manipulation of this ordering without corresponding gas price expenditure.
References:
Exploit 3: Sandwich Attacks on DEX Trades — $500M+ User Losses (Ongoing)
Root cause: Public mempool visibility combined with gas price-based transaction ordering enables systematic extraction.
Details: Sandwich attacks are the most prevalent MEV exploit on Ethereum. An attacker observes a pending DEX swap in the mempool, front-runs it with a buy (pushing the price up), lets the victim’s transaction execute at the worse price, then back-runs with a sell. The attacker profits from the price impact delta. Gas price is the instrument of ordering: the front-run transaction uses a higher priority fee than the victim, and the back-run uses a lower one. In January-February 2023 alone, MEV bots extracted 24M in MEV profit was extracted on Ethereum.
GASPRICE’s role: The attack is enabled by the gas price priority ordering mechanism. The attacker sets maxPriorityFeePerGas strategically: high enough to precede the victim, low enough to remain profitable. The GASPRICE opcode in the victim’s contract reflects a higher effective price (due to the base fee spike from the front-run), compounding the damage.
References:
- Kayssel: From Front-Running to Sandwich Attacks
- Block Magnates: Frontrunning Attacks Explained
- TechBuddies: MEV Bots Burning Half the Gas
Exploit 4: Gas Reimbursement Inflation in Meta-Transaction Relayers (Recurring Pattern)
Root cause: Refunding callers based on tx.gasprice without capping the reimbursement rate.
Details: Gas Station Network (GSN) and similar meta-transaction relayer contracts reimburse relayers for gas costs. Early implementations calculated refunds as gasUsed * tx.gasprice, trusting the relayer to use a reasonable gas price. Malicious relayers set extremely high gas prices, executed cheap operations, and claimed inflated refunds. This drained the contract’s ETH balance far faster than intended. The pattern recurred in multiple governance and DAO contracts that reimbursed proposal executors.
GASPRICE’s role: The GASPRICE opcode provided the inflated gas price value directly to the refund calculation. Without an on-chain cap or oracle-based price validation, the contract had no way to distinguish a legitimate high gas price from a manipulated one.
Impact: Affected multiple GSN-compatible contracts and DAO governance reimbursement systems. Exact losses vary; the pattern was identified and mitigated in OpenGSN v2+ by introducing gas price caps and trusted forwarder patterns.
Attack Scenarios
Scenario A: Lottery Manipulation via Gas Price Control
contract VulnerableLottery {
function enter() external payable {
require(msg.value == 0.1 ether);
// tx.gasprice is part of the seed -- attacker controls it
uint256 random = uint256(keccak256(abi.encodePacked(
block.prevrandao, block.timestamp, tx.gasprice, msg.sender
))) % 100;
if (random == 42) {
payable(msg.sender).transfer(address(this).balance);
}
}
}
// Attacker contract: brute-force gas price to hit winning seed
contract LotteryExploit {
function attack(VulnerableLottery lottery, uint256 gasPrice) external payable {
// Pre-check: simulate the hash off-chain, iterate gasPrice values
// until random == 42, then submit with that exact gas price
lottery.enter{value: 0.1 ether}();
}
}Scenario B: Gas Refund Drain
contract VulnerableDAO {
function executeProposal(uint256 proposalId) external {
uint256 startGas = gasleft();
_execute(proposalId);
uint256 gasUsed = startGas - gasleft() + 21000;
// Attacker sets tx.gasprice = 10000 gwei
// gasUsed = 100,000; refund = 100,000 * 10000 gwei = 1 ETH
// Actual cost at market rate (30 gwei): 0.003 ETH
payable(msg.sender).transfer(gasUsed * tx.gasprice);
}
}Scenario C: EIP-1559 Threshold Breakage
// Deployed in 2020, assumes gas prices stay below 100 gwei
contract LegacyBridge {
uint256 constant MAX_GAS_PRICE = 100 gwei;
function deposit(address token, uint256 amount) external {
// Post-EIP-1559: base fee can spike above 100 gwei during congestion
// Bridge becomes unusable exactly when users need it most
require(tx.gasprice <= MAX_GAS_PRICE, "Gas price too high");
_deposit(token, amount);
}
}Mitigations
| Threat | Mitigation | Implementation |
|---|---|---|
| T1: Gas price as randomness | Never use tx.gasprice (or any on-chain value) for randomness | Use Chainlink VRF or commit-reveal schemes |
| T2: Gas price-dependent logic | Do not branch on tx.gasprice; use oracle-based fee mechanisms | Replace tx.gasprice checks with TWAP-based or governance-set parameters |
| T3: Front-running detection | Use commit-reveal, time-locks, or private mempools instead | Integrate with Flashbots Protect or MEV-aware order flow auctions |
| T4: Gas refund gaming | Cap reimbursement rate using an oracle or governance-set gas price ceiling | refund = gasUsed * min(tx.gasprice, maxReimbursementRate) |
| T5: EIP-1559 semantic breakage | Avoid hardcoded gas price thresholds; use BASEFEE opcode for base fee awareness | Replace require(tx.gasprice < X) with dynamic checks relative to block.basefee |
| P2: MEV/sandwich attacks | Use private transaction submission or MEV-aware DEX designs | Flashbots Protect, MEV Blocker, or batch auction mechanisms (CoW Protocol) |
| P3: Zero gas price edge case | Do not assume tx.gasprice > 0 | Guard against zero-value multiplication in fee calculations |
| General | Treat tx.gasprice as untrusted, sender-controlled input | Never use it for security decisions, randomness, or uncapped financial calculations |
Design Principles
- GASPRICE is a user input, not an oracle: Treat it with the same suspicion as
msg.valueor calldata. Validate, cap, or ignore it. - Use BASEFEE for protocol awareness: If you need to know the network’s gas market conditions, use
block.basefee(opcode 0x48, available post-London). It is protocol-determined and not sender-manipulable. - Prefer off-chain gas price oracles: For reimbursement or fee calculation, use a trusted off-chain oracle or governance-set parameter rather than
tx.gasprice.
Severity Summary
| Threat ID | Category | Severity | Likelihood | Real-World Precedent |
|---|---|---|---|---|
| T1 | Smart Contract | Critical | High | FOMO3D airdrop manipulation (2018) |
| T2 | Smart Contract | High | High | Gas price-dependent fee evasion (recurring) |
| T3 | Smart Contract | Medium | Medium | Pre-EIP-1559 anti-front-running heuristics (broken) |
| T4 | Smart Contract | Medium | Medium | GSN relayer refund inflation (recurring) |
| T5 | Smart Contract | Medium | Low | Pre-London contracts with hardcoded thresholds |
| P1 | Protocol | Medium | Low | go-ethereum effective gas price bugs (#24001, #28130) |
| P2 | Protocol | High | High | Sandwich attacks ($500M+ losses in 2023), MEV relay race condition (2026) |
| P3 | Protocol | Low | Low | Flashbots zero-gas-price bundles |
Related Opcodes
| Opcode | Relationship |
|---|---|
| BASEFEE (0x48) | Returns the block’s base fee (EIP-3198). Protocol-determined, not sender-controlled. Use instead of GASPRICE for network gas market awareness. |
| GAS (0x5A) | Returns remaining gas in current execution context. Combined with GASPRICE, used in gas reimbursement calculations. |
| GASLIMIT (0x45) | Returns the block gas limit. Constrains how much gas is available; indirectly affects gas price market dynamics. |
| BLOBBASEFEE (0x4A) | Returns the blob base fee (EIP-7516). Separate fee market for EIP-4844 blob transactions; GASPRICE does not include blob fees. |
| ORIGIN (0x32) | Returns the original transaction sender. Like GASPRICE, reflects top-level transaction context (not affected by DELEGATECALL depth). |
| COINBASE (0x41) | Returns the block proposer’s address. MEV payments via direct coinbase transfers bypass the gas price mechanism entirely. |