Modification of Kode Sherpa Contract

In my previous article Generating Unit Tests From Kode Sherpa I discussed about unit tests generation and generated unit tests as approx 9 tests were failing so in this article we will now modify the test to foundry and then compile in foundry so that we can analyze that if the generated smart contract is adhering error free compilation from Kode Sherpa.

The test suite created looking at hardhat in foundry

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.20;

import "forge-std/Test.sol";

// --------------------------------------------------
// Minimal MockERC20 (self-contained)
// --------------------------------------------------
contract MockERC20 {
    string public name = "MockToken";
    string public symbol = "MTK";
    uint8 public decimals = 18;

    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;

    function mint(address to, uint256 amount) external {
        balanceOf[to] += amount;
    }

    function approve(address spender, uint256 amount) external returns (bool) {
        allowance[msg.sender][spender] = amount;
        return true;
    }

    function transfer(address to, uint256 amount) external returns (bool) {
        require(balanceOf[msg.sender] >= amount, "balance too low");
        balanceOf[msg.sender] -= amount;
        balanceOf[to] += amount;
        return true;
    }

    function transferFrom(address from, address to, uint256 amount) external returns (bool) {
        require(balanceOf[from] >= amount, "balance too low");
        require(allowance[from][msg.sender] >= amount, "allowance too low");

        allowance[from][msg.sender] -= amount;
        balanceOf[from] -= amount;
        balanceOf[to] += amount;

        return true;
    }
}

// --------------------------------------------------
// Import your staking contract
// --------------------------------------------------
import "../src/FixedAprSingleTokenStakingPullPayments.sol";

// --------------------------------------------------
// Test Contract
// --------------------------------------------------
contract FixedAprSingleTokenStakingTest is Test {
    MockERC20 stakingToken;
    FixedAprSingleTokenStakingPullPayments staking;

    address alice = address(1);
    address bob = address(2);

    uint256 stakeAmount = 1000 ether;
    uint256 stakeAmount2 = 250 ether;
    uint256 mintAmount = 1_000_000 ether;

    function setUp() public {
        stakingToken = new MockERC20();
        staking = new FixedAprSingleTokenStakingPullPayments(IERC20(address(stakingToken)));

        stakingToken.mint(alice, mintAmount);
        stakingToken.mint(bob, mintAmount);
    }

    // ----------------------------
    // Constructor
    // ----------------------------
    function testConstructor() public {
        assertEq(address(staking.stakingToken()), address(stakingToken));
        assertEq(staking.aprBps(), 500);
        assertEq(staking.totalStaked(), 0);
    }

    function testConstructorRevertZeroAddress() public {
        vm.expectRevert("staking token is zero");
         new FixedAprSingleTokenStakingPullPayments(IERC20(address(0)));
    }

    // ----------------------------
    // Stake
    // ----------------------------
    function testStake() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        assertEq(staking.stakedBalance(alice), stakeAmount);
        assertEq(staking.totalStaked(), stakeAmount);

        vm.stopPrank();
    }

    function testStakeRevertZero() public {
        vm.prank(alice);
        vm.expectRevert("amount=0");
        staking.stake(0);
    }

    function testStakeAccrual() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount + stakeAmount2);

        staking.stake(stakeAmount);

        vm.warp(block.timestamp + 30 days);

        staking.stake(stakeAmount2);

        assertGt(staking.owedBalance(alice), 0);

        vm.stopPrank();
    }

    // ----------------------------
    // Unstake
    // ----------------------------
    function testUnstake() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        staking.unstake(stakeAmount2);

        assertEq(staking.stakedBalance(alice), stakeAmount - stakeAmount2);
        assertEq(staking.owedBalance(alice), stakeAmount2);

        vm.stopPrank();
    }

    function testUnstakeWithRewards() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        vm.warp(block.timestamp + 60 days);

        staking.unstake(stakeAmount2);

        assertGt(staking.owedBalance(alice), stakeAmount2);

        vm.stopPrank();
    }

    // ----------------------------
    // Withdraw
    // ----------------------------
    function testWithdrawPrincipal() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        staking.unstake(stakeAmount2);

        uint256 owed = staking.owedBalance(alice);

        staking.withdraw();

        assertEq(staking.owedBalance(alice), 0);
        assertEq(stakingToken.balanceOf(alice), mintAmount - stakeAmount + owed);

        vm.stopPrank();
    }

    function testWithdrawRewards() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        vm.warp(block.timestamp + 90 days);

        uint256 beforeBal = stakingToken.balanceOf(alice);

        staking.withdraw();

        uint256 afterBal = stakingToken.balanceOf(alice);

        assertGt(afterBal, beforeBal);

        vm.stopPrank();
    }

    function testWithdrawRevert() public {
        vm.prank(alice);
        vm.expectRevert("nothing owed");
        staking.withdraw();
    }

    // ----------------------------
    // View functions
    // ----------------------------
    function testPendingRewardsGrowth() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount + stakeAmount2);

        staking.stake(stakeAmount);

        vm.warp(block.timestamp + 10 days);
        staking.stake(stakeAmount2);

        vm.warp(block.timestamp + 5 days);
        uint256 p1 = staking.pendingRewards(alice);

        vm.warp(block.timestamp + 5 days);
        uint256 p2 = staking.pendingRewards(alice);

        assertGt(p1, 0);
        assertGt(p2, p1);

        vm.stopPrank();
    }

    function testWithdrawable() public {
        vm.startPrank(alice);

        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);

        staking.unstake(stakeAmount2);

        assertEq(staking.withdrawable(alice), stakeAmount2);

        vm.stopPrank();
    }

    // ----------------------------
    // Multi-user
    // ----------------------------
    function testMultiUser() public {
        vm.startPrank(alice);
        stakingToken.approve(address(staking), stakeAmount);
        staking.stake(stakeAmount);
        vm.stopPrank();

        vm.startPrank(bob);
        stakingToken.approve(address(staking), stakeAmount2);
        staking.stake(stakeAmount2);
        vm.stopPrank();

        vm.warp(block.timestamp + 45 days);

        vm.prank(alice);
        staking.unstake(stakeAmount2);

        assertGt(staking.owedBalance(alice), stakeAmount2);
        assertEq(staking.owedBalance(bob), 0);
    }
}

