Skip to content

feat: auto enter#57

Open
alonecandies wants to merge 13 commits into
mainfrom
feat/auto-enter
Open

feat: auto enter#57
alonecandies wants to merge 13 commits into
mainfrom
feat/auto-enter

Conversation

@alonecandies

Copy link
Copy Markdown
Member

No description provided.

StructHash additions, V3Automation executeAutoEnter/executeFollowUp, EIP-712
bump to 6.0, 18 Foundry tests. See cross-repo contracts in §2.
…ollowUp

StructHash:
- New types: PoolSelection, AutoEnterAction, FollowUpTemplate, AutoEnterConfig
- Recompute OrderConfig_TYPEHASH and Order_TYPEHASH to include the new
  autoEnterConfig field (the recursive type-hash propagates upward).
- New constants use keccak256("...") inline so the string and hash can't drift.

V3Automation (v6.0):
- Bump EIP-712 version from 5.0 to 6.0 (the OrderConfig type-hash change
  invalidates all v5 signatures, so a new deployment is required).
- New Action.AUTO_ENTER + ExecuteAutoEnterParams/ExecuteFollowUpParams structs.
- executeAutoEnter pulls source tokens from the signer, deducts protocol+gas
  fees, calls inherited _swapAndMint, transfers NFT to signer, persists
  (orderDigest -> mintedTokenId, signer) for follow-up authorization.
- executeFollowUp re-uses the parent order's signature as authorization for
  pre-templated rebalance/compound/exit/harvest against the new tokenId.
- Verifies followUpConfigEncoded matches the signed templateConfigHash.

Notes:
- Recipient = signer for the NFT. For follow-ups to work the user must
  setApprovalForAll(V3Automation, true) before signing — same prerequisite
  as the existing rebalance/compound flow.
- v1 rejects dynamic pool selection on-chain (PoolSelection.mode != 0).
  The schema reserves space so Phase 2 is additive.
Validates the cross-repo invariant most likely to drift: the EIP-712 type-hash
computation. Frontend signs, contract verifies — if these diverge, every
auto-enter order fails verification silently.

Covered:
- DOMAIN_SEPARATOR matches v6.0 manually-computed value
- FollowUpTemplate type-hash is stable
- PoolSelection / AutoEnterAction hashes are deterministic and field-sensitive
- Full Order: sign with vm.sign, recover via ECDSA, signer round-trips
- Tampering with any field invalidates the recovered signer
- Follow-ups participate in the signed digest

Deferred to integration tests (need a fork): full mint, follow-up execution,
revert paths for expired/wrong-signer/slippage/cancellation. Plan §4.5 lists
the 18 integration scenarios.
V3Automation.executeAutoEnter:
- Handle msg.value > 0 when sourceToken == WETH: deposit ETH to WETH and
  pull only the remainder from the signer. If msg.value is supplied but
  sourceToken != WETH, revert NoEtherToken (rather than silently leaving
  ETH stuck in the contract).
- TooMuchEtherSent if msg.value > p.sourceAmount.

script/UpgradeV6.s.sol:
- Deploys V3Automation v6 with CREATE2 salt "V3AutomationV6" (distinct
  from v5's salt so addresses don't collide). Initializes + grants
  OPERATOR_ROLE to operators from env. Leaves v5 deployment in place for
  in-flight orders to drain.
The Solidity StructHash library only exposes _hash(bytes) externally — so
abigen against the library's ABI doesn't generate Go struct types for
Order/OrderConfig/AutoEnterConfig etc.

StructHashEncoder is a pure-view wrapper that takes the relevant structs by
calldata, exposing them in the contract's ABI. Backend's abi_gen.sh consumes
StructHashEncoder.json -> libs/contracts/krystalvaultv6/ to get Go bindings
with StructHashOrder, StructHashAutoEnterConfig, StructHashPoolSelection,
StructHashFollowUpTemplate types.

The wrapper itself is never deployed — it exists purely for ABI generation.
Comment thread src/V3Automation.sol Outdated
Comment thread src/V3Automation.sol
Comment thread src/V3Automation.sol
Comment thread src/V3Automation.sol
Comment thread src/V3Automation.sol Outdated
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed the recent commits on feat/auto-enter (no prior inline review comments were open). I found several correctness/security issues in the new auto-enter/follow-up authorization path and posted inline comments.

Key findings:

  • executeAutoEnter signatures are replayable and can pull/mint repeatedly.
  • Signed pool/NFPM/protocol fields are not fully bound to execution params.
  • Signed slippage/gas constraints are currently not enforced against concrete swap/mint params.
  • Follow-up templates are only hash-checked, but the actual ExecuteParams are not validated against the signed template.
  • Direct token0/token1 auto-enter appears to pass funds through amount2, which _swapAndPrepareAmounts ignores in those branches.

I could not run Foundry tests in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes (do not merge until the authorization/replay and execution-param validation issues are fixed).

…ount routing

- executeAutoEnter now marks the parent order digest consumed before pulling
  funds (_executedAutoEnter), so a valid signature can't be replayed to mint
  repeatedly until allowance/balance is drained.
