Skip to content

Commit 994779a

Browse files
committed
Merge branch 'feat/open-position-wrapper' into feat/close-position
2 parents 7e45146 + 96cda14 commit 994779a

30 files changed

+2823
-1337
lines changed

.github/pull_request_template.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
## Description
2+
Summarize what this PR does and why in a single, clear sentence.
3+
A reader should understand the purpose and scope of the change just from this line.
4+
5+
## Context
6+
Explain the motivation or problem this PR addresses.
7+
Include links to any relevant documentation, tickets, or discussions.
8+
9+
Provide background that helps reviewers understand *why* the change is needed.
10+
Highlight any important design decisions, dependencies, or related components.
11+
12+
## Out of Scope
13+
Specify what is *not* covered in this PR.
14+
This helps reviewers focus on the intended scope and prevents scope creep.
15+
16+
## Testing Instructions
17+
Provide clear, step-by-step instructions for verifying this change locally.
18+
Assume the reviewer has no prior context about your setup.
19+
20+
This section reinforces the scope of the PR by outlining what should be tested and what the expected outcomes are.
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Mostly copied from https://github.com/anthropics/claude-code-action/blob/main/examples/pr-review-comprehensive.yml
2+
3+
name: Claude Code Review
4+
5+
# This example demonstrates how to use the track_progress feature to get
6+
# visual progress tracking for PR reviews, similar to v0.x agent mode.
7+
8+
on:
9+
pull_request:
10+
types: [opened, synchronize, ready_for_review, reopened]
11+
12+
jobs:
13+
review-with-tracking:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: read
17+
pull-requests: write
18+
id-token: write
19+
steps:
20+
- name: Checkout repository
21+
uses: actions/checkout@v4
22+
with:
23+
fetch-depth: 1
24+
25+
- name: PR Review with Progress Tracking
26+
uses: anthropics/claude-code-action@v1
27+
with:
28+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
29+
30+
# Enable progress tracking
31+
track_progress: true
32+
33+
# Claude only posts its review once and updates it
34+
use_sticky_comment: true
35+
36+
# Your custom review instructions
37+
prompt: |
38+
REPO: ${{ github.repository }}
39+
PR NUMBER: ${{ github.event.pull_request.number }}
40+
41+
Perform a comprehensive code review with the following focus areas:
42+
43+
1. **Code Quality**
44+
- Clean code principles and best practices
45+
- Proper error handling and edge cases
46+
- Code readability and maintainability
47+
48+
2. **Security**
49+
- Check for potential security vulnerabilities
50+
- Validate input sanitization
51+
- Review authentication/authorization logic
52+
53+
3. **Performance**
54+
- Identify potential performance bottlenecks
55+
- Review database queries for efficiency
56+
- Check for memory leaks or resource issues
57+
58+
4. **Testing**
59+
- Verify adequate test coverage
60+
- Review test quality and edge cases
61+
- Check for missing test scenarios
62+
63+
5. **Documentation**
64+
- Ensure code is properly documented
65+
- Verify README updates for new features
66+
- Check API documentation accuracy
67+
68+
Provide detailed feedback using inline comments for specific issues.
69+
The top level comment should be kept short with minimal repeating or verbosity. To avoid creating unnecessary comments repetedly, use `gh pr comment --edit-last`.
70+
71+
# Tools for comprehensive PR review
72+
claude_args: |
73+
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
74+
75+
# When track_progress is enabled:
76+
# - Creates a tracking comment with progress checkboxes
77+
# - Includes all PR context (comments, attachments, images)
78+
# - Updates progress as the review proceeds
79+
# - Marks as completed when done