Now based on the above test suite I ran the foundry test and this was my output

To further check if my test is utilizing 100 percent coverage so I ran forge coverage and this was my result

Based on this result I can fairly conclude that the below generated contract from Kode Sherpa is exhibiting 100 percent coverage for contract and test as well.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

/**
 * @title FixedAprSingleTokenStakingPullPayments
 * @author akb
 * @notice Single-token ERC20 staking with fixed immutable APR rewards (in bps) and pull-payment withdrawals.
 *         - Stake/unstake only update accounting (no user transfers).
 *         - withdraw() is the only function that transfers tokens to users (principal + rewards).
 */
contract FixedAprSingleTokenStakingPullPayments is ReentrancyGuard {
    using SafeERC20 for IERC20;

    /**
     * @notice ERC20 token that users stake and in which rewards are paid.
     */
    IERC20 public immutable stakingToken;

    /**
     * @notice Basis points denominator used for APR calculations.
     * @dev 10,000 bps = 100%.
     */
    uint256 public constant RATE_DENOMINATOR = 10_000;

    /**
     * @notice Number of seconds used as one year for APR calculations.
     * @dev Fixed to 365 days.
     */
    uint256 public constant YEAR = 365 days;

    /**
     * @notice Fixed APR expressed in basis points (bps).
     * @dev Immutable and set in the constructor. Example: 500 bps = 5.00% APR.
     */
    uint256 public immutable aprBps;

    /**
     * @notice Amount of principal currently staked by each user.
     */
    mapping(address => uint256) public stakedBalance;

    /**
     * @notice Pull-payment balance owed to each user (principal moved out + accrued rewards).
     */
    mapping(address => uint256) public owedBalance;

    /**
     * @notice Last timestamp at which rewards were accrued/settled for each user.
     */
    mapping(address => uint256) public lastAccrualTime;

    /**
     * @notice Total principal staked across all users.
     */
    uint256 public totalStaked;

    // Events (must match tests exactly)
    event Staked(address indexed user, uint256 amount);
    event Unstaked(address indexed user, uint256 amount, uint256 creditedToOwed);
    event RewardsAccrued(address indexed user, uint256 reward, uint256 fromTime, uint256 toTime);
    event Withdrawn(address indexed user, uint256 amount);

    /**
     * @notice Creates the staking contract for a given ERC20 token.
     * @param _stakingToken The ERC20 token to be staked and used for reward payouts.
     */
    constructor(IERC20 _stakingToken) {
        require(address(_stakingToken) != address(0), "staking token is zero");
        stakingToken = _stakingToken;

        // Immutable APR set to 5.00% (500 bps)
        aprBps = 500;
    }

    /**
     * @notice Stake tokens. Requires prior approval.
     * @dev Settles rewards up to now before changing principal.
     * @param amount The amount of tokens to stake.
     */
    function stake(uint256 amount) external nonReentrant {
        require(amount > 0, "amount=0");

        // Must initialize lastAccrualTime on first stake (via _accrue)
        _accrue(msg.sender);

        stakingToken.safeTransferFrom(msg.sender, address(this), amount);

        stakedBalance[msg.sender] += amount;
        totalStaked += amount;

        emit Staked(msg.sender, amount);
    }

    /**
     * @notice Unstake tokens (principal). Does NOT transfer tokens to the user.
     * @dev Settles rewards up to now, then moves unstaked principal into owedBalance (pull pattern).
     * @param amount The amount of principal to unstake.
     */
    function unstake(uint256 amount) external nonReentrant {
        require(amount > 0, "amount=0");

        _accrue(msg.sender);

        require(stakedBalance[msg.sender] >= amount, "insufficient staked");

        stakedBalance[msg.sender] -= amount;
        totalStaked -= amount;

        owedBalance[msg.sender] += amount;

        emit Unstaked(msg.sender, amount, amount);
    }

    /**
     * @notice Withdraw owed tokens (principal + rewards).
     * @dev This is the ONLY function that transfers tokens to users.
     */
    function withdraw() external nonReentrant {
        _accrue(msg.sender);

        uint256 owed = owedBalance[msg.sender];
        require(owed > 0, "nothing owed");

        owedBalance[msg.sender] = 0;
        stakingToken.safeTransfer(msg.sender, owed);

        emit Withdrawn(msg.sender, owed);
    }

    /**
     * @notice View function to estimate pending rewards since last accrual (not yet credited to owedBalance).
     * @param user The address to query.
     * @return The amount of rewards accrued since the last checkpoint.
     */
    function pendingRewards(address user) external view returns (uint256) {
        uint256 principal = stakedBalance[user];
        if (principal == 0) return 0;

        uint256 last = lastAccrualTime[user];
        if (last == 0) return 0;

        uint256 elapsed = block.timestamp - last;
        if (elapsed == 0) return 0;

        return (principal * aprBps * elapsed) / YEAR / RATE_DENOMINATOR;
    }

    /**
     * @notice View function for total withdrawable amount (already owed; does not include unaccrued pending rewards).
     */
    function withdrawable(address user) external view returns (uint256) {
        return owedBalance[user];
    }

    /**
     * @dev Accrues rewards for `user` from lastAccrualTime to now and credits them to owedBalance.
     *      Emits RewardsAccrued when reward > 0 with fromTime=last and toTime=block.timestamp.
     */
    function _accrue(address user) internal {
        uint256 last = lastAccrualTime[user];

        // Initialize checkpoint on first interaction; no retroactive rewards.
        if (last == 0) {
            lastAccrualTime[user] = block.timestamp;
            return;
        }

        uint256 principal = stakedBalance[user];
        uint256 toTime = block.timestamp;

        if (toTime <= last) return;

        // No principal: just move checkpoint forward.
        if (principal == 0) {
            lastAccrualTime[user] = toTime;
            return;
        }

        uint256 elapsed = toTime - last;
        uint256 reward = (principal * aprBps * elapsed) / YEAR / RATE_DENOMINATOR;

        lastAccrualTime[user] = toTime;

        if (reward > 0) {
            owedBalance[user] += reward;
            emit RewardsAccrued(user, reward, last, toTime);
        }
    }
}