- Bind execution to the signed order beyond the NFPM whitelist: require
  order.nfpmAddress == p.nfpm, ps.poolManagerOrNfpm == p.nfpm, ps.protocol == 0
  (UNI_V3; v4/pancake belong on V4UtilsRouter), ps.hooks == 0, filterHash == 0.
  Prevents an operator redirecting the same signature to another whitelisted
  manager/protocol with matching pool params.
- _buildAutoEnterSwapMintParams routes the funded amount into amount0/amount1
  when the source token is a pool token (amount2 is only for third-token zaps);
  _swapAndPrepareAmounts ignores amount2 in the token0/token1 branches, so a
  direct token0/token1 auto-enter previously minted zero input or reverted.

Tests: fork-free binding reverts (non-v3 protocol, non-zero hooks).

NOT fixed here (require a cross-repo signed-schema change — the signed payload
would need concrete min amounts / canonical execute params, touching StructHash
+ Go v6 signer + frontend hashing): enforcing signed swap/liquidity slippage
bounds on-chain, and binding executeFollowUp's ExecuteParams (beyond action
type) to the follow-up template.
Comment thread src/V3Automation.sol
Comment thread script/UpgradeV6.s.sol
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed the latest commit dad495e since the previous review and re-checked the earlier findings.

Status of prior issues:

  • Replay guard: addressed with _executedAutoEnter.
  • Signed NFPM/pool fields: mostly addressed, but p.protocol is still not bound to the signed protocol (new inline comment).
  • Direct token0/token1 amount routing: addressed.
  • Signed slippage / max gas constraints: still unresolved per commit note; remains a material authorization gap before production use.
  • Follow-up template vs ExecuteParams validation: still unresolved per commit note; remains a material authorization gap before production use.

New findings posted inline:

  • executeAutoEnter still passes caller-controlled p.protocol into minting despite requiring the signed ps.protocol == 0.
  • UpgradeV6.s.sol reads/documents WITHDRAWER but never grants the withdrawer role.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The recent fixes move this in the right direction, but the remaining authorization gaps around follow-up execution/slippage plus the protocol binding issue should be resolved before merge.

…gured withdrawer

- executeAutoEnter now requires p.protocol == Nfpm.Protocol.UNI_V3.
  _buildAutoEnterSwapMintParams forwards p.protocol into _swapAndMint (which
  picks the Nfpm.mint branch); forcing ps.protocol alone left the actual mint
  protocol caller-controlled. Test: rejects a mismatched p.protocol.
- UpgradeV6 script grants WITHDRAWER_ROLE to the configured WITHDRAWER after
  initialize() (which only grants it to admin). Previously the env var was read
  but never used, so a separate withdrawer could never withdraw.
Comment thread src/V3Automation.sol
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed the latest commit f1b0d794 since the previous review and re-checked the prior findings.

Status of prior issues:

  • Replay guard: addressed with _executedAutoEnter.
  • Direct token0/token1 amount routing: addressed.
  • p.protocol binding for auto-enter minting: addressed in the latest commit.
  • WITHDRAWER env var/role grant: addressed in the latest commit.
  • Signed slippage / max gas constraints: still unresolved and remains a material authorization gap.
  • Follow-up template vs ExecuteParams validation: still unresolved and remains a material authorization gap.

New finding posted inline:

  • executeFollowUp authorizes by parent digest + tokenId only, but does not bind the follow-up NFPM/protocol to the NFT minted by executeAutoEnter; a same tokenId on another whitelisted NFPM owned by the signer could be operated on under the parent authorization.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The latest fixes address the recent protocol/withdrawer comments, but the remaining follow-up authorization gaps (including NFPM binding) and the acknowledged slippage/max-gas enforcement gap should be resolved before merge.

…e amount

executeFollowUp stored only the minted tokenId, so an operator could run a
parent-authorized follow-up against an unrelated NFT of the same numeric id on
a different whitelisted NFPM the signer also owns. Bind p.execute.nfpm/protocol
to the parent's signed poolSelection (mirrors V4UtilsRouter's POSM binding).

Also require p.sourceAmount == act.sourceAmount: the one-shot _executedAutoEnter
guard permanently consumes the signature, and partial fills are not part of the
signed schema, so a smaller pull would burn the order on a smaller-than-signed
mint. Add test_AutoEnter_RejectsPartialAmount.
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed latest commit 67d4537 since the last review and re-checked previously open issues.

Status of prior issues:

  • Replay guard: addressed.
  • Auto-enter NFPM/protocol binding: addressed.
  • Direct token0/token1 amount routing: addressed.
  • WITHDRAWER role grant in deploy script: addressed.
  • Follow-up NFPM/protocol binding: addressed by binding to the signed parent selection.
  • Partial fills: improved; auto-enter now requires exact signed sourceAmount.
  • Signed slippage / max-gas constraints: still unresolved and remains a material authorization gap.
  • Follow-up template vs actual ExecuteParams validation: still unresolved and remains a material authorization gap.

No new inline comments were added because the remaining issues are already under discussion on existing inline comments.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The latest commit fixes several important authorization gaps, but the remaining signed slippage/max-gas enforcement and follow-up parameter validation gaps should be resolved before merge.