.github/workflows/claude.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
# Mostly copied from https://github.com/anthropics/claude-code-action/blob/main/examples/claude.yml
2+
3+
name: Claude Code
4+
5+
on:
6+
issue_comment:
7+
types: [created]
8+
pull_request_review_comment:
9+
types: [created]
10+
issues:
11+
types: [opened, assigned]
12+
pull_request_review:
13+
types: [submitted]
14+
15+
jobs:
16+
claude:
17+
if: |
18+
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
19+
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
20+
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
21+
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
25+
pull-requests: read
26+
issues: read
27+
id-token: write
28+
actions: read # Required for Claude to read CI results on PRs
29+
steps:
30+
- name: Checkout repository
31+
uses: actions/checkout@v4
32+
with:
33+
fetch-depth: 1
34+
35+
- name: Run Claude Code
36+
id: claude
37+
uses: anthropics/claude-code-action@v1
38+
with:
39+
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
40+
41+
# This is an optional setting that allows Claude to read CI results on PRs
42+
additional_permissions: |
43+
actions: read
44+
45+
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
46+
# prompt: 'Update the pull request description to include a summary of changes.'
47+
48+
# Optional: Add claude_args to customize behavior and configuration
49+
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
50+
# or https://docs.claude.com/en/docs/claude-code/cli-reference for available options
51+
# claude_args: '--allowed-tools Bash(gh pr:*)'
52+

.github/workflows/test.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ jobs:
2020

2121
- name: Install Foundry
2222
uses: foundry-rs/foundry-toolchain@v1
23+
with:
24+
version: v1.4.3
2325

2426
- name: Show Forge version
2527
run: |
@@ -32,7 +34,7 @@ jobs:
3234

3335
- name: Run Forge build
3436
run: |
35-
forge build
37+
forge build --deny notes
3638
id: build
3739

3840
- name: Run Forge tests