The only tweak I did was introducing ERC20 interfaces in the contract and then adding reentracny guard properly pointing towards util folder rather than security folder.

In the next lesson we will further explore Kode Sherpa features.

Prometheus Has a Free API: Here’s How to Use It for Metrics Automation

Prometheus is the industry standard for metrics collection, and its HTTP API is completely free to use. You can query metrics, manage alerts, check targets, and build custom monitoring tools — all via simple HTTP calls.

Why Use the Prometheus API?

  • Query any metric with PromQL via HTTP
  • Build custom dashboards without Grafana
  • Automate alert management and silence rules
  • Monitor scrape targets and their health status

Getting Started

Prometheus API runs on port 9090 by default:

# Instant query
curl -s "http://localhost:9090/api/v1/query?query=up" | jq '.data.result[] | {instance: .metric.instance, job: .metric.job, value: .value[1]}'

# Range query (last hour, 15s steps)
curl -s "http://localhost:9090/api/v1/query_range?query=rate(http_requests_total[5m])&start=$(date -d '1 hour ago' +%s)&end=$(date +%s)&step=15" | jq '.data.result[0].values | length'

Python Client

import requests
from datetime import datetime, timedelta

PROM_URL = "http://localhost:9090"

def query_instant(promql):
    resp = requests.get(f"{PROM_URL}/api/v1/query", params={"query": promql})
    return resp.json()["data"]["result"]

