Go to course navigation

11 - Security Audit Assignment and Account Abstraction

Part 1: Task 1 - Evaluation

Part 2: Semester Task II - Security Audit Assignment

Each student acts as both Auditor (auditing a peer’s project) and Developer (responding to audit of their own project).

Grading Methodology

ComponentPointsCriteria
Report Quality10 pointsMethodology (2.5), findings evaluation system (2.5), system overview (2.5), trust model (2.5). Inspire with Ackee Blockchain or Trail of Bits reports.
Triage & Response10 pointsTriage findings (accept/reject with reasoning) and implement fixes.
Findings20 pointsStaking mechanism by severity: Critical (10), High (5), Medium (3), Low (1). Instructor validates findings based on project owner’s triage. Valid findings earn points; invalid findings lose points. Score range: 0-20.

Workflow

As Developer (initial setup):

  1. Grant read access to assigned Auditor(s) for your Task I repository

As Auditor:

  1. Fork Developer’s repository and make fork private
  2. Invite Developer as collaborator to your private fork
  3. Create audit branch (audit/username) in your private fork
  4. Push audit report PDF to audit branch in your fork
  5. Create GitHub issues in your private fork for each finding (use severity labels: Critical, High, Medium, Low)
  6. Once audit complete, create Pull Request from audit branch to main in your fork
  7. Link issues in PR description (e.g., "Findings: #1, #2, #3")

Important: All audit work stays in your private fork. Do not push anything to Developer’s original repository.

As Developer (triage and fixes):

  1. Accept collaboration invite to each Auditor’s private fork
  2. Review audit PR and linked issues in each fork
  3. Triage each issue (accept/reject with technical reasoning)
  4. For accepted findings: create fix branch in that fork, implement fixes, reference issue in commits
  5. Close accepted issues after fixes; reject invalid findings with justification

Important: Apply fixes separately in each Auditor’s private fork. Do not share fixes between auditors' forks or push to your original repository during audit period.

Privacy: Each Auditor works in their own private fork. Multiple Auditors cannot see each other’s findings.

All materials (PR, report PDF, issues, triage responses) remain in private fork for instructor evaluation.

Part 3: Account Abstraction

Introduction

This section explores Account Abstraction – a fundamental improvement to Ethereum’s account model that addresses limitations of Externally Owned Accounts (EOAs) introduced in Tutorials 3 and 4.

Tutorial Prerequisites

  • Understanding of EOAs and Contract Accounts (Tutorial 3)
  • Familiarity with Ethereum transaction model (Tutorial 4)
  • Basic knowledge of Safe multisig wallets (Tutorial 3)

Tutorial Objectives

After completing this section, students should be able to:

  1. Explain the limitations of EOAs and why account abstraction is necessary
  2. Describe the architecture of EIP-4337 and its key components
  3. Compare EIP-4337 and EIP-7702 approaches to account abstraction
  4. Identify security trade-offs in smart contract wallets

Problem Statement: EOA Limitations

EOAs are public-private key pairs with a binary access model:

  • Possession of the private key → enables any operation within the rules of the EVM
  • Absence of the private key → prevents all operations

Security Limitations

LimitationDescription
Single point of failureLoss of seed phrase results in permanent asset inaccessibility
Theft vulnerabilityStolen keys grant immediate access to all funds
No recovery mechanismNo equivalent to password recovery in traditional systems

Functional Limitations

LimitationDescription
Gas paymentTransaction fees require maintaining an ETH balance
No batchingEach operation requires a separate transaction
Fixed authenticationOnly ECDSA signature verification is supported

Account Abstraction: The Solution

Account abstraction decouples authentication logic from the protocol layer, enabling smart contracts to define custom:

  • Authentication – Multi-signature, biometrics, social recovery, passkeys
  • Authorization – Spending limits, whitelisted addresses, time-locks
  • Execution – Transaction batching, automation, gas abstraction

Implementation: EIP-4337

EIP-4337 introduces account abstraction without modifying Ethereum’s core protocol. Deployed to Mainnet on March 1, 2023, it has seen significant adoption, particularly on Layer 2 networks, with millions of smart accounts deployed across Ethereum, Arbitrum, Optimism, Polygon, and Base.

Architecture

ComponentRole
Smart Contract WalletUser’s account implementing custom validation logic
UserOperationPseudo-transaction object describing user intent
BundlerOff-chain actor collecting UserOperations into regular transactions
EntryPoint ContractSingleton contract validating and executing UserOperations
PaymasterOptional contract sponsoring gas fees for users
AggregatorOptional contract aggregating signatures from multiple UserOperations

