Skip to content

Security: Kumarutkarsh9470/plug-in

Security

SECURITY.md

GasVote Security Model

Status: educational / hackathon project, not audited for production use.

Trust assumptions

Actor Trust level Why
Deployer / Owner Fully trusted Owns GasPaymaster and GasAnalytics; controls sponsor policies, whitelisted contracts, authorized callers. Uses Ownable2Step for ownership transfer safety.
Relayer Semi-trusted Submits signed transactions on-chain but cannot forge user intent. All actions require valid EIP-712 signatures. Can censor (refuse to relay) but can't steal funds or execute unauthorized ops.
End User Untrusted Interacts only through signed meta-transactions. Replay, forgery, and nonce manipulation are prevented at the contract level.
Target Contracts Per-whitelist Only contracts in GasPaymaster.sponsoredContracts receive gas sponsorship. Unknown targets are rejected by preRelayCheck.

Replay protection

Mode 1 (MetaTxBatchForwarder / TrustedForwarder):

  • 2D nonce scheme: TrustedForwarder tracks nonces[from][key]. Each ForwardRequest specifies (from, nonce) and is rejected if nonce doesn't match.
  • Deadline: every ForwardRequest carries a deadline timestamp. Expired requests revert with ExpiredRequest.
  • Chain-bound EIP-712: domain separator includes chainId and verifyingContract, preventing cross-chain and cross-contract replay.
  • Nonce consumption: nonce is incremented before execution, so even reverted executions consume the nonce.

Mode 2 (MiniEntryPoint / SmartAccount):

  • Sequential nonce: SmartAccount maintains a nonce storage variable, checked and incremented by MiniEntryPoint.handleOp.
  • Deadline: UserOperation.deadline enforced identically to Mode 1.
  • Chain-bound EIP-712: separate domain ("GasVote EntryPoint") with chainId + verifyingContract.
  • Signature recovery: SmartAccount.validateUserOp recovers the signer via ECDSA and checks against owner. Invalid signatures revert.

Reentrancy protection

All state-changing contracts use TransientReentrancyGuard (EIP-1153):

Contract Protected functions
BatchExecutor executeBatch
TrustedForwarder execute
MetaTxBatchForwarder executeWithSponsor
MiniEntryPoint handleOp, handleOps
SmartAccount execute
GasPaymaster withdraw, reimburse
DemoVault deposit, withdraw

Traditional reentrancy guards use SSTORE (20,000 gas cold / 5,000 warm for write, 2,100 cold / 100 warm for read). EIP-1153 transient storage costs 100 gas for both TSTORE and TLOAD, saving ~5,000 gas per guard entry. Transient slots auto-clear at transaction end.

Requires Cancun-compatible EVM (mainnet since March 2024, Anvil with evm_version = "cancun").

Access control

GasPaymaster (Ownable2Step):

Function Access
setAuthorizedCaller onlyOwner
setSponsoredContract onlyOwner
setPolicy onlyOwner
withdraw onlyOwner + nonReentrant
withdrawTokens onlyOwner
deposit Public (anyone can fund the pool)
reimburse authorizedCallers only

Ownable2Step requires a two-step ownership transfer (propose then accept), preventing accidental transfers to wrong addresses.

GasAnalytics: setAuthorizedRecorder is onlyOwner, recordBatch is authorizedRecorders only, getGlobalStats is public view.

SmartAccount: execute, validateUserOp, and transferOwnership are all onlyEntryPoint.

EIP-712 structured signing

Both modes use EIP-712 typed data for user authorization.

ForwardRequest (Mode 1): from, nonce, deadline, gasPaymentMode, calls (array of BatchCall with target, callData, value, allowFailure, dependsOn, useERC2771).

UserOperation (Mode 2): sender, nonce, deadline, gasPaymentMode, calls (same structure).

Domain separators:

  • Mode 1: EIP712Domain("GasVote Forwarder", "1", chainId, trustedForwarder)
  • Mode 2: EIP712Domain("GasVote EntryPoint", "1", chainId, miniEntryPoint)

ERC-2771 meta-transaction context

TrustedForwarder appends the original msg.sender (20 bytes) to calldata before forwarding to target contracts. Targets using ERC2771Context (OpenZeppelin) extract the real sender from the last 20 bytes of msg.data.

Trust boundary: only calls routed through the TrustedForwarder (which validates signatures) carry appended sender data. Direct calls use msg.sender as-is. ERC2771Context._msgSender() handles both cases by checking msg.data.length >= 20 && msg.sender == trustedForwarder.

Known limitations and risks

Risk Severity Mitigation
Owner key compromise Critical Ownable2Step prevents instant transfer; multi-sig recommended for production
Relayer censorship Medium Relayer can refuse to relay; decentralized relay network would mitigate
Relayer front-running Low Relayer sees signed transactions first; signature-bound operations prevent fund theft
Gas price manipulation Low GasPaymaster.reimburse uses tx.gasprice for cost; on Anvil tx.gasprice = 0 (known test failure)
DemoToken unlimited mint Info faucetCap limits per-call mint (10k), but no total supply cap -- by design for demo/testing
DemoNFT supply cap Info Max supply of 10,000 with 5 per-call anti-griefing cap -- by design for demo
Batch gas limit Medium Large batches may exceed block gas limit; BatchExecutor enforces max 32 calls
Warm storage bias in scripts Info DemoMode2.s.sol measurements may differ from GasComparison.t.sol due to warm slots (documented)

Dependency security

Dependency Version Notes
OpenZeppelin Contracts 5.x ERC-2771, Ownable2Step, EIP712, ECDSA, ERC20Permit
Forge Std Latest Test framework only, not deployed
Solidity 0.8.24 Built-in overflow/underflow protection

Test coverage for security properties

Property Test file Result
Replay protection (nonce) TrustedForwarder.t.sol, MiniEntryPoint.t.sol Pass
Deadline enforcement Both unit test suites Pass
Invalid signature rejection Both unit test suites Pass
Self-dependency DAG rejection BatchExecutorSymbolic.t.sol Pass
Forward-dependency rejection BatchExecutorSymbolic.t.sol Pass (fuzz)
Reentrancy guard (7 contracts) Implicit via nonReentrant Pass
Paymaster pool invariants GasPaymasterInvariant.t.sol Pass (2/3)
Unauthorized recorder rejection GasAnalytics.t.sol Pass
Unauthorized reimburse rejection GasPaymaster.t.sol Pass
Wrong nonce rejection Both unit test suites Pass
E2E permit/deposit/stake GasComparison.t.sol Pass

Reporting vulnerabilities

This is an educational/hackathon project. If you discover a security issue, please open a GitHub issue or contact the maintainers directly.

There aren't any published security advisories