def query_range(promql, hours=1, step="15s"):
    end = datetime.now()
    start = end - timedelta(hours=hours)
    resp = requests.get(f"{PROM_URL}/api/v1/query_range", params={
        "query": promql,
        "start": start.timestamp(),
        "end": end.timestamp(),
        "step": step
    })
    return resp.json()["data"]["result"]

# Get all up/down targets
targets = query_instant("up")
for t in targets:
    status = "UP" if t["value"][1] == "1" else "DOWN"
    print(f"{t['metric']['job']:20s} {t['metric']['instance']:30s} {status}")

Build a Health Dashboard

def service_health_report():
    metrics = {
        "Request Rate": "sum(rate(http_requests_total[5m]))",
        "Error Rate": "sum(rate(http_requests_total{status=~'5..'}[5m])) / sum(rate(http_requests_total[5m])) * 100",
        "P99 Latency (ms)": "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) * 1000",
        "Active Connections": "sum(http_connections_active)",
        "CPU Usage (%)": "rate(process_cpu_seconds_total[5m]) * 100",
        "Memory (MB)": "process_resident_memory_bytes / 1024 / 1024"
    }

    print("=== Service Health Report ===")
    for name, query in metrics.items():
        result = query_instant(query)
        if result:
            value = float(result[0]["value"][1])
            print(f"{name:25s}: {value:.2f}")
        else:
            print(f"{name:25s}: N/A")

service_health_report()

Manage Alerting Rules

# Get all active alerts
curl -s "http://localhost:9090/api/v1/alerts" | jq '.data.alerts[] | {name: .labels.alertname, state: .state, severity: .labels.severity}'

# Get all alerting rules
curl -s "http://localhost:9090/api/v1/rules" | jq '.data.groups[] | {group: .name, rules: [.rules[] | {alert: .name, state: .state, query: .query}]}'

Check Scrape Targets

def check_targets():
    resp = requests.get(f"{PROM_URL}/api/v1/targets")
    targets = resp.json()["data"]["activeTargets"]

    healthy = sum(1 for t in targets if t["health"] == "up")
    unhealthy = [t for t in targets if t["health"] != "up"]

    print(f"Targets: {healthy}/{len(targets)} healthy")

    if unhealthy:
        print("nUnhealthy targets:")
        for t in unhealthy:
            print(f"  {t['labels']['job']:20s} {t['scrapeUrl']:40s} Error: {t.get('lastError', 'unknown')}")

check_targets()

Automated SLO Monitoring

