feat(contracts): ArcCycleExecutor + CREATE2 deploy + key-management design (Phase 3, WP 7908/7909/7910) #9
No reviewers
Labels
No labels
auto-merge
auto-merge
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
fortiblox/arc-mev-bot!9
Loading…
Reference in a new issue
No description provided.
Delete branch "sec/phase3-executor"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Phase 3 — WP 7908 / 7909 / 7910 (security-director lane
sec)What lands
contracts/Foundry project:ArcCycleExecutor+UniV2Adapter(kind 0) + reserved kinds 1-4 (revertUnsupportedKind),SafeTransfer, CREATE2Deploy.s.solwithpredict(), 40 tests (35 unit incl. fuzz, 3 deploy, 2 fork gated onARC_RPC_URL),.gas-snapshot, full ABI/encoding/chain-facts incontracts/README.md.docs/key-management.md— key locations, safe generation + derive-back, wiring, rotation, funding rule..gitignore— one line for forgedry-run/simulation artefacts.Deltas vs. the brief / architecture (I win on the Solidity side; nothing in
docs/architecture.mdneeds changing)docs/architecture.md§3 (5 fields, selector0x7328892b). The brief's "fee bps per hop or per pool" is implemented as an owner-curated per-pool registry (setPoolFee,poolFeeBps, default 30 bps) — the hot key cannot tamper with quote math, and Phase 4's encoding is unchanged.lib/forge-std/VENDORED.md) rather than a submodule: PR #5'sforge-testsjob checks out with a rawgit fetch --depth 1+checkout FETCH_HEAD(no submodule init), so a submodule would be empty in CI. Two upstream comment lines carrysecret-scan:allow(full commit SHAs in URLs,token-40hexfalse positives). This is the one external dependency;.gitmoduleswas not added.docs/architecture.md§2 marksfee_bps"unverified per factory": verified 30 bps on all 8 pools / both pair implementations (README §3). Project-director can flip that row.Evidence
forge test→ 38 passed, 0 failed, 2 skipped (fork). On the box withARC_RPC_URL=http://127.0.0.1:8545:test_Fork_Impl1_QuoteIsExactandtest_Fork_Impl2_QuoteIsExactPASS against the real pair bytecode (received == 30-bps quote; 29 bps refused by the pair).amountOutwith floor division.eth_callon the real node with--override-code/--override-state/--override-balanceat the predicted address: USDC→ARC_TEST→USDC on0xeDd3…/0x194c…returned312813= exactly the quoted profit (calldata 452 bytes).SIMULATION COMPLETE, predicted == deployed0xD9ec…9aad(placeholder args), 2 693 964 gas. Nothing broadcast.0x3600…= 6-dec view of native balance (native_wei // 1e12).For the CEO peer-review / a second Solidity reviewer
UniV2Adapter.swap: token0/token1 set-equality check + quote fromgetReserves()+swap(a0,a1,to,""). Confirm the pool-to-pooltorouting (nextIsV2 ? hops[i+1].pool : this) and theinputAtPoolflag cannot desync for a mixed-kind path once kinds 1-4 exist (today every non-0 kind reverts before it matters).executeprofit gate:balanceOf(base)before/after onaddress(this)— check the argument that a base token appearing mid-path (A→B→A→C→A) is routed pool-to-pool and cannot inflatebalanceAfter.SafeTransfer:ret.length == 0 ? code.length == 0 : !decode(bool)— USDC facade has code (1 799 bytes) so it passes; confirm no Arc token returns malformed data.bool transient) — pattern and evm_version pin (cancun) vs. Arc (Osaka-capable).onlyExecutortreatsexecutor == address(0)as "owner-only" — check the modifier's boolean.token0()/token1()read per hop (≈1.5 k/hop) — acceptable or worth a Phase 4zeroForOnehint?Escalations / not done
cast wallet new → /etc/arc-mev-bot/*.keywrite (Secret-Store Writes). Runbook is indocs/key-management.md§2 — an operator step.0xAdec…2D61(key onmainnet.fortiblox.com, not on LXC 140; 64.7 USDC). The LXC 140-local/etc/arcarb/executor.keywallet (0xCb07…A1e9) has 0 balance. No faucet URL is documented anywhere infortiblox-arc-arb.config/bot.example.tomldoes not exist onmain; the deployed executor address will be recorded there + README §4 in a follow-up PR once deployed.🤖 Generated with Claude Code
196216a1aftoaa9e83c53bautomerger v2 auto-approved: all 7 gates pass. Approver: fortiblox-dev (opposite-identity rule). Gates: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker.
New commits pushed, approval review dismissed automatically according to repository settings
automerger v2 auto-approved: all 7 gates pass. Approver: fortiblox-dev (opposite-identity rule). Gates: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker.
automerger v2 auto-approved: all 7 gates pass. Approver: fortiblox-dev (opposite-identity rule). Gates: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker.
automerger v2 auto-approved: all 7 gates pass. Approver: fortiblox-dev (opposite-identity rule). Gates: mergeable=true,label=auto-merge,author=buddysan,identity=ok,status_checks=not_required,signatures=upstream_BP_only,opt_in=repo_marker.
Closing as superseded: PR #16 was branched from this PR and merged first, carrying all of this PR's commits (
aa9e83ccontracts, plus its owne14ce41deploy-record) intomain. Diff against current main is now empty (0 files changed). Content is fully live — seecontracts/,docs/key-management.mdonmain. Closing without merge.Pull request closed