UserOperation Structure

{
  "sender": "0x...",           // Smart wallet address
  "nonce": "0x1",
  "initCode": "0x...",         // Wallet deployment code (if needed)
  "callData": "0x...",         // Operation to execute
  "callGasLimit": "0x...",
  "verificationGasLimit": "0x...",
  "preVerificationGas": "0x...",
  "maxFeePerGas": "0x...",
  "maxPriorityFeePerGas": "0x...",
  "paymasterAndData": "0x...", // Gas sponsorship data
  "signature": "0x..."         // Wallet-specific signature
}

Transaction Flow

The following diagram illustrates the complete EIP-4337 architecture and transaction flow:

EIP-4337 Architecture

Flow explanation:

  1. User creates UserOperation – The Smart Contract Wallet generates a UserOperation containing transaction details: sender, callData, signature, nonce, and gas parameters (callGasLimit, verificationGasLimit, maxFeePerGas)
  2. Alternative Mempool – UserOperations are sent to a separate mempool (not Ethereum’s standard mempool) where bundlers can access them
  3. Bundler collects operations – The Bundler (off-chain actor) selects multiple UserOperations and bundles them together
  4. Bundler simulates – The Bundler calls the EntryPoint Contract’s simulateValidation() to verify operations will succeed before submitting
  5. Bundler executes – The Bundler submits the bundle to the EntryPoint Contract’s handleOps() function via a regular Ethereum transaction
  6. Validation phase – The EntryPoint Contract calls each wallet’s validateUserOp() function:
    • If an Aggregator is specified, it validates aggregated signatures
    • If a Paymaster is specified (paymasterAndData), it validates and commits to sponsor gas fees
    • The Smart Contract Wallet verifies the operation is authorized
  7. Execution phase – If validation passes, the EntryPoint Contract executes the operation (callData) in the wallet’s context
  8. Result – The Smart Contract Wallet executes the intended operation (e.g., token transfer, contract interaction)

This separation of validation and execution enables arbitrary authentication logic while maintaining protocol security guarantees.

Implementation: EIP-7702

EIP-7702 enables native account abstraction by allowing EOAs to delegate to smart contract code. Deployed as part of Ethereum’s Pectra upgrade on May 7, 2025.

Mechanism

EIP-7702 introduces a delegation designator that points an EOA to a smart contract:

  1. EOA sets delegation to a smart contract address
  2. When the EOA receives a transaction, EVM loads the designated contract’s code
  3. Code executes in the context of the EOA (using EOA’s storage and balance)
  4. EOA gains smart contract capabilities while retaining its address

Comparison: EIP-4337 vs EIP-7702

AspectEIP-4337EIP-7702
Protocol changesNone requiredRequires hard fork
Account typeNew smart contract walletsUpgrades existing EOAs
AddressNew addressKeeps existing EOA address
StatusLive (March 2023)Deployed (May 2025)
Gas overheadHigher (bundler infrastructure)Lower (native execution)
Important:

Complementary Approaches: EIP-7702 does not replace EIP-4337. EOAs upgraded via EIP-7702 can utilize EIP-4337 infrastructure (bundlers, paymasters) for advanced features. The ecosystem is evolving toward a hybrid model.

Key Features Enabled

Social Recovery

Designation of guardians who can facilitate account recovery:

contract SocialRecoveryWallet {
    address[] public guardians;
    uint256 public threshold;
    mapping(address => mapping(address => bool)) public recoveryApprovals;

    function initiateRecovery(address newOwner) external {
        require(isGuardian(msg.sender), "Not a guardian");
        recoveryApprovals[newOwner][msg.sender] = true;

        if (countApprovals(newOwner) >= threshold) {
            owner = newOwner;
        }
    }
}

Gas Sponsorship (Paymasters)

Third-party gas payment enabling:

  • Dapp-sponsored transactions – Applications subsidize user onboarding
  • Token payments – Gas fees paid in ERC-20 tokens (USDC, DAI)
  • Subscription models – Prepaid transaction allowances

Session Keys

Temporary, scoped permissions for dapps:

struct SessionKey {
    address key;
    uint256 validUntil;
    uint256 spendingLimit;
    address[] allowedContracts;
}

Transaction Batching

Atomic execution of multiple operations:

// Single transaction replacing approve + swap
wallet.executeBatch([
    Call(token, abi.encodeCall(IERC20.approve, (dex, amount))),
    Call(dex, abi.encodeCall(IDex.swap, (tokenIn, tokenOut, amount)))
]);

Security Considerations