def check_slo(service, target_availability=99.9, window_hours=24):
    # Calculate error budget
    query = f'1 - (sum(rate(http_requests_total{{job="{service}",status=~"5.."}}[{window_hours}h])) / sum(rate(http_requests_total{{job="{service}"}}[{window_hours}h])))'
    result = query_instant(query)

    if result:
        availability = float(result[0]["value"][1]) * 100
        budget_remaining = availability - target_availability

        print(f"Service: {service}")
        print(f"  Availability: {availability:.3f}%")
        print(f"  Target: {target_availability}%")
        print(f"  Error Budget: {budget_remaining:+.3f}%")

        if budget_remaining < 0:
            print(f"  STATUS: SLO VIOLATED!")
        elif budget_remaining < 0.01:
            print(f"  STATUS: Warning - budget almost exhausted")
        else:
            print(f"  STATUS: Healthy")

check_slo("api-server")
check_slo("payment-service", target_availability=99.99)

Real-World Use Case

A fintech team built an automated SLO tracker using the Prometheus API. Every hour, it calculated error budgets for 50+ services and posted a summary to Slack. When a service burned through 50% of its error budget, it automatically created a Jira ticket. Result: mean time to detection dropped from 45 minutes to 3 minutes.

What You Can Build

  • Custom SLO dashboard with error budget tracking
  • Automated capacity planning based on growth trends
  • Anomaly detector comparing current metrics to baselines
  • Cost optimizer correlating resource usage with cloud spend
  • Incident reporter generating post-mortem data automatically

Need custom monitoring solutions? I build observability tools and data pipelines.

Email me: [email protected]
Check out my developer tools: https://apify.com/spinov001

EVMbench Deep Dive: Can AI Agents Actually Find Smart Contract Bugs Better Than Human Auditors? We Tested the Claims

TL;DR

OpenAI and Paradigm’s EVMbench benchmark claims GPT-5.3-Codex can exploit 71% of smart contract vulnerabilities autonomously. BlockSec’s re-evaluation in March 2026 challenged those numbers, finding scaffold design inflated exploit scores. Meanwhile, Anatomist Security’s AI agent earned the largest-ever AI bug bounty ($400K) for finding a critical Solana vulnerability. This article breaks down what EVMbench actually measures, where AI auditing genuinely works today, where it fails catastrophically, and the practical hybrid workflow that outperforms either humans or AI alone.

The State of AI Auditing in March 2026

Three events in the past six weeks have forced a reckoning in smart contract security:

  1. EVMbench launch (February 2026): OpenAI and Paradigm release the first serious benchmark for AI agents auditing smart contracts — 117 vulnerabilities across 40 audits
  2. BlockSec re-evaluation (March 2026): Independent testing suggests EVMbench’s exploit scores are inflated by scaffold design, but confirms AI detection capabilities are real
  3. Anatomist Security’s $400K bounty (March 2026): An AI agent autonomously discovers a critical vulnerability in the Solana blockchain itself — not a DeFi app, the L1

These aren’t incremental improvements. They represent a phase transition in how we should think about smart contract security tooling.

What EVMbench Actually Measures

EVMbench evaluates three distinct capabilities:

Detect Mode

The agent audits a smart contract repository and identifies known vulnerabilities. Scored on recall — did the agent find the bugs that human auditors found?

Patch Mode

The agent modifies vulnerable contracts to eliminate exploitability while preserving intended functionality. Verified through automated tests.

Exploit Mode

The agent executes end-to-end fund-draining attacks against contracts deployed on a sandboxed Anvil blockchain. Grading is programmatic — did funds actually move?

The benchmark draws from 117 curated vulnerabilities, mostly from Code4rena audit competitions, plus scenarios from the Tempo blockchain (a payment-focused L1).

The Headline Numbers

Model Detect (Recall) Patch (Success) Exploit (Success)
GPT-5.3-Codex ~45% ~38% 71.0%
GPT-5 ~30% ~25% 33.3%
Claude Opus 4.6 ~52% ~35% ~48%

The exploit numbers are striking — GPT-5.3-Codex doubled its predecessor’s exploit rate in six months. But the detect and patch numbers tell a different story: AI agents still miss more than half of known vulnerabilities and fail to fix most of the ones they find.

