Skip to content

Add tenderly-testnet skill#259

Draft
tcxcx wants to merge 2 commits into
vercel-labs:mainfrom
tcxcx:add-tenderly-testnet-skill
Draft

Add tenderly-testnet skill#259
tcxcx wants to merge 2 commits into
vercel-labs:mainfrom
tcxcx:add-tenderly-testnet-skill

Conversation

@tcxcx

@tcxcx tcxcx commented May 14, 2026

Copy link
Copy Markdown

Summary

Adds a new tenderly-testnet skill that sets up a Tenderly Virtual TestNet (testnet-only, refuses mainnet) and ends with every deployed contract properly verified + named in the Tenderly dashboard's Contracts tab — not the Wallets tab, which is where the obvious-looking POST /wallet endpoint silently lands them.

The skill captures lessons that aren't in Tenderly's published docs:

  • POST /wallet mis-classifies contract addresses as account_type=wallet — they show up under Wallets, source isn't attached, traces stay opaque.
  • The official path is forge verify-contract --verifier custom --verifier-url <tenderly-etherscan-compat> — uploads source, sets account_type=contract, and unlocks decoded traces in the dashboard.
  • Tenderly's verifier rejects forge --guess-constructor-args ("Action not supported"). Args must be encoded manually with cast abi-encode.
  • Re-verifying an already-verified contract is idempotent — returns Pass - Verified again, no special handling needed.
  • Free-plan caps worth planning around: 20 monitored addresses per project, 2 vnets, max block height per vnet, TUs/s rate limit (use forge --slow to spread bursts).
  • The rename / tag / bulk-delete REST endpoints needed to manage a project — none appear in the published API reference.

Layout

skills/tenderly-testnet/
├── LICENSE
├── README.md
├── SKILL.md                       # 343 lines, frontmatter matches the format in CLAUDE.md
└── scripts/
    ├── tenderly-verify-many.sh    # verify + name everything in a deployments manifest
    └── tenderly-verify-one.sh     # verify + name a single contract
skills/tenderly-testnet.zip

Both scripts resolve their manifest argument to an absolute path before any internal cd — guards against the silent-broken-read bug I hit when first writing them with relative paths.

Test plan

  • SKILL.md frontmatter matches the format documented in CLAUDE.md (name + description + metadata)
  • Under the 500-line guidance (343 lines)
  • Hard-refuses mainnet network IDs (1, 10, 137, 8453, 42161, 43114, 130)
  • Scripts use #!/bin/bash + set -e
  • Verified end-to-end on Base Sepolia + Unichain Sepolia in a real project: 10 contracts moved from Wallets → Contracts, source-decoded, named.

🤖 Generated with Claude Code

@vercel

vercel Bot commented May 14, 2026

Copy link
Copy Markdown

@tcxcx is attempting to deploy a commit to the Vercel Team on Vercel.

A member of the Team first needs to authorize it.

@@ -0,0 +1,94 @@
#!/bin/bash

@vercel vercel Bot May 14, 2026

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing set -o pipefail causes forge verify-contract failures to be silently ignored when piped through tail

Fix on Vercel

Comment thread skills/tenderly-testnet/scripts/tenderly-verify-many.sh
Sets up a Tenderly Virtual TestNet (testnet-only, refuses mainnet), deploys
contracts to it or to a real public testnet Tenderly indexes, and ends with
every contract verified + named in the dashboard's Contracts tab — not the
Wallets tab, which is where the obvious `POST /wallet` endpoint silently
lands them.

Captures lessons that aren't in Tenderly's published docs:

- The /wallet REST endpoint mis-classifies contracts as wallets. The
  Foundry verifier path is the only one that surfaces a contract under
  the Contracts tab with source-decoded traces.
- Tenderly's verifier rejects forge --guess-constructor-args ("Action not
  supported") — encode args manually with cast abi-encode.
- Re-verifying is idempotent (returns Pass - Verified).
- Free-plan caps to plan around: 20 monitored addresses, 2 vnets, max
  block height per vnet, TUs/s rate limit (mitigate with forge --slow).
- The rename / tag / bulk-delete REST endpoints needed to manage a
  project (none appear in the official API reference).

Ships two reusable bash helpers:
- scripts/tenderly-verify-one.sh
- scripts/tenderly-verify-many.sh