Advantages

  • Reduced single point of failure – Multiple recovery mechanisms available
  • Programmable security – Custom rules per transaction type or value
  • Phishing resistance – Eliminates seed phrase as attack vector
  • Replay protection – Implemented in smart contract logic

New Attack Vectors

  • Smart contract bugs – Wallet code vulnerabilities can compromise all funds
  • Bundler centralization – Dependence on bundlers for transaction inclusion
  • Paymaster trust – Malicious paymasters may censor or front-run transactions
  • Increased complexity – Larger attack surface compared to EOAs
  • Delegatecall vulnerabilities – Untrusted delegatecalls can execute arbitrary code in wallet context
Delegatecall Attack Vector: The Bybit Hack

On February 21, 2025, cryptocurrency exchange Bybit suffered a $1.5 billion hack — the largest in crypto history. This wasn’t a smart contract vulnerability but an operational security failure exploiting Safe wallet’s delegatecall functionality.

Attack Mechanics:

Attackers compromised the Safe signing frontend used by all Bybit multisig signers. When signers authorized what appeared to be routine transactions, they were actually signing transactions that:

  1. Changed the implementation address of their Safe multisig wallet via delegatecall
  2. Replaced it with a malicious implementation granting attacker control
  3. Bypassed the multisig security entirely

The delegatecall opcode is particularly dangerous in smart contract wallets because it executes external code in the wallet’s context with full access to storage and balance.

Why Signers Didn’t Detect the Attack:

  • Malware modified the wallet interface to hide transaction details
  • Blind signing on hardware wallets — devices display only transaction hashes, not complete semantic information
  • Single verification interface without secondary confirmation mechanisms

Attack Scenario:

// Malicious contract
contract Malicious {
    // Storage slot 0 matches wallet's owner variable
    address public owner;

    function attack() external {
        // Changes the wallet's owner to attacker
        owner = msg.sender;
    }
}

// If wallet executes: delegatecall(malicious.attack())
// The attacker becomes the new owner

Lessons from Bybit:

  1. Disable delegatecall entirely in production wallets, or restrict it to whitelisted contracts
  2. Verify the operation field (0 = CALL, 1 = DELEGATECALL) before signing
  3. Implement secondary verification using independent tools (see below)
  4. Configure Safe Guards — Use on-chain security protocols to prevent unauthorized operations
Safe Guards: On-Chain Protection

Safe Guards are on-chain security modules that can prevent the Bybit-style attack at the protocol level. Guards implement pre-checks and post-checks for every transaction.

Example: ScopeGuard

function checkTransaction(
    address to,
    uint256 value,
    bytes memory data,
    Enum.Operation operation,
    ...
) external view override {
    // Prevent delegatecalls to untrusted addresses
    require(
        operation != Enum.Operation.DelegateCall ||
        allowedTargets[to].delegateCallAllowed,
        "Delegate call not allowed to this address"
    );

    // Whitelist target addresses
    require(allowedTargets[to].allowed, "Target address is not allowed");

    // Restrict ETH transfers
    if (value > 0) {
        require(allowedTargets[to].valueAllowed, "Cannot send ETH to this target");
    }

    // Whitelist function selectors
    if (data.length >= 4) {
        require(
            !allowedTargets[to].scoped ||
            allowedTargets[to].allowedFunctions[bytes4(data)],
            "Target function is not allowed"
        );
    }
}

Guard Use Cases:

  • Prevent all delegatecalls — Block operation type 1 entirely
  • Whitelist addresses — Only allow transactions to approved contracts
  • Function-level restrictions — Permit only specific function selectors
  • Timelocks — Delay high-value transactions for monitoring
  • Invariant checking — Verify state transitions after execution
Important:

Safe Guards could have prevented the Bybit hack entirely. If Bybit had configured a guard to block delegatecall operations or whitelist allowed targets, the malicious implementation swap would have failed on-chain, regardless of compromised frontends or blind signing.

For detailed analysis:

Transaction Verification Best Practices

Always verify Safe transactions before signing using independent tools. The Safe Transaction Hash Verification Tool provides cryptographic verification:

Usage Example:

# Verify a Safe transaction on Arbitrum
./safe_hashes.sh --network arbitrum \
  --address 0x111CEEee040739fD91D29C34C33E6B3E112F2177 \
  --nonce 234

Output includes:

  • Domain hash
  • Message hash
  • Safe transaction hash
  • Decoded method and parameters
  • Warnings for delegatecalls to untrusted addresses
Warning:

Smart contract wallets require thorough security audits. A vulnerability in wallet validation logic could enable unauthorized access to user funds.

Resources

Specifications

Videos

Further Reading

Analytics