BlockSec’s Reality Check

In March 2026, BlockSec published a re-evaluation of EVMbench that raised important methodological concerns:

Scaffold Bias in Exploit Mode: EVMbench’s exploit harness provides agents with deployment scripts, contract ABIs, and in some cases partial proof-of-concept code. In real auditing, none of this exists. The exploit task essentially asks: “Given a vulnerability and a test environment, can you write working exploit code?” — which is different from: “Can you find and exploit a vulnerability from scratch?”

Detection Is the Real Signal: BlockSec found that Claude Opus 4.6 successfully identified a significant number of real-world vulnerabilities in detection mode — without the scaffold assistance. This is closer to actual auditing work.

The Exploit ≠ Audit Paradox: An agent that’s great at exploiting known bugs in prepared environments isn’t necessarily great at finding unknown bugs in production code. EVMbench conflates execution capability with discovery capability.

What This Means for Practitioners

Don’t use EVMbench scores to decide whether AI can replace your auditor. Use them to understand which subtasks of auditing AI handles well:

  • AI is good at: Executing known attack patterns, generating exploit PoCs, identifying vulnerability classes it’s been trained on
  • AI is bad at: Exhaustive codebase review, finding novel vulnerability classes, understanding protocol-specific economic logic, cross-contract interaction analysis

The Anatomist Security Breakthrough

While EVMbench debates methodology, Anatomist Security demonstrated something more important: an AI agent finding a real critical vulnerability in production infrastructure.

The details:

  • Target: Solana L1 blockchain (not a DeFi app — the base layer)
  • Vulnerability: Critical severity, specific details undisclosed per responsible disclosure
  • Bounty: $400,000 — largest ever awarded to an AI
  • Previous work: Same team’s AI found the first Remote Code Execution vulnerability on Solana

This is qualitatively different from EVMbench benchmarks. The agent wasn’t given a curated vulnerability to exploit in a sandbox. It autonomously analyzed production code and found a bug that human researchers had missed.

Why This Matters More Than Benchmarks

Benchmarks measure capability in controlled environments. Anatomist’s result demonstrates capability in the wild. The gap between benchmark performance and real-world performance is where most AI tools fail — and where the $400K bounty proves at least some AI approaches actually deliver.

Building a Practical AI-Augmented Audit Workflow

Based on EVMbench results, BlockSec’s analysis, and real-world outcomes, here’s a workflow that leverages AI strengths while compensating for its weaknesses:

Phase 1: AI-First Sweep (Hours 1-4)

Run multiple AI agents in parallel on the target codebase:

# Example: Using multiple AI tools for initial sweep
# Tool 1: Static analysis with AI classification
slither . --json slither-output.json
cat slither-output.json | ai-classifier --model claude-opus --context "DeFi lending protocol"

# Tool 2: AI-powered code review
ai-audit --model gpt-5.3 --scope contracts/ --checklist common-defi-vulns.yaml

# Tool 3: Pattern matching against known exploits
semgrep --config p/smart-contracts contracts/

What you’re looking for: Known vulnerability patterns, reentrancy, access control issues, oracle dependencies, unchecked return values, integer overflow potential.

What AI catches here: ~50% of vulnerability classes, particularly those with well-known patterns.

Phase 2: AI-Generated Attack Surface Map (Hours 4-8)

Use AI to map the protocol’s economic attack surface:

Prompt: "Analyze this DeFi protocol's architecture. Map every external call, 
every price dependency, every privileged role, and every state transition that 
involves value transfer. Identify assumptions that each component makes about 
other components."

This is where large context windows shine. An AI agent can hold the entire protocol in context and trace value flows across contracts — something that takes human auditors days to do manually.

Phase 3: Human Deep Dive on AI-Flagged Areas (Hours 8-40)

The human auditor focuses exclusively on:

  1. AI-flagged potential issues — verify, dismiss false positives, investigate true positives
  2. Areas AI explicitly marked as “uncertain” — these often contain the highest-severity bugs
  3. Protocol-specific economic logic — AI doesn’t understand tokenomics, governance dynamics, or market conditions
  4. Cross-protocol interactions — composability risks that span multiple contracts and external protocols