Both resolve manifest paths to absolute before any cd to avoid the
silent-broken-read bug that bit me when I first wrote them with relative
paths.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@tcxcx
tcxcx force-pushed the add-tenderly-testnet-skill branch from 4c679f7 to 14979b9 Compare May 14, 2026 07:51
@tcxcx

tcxcx commented May 14, 2026

Copy link
Copy Markdown
Author

Fixed in 14979b9 — added set -eo pipefail to both verify scripts. Forge failures now propagate through tail -N instead of being swallowed.

Working on the verified-signature side next (need to register the SSH key as a GitHub signing key first).

…-slot patterns

Bumps version to 1.1.0. Adds five new sections to SKILL.md covering live-
chain test patterns that came out of an extended Tenderly dogfood session:

Step 10 — Simulate API for integration tests
  Personas pattern (whale/mid/small EOAs with state_objects-overridden
  ERC-20 balances + allowances). simulate-bundle for sequences where
  state needs to propagate (ERC-4626 totalSupply, lending bookkeeping).
  Pyth-fresh bundle: fetch Hermes VAA at runtime + updatePriceFeeds to
  flip OracleStale reverts to passes on testnet feeds.

Step 11 — Storage layout debugging
  forge inspect ... storage-layout is the only authoritative source. OZ
  v5's transient-storage ReentrancyGuard frees slot 0 for the child's
  first state variable, breaking the "ReentrancyGuard owns slot 0"
  assumption. cast storage verification pattern.

Step 12 — Mock contracts via setCode
  MockMTStub pattern for stubbing CCTP V2 MessageTransmitter (or any
  external dependency): compile a tiny Solidity stub, extract
  deployedBytecode, use as state_objects.<addr>.code with packed storage
  (address low 20B + uint96 high 12B in slot 0).

Step 13 — Universal Router + Permit2 sim patterns
  Permit2.allowance storage derivation for the triple-nested mapping at
  slot 1 (allowance owner→token→spender PackedAllowance). Pack helper:
  amount uint160 | expiration uint48 | nonce uint48 in one 32-byte slot.

Step 14 — Forks deprecated → primed vnet workflow
  POST /fork returns 410 Gone since mid-2025 ("Forks are deprecated.
  Please use Virtual Testnets"). Migration: vnet + admin RPC priming
  (tenderly_setBalance, tenderly_setErc20Balance) + sim against vnet's
  Public RPC instead of /simulate.

Also updates:
- Undocumented endpoints table with /simulate, /simulate-bundle, and the
  410-Gone /fork.
- README intro to cover the live-state-sim use case + reference the
  example protocol it was extracted from (CCTP V2 cross-chain stack
  with Uniswap v4 hook + Morpho Blue hub).
- LICENSE, frontmatter version bump 1.0.0 → 1.1.0.

All script files unchanged.
@tcxcx

tcxcx commented May 14, 2026

Copy link
Copy Markdown
Author

Updated to v1.1.0 with five new sections covering live-chain integration
testing patterns extracted from a longer Tenderly dogfood session on a
cross-chain stack (CCTP V2 + Uniswap v4 hook + Morpho Blue + Pyth pull
oracle):

  • Step 10 — Simulate API — persona pattern with state_objects-overridden
    ERC-20 balances/allowances, simulate-bundle for sequences that need
    state propagation (ERC-4626 totalSupply, lending bookkeeping), and the
    Pyth-fresh-VAA bundle that flips testnet OracleStale reverts to passes.
  • Step 11 — Storage layout debuggingforge inspect ... storage-layout
    as the only authoritative source. OZ v5's transient-storage ReentrancyGuard
    trap (slot 0 reassignment).
  • Step 12 — Mock contracts via setCodeMockMTStub pattern for stubbing
    any external dependency (CCTP V2 MessageTransmitter, Chainlink callback, …)
    with packed-storage runtime override.
  • Step 13 — UR + Permit2 sim patterns — triple-nested allowance slot
    derivation + PackedAllowance (uint160 | uint48 | uint48) packing.
  • Step 14 — Forks deprecated → primed vnet workflow — the legacy
    POST /fork returns 410 Gone since mid-2025; the migration is a
    vnet + admin RPC priming.

Plus an updated /simulate and /simulate-bundle line in the undocumented-
endpoints table, and an Example use case block in the README that points
at the protocol the patterns came from.

Re-zipped. All script files unchanged.

@tcxcx
tcxcx marked this pull request as draft May 14, 2026 18:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant