Skip to content

Contribution model + shared placeholder foundation - #297

Draft
qu0b wants to merge 3 commits into
masterfrom
qu0b/contribution-foundations
Draft

qu0b wants to merge 3 commits into
masterfrom
qu0b/contribution-foundations

Conversation

@qu0b

@qu0b qu0b commented Oct 2, 2026 •

Copy link
Copy Markdown
Member

Why

Recent contributions (#289, #290, #291, #296) add workload-specific features to generic scenarios, e.g. two copies of a ~270-line CREATE2 target-pool package in eoatx and calltx. This PR proposes a structure where workloads are contributed at the highest layer that can express them, and core only accepts primitives.

Contribution model (docs/contributing-workloads.md)

  1. Spammer config: YAML composing generic scenarios (geastx, calltx, eoatx, factorydeploytx, taskrunner). Default.
  2. Plugin: custom Go logic, hosted by the contributor, loaded with --plugin <url>. Not reviewed by core.
  3. Core primitive: only what layers 1–2 are missing; must ship with its consumer, be generic, tested, and documented.

First primitive: shared placeholders

  • utils.Placeholders replaces three separate implementations (utils/abi.go, taskrunner, calltx). Resolution is innermost-first, so placeholders nest; unknown names are left untouched, so JSON and geas braces are safe.
  • New {create2:<factory>:<initcodehash>:<salt>}.
  • scenario.TxPlaceholders(walletPool, txIdx) adds {factory_address}; scenario.Create2FactoryAddress replaces the duplicated factory derivation in calltx.
  • eoatx: to is resolved per tx and validated at init.
  • geastx: {factory_address} is resolved in geas code/files.
  • Plugin symbols regenerated, so plugins can use all of the above.

One example per layer

Layer Example
Spammer config spammer-configs/create2-receiver-transfers.yaml: factorydeploytx + eoatx to {create2:...} targets
Plugin plugins/_example-delegation: deploy counter → EIP-7702 delegate an EOA → send txs to the EOA (receipt-dependent setup a config cannot express)
Core primitive This PR's {create2:...} / {factory_address} placeholders, mapped to the core checklist in the guide

Plugin verified on anvil: 40 txs → authority storage slot 0 = 40; passes validate-plugin as a directory and as the make plugins archive.

Proof

spammer-configs/create2-receiver-transfers.yaml expresses #289's CREATE2 use case (ETH transfers to a CREATE2 contract set) with factorydeploytx + eoatx and no scenario-specific Go code:

to: "{create2:{factory_address}:0xd092...a07a:{random:1000}}"

Verification

  • Scaled-down recipe (50 contracts, 100 transfers) on anvil: all 50 receivers have 1 KiB code and hold exactly 100 gwei total.
  • calltx regression with {factory_address} + {txid} in call_args: calldata contains the factorydeploytx factory address; txs succeed.
  • A Yaegi plugin calling scenario.TxPlaceholders passes spamoor-utils validate-plugin.
  • go test ./..., go vet ./... pass; staticcheck reports only the existing SA1019 warnings in generated symbols.

Open questions

  • Where plugins live: the guide assumes contributor-owned repos; a shared ethpandaops/spamoor-plugins repo is the alternative.
  • Config that brings its own plugin: a plugin: <url> import item would make plugin-backed library configs self-contained, but importing a config would then run remote Go code, so it must respect the disable-plugin-API setting. Not implemented here.
  • Recipe Min_Version: v1.2.5 assumes the next release.

Contributions go to the highest layer that can express them: spammer
config, plugin, or core primitive (docs/contributing-workloads.md).

The first primitive unifies the three placeholder implementations
(utils/abi.go, taskrunner, calltx) into utils.Placeholders with nested,
innermost-first resolution, and adds {create2:factory:hash:salt}.
scenario.TxPlaceholders adds {factory_address}; eoatx resolves --to per
tx, geastx resolves {factory_address} in geas code. Both are exported to
plugins.

spammer-configs/create2-receiver-transfers.yaml expresses ETH transfers
to a CREATE2 contract set with factorydeploytx + eoatx and no
scenario-specific Go code.

@redpandabot redpandabot Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Summary

The PR adds a shared placeholder resolver (utils/placeholders.go, scenario/placeholders.go) replacing three duplicated implementations, a CREATE2 address placeholder, per-tx --to resolution in eoatx, regenerated plugin symbols, a contribution-model guide, and a new EIP-7702 delegation plugin example. The refactor is coherent and the new example's constants check out (init-code hashes match); the only real defect is the salt parsing in the new CREATE2 resolver, which is still unfixed since the last review.

Issues

  • 🟡 utils/placeholders.go:102 — CREATE2 salt parsed with base 0, so leading-zero decimals become octal — see the thread on that line

Reviewed @ 296bec4d
"The bug is always in the last place you look — because you stop looking after you find it."

Comment thread utils/placeholders.go
if err != nil {
return common.Address{}, err
}
salt, ok := new(big.Int).SetString(parts[2], 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟢 salt parsed with base 0, so leading-zero decimal salts become octal

SetString(parts[2], 0) uses Go's base-0 mode: a salt like 0100 silently parses as octal 64 (and 0b/0o/underscore forms are also accepted), contradicting the documented 'decimal or 0x uint256' encoding and yielding a wrong CREATE2 address with no error. Parse 0x-prefixed salts separately and use base 10 otherwise.

qu0b added 2 commits October 6, 2026 17:35
Adds plugins/_example-delegation, an EIP-7702 delegated-counter plugin
whose receipt-dependent setup cannot be expressed as a spammer config,
and an Examples section in docs/contributing-workloads.md pointing to
the config, plugin and core-primitive references.
@redpandabot

redpandabot Bot commented Oct 6, 2026

Copy link
Copy Markdown

RedPandaBot v2 prototype

Reviewed head 296bec4d941c980b3c214979a9c5f3bb3e9ad184. Partial review: one or more lanes or scope sections were incomplete.

No verified findings.

Automatic approval is disabled for the v2 prototype.

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