Phase 4: AI-Assisted Exploit Verification (Hours 40-48)

For every confirmed vulnerability, use AI to generate working PoCs:

// AI prompt: "Write a Foundry test that exploits this vulnerability.
// The vulnerable function is X in contract Y.
// The exploit should demonstrate fund extraction."

contract ExploitTest is Test {
    // AI generates the full exploit PoC
    function testExploit() public {
        // Setup
        vm.createSelectFork("mainnet", BLOCK_NUMBER);

        // Attack steps (AI-generated)
        // ...

        // Verify funds were extracted
        assertGt(token.balanceOf(attacker), 0);
    }
}

This is where EVMbench’s 71% exploit success rate is actually useful — AI excels at turning known vulnerabilities into working PoCs.

Phase 5: AI-Powered Report Generation (Hours 48-52)

AI generates the initial audit report draft from findings. Human auditor reviews, corrects, and adds nuance. This cuts report writing time by ~60%.

The Tools That Actually Work in 2026

For Detection

Tool Type Best For Limitation
Slither Static analysis Known patterns, data flow High false positive rate
Cyfrin Aderyn AST-based analysis Solidity-specific patterns Limited to known detectors
QuillShield AI-powered analysis Logical errors, novel patterns Requires integration setup
Claude/GPT (direct) LLM review Broad understanding, explanation Context limits, hallucination

For Exploitation/Testing

Tool Type Best For Limitation
Foundry Testing framework Fast fuzzing, fork testing Requires test writing
Echidna Property-based fuzzing Invariant violations Property definition is manual
Medusa Parallel fuzzing Throughput, coverage Experimental
Certora Formal verification Mathematical guarantees Steep learning curve

For Monitoring (Post-Deployment)

Tool Type Best For Limitation
Tenderly Firewall AI monitoring Real-time threat detection Cost at scale
OpenZeppelin Sentinel Automated response Auto-pause on anomaly Configuration complexity
Forta Detection network Community-driven alerts Signal-to-noise ratio

What AI Can’t Do (Yet)

1. Understand Economic Context

AI doesn’t know that a lending protocol’s collateral factor is set too aggressively for the asset’s real liquidity. The YieldBlox exploit ($10.97M, February 2026) succeeded because the oracle was technically correct but economically meaningless — no AI tool would have flagged “insufficient market liquidity for oracle reliability” as a vulnerability.

2. Reason About Governance Dynamics

The Moonwell governance attack (March 2026) required understanding that a $1,808 investment in governance tokens could create a proposal to drain $1M. AI can’t model voter behavior, quorum dynamics, or the social engineering required to pass malicious proposals.

3. Anticipate Novel Attack Vectors

The GlassWorm malware using Solana memo fields as a C2 channel was a fundamentally creative attack. AI auditing tools look for patterns they’ve been trained on. When someone invents a new attack class, AI is the last to catch it.

4. Audit Across Trust Boundaries

Modern DeFi protocols don’t exist in isolation. They depend on oracles, bridges, governance tokens, liquidity pools, and off-chain infrastructure (like Langflow instances running AI agents with wallet access — see CVE-2026-33017). No AI tool currently maps and audits these cross-boundary trust assumptions.

The Verdict: AI as Force Multiplier, Not Replacement

EVMbench proves AI agents have crossed the threshold of usefulness for smart contract security. But it also proves they’re nowhere near sufficient on their own.

The optimal 2026 audit workflow:

  • AI handles the first 50% of vulnerability detection (breadth)
  • AI generates exploit PoCs 3-5x faster than manual writing
  • AI cuts report generation time by 60%
  • Human auditors spend their time on the remaining 50% that AI misses (depth)
  • Human auditors validate AI findings and catch false positives

The numbers: A competent human auditor + AI tools finds ~80% of vulnerabilities. A human auditor alone finds ~65%. AI alone finds ~50%. The combination isn’t additive — it’s synergistic, because AI and humans tend to find different types of bugs.

The cost: AI-assisted audits cost ~30% less in auditor-hours while achieving higher coverage. This isn’t about replacing auditors — it’s about making the same auditor 2x more effective.