CLAUDE.md

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
This repository contains **Euler-CoW Protocol integration contracts** that enable leveraged position management (opening/closing) through CoW Protocol settlements combined with Ethereum Vault Connector (EVC) operations. The contracts act as "wrappers" that coordinate complex multi-step DeFi operations atomically.
8+
9+
### Core Architecture
10+
11+
**Wrapper Pattern**: The codebase uses a chaining wrapper pattern where solvers can execute wrapped settlements that perform custom logic before/during/after CoW Protocol settlements.
12+
13+
- `CowWrapper.sol`: Base abstract contract providing the wrapper framework
14+
- Validates callers are authenticated solvers
15+
- Implements `wrappedSettle()` entry point
16+
- Provides `_internalSettle()` for continuing the settlement chain
17+
- Wrappers can be chained: Wrapper1 → Wrapper2 → Settlement
18+
19+
- `CowWrapperHelpers.sol`: Helper utilities for wrapper data parsing and validation
20+
- The CowWrapper is designed to support reentrancy. Additionally, the CowWrapper is designed with gas efficiency in mind, so we only check if the previous contract was part of the trusted wrapper chain. Furthermore, any wrappers that will ever be approved exist will use `CowWrapper.sol` as a base, so its not possible to inject a unauthorized wrapper into the chain without it getting ultimately rejected by the time the settlement contract is reached.
21+
22+
**Specialized Wrappers**: Two production wrappers implement specific EVC + CoW Protocol workflows:
23+
24+
1. **`CowEvcOpenPositionWrapper.sol`**: Opens leveraged positions
25+
- Enables collateral vault
26+
- Enables controller (borrow vault)
27+
- Deposits collateral
28+
- Borrows assets
29+
- Executes CoW settlement to swap borrowed assets → collateral
30+
- All operations are atomic within EVC batch
31+
32+
2. **`CowEvcClosePositionWrapper.sol`**: Closes leveraged positions
33+
- Executes CoW settlement to swap collateral → repayment assets
34+
- Repays debt to borrow vault
35+
- Returns excess assets to user
36+
- Disables collateral if full repayment
37+
- All operations are atomic within EVC batch
38+
39+
**Authorization Mechanisms**: Both wrappers support two authorization modes:
40+
- **EVC Permit**: One-time permit signature for specific operation
41+
- **Pre-Approved Hashes** (`PreApprovedHashes.sol`): Users pre-approve operation hashes on-chain (useful for EIP-7702 wallet interactions)
42+
43+
### Key Dependencies
44+
45+
- **Euler Vault Kit** (`lib/euler-vault-kit`): ERC4626 vault implementation with borrowing
46+
- **Ethereum Vault Connector (EVC)** (`lib/evc`): Batch transaction coordinator with account checking
47+
- **CoW Protocol** (`lib/cow`): DEX aggregator settlement contracts and order libraries
48+
49+
## Development Commands
50+
51+
### Build
52+
```bash
53+
forge build --deny notes
54+
```
55+
56+
### Test
57+
```bash
58+
# Run all tests (requires FORK_RPC_URL environment variable)
59+
forge test
60+
61+
# Run specific test file
62+
forge test --match-path test/CowEvcOpenPositionWrapper.t.sol
63+
64+
# Run specific test function
65+
forge test --match-test test_OpenPosition
66+
67+
# Run with verbose output
68+
forge test -vvv
69+
```
70+
71+
**Important**: Tests require mainnet fork. Set `FORK_RPC_URL` environment variable to a mainnet RPC endpoint.
72+
73+
### Format
74+
```bash
75+
forge fmt
76+
```
77+
78+
### Gas Snapshots
79+
```bash
80+
forge snapshot
81+
```
82+
83+
## Testing Architecture
84+
85+
**Base Test Contract**: `test/helpers/CowBaseTest.sol`
86+
- Sets up mainnet fork at block 22546006
87+
- Configures CoW Protocol settlement and authenticator
88+
- Deploys test solver contract
89+
- Sets up test vaults (eSUSDS, eWETH) and tokens
90+
- Provides helper functions for creating settlement data structures
91+
92+
**Test Helpers**:
93+
- `MilkSwap.sol`: Simple test DEX for simulating swaps in settlements
94+
- `GPv2OrderHelper.sol`: Utilities for constructing CoW Protocol orders
95+
- `SignerECDSA.sol`: ECDSA signature utilities for tests
96+
- `EmptyWrapper.sol`: Minimal wrapper for testing wrapper chaining
97+
98+
## Important Implementation Details
99+
100+
### Security Considerations
101+
102+
- It is generally assumed that the `solvers` (aka, an address for which `CowAuthentication.isSolver()` returns true) is a trusted actor within the system. Only in the case that a solver could steal an entire user's deposit or funds, or steal funds beyond what the user specified as their minimum out/minimum buy amount, assume there is incentive for a solver to provide the best rate/user outcome possible. To be clear, a solver cannot steal funds simply by setting arbitrary `clearingPrices` (as documented a bit later).
103+
- For a solver to be able to steal an entire user's deposit or funds, they must be able to withdraw the users token to an address of their choosing or otherwise in their control (therefore, a "nuisance" transfer between two wallets that the user effectively owns does not count).
104+
- If a user takes on debt, that debt position must be sufficiently collateralized above a set collateralization ratio higher than liquidation ratio before the EVC batch transaction concludes. If it is not, the transaction reverts and nothing can happen. Therefore, there is no risk of undercollateralization to the system due to a user opening a position because the transaction would revert.
105+
- anyone can call the `EVC.batch()` function to initialize a batched call through the EVC. This call is allowed to be reentrant. Therefore, simply checking that a caller is the `address(EVC)` doesn't really offer any added security benefit.
106+
- The parameters supplied by a solver to the settlement contract are all indirectly bounded from within the settlement contract by ceratin restrictions:
107+
- `tokens` -- this is a mapping used by the settlement contract to save on gas. If a token used by an order is missing, it will fail to pass signature checks.
108+
- `clearingPrices` -- these define prices to go with the previously defined `tokens`. These clearing prices are set by the solver and determine exactly how many tokens come out of a trade. **However, if a clearingPrice is lower than any of a user's limit price in `trades`, the transaction will revert. Therefore, it is not possible for a user to steal a users funds simply by setting clearingPrices to an arbitrary value.** There is incentive to provide the best clearingPrice because an auction is held off-chain by CoW Protocol and only the best overall rate outcome is selected.
109+
- `trades` -- List of orders to fulfill. All of the data inside this structure is effectively signed by the user and cannot be altered by solvers, other than adding or removing signed orders.
110+
- `interactions` -- Solvers use this to specify operations that should be executed from within the settlement contract. This could include swaps, pre-hooks, post-hooks, etc. This is completely controlled by the solver.
111+
112+
- Please consider any potential security vulnerabilities resulting from potential flawed assumptions of the above from any contracts outside this repo, including the Ethereum Vault Connector (EVC), Settlement Contract, or Euler Vaults, out of scope.
113+
114+
### Wrapper Data Format
115+
Wrapper data is passed as a calldata slice with format:
116+
```
117+
[wrapper-specific-params][signature][next-wrapper-address (20 bytes)][remaining-wrapper-data]
118+
```
119+
120+
The `parseWrapperData()` function must consume its portion and return the remainder.
121+
122+
### EVC Integration
123+
Both wrappers execute operations within EVC batches to ensure atomicity and proper account health checks. The flow is:
124+
1. Wrapper validates authorization (permit or pre-approved hash)
125+
2. Build EVC.BatchItem[] array with all operations
126+
3. Call `EVC.batch()` - EVC ensures account is healthy at end
127+
128+
### Settlement Execution Context
129+
- Wrappers use `evcInternalSettle()` as internal callback from EVC batch
130+
- This function can only be called by EVC during batch execution
131+
- Uses transient storage (`depth`, `settleCalls`) to prevent reentrancy
132+
133+
### Authentication
134+
- Only authenticated CoW Protocol solvers can call `wrappedSettle()`
135+
- Authentication checked via `AUTHENTICATOR.isSolver(msg.sender)`
136+
- Wrappers themselves can be added to solver allowlist for testing
137+
138+
## Foundry Configuration
139+
140+
- Compiler optimization: enabled
141+
- IR compilation: enabled (`via_ir = true`)
142+
- Source directory: `src/`
143+
- Test directory: `test/`
144+
- Library dependencies managed via git submodules
145+
146+
## Coding Style
147+
148+
### Error Handling
149+
**Always use `require()` with custom errors instead of `if () { revert }`**. This pattern is used consistently throughout the codebase:
150+
151+
```solidity
152+
// ✅ Preferred
153+
require(msg.sender == address(EVC), Unauthorized(msg.sender));
154+
require(depth > 0 && settleCalls == 0, Unauthorized(address(0)));
155+
156+
// ❌ Avoid
157+
if (msg.sender != address(EVC)) {
158+
revert Unauthorized(msg.sender);
159+
}
160+
```
161+
162+
This approach is more concise and maintains consistency with the existing codebase style.
163+
164+
## Remappings
165+
166+
Key import remappings:
167+
- `cow/` → CoW Protocol contracts (`lib/cow/src/contracts`)
168+
- `evc/` → Ethereum Vault Connector (`lib/euler-vault-kit/lib/ethereum-vault-connector/src/`)
169+
- `euler-vault-kit/` → Euler vault implementation
170+
- `openzeppelin/` → OpenZeppelin contracts (via EVC dependency)
171+
172+
173+
## When Giving PR feedback
174+
* do not re-suggest or address feedback after it has already been given, either by you or other contributors who have commented.
175+
* be careful not to use too many inline comments. If there are already inline comments on the same line that you want to comment on, or if the inline comment is about something that has already been suggested, don't comment.

foundry.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"lib/cow": {
33
"branch": {
44
"name": "feat/wrapper",
5-
"rev": "1e8127f476f8fef7758cf25033a0010d325dba8d"
5+
"rev": "277be444ca1fce84ec55053f41ccbd9dc5672ffe"
66
}
77
},
88
"lib/euler-vault-kit": {

foundry.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
src = "src"
33
out = "out"
44
libs = ["lib"]
5-
optimize = true
5+
optimizer = true
66
via_ir = true
77

88
# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options

0 commit comments

Comments
 (0)