Adds pr-test.yaml running 'forge test --match-path test/AutoEnter.t.sol' on PRs
to master and feat/auto-enter. The AUTO_ENTER suite is fork-free (no RPC/.env),
so the gate is deterministic and green; previously v3utils had only the AI
pi-reviewer workflow and no test gate on the feature branch.
Comment thread .github/workflows/pr-test.yaml
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed the latest commit 015eef8 since the last review and re-checked previously open issues.

Status of prior issues:

  • Replay guard: addressed.
  • Auto-enter NFPM/protocol binding: addressed.
  • Direct token0/token1 amount routing: addressed.
  • WITHDRAWER role grant in deploy script: addressed.
  • Follow-up NFPM/protocol binding: addressed.
  • Partial fills: addressed by requiring exact signed sourceAmount.
  • Signed slippage / max-gas constraints: still unresolved and remains a material authorization gap (already under discussion on an existing inline comment).
  • Follow-up template vs actual ExecuteParams validation: still unresolved and remains a material authorization gap (already under discussion on an existing inline comment).

New finding posted inline:

  • The new PR test workflow is filtered to master / feat/auto-enter, so it will not run for this PR or future PRs targeting main.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The CI addition is welcome, but it currently does not gate the intended branch, and the previously noted authorization gaps around signed slippage/max-gas and follow-up parameter validation should be resolved before merge.

Parity with V4UtilsRouter's minLiquidity guard. Operator-supplied amountAddMin0/1
unbound to signed value; both zero disables V3Utils' mint slippage floor (dust
mint). Require at least one non-zero (single-sided range legitimately has one
zero side).
@krystal-reviewer

krystal-reviewer Bot commented Jun 15, 2026

Copy link
Copy Markdown

PR Review Summary

Reviewed latest commit 1908dec since the last review and re-checked previously open issues.

Status of prior issues:

  • Replay guard: addressed.
  • Auto-enter NFPM/protocol binding: addressed.
  • Direct token0/token1 amount routing: addressed.
  • WITHDRAWER role grant in deploy script: addressed.
  • Follow-up NFPM/protocol binding: addressed.
  • Partial fills: addressed by requiring exact signed sourceAmount.
  • Zero liquidity floor: improved in 1908dec by rejecting amountAddMin0 == 0 && amountAddMin1 == 0.
  • Signed slippage / max-gas constraints: still unresolved. The new non-zero floor prevents the worst dust-mint case, but swapSlippageX64, liquiditySlippageX64, and maxGasProportionX64 are still not fully enforced against the concrete swap/mint/fee params (already under discussion on an existing inline comment).
  • Follow-up template vs actual ExecuteParams validation: still unresolved and remains a material authorization gap (already under discussion on an existing inline comment).
  • PR test workflow branch filter: still unresolved; it targets master / feat/auto-enter but PRs target main (already under discussion on an existing inline comment).

No new inline comments were added because the remaining findings are already covered by existing review comments.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The latest commit is a useful hardening step, but the remaining signed-constraint/follow-up authorization gaps and the CI branch filter should be fixed before merge.

Add uint256 minLiquidity to the signed AutoEnterAction (parity with v4 StructHash) and
enforce require(result.liquidity >= act.minLiquidity) post-mint in executeAutoEnter, so
the operator cannot weaken the signed liquidity floor (replaces the amountAddMin>0 guard;
operator amountAddMin0/1 remain as secondary per-token mins). Tests updated + new
test_MinLiquidityAffectsOrderHash.
@krystal-reviewer

Copy link
Copy Markdown

PR Review Summary

Reviewed latest commit e853f32 since the last review and re-checked the previously open findings.

Status of prior issues:

  • Replay guard: addressed.
  • Auto-enter NFPM/protocol binding: addressed.
  • Direct token0/token1 amount routing: addressed.
  • WITHDRAWER role grant in deploy script: addressed.
  • Follow-up NFPM/protocol binding: addressed.
  • Partial fills: addressed by requiring exact signed sourceAmount.
  • Zero/dust liquidity floor: improved in e853f32 by adding signed AutoEnterAction.minLiquidity and enforcing result.liquidity >= act.minLiquidity.
  • Signed slippage / max-gas constraints: partially improved by signed minLiquidity, but still not fully resolved. swapSlippageX64 and maxGasProportionX64 are still not enforced against concrete swap/fee params, and per-token mint mins remain operator-supplied (already under discussion on an existing inline comment).
  • Follow-up template vs actual ExecuteParams validation: still unresolved and remains a material authorization gap (already under discussion on an existing inline comment).
  • PR test workflow branch filter: still unresolved; it targets master / feat/auto-enter while PRs target main (already under discussion on an existing inline comment).

No new inline comments were added because the remaining findings are already covered by existing review comments.

I could not run the test suite in this environment because forge is not installed (forge: command not found).

Verdict: Request Changes. The signed minLiquidity addition is a meaningful hardening step, but the remaining signed-constraint/follow-up authorization gaps and CI branch filter should be fixed before merge.

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