Action Items for Protocol Teams

  1. Today: Add Slither + AI classification to your CI/CD pipeline — it catches low-hanging fruit automatically
  2. This week: Run your protocol through at least one AI-powered audit tool (QuillShield, or direct LLM review) before your human audit
  3. Before your next audit: Prepare an AI-friendly audit package — clear documentation, architectural diagrams, and invariant specifications make AI tools dramatically more effective
  4. Post-deployment: Implement AI-powered monitoring (Tenderly Firewall or OpenZeppelin Sentinel) — the $137M lost in Q1 2026 proves that pre-deployment audits aren’t enough

The question isn’t whether to use AI in smart contract security. It’s how to use it without developing a false sense of security. EVMbench gives us the data to make that distinction. Use it wisely.

DreamWork Security publishes daily DeFi security research. Follow @ohmygod on dev.to for vulnerability analysis, audit tooling, and defense patterns.

ÖZEL HABER GÜNDEMİ / 28 Mart 2026

Telefonlarda 5G’yi kullanabilmek için şebeke ayarı gerekiyorUyumlu telefon ve SIM karta sahip, hem operatör hem de telefonda 5G sistemlerini aktif eden kullanıcılar, 1 Nisan itibarıyla kapsama alanı içinde 5G’yi kullanabilecekBu teknolojiyi kullanmak için telefonun…

Debugging Kubernetes is Painful… So I Built an AI Tool to Fix It

🤯 The Problem

Debugging Kubernetes is one of the most frustrating parts of DevOps.

You check logs.
You run kubectl describe.
You search errors manually.

And still…

👉 You don’t know what actually went wrong.
This process is:
• Time-consuming
• Repetitive
• Mentally exhausting

So I asked myself:
What if Kubernetes debugging could be automated?

Architectural High level Overview

💡 The Idea
Instead of manually analyzing logs and pod states, I wanted a system that could:
• Detect failing pods automatically
• Analyze logs in real-time
• Identify root cause
• Suggest fixes

That’s how KubeAI was born — an AI-powered Kubernetes debugger.

🏗️** What I Built**
I created a complete end-to-end system:
• FastAPI Backend → Handles analysis
• Kubernetes Integration → Fetches pods and logs
• AI Engine → Detects issues and generates insights
• Streamlit Dashboard → Visual interface

🔍 How It Works

1. Pod Monitoring
The system fetches all pods from a namespace:
kubectl get pods

2. State-Based Detection
It detects failures like:
• CrashLoopBackOff
• ImagePullBackOff
• ErrImagePull

These are marked as CRITICAL issues.

3. Log Analysis
Logs are parsed and analyzed:
• ERROR logs → Warning
• Repeated failures → Critical

4. **AI Insight Generation
Instead of raw logs, the system generates:
Issue: CrashLoopBackOff
Root Cause: Container failed to start properly
Fix: Check container logs and deployment configuration
Confidence: 95%

📊 **Dashboard Features**

I built a real-time dashboard using Streamlit:
• Cluster summary (Healthy vs Unhealthy pods)
• Top issues panel
• Pod-level issue breakdown
• AI-generated insights
• Auto-refresh (live monitoring)
• Filter: Show only unhealthy pods

💥 Demo Scenario
To test the system, I simulated real-world failures.
Scenario 1: Runtime Errors
I injected error logs into the application.
The system automatically detected issues.

Scenario 2: CrashLoopBackOff
I intentionally broke container startup.
Kubernetes marked the pod unhealthy.
KubeAI detected it and explained the issue.

🧠 Key Learning
The biggest realization:
Logs alone are not enough.
You need to combine:
• Pod state
• Logs
• Context
That’s where intelligent systems make a difference.

🚀 Impact
This tool helps:
• Reduce debugging time
• Automate root cause analysis
• Improve developer productivity
**
🔮 What’s Next
**
I’m planning to extend this into:
• Cloud deployment (AWS)
• Historical tracking
• LLM-based deeper analysis
• Multi-user SaaS
Final Dashboard with Auto refresh:

🔗 Project Link

GitHub Link